Skip to content

Commit 6f428df

Browse files
committed
preseve SIMD element type information
and provide it to LLVM for better optimization
1 parent 14196db commit 6f428df

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)