diff options
| author | León Orell Valerian Liehr <me@fmease.dev> | 2024-09-14 18:12:10 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-14 18:12:10 +0200 |
| commit | a9dcd7f25da53adf368293c47494b4819e426a35 (patch) | |
| tree | 13e20a254df581d2a423aed3649dbcb2be325a2f /compiler/rustc_codegen_ssa/src | |
| parent | 2b12b574efc6ad155c59447e2a5feb3084a51f89 (diff) | |
| parent | 60ee1b7ac6e1c18679573d4a752e6fc02790d892 (diff) | |
| download | rust-a9dcd7f25da53adf368293c47494b4819e426a35.tar.gz rust-a9dcd7f25da53adf368293c47494b4819e426a35.zip | |
Rollup merge of #130268 - RalfJung:simd-shuffle-idx-vector, r=compiler-errors
simd_shuffle: require index argument to be a vector Remove some codegen hacks by forcing the SIMD shuffle `index` argument to be a vector, which means (thanks to https://github.com/rust-lang/rust/pull/128537) that it will automatically be passed as an immediate in LLVM. The only special-casing we still have is for the extra sanity-checks we add that ensure that the indices are all in-bounds. (And the GCC backend needs to do a bunch of work since the Rust intrinsic is modeled after what LLVM expects, which seems to be quite different from what GCC expects.) Fixes https://github.com/rust-lang/rust/issues/128738, see that issue for more context.
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/block.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/constant.rs | 35 |
2 files changed, 13 insertions, 50 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 817e2ca72ec..8f96c462240 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -915,32 +915,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }; - let args: Vec<_> = args - .iter() - .enumerate() - .map(|(i, arg)| { - // The indices passed to simd_shuffle in the - // third argument must be constant. This is - // checked by the type-checker. - if i == 2 && intrinsic.name == sym::simd_shuffle { - // FIXME: the simd_shuffle argument is actually an array, - // not a vector, so we need this special hack to make sure - // it is passed as an immediate. We should pass the - // shuffle indices as a vector instead to avoid this hack. - if let mir::Operand::Constant(constant) = &arg.node { - let (llval, ty) = self.immediate_const_vector(bx, constant); - return OperandRef { - val: Immediate(llval), - layout: bx.layout_of(ty), - }; - } else { - span_bug!(span, "shuffle indices must be constant"); - } - } - - self.codegen_operand(bx, &arg.node) - }) - .collect(); + let args: Vec<_> = + args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect(); if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) { let location = self diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 0aa85b82038..8254fb3d866 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -1,6 +1,6 @@ use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::layout::HasTyCtxt; -use rustc_middle::ty::{self, Ty, ValTree}; +use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir, span_bug}; use rustc_target::abi::Abi; @@ -66,15 +66,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { constant: &mir::ConstOperand<'tcx>, ) -> (Bx::Value, Ty<'tcx>) { let ty = self.monomorphize(constant.ty()); - let ty_is_simd = ty.is_simd(); - // FIXME: ideally we'd assert that this is a SIMD type, but simd_shuffle - // in its current form relies on a regular array being passed as an - // immediate argument. This hack can be removed once that is fixed. - let field_ty = if ty_is_simd { - ty.simd_size_and_type(bx.tcx()).1 - } else { - ty.builtin_index().unwrap() - }; + assert!(ty.is_simd()); + let field_ty = ty.simd_size_and_type(bx.tcx()).1; let val = self .eval_unevaluated_mir_constant_to_valtree(constant) @@ -82,19 +75,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .map(|x| x.ok()) .flatten() .map(|val| { - // Depending on whether this is a SIMD type with an array field - // or a type with many fields (one for each elements), the valtree - // is either a single branch with N children, or a root node - // with exactly one child which then in turn has many children. - // So we look at the first child to determine whether it is a - // leaf or whether we have to go one more layer down. - let branch_or_leaf = val.unwrap_branch(); - let first = branch_or_leaf.get(0).unwrap(); - let field_iter = match first { - ValTree::Branch(_) => first.unwrap_branch().iter(), - ValTree::Leaf(_) => branch_or_leaf.iter(), - }; - let values: Vec<_> = field_iter + // A SIMD type has a single field, which is an array. + let fields = val.unwrap_branch(); + assert_eq!(fields.len(), 1); + let array = fields[0].unwrap_branch(); + // Iterate over the array elements to obtain the values in the vector. + let values: Vec<_> = array + .iter() .map(|field| { if let Some(prim) = field.try_to_scalar() { let layout = bx.layout_of(field_ty); @@ -107,7 +94,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }) .collect(); - if ty_is_simd { bx.const_vector(&values) } else { bx.const_struct(&values, false) } + bx.const_vector(&values) }) .unwrap_or_else(|| { bx.tcx().dcx().emit_err(errors::ShuffleIndicesEvaluation { span: constant.span }); |
