Rollup merge of #137953 - RalfJung:simd-intrinsic-masks, r=WaffleLapkin

simd intrinsics with mask: accept unsigned integer masks, and fix some of the errors

It's not clear at all why the mask would have to be signed, it is anyway interpreted bitwise. The backend should just make sure that works no matter the surface-level type; our LLVM backend already does this correctly. The note of "the mask may be widened, which only has the correct behavior for signed integers" explains... nothing? Why can't the code do the widening correctly? If necessary, just cast to the signed type first...

Also while we are at it, fix the errors. For simd_masked_load/store, the errors talked about the "third argument" but they meant the first argument (the mask is the first argument there). They also used the wrong type for `expected_element`.

I have extremely low confidence in the GCC part of this PR.

See [discussion on Zulip](https://rust-lang.zulipchat.com/#narrow/channel/257879-project-portable-simd/topic/On.20the.20sign.20of.20masks)
This commit is contained in:
Chris Denton 2025-04-20 13:02:48 +00:00 committed by GitHub
commit d15c603173
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 119 additions and 148 deletions

View file

@ -29,6 +29,19 @@ pub unsafe fn gather_f32x2(
simd_gather(values, pointers, mask)
}
// CHECK-LABEL: @gather_f32x2_unsigned
#[no_mangle]
pub unsafe fn gather_f32x2_unsigned(
pointers: Vec2<*const f32>,
mask: Vec2<u32>,
values: Vec2<f32>,
) -> Vec2<f32> {
// CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{<i32 31, i32 31>|splat \(i32 31\)}}
// CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
// CHECK: call <2 x float> @llvm.masked.gather.v2f32.v2p0(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}})
simd_gather(values, pointers, mask)
}
// CHECK-LABEL: @gather_pf32x2
#[no_mangle]
pub unsafe fn gather_pf32x2(

View file

@ -23,6 +23,19 @@ pub unsafe fn load_f32x2(mask: Vec2<i32>, pointer: *const f32, values: Vec2<f32>
simd_masked_load(mask, pointer, values)
}
// CHECK-LABEL: @load_f32x2_unsigned
#[no_mangle]
pub unsafe fn load_f32x2_unsigned(
mask: Vec2<u32>,
pointer: *const f32,
values: Vec2<f32>,
) -> Vec2<f32> {
// CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{<i32 31, i32 31>|splat \(i32 31\)}}
// CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
// CHECK: call <2 x float> @llvm.masked.load.v2f32.p0(ptr {{.*}}, i32 4, <2 x i1> [[B]], <2 x float> {{.*}})
simd_masked_load(mask, pointer, values)
}
// CHECK-LABEL: @load_pf32x4
#[no_mangle]
pub unsafe fn load_pf32x4(

View file

@ -23,6 +23,15 @@ pub unsafe fn store_f32x2(mask: Vec2<i32>, pointer: *mut f32, values: Vec2<f32>)
simd_masked_store(mask, pointer, values)
}
// CHECK-LABEL: @store_f32x2_unsigned
#[no_mangle]
pub unsafe fn store_f32x2_unsigned(mask: Vec2<u32>, pointer: *mut f32, values: Vec2<f32>) {
// CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{<i32 31, i32 31>|splat \(i32 31\)}}
// CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
// CHECK: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr {{.*}}, i32 4, <2 x i1> [[B]])
simd_masked_store(mask, pointer, values)
}
// CHECK-LABEL: @store_pf32x4
#[no_mangle]
pub unsafe fn store_pf32x4(mask: Vec4<i32>, pointer: *mut *const f32, values: Vec4<*const f32>) {

View file

@ -25,6 +25,15 @@ pub unsafe fn scatter_f32x2(pointers: Vec2<*mut f32>, mask: Vec2<i32>, values: V
simd_scatter(values, pointers, mask)
}
// CHECK-LABEL: @scatter_f32x2_unsigned
#[no_mangle]
pub unsafe fn scatter_f32x2_unsigned(pointers: Vec2<*mut f32>, mask: Vec2<u32>, values: Vec2<f32>) {
// CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{<i32 31, i32 31>|splat \(i32 31\)}}
// CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
// CHECK: call void @llvm.masked.scatter.v2f32.v2p0(<2 x float> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]]
simd_scatter(values, pointers, mask)
}
// CHECK-LABEL: @scatter_pf32x2
#[no_mangle]
pub unsafe fn scatter_pf32x2(

View file

@ -22,6 +22,10 @@ pub struct b8x4(pub [i8; 4]);
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct i32x4([i32; 4]);
#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct u32x4([u32; 4]);
// CHECK-LABEL: @select_m8
#[no_mangle]
pub unsafe fn select_m8(m: b8x4, a: f32x4, b: f32x4) -> f32x4 {
@ -40,6 +44,15 @@ pub unsafe fn select_m32(m: i32x4, a: f32x4, b: f32x4) -> f32x4 {
simd_select(m, a, b)
}
// CHECK-LABEL: @select_m32_unsigned
#[no_mangle]
pub unsafe fn select_m32_unsigned(m: u32x4, a: f32x4, b: f32x4) -> f32x4 {
// CHECK: [[A:%[0-9]+]] = lshr <4 x i32> %{{.*}}, {{<i32 31, i32 31, i32 31, i32 31>|splat \(i32 31\)}}
// CHECK: [[B:%[0-9]+]] = trunc <4 x i32> [[A]] to <4 x i1>
// CHECK: select <4 x i1> [[B]]
simd_select(m, a, b)
}
// CHECK-LABEL: @select_bitmask
#[no_mangle]
pub unsafe fn select_bitmask(m: i8, a: f32x8, b: f32x8) -> f32x8 {

View file

@ -20,7 +20,6 @@ fn main() {
let s_strided = x4([0_f32, 2., -3., 6.]);
let mask = x4([-1_i32, -1, 0, -1]);
let umask = x4([0u16; 4]);
let fmask = x4([0_f32; 4]);
let pointer = x.as_mut_ptr();
@ -31,11 +30,8 @@ fn main() {
simd_gather(default, mask, mask);
//~^ ERROR expected element type `i32` of second argument `x4<i32>` to be a pointer to the element type `f32`
simd_gather(default, pointers, umask);
//~^ ERROR expected element type `u16` of third argument `x4<u16>` to be a signed integer type
simd_gather(default, pointers, fmask);
//~^ ERROR expected element type `f32` of third argument `x4<f32>` to be a signed integer type
//~^ ERROR expected mask element type to be an integer, found `f32`
}
unsafe {
@ -43,10 +39,7 @@ fn main() {
simd_scatter(values, mask, mask);
//~^ ERROR expected element type `i32` of second argument `x4<i32>` to be a pointer to the element type `f32` of the first argument `x4<f32>`, found `i32` != `*mut f32`
simd_scatter(values, pointers, umask);
//~^ ERROR expected element type `u16` of third argument `x4<u16>` to be a signed integer type
simd_scatter(values, pointers, fmask);
//~^ ERROR expected element type `f32` of third argument `x4<f32>` to be a signed integer type
//~^ ERROR expected mask element type to be an integer, found `f32`
}
}

View file

@ -1,39 +1,27 @@
error[E0511]: invalid monomorphization of `simd_gather` intrinsic: expected element type `i32` of second argument `x4<i32>` to be a pointer to the element type `f32` of the first argument `x4<f32>`, found `i32` != `*_ f32`
--> $DIR/generic-gather.rs:31:9
--> $DIR/generic-gather-scatter.rs:30:9
|
LL | simd_gather(default, mask, mask);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_gather` intrinsic: expected element type `u16` of third argument `x4<u16>` to be a signed integer type
--> $DIR/generic-gather.rs:34:9
|
LL | simd_gather(default, pointers, umask);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_gather` intrinsic: expected element type `f32` of third argument `x4<f32>` to be a signed integer type
--> $DIR/generic-gather.rs:37:9
error[E0511]: invalid monomorphization of `simd_gather` intrinsic: expected mask element type to be an integer, found `f32`
--> $DIR/generic-gather-scatter.rs:33:9
|
LL | simd_gather(default, pointers, fmask);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_scatter` intrinsic: expected element type `i32` of second argument `x4<i32>` to be a pointer to the element type `f32` of the first argument `x4<f32>`, found `i32` != `*mut f32`
--> $DIR/generic-gather.rs:43:9
--> $DIR/generic-gather-scatter.rs:39:9
|
LL | simd_scatter(values, mask, mask);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_scatter` intrinsic: expected element type `u16` of third argument `x4<u16>` to be a signed integer type
--> $DIR/generic-gather.rs:46:9
|
LL | simd_scatter(values, pointers, umask);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_scatter` intrinsic: expected element type `f32` of third argument `x4<f32>` to be a signed integer type
--> $DIR/generic-gather.rs:49:9
error[E0511]: invalid monomorphization of `simd_scatter` intrinsic: expected mask element type to be an integer, found `f32`
--> $DIR/generic-gather-scatter.rs:42:9
|
LL | simd_scatter(values, pointers, fmask);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0511`.

View file

@ -36,11 +36,8 @@ fn main() {
simd_select(m8, x, x);
//~^ ERROR mismatched lengths: mask length `8` != other vector length `4`
simd_select(x, x, x);
//~^ ERROR mask element type is `u32`, expected a signed integer type
simd_select(z, z, z);
//~^ ERROR mask element type is `f32`, expected a signed integer type
//~^ ERROR expected mask element type to be an integer, found `f32`
simd_select(m4, 0u32, 1u32);
//~^ ERROR found non-SIMD `u32`

View file

@ -4,52 +4,42 @@ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mismatched le
LL | simd_select(m8, x, x);
| ^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_select` intrinsic: found mask element type is `u32`, expected a signed integer type
error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected mask element type to be an integer, found `f32`
--> $DIR/generic-select.rs:39:9
|
LL | simd_select(x, x, x);
| ^^^^^^^^^^^^^^^^^^^^
|
= note: the mask may be widened, which only has the correct behavior for signed integers
error[E0511]: invalid monomorphization of `simd_select` intrinsic: found mask element type is `f32`, expected a signed integer type
--> $DIR/generic-select.rs:42:9
|
LL | simd_select(z, z, z);
| ^^^^^^^^^^^^^^^^^^^^
|
= note: the mask may be widened, which only has the correct behavior for signed integers
error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32`
--> $DIR/generic-select.rs:45:9
--> $DIR/generic-select.rs:42:9
|
LL | simd_select(m4, 0u32, 1u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `u16`, expected `u8` or `[u8; 1]`
--> $DIR/generic-select.rs:48:9
--> $DIR/generic-select.rs:45:9
|
LL | simd_select_bitmask(0u16, x, x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32`
--> $DIR/generic-select.rs:51:9
--> $DIR/generic-select.rs:48:9
|
LL | simd_select_bitmask(0u8, 1u32, 2u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `f32`, expected `u8` or `[u8; 1]`
--> $DIR/generic-select.rs:54:9
--> $DIR/generic-select.rs:51:9
|
LL | simd_select_bitmask(0.0f32, x, x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `&str`, expected `u8` or `[u8; 1]`
--> $DIR/generic-select.rs:57:9
--> $DIR/generic-select.rs:54:9
|
LL | simd_select_bitmask("x", x, x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 8 previous errors
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0511`.

View file

@ -21,8 +21,8 @@ fn main() {
simd_masked_load(Simd::<i8, 4>([-1, 0, -1, -1]), arr.as_ptr(), Simd::<u32, 4>([9; 4]));
//~^ ERROR expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*_ u32`
simd_masked_load(Simd::<u8, 4>([1, 0, 1, 1]), arr.as_ptr(), default);
//~^ ERROR expected element type `u8` of third argument `Simd<u8, 4>` to be a signed integer type
simd_masked_load(Simd::<f32, 4>([1.0, 0.0, 1.0, 1.0]), arr.as_ptr(), default);
//~^ ERROR expected mask element type to be an integer, found `f32`
simd_masked_store(Simd([-1i8; 4]), arr.as_ptr(), Simd([5u32; 4]));
//~^ ERROR expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*mut u32`
@ -33,7 +33,7 @@ fn main() {
simd_masked_store(Simd([-1i8; 4]), arr.as_mut_ptr(), Simd([5u8; 2]));
//~^ ERROR expected third argument with length 4 (same as input type `Simd<i8, 4>`), found `Simd<u8, 2>` with length 2
simd_masked_store(Simd([1u32; 4]), arr.as_mut_ptr(), Simd([5u8; 4]));
//~^ ERROR expected element type `u8` of third argument `Simd<u32, 4>` to be a signed integer type
simd_masked_store(Simd([1f32; 4]), arr.as_mut_ptr(), Simd([5u8; 4]));
//~^ ERROR expected mask element type to be an integer, found `f32`
}
}

View file

@ -16,11 +16,11 @@ error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected
LL | simd_masked_load(Simd::<i8, 4>([-1, 0, -1, -1]), arr.as_ptr(), Simd::<u32, 4>([9; 4]));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u8` of third argument `Simd<u8, 4>` to be a signed integer type
error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected mask element type to be an integer, found `f32`
--> $DIR/masked-load-store-build-fail.rs:24:9
|
LL | simd_masked_load(Simd::<u8, 4>([1, 0, 1, 1]), arr.as_ptr(), default);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | simd_masked_load(Simd::<f32, 4>([1.0, 0.0, 1.0, 1.0]), arr.as_ptr(), default);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*mut u32`
--> $DIR/masked-load-store-build-fail.rs:27:9
@ -40,10 +40,10 @@ error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expecte
LL | simd_masked_store(Simd([-1i8; 4]), arr.as_mut_ptr(), Simd([5u8; 2]));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u8` of third argument `Simd<u32, 4>` to be a signed integer type
error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected mask element type to be an integer, found `f32`
--> $DIR/masked-load-store-build-fail.rs:36:9
|
LL | simd_masked_store(Simd([1u32; 4]), arr.as_mut_ptr(), Simd([5u8; 4]));
LL | simd_masked_store(Simd([1f32; 4]), arr.as_mut_ptr(), Simd([5u8; 4]));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 8 previous errors