Permit pre-evaluated constants in simd_shuffle
This commit is contained in:
parent
6b9236ed5a
commit
9e5a67e57f
@ -67,6 +67,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
|
) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
|
||||||
let uv = match constant.literal {
|
let uv = match constant.literal {
|
||||||
mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(),
|
mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(),
|
||||||
|
mir::ConstantKind::Ty(c) => match c.kind() {
|
||||||
|
// A constant that came from a const generic but was then used as an argument to old-style
|
||||||
|
// simd_shuffle (passing as argument instead of as a generic param).
|
||||||
|
rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)),
|
||||||
|
other => span_bug!(constant.span, "{other:#?}"),
|
||||||
|
},
|
||||||
|
// We should never encounter `ConstantKind::Val` unless MIR opts (like const prop) evaluate
|
||||||
|
// a constant and write that value back into `Operand`s. This could happen, but is unlikely.
|
||||||
|
// Also: all users of `simd_shuffle` are on unstable and already need to take a lot of care
|
||||||
|
// around intrinsics. For an issue to happen here, it would require a macro expanding to a
|
||||||
|
// `simd_shuffle` call without wrapping the constant argument in a `const {}` block, but
|
||||||
|
// the user pass through arbitrary expressions.
|
||||||
|
// FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a real
|
||||||
|
// const generic.
|
||||||
other => span_bug!(constant.span, "{other:#?}"),
|
other => span_bug!(constant.span, "{other:#?}"),
|
||||||
};
|
};
|
||||||
let uv = self.monomorphize(uv);
|
let uv = self.monomorphize(uv);
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
//run-pass
|
//run-pass
|
||||||
#![feature(repr_simd, platform_intrinsics)]
|
#![feature(repr_simd, platform_intrinsics)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(adt_const_params)]
|
||||||
|
|
||||||
extern "platform-intrinsic" {
|
extern "platform-intrinsic" {
|
||||||
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
|
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
|
||||||
|
fn simd_shuffle16<T, U>(x: T, y: T, idx: [u32; 16]) -> U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
#[repr(simd)]
|
#[repr(simd)]
|
||||||
struct Simd<T, const N: usize>([T; N]);
|
struct Simd<T, const N: usize>([T; N]);
|
||||||
|
|
||||||
|
pub unsafe fn __shuffle_vector16<const IDX: [u32; 16], T, U>(x: T, y: T) -> U {
|
||||||
|
simd_shuffle16(x, y, IDX)
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
const I1: [u32; 4] = [0, 2, 4, 6];
|
const I1: [u32; 4] = [0, 2, 4, 6];
|
||||||
const I2: [u32; 2] = [1, 5];
|
const I2: [u32; 2] = [1, 5];
|
||||||
@ -21,4 +28,16 @@ fn main() {
|
|||||||
let y: Simd<u8, 2> = simd_shuffle(a, b, I2);
|
let y: Simd<u8, 2> = simd_shuffle(a, b, I2);
|
||||||
assert_eq!(y.0, [1, 5]);
|
assert_eq!(y.0, [1, 5]);
|
||||||
}
|
}
|
||||||
|
// Test that an indirection (via an unnamed constant)
|
||||||
|
// through a const generic parameter also works.
|
||||||
|
// See https://github.com/rust-lang/rust/issues/113500 for details.
|
||||||
|
let a = Simd::<u8, 16>([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
|
||||||
|
let b = Simd::<u8, 16>([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]);
|
||||||
|
unsafe {
|
||||||
|
__shuffle_vector16::<
|
||||||
|
{ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] },
|
||||||
|
Simd<u8, 16>,
|
||||||
|
Simd<u8, 16>,
|
||||||
|
>(a, b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user