1
Fork 0

Auto merge of #114156 - calebzulawski:simd-bswap, r=compiler-errors

Add simd_bswap, simd_bitreverse, simd_ctlz, and simd_cttz intrinsics

cc `@workingjubilee`
This commit is contained in:
bors 2023-07-29 18:51:45 +00:00
commit 03a57254b5
6 changed files with 173 additions and 25 deletions

View file

@ -2074,6 +2074,53 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
simd_neg: Int => neg, Float => fneg; simd_neg: Int => neg, Float => fneg;
} }
// Unary integer intrinsics
if matches!(name, sym::simd_bswap | sym::simd_bitreverse | sym::simd_ctlz | sym::simd_cttz) {
let vec_ty = bx.cx.type_vector(
match *in_elem.kind() {
ty::Int(i) => bx.cx.type_int_from_ty(i),
ty::Uint(i) => bx.cx.type_uint_from_ty(i),
_ => return_error!(InvalidMonomorphization::UnsupportedOperation {
span,
name,
in_ty,
in_elem
}),
},
in_len as u64,
);
let intrinsic_name = match name {
sym::simd_bswap => "bswap",
sym::simd_bitreverse => "bitreverse",
sym::simd_ctlz => "ctlz",
sym::simd_cttz => "cttz",
_ => unreachable!(),
};
let llvm_intrinsic = &format!(
"llvm.{}.v{}i{}",
intrinsic_name,
in_len,
in_elem.int_size_and_signed(bx.tcx()).0.bits(),
);
return Ok(if matches!(name, sym::simd_ctlz | sym::simd_cttz) {
let fn_ty = bx.type_func(&[vec_ty, bx.type_i1()], vec_ty);
let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
bx.call(
fn_ty,
None,
None,
f,
&[args[0].immediate(), bx.const_int(bx.type_i1(), 0)],
None,
)
} else {
let fn_ty = bx.type_func(&[vec_ty], vec_ty);
let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
bx.call(fn_ty, None, None, f, &[args[0].immediate()], None)
});
}
if name == sym::simd_arith_offset { if name == sym::simd_arith_offset {
// This also checks that the first operand is a ptr type. // This also checks that the first operand is a ptr type.
let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| { let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| {

View file

@ -521,6 +521,10 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
| sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)), | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)),
sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)), sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)),
sym::simd_neg sym::simd_neg
| sym::simd_bswap
| sym::simd_bitreverse
| sym::simd_ctlz
| sym::simd_cttz
| sym::simd_fsqrt | sym::simd_fsqrt
| sym::simd_fsin | sym::simd_fsin
| sym::simd_fcos | sym::simd_fcos

View file

@ -1371,9 +1371,13 @@ symbols! {
simd_arith_offset, simd_arith_offset,
simd_as, simd_as,
simd_bitmask, simd_bitmask,
simd_bitreverse,
simd_bswap,
simd_cast, simd_cast,
simd_cast_ptr, simd_cast_ptr,
simd_ceil, simd_ceil,
simd_ctlz,
simd_cttz,
simd_div, simd_div,
simd_eq, simd_eq,
simd_expose_addr, simd_expose_addr,

View file

@ -27,6 +27,10 @@ extern "platform-intrinsic" {
fn simd_xor<T>(x: T, y: T) -> T; fn simd_xor<T>(x: T, y: T) -> T;
fn simd_neg<T>(x: T) -> T; fn simd_neg<T>(x: T) -> T;
fn simd_bswap<T>(x: T) -> T;
fn simd_bitreverse<T>(x: T) -> T;
fn simd_ctlz<T>(x: T) -> T;
fn simd_cttz<T>(x: T) -> T;
} }
fn main() { fn main() {
@ -64,6 +68,14 @@ fn main() {
simd_neg(x); simd_neg(x);
simd_neg(z); simd_neg(z);
simd_bswap(x);
simd_bswap(y);
simd_bitreverse(x);
simd_bitreverse(y);
simd_ctlz(x);
simd_ctlz(y);
simd_cttz(x);
simd_cttz(y);
simd_add(0, 0); simd_add(0, 0);
@ -87,6 +99,14 @@ fn main() {
simd_neg(0); simd_neg(0);
//~^ ERROR expected SIMD input type, found non-SIMD `i32` //~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_bswap(0);
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_bitreverse(0);
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_ctlz(0);
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_cttz(0);
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
simd_shl(z, z); simd_shl(z, z);
@ -98,6 +118,14 @@ fn main() {
simd_or(z, z); simd_or(z, z);
//~^ ERROR unsupported operation on `f32x4` with element `f32` //~^ ERROR unsupported operation on `f32x4` with element `f32`
simd_xor(z, z); simd_xor(z, z);
//~^ ERROR unsupported operation on `f32x4` with element `f32`
simd_bswap(z);
//~^ ERROR unsupported operation on `f32x4` with element `f32`
simd_bitreverse(z);
//~^ ERROR unsupported operation on `f32x4` with element `f32`
simd_ctlz(z);
//~^ ERROR unsupported operation on `f32x4` with element `f32`
simd_cttz(z);
//~^ ERROR unsupported operation on `f32x4` with element `f32` //~^ ERROR unsupported operation on `f32x4` with element `f32`
} }
} }

View file

@ -1,93 +1,141 @@
error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32` error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:69:9 --> $DIR/generic-arithmetic-2.rs:81:9
| |
LL | simd_add(0, 0); LL | simd_add(0, 0);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_sub` intrinsic: expected SIMD input type, found non-SIMD `i32` error[E0511]: invalid monomorphization of `simd_sub` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:71:9 --> $DIR/generic-arithmetic-2.rs:83:9
| |
LL | simd_sub(0, 0); LL | simd_sub(0, 0);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_mul` intrinsic: expected SIMD input type, found non-SIMD `i32` error[E0511]: invalid monomorphization of `simd_mul` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:73:9 --> $DIR/generic-arithmetic-2.rs:85:9
| |
LL | simd_mul(0, 0); LL | simd_mul(0, 0);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_div` intrinsic: expected SIMD input type, found non-SIMD `i32` error[E0511]: invalid monomorphization of `simd_div` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:75:9 --> $DIR/generic-arithmetic-2.rs:87:9
| |
LL | simd_div(0, 0); LL | simd_div(0, 0);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shl` intrinsic: expected SIMD input type, found non-SIMD `i32` error[E0511]: invalid monomorphization of `simd_shl` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:77:9 --> $DIR/generic-arithmetic-2.rs:89:9
| |
LL | simd_shl(0, 0); LL | simd_shl(0, 0);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shr` intrinsic: expected SIMD input type, found non-SIMD `i32` error[E0511]: invalid monomorphization of `simd_shr` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:79:9 --> $DIR/generic-arithmetic-2.rs:91:9
| |
LL | simd_shr(0, 0); LL | simd_shr(0, 0);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_and` intrinsic: expected SIMD input type, found non-SIMD `i32` error[E0511]: invalid monomorphization of `simd_and` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:81:9 --> $DIR/generic-arithmetic-2.rs:93:9
| |
LL | simd_and(0, 0); LL | simd_and(0, 0);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_or` intrinsic: expected SIMD input type, found non-SIMD `i32` error[E0511]: invalid monomorphization of `simd_or` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:83:9 --> $DIR/generic-arithmetic-2.rs:95:9
| |
LL | simd_or(0, 0); LL | simd_or(0, 0);
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_xor` intrinsic: expected SIMD input type, found non-SIMD `i32` error[E0511]: invalid monomorphization of `simd_xor` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:85:9 --> $DIR/generic-arithmetic-2.rs:97:9
| |
LL | simd_xor(0, 0); LL | simd_xor(0, 0);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_neg` intrinsic: expected SIMD input type, found non-SIMD `i32` error[E0511]: invalid monomorphization of `simd_neg` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:88:9 --> $DIR/generic-arithmetic-2.rs:100:9
| |
LL | simd_neg(0); LL | simd_neg(0);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_bswap` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:102:9
|
LL | simd_bswap(0);
| ^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_bitreverse` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:104:9
|
LL | simd_bitreverse(0);
| ^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_ctlz` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:106:9
|
LL | simd_ctlz(0);
| ^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_cttz` intrinsic: expected SIMD input type, found non-SIMD `i32`
--> $DIR/generic-arithmetic-2.rs:108:9
|
LL | simd_cttz(0);
| ^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shl` intrinsic: unsupported operation on `f32x4` with element `f32` error[E0511]: invalid monomorphization of `simd_shl` intrinsic: unsupported operation on `f32x4` with element `f32`
--> $DIR/generic-arithmetic-2.rs:92:9 --> $DIR/generic-arithmetic-2.rs:112:9
| |
LL | simd_shl(z, z); LL | simd_shl(z, z);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shr` intrinsic: unsupported operation on `f32x4` with element `f32` error[E0511]: invalid monomorphization of `simd_shr` intrinsic: unsupported operation on `f32x4` with element `f32`
--> $DIR/generic-arithmetic-2.rs:94:9 --> $DIR/generic-arithmetic-2.rs:114:9
| |
LL | simd_shr(z, z); LL | simd_shr(z, z);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_and` intrinsic: unsupported operation on `f32x4` with element `f32` error[E0511]: invalid monomorphization of `simd_and` intrinsic: unsupported operation on `f32x4` with element `f32`
--> $DIR/generic-arithmetic-2.rs:96:9 --> $DIR/generic-arithmetic-2.rs:116:9
| |
LL | simd_and(z, z); LL | simd_and(z, z);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_or` intrinsic: unsupported operation on `f32x4` with element `f32` error[E0511]: invalid monomorphization of `simd_or` intrinsic: unsupported operation on `f32x4` with element `f32`
--> $DIR/generic-arithmetic-2.rs:98:9 --> $DIR/generic-arithmetic-2.rs:118:9
| |
LL | simd_or(z, z); LL | simd_or(z, z);
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_xor` intrinsic: unsupported operation on `f32x4` with element `f32` error[E0511]: invalid monomorphization of `simd_xor` intrinsic: unsupported operation on `f32x4` with element `f32`
--> $DIR/generic-arithmetic-2.rs:100:9 --> $DIR/generic-arithmetic-2.rs:120:9
| |
LL | simd_xor(z, z); LL | simd_xor(z, z);
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: aborting due to 15 previous errors error[E0511]: invalid monomorphization of `simd_bswap` intrinsic: unsupported operation on `f32x4` with element `f32`
--> $DIR/generic-arithmetic-2.rs:122:9
|
LL | simd_bswap(z);
| ^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_bitreverse` intrinsic: unsupported operation on `f32x4` with element `f32`
--> $DIR/generic-arithmetic-2.rs:124:9
|
LL | simd_bitreverse(z);
| ^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_ctlz` intrinsic: unsupported operation on `f32x4` with element `f32`
--> $DIR/generic-arithmetic-2.rs:126:9
|
LL | simd_ctlz(z);
| ^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_cttz` intrinsic: unsupported operation on `f32x4` with element `f32`
--> $DIR/generic-arithmetic-2.rs:128:9
|
LL | simd_cttz(z);
| ^^^^^^^^^^^^
error: aborting due to 23 previous errors
For more information about this error, try `rustc --explain E0511`. For more information about this error, try `rustc --explain E0511`.

View file

@ -1,8 +1,6 @@
// run-pass // run-pass
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
// ignore-emscripten FIXME(#45351) hits an LLVM assert // ignore-emscripten FIXME(#45351) hits an LLVM assert
#![feature(repr_simd, platform_intrinsics)] #![feature(repr_simd, platform_intrinsics)]
#[repr(simd)] #[repr(simd)]
@ -22,7 +20,7 @@ macro_rules! all_eq {
let a = $a; let a = $a;
let b = $b; let b = $b;
assert!(a.0 == b.0 && a.1 == b.1 && a.2 == b.2 && a.3 == b.3); assert!(a.0 == b.0 && a.1 == b.1 && a.2 == b.2 && a.3 == b.3);
}} }};
} }
macro_rules! all_eq_ { macro_rules! all_eq_ {
@ -30,10 +28,9 @@ macro_rules! all_eq_ {
let a = $a; let a = $a;
let b = $b; let b = $b;
assert!(a.0 == b.0); assert!(a.0 == b.0);
}} }};
} }
extern "platform-intrinsic" { extern "platform-intrinsic" {
fn simd_add<T>(x: T, y: T) -> T; fn simd_add<T>(x: T, y: T) -> T;
fn simd_sub<T>(x: T, y: T) -> T; fn simd_sub<T>(x: T, y: T) -> T;
@ -47,6 +44,10 @@ extern "platform-intrinsic" {
fn simd_xor<T>(x: T, y: T) -> T; fn simd_xor<T>(x: T, y: T) -> T;
fn simd_neg<T>(x: T) -> T; fn simd_neg<T>(x: T) -> T;
fn simd_bswap<T>(x: T) -> T;
fn simd_bitreverse<T>(x: T) -> T;
fn simd_ctlz<T>(x: T) -> T;
fn simd_cttz<T>(x: T) -> T;
} }
fn main() { fn main() {
@ -84,8 +85,8 @@ fn main() {
all_eq_!(simd_div(y1, y1), U32::<4>([1, 1, 1, 1])); all_eq_!(simd_div(y1, y1), U32::<4>([1, 1, 1, 1]));
all_eq_!(simd_div(U32::<4>([2, 4, 6, 8]), U32::<4>([2, 2, 2, 2])), y1); all_eq_!(simd_div(U32::<4>([2, 4, 6, 8]), U32::<4>([2, 2, 2, 2])), y1);
all_eq!(simd_div(z1, z1), f32x4(1.0, 1.0, 1.0, 1.0)); all_eq!(simd_div(z1, z1), f32x4(1.0, 1.0, 1.0, 1.0));
all_eq!(simd_div(z1, z2), f32x4(1.0/2.0, 2.0/3.0, 3.0/4.0, 4.0/5.0)); all_eq!(simd_div(z1, z2), f32x4(1.0 / 2.0, 2.0 / 3.0, 3.0 / 4.0, 4.0 / 5.0));
all_eq!(simd_div(z2, z1), f32x4(2.0/1.0, 3.0/2.0, 4.0/3.0, 5.0/4.0)); all_eq!(simd_div(z2, z1), f32x4(2.0 / 1.0, 3.0 / 2.0, 4.0 / 3.0, 5.0 / 4.0));
all_eq!(simd_rem(x1, x1), i32x4(0, 0, 0, 0)); all_eq!(simd_rem(x1, x1), i32x4(0, 0, 0, 0));
all_eq!(simd_rem(x2, x1), i32x4(0, 1, 1, 1)); all_eq!(simd_rem(x2, x1), i32x4(0, 1, 1, 1));
@ -109,8 +110,10 @@ fn main() {
// ensure we get logical vs. arithmetic shifts correct // ensure we get logical vs. arithmetic shifts correct
let (a, b, c, d) = (-12, -123, -1234, -12345); let (a, b, c, d) = (-12, -123, -1234, -12345);
all_eq!(simd_shr(i32x4(a, b, c, d), x1), i32x4(a >> 1, b >> 2, c >> 3, d >> 4)); all_eq!(simd_shr(i32x4(a, b, c, d), x1), i32x4(a >> 1, b >> 2, c >> 3, d >> 4));
all_eq_!(simd_shr(U32::<4>([a as u32, b as u32, c as u32, d as u32]), y1), all_eq_!(
U32::<4>([(a as u32) >> 1, (b as u32) >> 2, (c as u32) >> 3, (d as u32) >> 4])); simd_shr(U32::<4>([a as u32, b as u32, c as u32, d as u32]), y1),
U32::<4>([(a as u32) >> 1, (b as u32) >> 2, (c as u32) >> 3, (d as u32) >> 4])
);
all_eq!(simd_and(x1, x2), i32x4(0, 2, 0, 4)); all_eq!(simd_and(x1, x2), i32x4(0, 2, 0, 4));
all_eq!(simd_and(x2, x1), i32x4(0, 2, 0, 4)); all_eq!(simd_and(x2, x1), i32x4(0, 2, 0, 4));
@ -132,5 +135,19 @@ fn main() {
all_eq!(simd_neg(z1), f32x4(-1.0, -2.0, -3.0, -4.0)); all_eq!(simd_neg(z1), f32x4(-1.0, -2.0, -3.0, -4.0));
all_eq!(simd_neg(z2), f32x4(-2.0, -3.0, -4.0, -5.0)); all_eq!(simd_neg(z2), f32x4(-2.0, -3.0, -4.0, -5.0));
all_eq!(simd_bswap(x1), i32x4(0x01000000, 0x02000000, 0x03000000, 0x04000000));
all_eq_!(simd_bswap(y1), U32::<4>([0x01000000, 0x02000000, 0x03000000, 0x04000000]));
all_eq!(
simd_bitreverse(x1),
i32x4(0x80000000u32 as i32, 0x40000000, 0xc0000000u32 as i32, 0x20000000)
);
all_eq_!(simd_bitreverse(y1), U32::<4>([0x80000000, 0x40000000, 0xc0000000, 0x20000000]));
all_eq!(simd_ctlz(x1), i32x4(31, 30, 30, 29));
all_eq_!(simd_ctlz(y1), U32::<4>([31, 30, 30, 29]));
all_eq!(simd_cttz(x1), i32x4(0, 1, 0, 2));
all_eq_!(simd_cttz(y1), U32::<4>([0, 1, 0, 2]));
} }
} }