From 4457ef2c6db2aa65aeaba084d2d85f3355595f5a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 10 Jul 2023 13:03:48 +0000 Subject: [PATCH] Forbid old-style `simd_shuffleN` intrinsics --- .../src/intrinsics/simd.rs | 54 +-- .../rustc_codegen_gcc/src/intrinsic/simd.rs | 445 ++++++++++-------- compiler/rustc_codegen_llvm/src/intrinsic.rs | 34 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 4 +- .../src/error_codes/E0439.md | 2 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 14 - .../src/lower_intrinsics.rs | 2 +- tests/incremental/issue-61530.rs | 6 +- .../simd/intrinsic/generic-elements-pass.rs | 22 +- tests/ui/simd/intrinsic/generic-elements.rs | 22 +- .../ui/simd/intrinsic/generic-elements.stderr | 74 +-- .../simd/intrinsic/inlining-issue67557-ice.rs | 4 +- .../ui/simd/intrinsic/inlining-issue67557.rs | 6 +- tests/ui/simd/shuffle-not-out-of-bounds.rs | 31 +- .../ui/simd/shuffle-not-out-of-bounds.stderr | 50 +- tests/ui/simd/shuffle.rs | 3 +- 16 files changed, 393 insertions(+), 380 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index d1c29f24ab96d..9863e40b5b7a1 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -117,8 +117,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }); } - // simd_shuffle32(x: T, y: T, idx: [u32; 32]) -> U - _ if intrinsic.as_str().starts_with("simd_shuffle") => { + // simd_shuffle(x: T, y: T, idx: I) -> U + sym::simd_shuffle => { let (x, y, idx) = match args { [x, y, idx] => (x, y, idx), _ => { @@ -133,36 +133,26 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( return; } - // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer. - // If there is no suffix, use the index array length. - let n: u16 = if intrinsic == sym::simd_shuffle { - // Make sure this is actually an array, since typeck only checks the length-suffixed - // version of this intrinsic. - let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); - match idx_ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len - .try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all()) - .unwrap_or_else(|| { - span_bug!(span, "could not evaluate shuffle index array length") - }) - .try_into() - .unwrap(), - _ => { - fx.tcx.sess.span_err( - span, - format!( - "simd_shuffle index must be an array of `u32`, got `{}`", - idx_ty, - ), - ); - // Prevent verifier error - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); - return; - } + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); + let n: u16 = match idx_ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len + .try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all()) + .unwrap_or_else(|| { + span_bug!(span, "could not evaluate shuffle index array length") + }) + .try_into() + .unwrap(), + _ => { + fx.tcx.sess.span_err( + span, + format!("simd_shuffle index must be an array of `u32`, got `{}`", idx_ty), + ); + // Prevent verifier error + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + return; } - } else { - // FIXME remove this case - intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap() }; assert_eq!(x.layout(), y.layout()); @@ -179,7 +169,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let indexes = { use rustc_middle::mir::interpret::*; let idx_const = crate::constant::mir_operand_get_const_val(fx, idx) - .expect("simd_shuffle* idx not const"); + .expect("simd_shuffle idx not const"); let idx_bytes = match idx_const { ConstValue::ByRef { alloc, offset } => { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index f27de867d367b..85d3e7234a0e6 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -1,11 +1,11 @@ -#[cfg(feature="master")] -use gccjit::{ComparisonOp, UnaryOp}; use gccjit::ToRValue; use gccjit::{BinaryOp, RValue, Type}; +#[cfg(feature = "master")] +use gccjit::{ComparisonOp, UnaryOp}; use rustc_codegen_ssa::base::compare_simd_types; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; -#[cfg(feature="master")] +#[cfg(feature = "master")] use rustc_codegen_ssa::errors::ExpectedPointerMutability; use rustc_codegen_ssa::errors::InvalidMonomorphization; use rustc_codegen_ssa::mir::operand::OperandRef; @@ -19,7 +19,7 @@ use rustc_span::{sym, Span, Symbol}; use rustc_target::abi::Align; use crate::builder::Builder; -#[cfg(feature="master")] +#[cfg(feature = "master")] use crate::context::CodegenCx; pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( @@ -57,7 +57,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { - require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let expected_int_bits = (len.max(8) - 1).next_power_of_two(); @@ -95,7 +98,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // NOTE: since the arguments can be vectors of floats, make sure the mask is a vector of // integer. let mask_element_type = bx.type_ix(arg1_element_type.get_size() as u64 * 8); - let vector_mask_type = bx.context.new_vector_type(mask_element_type, arg1_vector_type.get_num_units() as u64); + let vector_mask_type = + bx.context.new_vector_type(mask_element_type, arg1_vector_type.get_num_units() as u64); let mut elements = vec![]; let one = bx.context.new_rvalue_one(mask.get_type()); @@ -149,38 +153,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // compare them as equal, so bitcast. // FIXME(antoyo): allow comparing vector types as equal in libgccjit. let arg2 = bx.context.new_bitcast(None, args[1].immediate(), arg1.get_type()); - return Ok(compare_simd_types( - bx, - arg1, - arg2, - in_elem, - llret_ty, - cmp_op, - )); + return Ok(compare_simd_types(bx, arg1, arg2, in_elem, llret_ty, cmp_op)); } - if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") { - let n: u64 = if stripped.is_empty() { - // Make sure this is actually an array, since typeck only checks the length-suffixed - // version of this intrinsic. - match args[2].layout.ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { - len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( - || span_bug!(span, "could not evaluate shuffle index array length"), - ) - } - _ => return_error!(InvalidMonomorphization::SimdShuffle { - span, - name, - ty: args[2].layout.ty - }), + if name == sym::simd_shuffle { + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + let n: u64 = match args[2].layout.ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { + len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( + || span_bug!(span, "could not evaluate shuffle index array length"), + ) } - } else { - stripped.parse().unwrap_or_else(|_| { - span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") - }) + _ => return_error!(InvalidMonomorphization::SimdShuffle { + span, + name, + ty: args[2].layout.ty + }), }; - require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); @@ -202,7 +192,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_insert { require!( in_elem == arg_tys[2], - InvalidMonomorphization::InsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] } + InvalidMonomorphization::InsertedType { + span, + name, + in_elem, + in_ty, + out_ty: arg_tys[2] + } ); let vector = args[0].immediate(); let index = args[1].immediate(); @@ -228,7 +224,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_select { let m_elem_ty = in_elem; let m_len = in_len; - require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); require!( m_len == v_len, @@ -241,7 +240,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate())); } - #[cfg(feature="master")] + #[cfg(feature = "master")] if name == sym::simd_cast || name == sym::simd_as { require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); @@ -267,19 +266,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( Unsupported, } - let in_style = - match in_elem.kind() { - ty::Int(_) | ty::Uint(_) => Style::Int, - ty::Float(_) => Style::Float, - _ => Style::Unsupported, - }; + let in_style = match in_elem.kind() { + ty::Int(_) | ty::Uint(_) => Style::Int, + ty::Float(_) => Style::Float, + _ => Style::Unsupported, + }; - let out_style = - match out_elem.kind() { - ty::Int(_) | ty::Uint(_) => Style::Int, - ty::Float(_) => Style::Float, - _ => Style::Unsupported, - }; + let out_style = match out_elem.kind() { + ty::Int(_) | ty::Uint(_) => Style::Int, + ty::Float(_) => Style::Float, + _ => Style::Unsupported, + }; match (in_style, out_style) { (Style::Unsupported, Style::Unsupported) => { @@ -294,7 +291,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( out_elem } ); - }, + } _ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)), } } @@ -342,10 +339,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let mut shift = 0; for i in 0..in_len { - let elem = bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32)); + let elem = + bx.extract_element(vector, bx.context.new_rvalue_from_int(bx.int_type, i as i32)); let shifted = elem >> sign_shift; let masked = shifted & one; - result = result | (bx.context.new_cast(None, masked, result_type) << bx.context.new_rvalue_from_int(result_type, shift)); + result = result + | (bx.context.new_cast(None, masked, result_type) + << bx.context.new_rvalue_from_int(result_type, shift)); shift += 1; } @@ -394,46 +394,50 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Err(()); }}; } - let (elem_ty_str, elem_ty) = - if let ty::Float(f) = in_elem.kind() { - let elem_ty = bx.cx.type_float_from_ty(*f); - match f.bit_width() { - 32 => ("f", elem_ty), - 64 => ("", elem_ty), - _ => { - return_error!(InvalidMonomorphization::FloatingPointVector { span, name, f_ty: *f, in_ty }); - } + let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() { + let elem_ty = bx.cx.type_float_from_ty(*f); + match f.bit_width() { + 32 => ("f", elem_ty), + 64 => ("", elem_ty), + _ => { + return_error!(InvalidMonomorphization::FloatingPointVector { + span, + name, + f_ty: *f, + in_ty + }); } } - else { - return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); - }; + } else { + return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); + }; let vec_ty = bx.cx.type_vector(elem_ty, in_len); - let intr_name = - match name { - sym::simd_ceil => "ceil", - sym::simd_fabs => "fabs", // TODO(antoyo): pand with 170141183420855150465331762880109871103 - sym::simd_fcos => "cos", - sym::simd_fexp2 => "exp2", - sym::simd_fexp => "exp", - sym::simd_flog10 => "log10", - sym::simd_flog2 => "log2", - sym::simd_flog => "log", - sym::simd_floor => "floor", - sym::simd_fma => "fma", - sym::simd_fpowi => "__builtin_powi", - sym::simd_fpow => "pow", - sym::simd_fsin => "sin", - sym::simd_fsqrt => "sqrt", - sym::simd_round => "round", - sym::simd_trunc => "trunc", - _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }) - }; + let intr_name = match name { + sym::simd_ceil => "ceil", + sym::simd_fabs => "fabs", // TODO(antoyo): pand with 170141183420855150465331762880109871103 + sym::simd_fcos => "cos", + sym::simd_fexp2 => "exp2", + sym::simd_fexp => "exp", + sym::simd_flog10 => "log10", + sym::simd_flog2 => "log2", + sym::simd_flog => "log", + sym::simd_floor => "floor", + sym::simd_fma => "fma", + sym::simd_fpowi => "__builtin_powi", + sym::simd_fpow => "pow", + sym::simd_fsin => "sin", + sym::simd_fsqrt => "sqrt", + sym::simd_round => "round", + sym::simd_trunc => "trunc", + _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }), + }; let builtin_name = format!("{}{}", intr_name, elem_ty_str); let funcs = bx.cx.functions.borrow(); - let function = funcs.get(&builtin_name).unwrap_or_else(|| panic!("unable to find builtin function {}", builtin_name)); + let function = funcs + .get(&builtin_name) + .unwrap_or_else(|| panic!("unable to find builtin function {}", builtin_name)); // TODO(antoyo): add platform-specific behavior here for architectures that have these // intrinsics as instructions (for instance, gpus) @@ -479,8 +483,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args); } - #[cfg(feature="master")] - fn vector_ty<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, elem_ty: Ty<'tcx>, vec_len: u64) -> Type<'gcc> { + #[cfg(feature = "master")] + fn vector_ty<'gcc, 'tcx>( + cx: &CodegenCx<'gcc, 'tcx>, + elem_ty: Ty<'tcx>, + vec_len: u64, + ) -> Type<'gcc> { // FIXME: use cx.layout_of(ty).llvm_type() ? let elem_ty = match *elem_ty.kind() { ty::Int(v) => cx.type_int_from_ty(v), @@ -491,15 +499,22 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( cx.type_vector(elem_ty, vec_len) } - #[cfg(feature="master")] - fn gather<'a, 'gcc, 'tcx>(default: RValue<'gcc>, pointers: RValue<'gcc>, mask: RValue<'gcc>, pointer_count: usize, bx: &mut Builder<'a, 'gcc, 'tcx>, in_len: u64, underlying_ty: Ty<'tcx>, invert: bool) -> RValue<'gcc> { - let vector_type = - if pointer_count > 1 { - bx.context.new_vector_type(bx.usize_type, in_len) - } - else { - vector_ty(bx, underlying_ty, in_len) - }; + #[cfg(feature = "master")] + fn gather<'a, 'gcc, 'tcx>( + default: RValue<'gcc>, + pointers: RValue<'gcc>, + mask: RValue<'gcc>, + pointer_count: usize, + bx: &mut Builder<'a, 'gcc, 'tcx>, + in_len: u64, + underlying_ty: Ty<'tcx>, + invert: bool, + ) -> RValue<'gcc> { + let vector_type = if pointer_count > 1 { + bx.context.new_vector_type(bx.usize_type, in_len) + } else { + vector_ty(bx, underlying_ty, in_len) + }; let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type(); let mut values = vec![]; @@ -530,13 +545,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if invert { bx.shuffle_vector(vector, default, mask) - } - else { + } else { bx.shuffle_vector(default, vector, mask) } } - #[cfg(feature="master")] + #[cfg(feature = "master")] if name == sym::simd_gather { // simd_gather(values: , pointers: , // mask: ) -> @@ -546,8 +560,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // All types must be simd vector types require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); - require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }); - require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); // Of the same length: @@ -641,10 +661,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } } - return Ok(gather(args[0].immediate(), args[1].immediate(), args[2].immediate(), pointer_count, bx, in_len, underlying_ty, false)); + return Ok(gather( + args[0].immediate(), + args[1].immediate(), + args[2].immediate(), + pointer_count, + bx, + in_len, + underlying_ty, + false, + )); } - #[cfg(feature="master")] + #[cfg(feature = "master")] if name == sym::simd_scatter { // simd_scatter(values: , pointers: , // mask: ) -> () @@ -654,8 +683,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // All types must be simd vector types require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); - require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }); - require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); // Of the same length: let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx()); @@ -744,17 +779,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } } - let result = gather(args[0].immediate(), args[1].immediate(), args[2].immediate(), pointer_count, bx, in_len, underlying_ty, true); + let result = gather( + args[0].immediate(), + args[1].immediate(), + args[2].immediate(), + pointer_count, + bx, + in_len, + underlying_ty, + true, + ); let pointers = args[1].immediate(); - let vector_type = - if pointer_count > 1 { - bx.context.new_vector_type(bx.usize_type, in_len) - } - else { - vector_ty(bx, underlying_ty, in_len) - }; + let vector_type = if pointer_count > 1 { + bx.context.new_vector_type(bx.usize_type, in_len) + } else { + vector_ty(bx, underlying_ty, in_len) + }; let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type(); for i in 0..in_len { @@ -809,11 +851,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let rhs = args[1].immediate(); let is_add = name == sym::simd_saturating_add; let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _; - let (signed, elem_width, elem_ty) = - match *in_elem.kind() { - ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)), - ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)), - _ => { + let (signed, elem_width, elem_ty) = match *in_elem.kind() { + ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)), + ty::Uint(i) => { + (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)) + } + _ => { return_error!(InvalidMonomorphization::ExpectedVectorElementType { span, name, @@ -823,77 +866,82 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } }; - let result = - match (signed, is_add) { - (false, true) => { - let res = lhs + rhs; - let cmp = bx.context.new_comparison(None, ComparisonOp::LessThan, res, lhs); - res | cmp - }, - (true, true) => { - // Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition - // TODO(antoyo): improve using conditional operators if possible. - // TODO(antoyo): dyncast_vector should not require a call to unqualified. - let arg_type = lhs.get_type().unqualified(); - // TODO(antoyo): convert lhs and rhs to unsigned. - let sum = lhs + rhs; - let vector_type = arg_type.dyncast_vector().expect("vector type"); - let unit = vector_type.get_num_units(); - let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); - let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); - - let xor1 = lhs ^ rhs; - let xor2 = lhs ^ sum; - let and = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; - let mask = and >> width; - - let one = bx.context.new_rvalue_one(elem_ty); - let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); - let shift1 = ones << width; - let shift2 = sum >> width; - let mask_min = shift1 ^ shift2; - - let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; - let and2 = mask & mask_min; - - and1 + and2 - }, - (false, false) => { - let res = lhs - rhs; - let cmp = bx.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs); - res & cmp - }, - (true, false) => { - // TODO(antoyo): dyncast_vector should not require a call to unqualified. - let arg_type = lhs.get_type().unqualified(); - // TODO(antoyo): this uses the same algorithm from saturating add, but add the - // negative of the right operand. Find a proper subtraction algorithm. - let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs); - - // TODO(antoyo): convert lhs and rhs to unsigned. - let sum = lhs + rhs; - let vector_type = arg_type.dyncast_vector().expect("vector type"); - let unit = vector_type.get_num_units(); - let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); - let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); - - let xor1 = lhs ^ rhs; - let xor2 = lhs ^ sum; - let and = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; - let mask = and >> width; - - let one = bx.context.new_rvalue_one(elem_ty); - let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); - let shift1 = ones << width; - let shift2 = sum >> width; - let mask_min = shift1 ^ shift2; - - let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; - let and2 = mask & mask_min; - - and1 + and2 - } - }; + let result = match (signed, is_add) { + (false, true) => { + let res = lhs + rhs; + let cmp = bx.context.new_comparison(None, ComparisonOp::LessThan, res, lhs); + res | cmp + } + (true, true) => { + // Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition + // TODO(antoyo): improve using conditional operators if possible. + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let arg_type = lhs.get_type().unqualified(); + // TODO(antoyo): convert lhs and rhs to unsigned. + let sum = lhs + rhs; + let vector_type = arg_type.dyncast_vector().expect("vector type"); + let unit = vector_type.get_num_units(); + let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); + let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); + + let xor1 = lhs ^ rhs; + let xor2 = lhs ^ sum; + let and = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; + let mask = and >> width; + + let one = bx.context.new_rvalue_one(elem_ty); + let ones = + bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); + let shift1 = ones << width; + let shift2 = sum >> width; + let mask_min = shift1 ^ shift2; + + let and1 = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; + let and2 = mask & mask_min; + + and1 + and2 + } + (false, false) => { + let res = lhs - rhs; + let cmp = bx.context.new_comparison(None, ComparisonOp::LessThanEquals, res, lhs); + res & cmp + } + (true, false) => { + // TODO(antoyo): dyncast_vector should not require a call to unqualified. + let arg_type = lhs.get_type().unqualified(); + // TODO(antoyo): this uses the same algorithm from saturating add, but add the + // negative of the right operand. Find a proper subtraction algorithm. + let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs); + + // TODO(antoyo): convert lhs and rhs to unsigned. + let sum = lhs + rhs; + let vector_type = arg_type.dyncast_vector().expect("vector type"); + let unit = vector_type.get_num_units(); + let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); + let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); + + let xor1 = lhs ^ rhs; + let xor2 = lhs ^ sum; + let and = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; + let mask = and >> width; + + let one = bx.context.new_rvalue_one(elem_ty); + let ones = + bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); + let shift1 = ones << width; + let shift2 = sum >> width; + let mask_min = shift1 ^ shift2; + + let and1 = + bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; + let and2 = mask & mask_min; + + and1 + and2 + } + }; return Ok(result); } @@ -968,7 +1016,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( 1.0 ); - macro_rules! minmax_red { ($name:ident: $int_red:ident, $float_red:ident) => { if name == sym::$name { @@ -979,13 +1026,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())), ty::Float(_) => Ok(bx.$float_red(args[0].immediate())), - _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { - span, + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, name, symbol: sym::$name, in_ty, - in_elem, - ret_ty + in_elem, + ret_ty }), }; } @@ -1025,7 +1072,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => { let r = bx.vector_reduce_op(input, $op); - Ok(if !$boolean { r } else { bx.icmp(IntPredicate::IntNE, r, bx.context.new_rvalue_zero(r.get_type())) }) + Ok(if !$boolean { + r + } else { + bx.icmp( + IntPredicate::IntNE, + r, + bx.context.new_rvalue_zero(r.get_type()), + ) + }) } _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 86c39ab5e943f..6f1e4c5178aae 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1020,28 +1020,20 @@ fn generic_simd_intrinsic<'ll, 'tcx>( )); } - if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") { - // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer. - // If there is no suffix, use the index array length. - let n: u64 = if stripped.is_empty() { - // Make sure this is actually an array, since typeck only checks the length-suffixed - // version of this intrinsic. - match args[2].layout.ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { - len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( - || span_bug!(span, "could not evaluate shuffle index array length"), - ) - } - _ => return_error!(InvalidMonomorphization::SimdShuffle { - span, - name, - ty: args[2].layout.ty - }), + if name == sym::simd_shuffle { + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + let n: u64 = match args[2].layout.ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { + len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else( + || span_bug!(span, "could not evaluate shuffle index array length"), + ) } - } else { - stripped.parse().unwrap_or_else(|_| { - span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?") - }) + _ => return_error!(InvalidMonomorphization::SimdShuffle { + span, + name, + ty: args[2].layout.ty + }), }; require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index f13dfd96b8ee9..4f26383ed05f0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -862,11 +862,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .iter() .enumerate() .map(|(i, arg)| { - // The indices passed to simd_shuffle* in the + // The indices passed to simd_shuffle in the // third argument must be constant. This is // checked by const-qualification, which also // promotes any complex rvalues to constants. - if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") { + if i == 2 && intrinsic == sym::simd_shuffle { if let mir::Operand::Constant(constant) = arg { let (llval, ty) = self.simd_shuffle_indices(&bx, constant); return OperandRef { diff --git a/compiler/rustc_error_codes/src/error_codes/E0439.md b/compiler/rustc_error_codes/src/error_codes/E0439.md index 24268aef2222a..369226c383ec5 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0439.md +++ b/compiler/rustc_error_codes/src/error_codes/E0439.md @@ -16,7 +16,7 @@ extern "platform-intrinsic" { The `simd_shuffle` function needs the length of the array passed as last parameter in its name. Example: -``` +```ignore (no longer compiles) #![feature(platform_intrinsics)] extern "platform-intrinsic" { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 064021b1ea429..970efaf312c54 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -567,20 +567,6 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_reduce_min_nanless | sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)), sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)), - name if name.as_str().starts_with("simd_shuffle") => { - match name.as_str()["simd_shuffle".len()..].parse() { - Ok(n) => { - let params = vec![param(0), param(0), Ty::new_array(tcx, tcx.types.u32, n)]; - (2, params, param(1)) - } - Err(_) => { - let msg = - format!("unrecognized platform-specific intrinsic function: `{name}`"); - tcx.sess.struct_span_err(it.span, msg).emit(); - return; - } - } - } _ => { let msg = format!("unrecognized platform-specific intrinsic function: `{name}`"); tcx.sess.struct_span_err(it.span, msg).emit(); diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index d1ecfe9f8512d..fc36c6e4124a6 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -305,7 +305,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Unreachable; } } - _ if intrinsic_name.as_str().starts_with("simd_shuffle") => { + sym::simd_shuffle => { validate_simd_shuffle(tcx, args, terminator.source_info.span); } _ => {} diff --git a/tests/incremental/issue-61530.rs b/tests/incremental/issue-61530.rs index edb3d60ba3f89..1dcb41ddedae2 100644 --- a/tests/incremental/issue-61530.rs +++ b/tests/incremental/issue-61530.rs @@ -6,13 +6,13 @@ struct I32x2(i32, i32); extern "platform-intrinsic" { - fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + fn simd_shuffle(x: T, y: T, idx: I) -> U; } fn main() { unsafe { const IDX: [u32; 2] = [0, 0]; - let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), IDX); - let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), IDX); + let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX); + let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX); } } diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs index 3c913c0adfa60..905c3b8d3cca1 100644 --- a/tests/ui/simd/intrinsic/generic-elements-pass.rs +++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs @@ -22,9 +22,7 @@ extern "platform-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; fn simd_extract(x: T, idx: u32) -> E; - fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; - fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; - fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; + fn simd_shuffle(x: T, y: T, idx: I) -> U; } macro_rules! all_eq { @@ -83,19 +81,19 @@ fn main() { let y4 = i32x4(140, 141, 142, 143); let y8 = i32x8(180, 181, 182, 183, 184, 185, 186, 187); unsafe { - all_eq!(simd_shuffle2(x2, y2, const { [3u32, 0] }), i32x2(121, 20)); - all_eq!(simd_shuffle4(x2, y2, const { [3u32, 0, 1, 2] }), i32x4(121, 20, 21, 120)); - all_eq!(simd_shuffle8(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }), + all_eq!(simd_shuffle(x2, y2, const { [3u32, 0] }), i32x2(121, 20)); + all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2] }), i32x4(121, 20, 21, 120)); + all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }), i32x8(121, 20, 21, 120, 21, 120, 121, 20)); - all_eq!(simd_shuffle2(x4, y4, const { [7u32, 2] }), i32x2(143, 42)); - all_eq!(simd_shuffle4(x4, y4, const { [7u32, 2, 5, 0] }), i32x4(143, 42, 141, 40)); - all_eq!(simd_shuffle8(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }), + all_eq!(simd_shuffle(x4, y4, const { [7u32, 2] }), i32x2(143, 42)); + all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0] }), i32x4(143, 42, 141, 40)); + all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }), i32x8(143, 42, 141, 40, 43, 142, 140, 41)); - all_eq!(simd_shuffle2(x8, y8, const { [11u32, 5] }), i32x2(183, 85)); - all_eq!(simd_shuffle4(x8, y8, const { [11u32, 5, 15, 0] }), i32x4(183, 85, 187, 80)); - all_eq!(simd_shuffle8(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }), + all_eq!(simd_shuffle(x8, y8, const { [11u32, 5] }), i32x2(183, 85)); + all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0] }), i32x4(183, 85, 187, 80)); + all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }), i32x8(183, 85, 187, 80, 83, 180, 184, 81)); } diff --git a/tests/ui/simd/intrinsic/generic-elements.rs b/tests/ui/simd/intrinsic/generic-elements.rs index abde69163bd4e..0ff2203ec722e 100644 --- a/tests/ui/simd/intrinsic/generic-elements.rs +++ b/tests/ui/simd/intrinsic/generic-elements.rs @@ -34,9 +34,7 @@ extern "platform-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; fn simd_extract(x: T, idx: u32) -> E; - fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; - fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; - fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; + fn simd_shuffle(x: T, y: T, idx: I) -> U; } fn main() { @@ -51,27 +49,27 @@ fn main() { //~^ ERROR expected return type `i32` (element of input `i32x4`), found `f32` const IDX2: [u32; 2] = [0; 2]; - simd_shuffle2::(0, 0, IDX2); + simd_shuffle::(0, 0, IDX2); //~^ ERROR expected SIMD input type, found non-SIMD `i32` const IDX4: [u32; 4] = [0; 4]; - simd_shuffle4::(0, 0, IDX4); + simd_shuffle::(0, 0, IDX4); //~^ ERROR expected SIMD input type, found non-SIMD `i32` const IDX8: [u32; 8] = [0; 8]; - simd_shuffle8::(0, 0, IDX8); + simd_shuffle::(0, 0, IDX8); //~^ ERROR expected SIMD input type, found non-SIMD `i32` - simd_shuffle2::<_, f32x2>(x, x, IDX2); + simd_shuffle::<_, _, f32x2>(x, x, IDX2); //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - simd_shuffle4::<_, f32x4>(x, x, IDX4); + simd_shuffle::<_, _, f32x4>(x, x, IDX4); //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - simd_shuffle8::<_, f32x8>(x, x, IDX8); + simd_shuffle::<_, _, f32x8>(x, x, IDX8); //~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - simd_shuffle2::<_, i32x8>(x, x, IDX2); + simd_shuffle::<_, _, i32x8>(x, x, IDX2); //~^ ERROR expected return type of length 2, found `i32x8` with length 8 - simd_shuffle4::<_, i32x8>(x, x, IDX4); + simd_shuffle::<_, _, i32x8>(x, x, IDX4); //~^ ERROR expected return type of length 4, found `i32x8` with length 8 - simd_shuffle8::<_, i32x2>(x, x, IDX8); + simd_shuffle::<_, _, i32x2>(x, x, IDX8); //~^ ERROR expected return type of length 8, found `i32x2` with length 2 } } diff --git a/tests/ui/simd/intrinsic/generic-elements.stderr b/tests/ui/simd/intrinsic/generic-elements.stderr index 5b423f7040f90..115d9d4b3f3ac 100644 --- a/tests/ui/simd/intrinsic/generic-elements.stderr +++ b/tests/ui/simd/intrinsic/generic-elements.stderr @@ -1,74 +1,74 @@ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:46:9 + --> $DIR/generic-elements.rs:44:9 | LL | simd_insert(0, 0, 0); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64` - --> $DIR/generic-elements.rs:48:9 + --> $DIR/generic-elements.rs:46:9 | LL | simd_insert(x, 0, 1.0); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32` - --> $DIR/generic-elements.rs:50:9 + --> $DIR/generic-elements.rs:48:9 | LL | simd_extract::<_, f32>(x, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:54:9 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:52:9 | -LL | simd_shuffle2::(0, 0, IDX2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::(0, 0, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:57:9 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:55:9 | -LL | simd_shuffle4::(0, 0, IDX4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::(0, 0, IDX4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:60:9 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` + --> $DIR/generic-elements.rs:58:9 | -LL | simd_shuffle8::(0, 0, IDX8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::(0, 0, IDX8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` + --> $DIR/generic-elements.rs:61:9 + | +LL | simd_shuffle::<_, _, f32x2>(x, x, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` --> $DIR/generic-elements.rs:63:9 | -LL | simd_shuffle2::<_, f32x2>(x, x, IDX2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::<_, _, f32x4>(x, x, IDX4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` --> $DIR/generic-elements.rs:65:9 | -LL | simd_shuffle4::<_, f32x4>(x, x, IDX4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::<_, _, f32x8>(x, x, IDX8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/generic-elements.rs:67:9 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `i32x8` with length 8 + --> $DIR/generic-elements.rs:68:9 | -LL | simd_shuffle8::<_, f32x8>(x, x, IDX8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::<_, _, i32x8>(x, x, IDX2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 4, found `i32x8` with length 8 --> $DIR/generic-elements.rs:70:9 | -LL | simd_shuffle2::<_, i32x8>(x, x, IDX2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::<_, _, i32x8>(x, x, IDX4); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x8` with length 8 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 8, found `i32x2` with length 2 --> $DIR/generic-elements.rs:72:9 | -LL | simd_shuffle4::<_, i32x8>(x, x, IDX4); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return type of length 8, found `i32x2` with length 2 - --> $DIR/generic-elements.rs:74:9 - | -LL | simd_shuffle8::<_, i32x2>(x, x, IDX8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_shuffle::<_, _, i32x2>(x, x, IDX8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs index 7221b3ab769db..5ca684a9d7831 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs @@ -6,7 +6,7 @@ #![feature(platform_intrinsics, repr_simd)] extern "platform-intrinsic" { - fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + fn simd_shuffle(x: T, y: T, idx: I) -> U; } #[repr(simd)] @@ -22,5 +22,5 @@ fn main() { #[inline(always)] unsafe fn inline_me() -> Simd2 { const IDX: [u32; 2] = [0, 3]; - simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX) + simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX) } diff --git a/tests/ui/simd/intrinsic/inlining-issue67557.rs b/tests/ui/simd/intrinsic/inlining-issue67557.rs index 0d15427095a74..5633ad70cd318 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557.rs @@ -6,7 +6,7 @@ #![feature(platform_intrinsics, repr_simd)] extern "platform-intrinsic" { - fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + fn simd_shuffle(x: T, y: T, idx: I) -> U; } #[repr(simd)] @@ -16,7 +16,7 @@ struct Simd2(u8, u8); fn main() { unsafe { const IDX: [u32; 2] = [0, 1]; - let p_res: Simd2 = simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX); + let p_res: Simd2 = simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX); let a_res: Simd2 = inline_me(); assert_10_11(p_res); @@ -38,5 +38,5 @@ fn assert_10_13(x: Simd2) { #[inline(always)] unsafe fn inline_me() -> Simd2 { const IDX: [u32; 2] = [0, 3]; - simd_shuffle2(Simd2(10, 11), Simd2(12, 13), IDX) + simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX) } diff --git a/tests/ui/simd/shuffle-not-out-of-bounds.rs b/tests/ui/simd/shuffle-not-out-of-bounds.rs index 0dee3a0e869d7..18939bcc5b4b2 100644 --- a/tests/ui/simd/shuffle-not-out-of-bounds.rs +++ b/tests/ui/simd/shuffle-not-out-of-bounds.rs @@ -29,12 +29,7 @@ struct u8x32([u8; 32]); struct u8x64([u8; 64]); extern "platform-intrinsic" { - pub fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; - pub fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; - pub fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; - pub fn simd_shuffle16(x: T, y: T, idx: [u32; 16]) -> U; - pub fn simd_shuffle32(x: T, y: T, idx: [u32; 32]) -> U; - pub fn simd_shuffle64(x: T, y: T, idx: [u32; 64]) -> U; + pub fn simd_shuffle(x: T, y: T, idx: I) -> U; } // Test vectors by lane size. Since LLVM does not distinguish between a shuffle @@ -58,22 +53,22 @@ macro_rules! test_shuffle_lanes { } } } -//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle2` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle4` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle8` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle16` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle32` intrinsic -//~| ERROR: invalid monomorphization of `simd_shuffle64` intrinsic +//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic +//~| ERROR: invalid monomorphization of `simd_shuffle` intrinsic // Because the test is mostly embedded in a macro, all the errors have the same origin point. // And unfortunately, standard comments, as in the UI test harness, disappear in macros! fn main() { - test_shuffle_lanes!(2, u8x2, simd_shuffle2); - test_shuffle_lanes!(4, u8x4, simd_shuffle4); - test_shuffle_lanes!(8, u8x8, simd_shuffle8); - test_shuffle_lanes!(16, u8x16, simd_shuffle16); - test_shuffle_lanes!(32, u8x32, simd_shuffle32); - test_shuffle_lanes!(64, u8x64, simd_shuffle64); + test_shuffle_lanes!(2, u8x2, simd_shuffle); + test_shuffle_lanes!(4, u8x4, simd_shuffle); + test_shuffle_lanes!(8, u8x8, simd_shuffle); + test_shuffle_lanes!(16, u8x16, simd_shuffle); + test_shuffle_lanes!(32, u8x32, simd_shuffle); + test_shuffle_lanes!(64, u8x64, simd_shuffle); extern "platform-intrinsic" { fn simd_shuffle(a: T, b: T, i: I) -> U; diff --git a/tests/ui/simd/shuffle-not-out-of-bounds.stderr b/tests/ui/simd/shuffle-not-out-of-bounds.stderr index 415f04d933f25..59e5ab858664a 100644 --- a/tests/ui/simd/shuffle-not-out-of-bounds.stderr +++ b/tests/ui/simd/shuffle-not-out-of-bounds.stderr @@ -1,71 +1,71 @@ -error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: shuffle index #0 is out of bounds (limit 4) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(2, u8x2, simd_shuffle2); - | ------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(2, u8x2, simd_shuffle); + | ------------------------------------------ in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: shuffle index #0 is out of bounds (limit 8) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 8) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(4, u8x4, simd_shuffle4); - | ------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(4, u8x4, simd_shuffle); + | ------------------------------------------ in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: shuffle index #0 is out of bounds (limit 16) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 16) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(8, u8x8, simd_shuffle8); - | ------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(8, u8x8, simd_shuffle); + | ------------------------------------------ in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle16` intrinsic: shuffle index #0 is out of bounds (limit 32) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 32) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(16, u8x16, simd_shuffle16); - | ---------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(16, u8x16, simd_shuffle); + | -------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle32` intrinsic: shuffle index #0 is out of bounds (limit 64) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 64) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(32, u8x32, simd_shuffle32); - | ---------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(32, u8x32, simd_shuffle); + | -------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0511]: invalid monomorphization of `simd_shuffle64` intrinsic: shuffle index #0 is out of bounds (limit 128) - --> $DIR/shuffle-not-out-of-bounds.rs:56:21 +error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 128) + --> $DIR/shuffle-not-out-of-bounds.rs:51:21 | LL | $y(vec1, vec2, ARR) | ^^^^^^^^^^^^^^^^^^^ ... -LL | test_shuffle_lanes!(64, u8x64, simd_shuffle64); - | ---------------------------------------------- in this macro invocation +LL | test_shuffle_lanes!(64, u8x64, simd_shuffle); + | -------------------------------------------- in this macro invocation | = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4) - --> $DIR/shuffle-not-out-of-bounds.rs:84:23 + --> $DIR/shuffle-not-out-of-bounds.rs:79:23 | LL | let _: u8x2 = simd_shuffle(v, v, I); | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/shuffle.rs b/tests/ui/simd/shuffle.rs index 461243d489283..838e31f8e4154 100644 --- a/tests/ui/simd/shuffle.rs +++ b/tests/ui/simd/shuffle.rs @@ -8,7 +8,6 @@ extern "platform-intrinsic" { fn simd_shuffle(a: T, b: T, i: I) -> U; - fn simd_shuffle16(x: T, y: T, idx: [u32; 16]) -> U; } #[derive(Copy, Clone)] @@ -16,7 +15,7 @@ extern "platform-intrinsic" { struct Simd([T; N]); pub unsafe fn __shuffle_vector16(x: T, y: T) -> U { - simd_shuffle16(x, y, IDX) + simd_shuffle(x, y, IDX) } fn main() {