Skip to content

Commit f53af8d

Browse files
authored
Unrolled build for #155005
Rollup merge of #155005 - folkertdev:simd-element-type-llvm, r=nnethercote preserve SIMD element type information Preserve the SIMD element type and provide it to LLVM for better optimization. This is relevant for AArch64 types like `int16x4x2_t`, see also llvm/llvm-project#181514. Such types are defined like so: ```rust #[repr(simd)] struct int16x4_t([i16; 4]); #[repr(C)] struct int16x4x2_t(pub int16x4_t, pub int16x4_t); ``` Previously this would be translated to the opaque `[2 x <8 x i8>]`, with this PR it is instead `[2 x <4 x i16>]`. That change is not relevant for the ABI, but using the correct type prevents bitcasts that can (indeed, do) confuse the LLVM pattern matcher. This change will make it possible to implement the deinterleaving loads on AArch64 in a portable way (without neon-specific intrinsics), which means that e.g. Miri or the cranelift backend can run them without additional support. discussion at [#t-compiler > loss of vector element type information](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/loss.20of.20vector.20element.20type.20information/with/584483611)
2 parents 0006519 + 6f428df commit f53af8d

16 files changed

Lines changed: 212 additions & 27 deletions

File tree

compiler/rustc_abi/src/callconv.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,11 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
7575
Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
7676
}
7777

78-
BackendRepr::SimdVector { .. } => {
78+
BackendRepr::SimdVector { element, count: _ } => {
7979
assert!(!self.is_zst());
80+
8081
Ok(HomogeneousAggregate::Homogeneous(Reg {
81-
kind: RegKind::Vector,
82+
kind: RegKind::Vector { hint_vector_elem: element.primitive() },
8283
size: self.size,
8384
}))
8485
}

compiler/rustc_abi/src/callconv/reg.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
#[cfg(feature = "nightly")]
22
use rustc_macros::HashStable_Generic;
33

4-
use crate::{Align, HasDataLayout, Size};
4+
use crate::{Align, HasDataLayout, Integer, Primitive, Size};
55

66
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
77
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
88
pub enum RegKind {
99
Integer,
1010
Float,
11-
Vector,
11+
Vector {
12+
/// The `hint_vector_elem` is strictly for optimization purposes. E.g. it can be used by
13+
/// a codegen backend to prevent extra bitcasts that obscure a pattern. Alternatively,
14+
/// it can be safely ignored by always picking i8.
15+
hint_vector_elem: Primitive,
16+
},
1217
}
1318

1419
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
@@ -36,6 +41,12 @@ impl Reg {
3641
reg_ctor!(f32, Float, 32);
3742
reg_ctor!(f64, Float, 64);
3843
reg_ctor!(f128, Float, 128);
44+
45+
/// A vector of the given size with an unknown (and irrelevant) element type.
46+
pub fn opaque_vector(size: Size) -> Reg {
47+
// Default to an i8 vector of the given size.
48+
Reg { kind: RegKind::Vector { hint_vector_elem: Primitive::Int(Integer::I8, true) }, size }
49+
}
3950
}
4051

4152
impl Reg {
@@ -58,7 +69,7 @@ impl Reg {
5869
128 => dl.f128_align,
5970
_ => panic!("unsupported float: {self:?}"),
6071
},
61-
RegKind::Vector => dl.llvmlike_vector_align(self.size),
72+
RegKind::Vector { .. } => dl.llvmlike_vector_align(self.size),
6273
}
6374
}
6475
}

compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam {
2626
(RegKind::Float, 4) => types::F32,
2727
(RegKind::Float, 8) => types::F64,
2828
(RegKind::Float, 16) => types::F128,
29-
(RegKind::Vector, size) => types::I8.by(u32::try_from(size).unwrap()).unwrap(),
29+
(RegKind::Vector { hint_vector_elem: _ }, size) => {
30+
types::I8.by(u32::try_from(size).unwrap()).unwrap()
31+
}
3032
_ => unreachable!("{:?}", reg),
3133
};
3234
AbiParam::new(clif_ty)

compiler/rustc_codegen_gcc/src/abi.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ impl GccType for Reg {
9090
64 => cx.type_f64(),
9191
_ => bug!("unsupported float: {:?}", self),
9292
},
93-
RegKind::Vector => cx.type_vector(cx.type_i8(), self.size.bytes()),
93+
RegKind::Vector { hint_vector_elem: _ } => {
94+
cx.type_vector(cx.type_i8(), self.size.bytes())
95+
}
9496
}
9597
}
9698
}

compiler/rustc_codegen_llvm/src/abi.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use std::cmp;
22

33
use libc::c_uint;
44
use rustc_abi::{
5-
ArmCall, BackendRepr, CanonAbi, HasDataLayout, InterruptKind, Primitive, Reg, RegKind, Size,
6-
X86Call,
5+
ArmCall, BackendRepr, CanonAbi, Float, HasDataLayout, Integer, InterruptKind, Primitive, Reg,
6+
RegKind, Size, X86Call,
77
};
88
use rustc_codegen_ssa::MemFlags;
99
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
@@ -137,7 +137,31 @@ impl LlvmType for Reg {
137137
128 => cx.type_f128(),
138138
_ => bug!("unsupported float: {:?}", self),
139139
},
140-
RegKind::Vector => cx.type_vector(cx.type_i8(), self.size.bytes()),
140+
RegKind::Vector { hint_vector_elem } => {
141+
// NOTE: it is valid to ignore the element type hint (and always pick i8).
142+
// But providing a more accurate type means fewer casts in LLVM IR,
143+
// which helps with optimization.
144+
let ty = match hint_vector_elem {
145+
Primitive::Int(integer, _) => match integer {
146+
Integer::I8 => cx.type_ix(8),
147+
Integer::I16 => cx.type_ix(16),
148+
Integer::I32 => cx.type_ix(32),
149+
Integer::I64 => cx.type_ix(64),
150+
Integer::I128 => cx.type_ix(128),
151+
},
152+
Primitive::Float(float) => match float {
153+
Float::F16 => cx.type_f16(),
154+
Float::F32 => cx.type_f32(),
155+
Float::F64 => cx.type_f64(),
156+
Float::F128 => cx.type_f128(),
157+
},
158+
Primitive::Pointer(_) => cx.type_ptr(),
159+
};
160+
161+
assert!(self.size.bytes().is_multiple_of(hint_vector_elem.size(cx).bytes()));
162+
let len = self.size.bytes() / hint_vector_elem.size(cx).bytes();
163+
cx.type_vector(ty, len)
164+
}
141165
}
142166
}
143167
}

compiler/rustc_codegen_ssa/src/mir/naked_asm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ fn wasm_type<'tcx>(signature: &mut String, arg_abi: &ArgAbi<'_, Ty<'tcx>>, ptr_t
421421
..=8 => "f64",
422422
_ => ptr_type,
423423
},
424-
RegKind::Vector => "v128",
424+
RegKind::Vector { .. } => "v128",
425425
};
426426

427427
signature.push_str(wrapped_wasm_type);

compiler/rustc_monomorphize/src/mono_checks/abi_check.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ fn passes_vectors_by_value(mode: &PassMode, repr: &BackendRepr) -> UsesVectorReg
2525
match mode {
2626
PassMode::Ignore | PassMode::Indirect { .. } => UsesVectorRegisters::No,
2727
PassMode::Cast { pad_i32: _, cast }
28-
if cast.prefix.iter().any(|r| r.is_some_and(|x| x.kind == RegKind::Vector))
29-
|| cast.rest.unit.kind == RegKind::Vector =>
28+
if cast
29+
.prefix
30+
.iter()
31+
.any(|r| r.is_some_and(|x| matches!(x.kind, RegKind::Vector { .. })))
32+
|| matches!(cast.rest.unit.kind, RegKind::Vector { .. }) =>
3033
{
3134
UsesVectorRegisters::FixedVector
3235
}

compiler/rustc_target/src/callconv/aarch64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ where
3535
// The softfloat ABI treats floats like integers, so they
3636
// do not get homogeneous aggregate treatment.
3737
RegKind::Float => cx.target_spec().rustc_abi != Some(RustcAbi::Softfloat),
38-
RegKind::Vector => size.bits() == 64 || size.bits() == 128,
38+
RegKind::Vector { .. } => size.bits() == 64 || size.bits() == 128,
3939
};
4040

4141
valid_unit.then_some(Uniform::consecutive(unit, size))

compiler/rustc_target/src/callconv/arm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ where
1919
let valid_unit = match unit.kind {
2020
RegKind::Integer => false,
2121
RegKind::Float => true,
22-
RegKind::Vector => size.bits() == 64 || size.bits() == 128,
22+
RegKind::Vector { .. } => size.bits() == 64 || size.bits() == 128,
2323
};
2424

2525
valid_unit.then_some(Uniform::consecutive(unit, size))

compiler/rustc_target/src/callconv/powerpc64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ where
3636
let valid_unit = match unit.kind {
3737
RegKind::Integer => false,
3838
RegKind::Float => true,
39-
RegKind::Vector => arg.layout.size.bits() == 128,
39+
RegKind::Vector { .. } => arg.layout.size.bits() == 128,
4040
};
4141

4242
valid_unit.then_some(Uniform::consecutive(unit, arg.layout.size))

0 commit comments

Comments
 (0)