Skip to content

Commit d95d03a

Browse files
committed
Support #[repr(simd)] on array wrappers
Complement to rust-lang/rust#78863
1 parent 64e7ff2 commit d95d03a

File tree

3 files changed

+28
-43
lines changed

3 files changed

+28
-43
lines changed

src/intrinsics/llvm.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
2323

2424
// Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
2525
llvm.x86.sse2.pmovmskb.128 | llvm.x86.avx2.pmovmskb | llvm.x86.sse2.movmsk.pd, (c a) {
26-
let (lane_layout, lane_count) = lane_type_and_count(fx.tcx, a.layout());
27-
let lane_ty = fx.clif_type(lane_layout.ty).unwrap();
26+
let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
27+
let lane_ty = fx.clif_type(lane_ty).unwrap();
2828
assert!(lane_count <= 32);
2929

3030
let mut res = fx.bcx.ins().iconst(types::I32, 0);

src/intrinsics/mod.rs

+13-29
Original file line numberDiff line numberDiff line change
@@ -171,27 +171,6 @@ macro validate_simd_type($fx:ident, $intrinsic:ident, $span:ident, $ty:expr) {
171171
}
172172
}
173173

174-
fn lane_type_and_count<'tcx>(
175-
tcx: TyCtxt<'tcx>,
176-
layout: TyAndLayout<'tcx>,
177-
) -> (TyAndLayout<'tcx>, u16) {
178-
assert!(layout.ty.is_simd());
179-
let lane_count = match layout.fields {
180-
rustc_target::abi::FieldsShape::Array { stride: _, count } => u16::try_from(count).unwrap(),
181-
_ => unreachable!("lane_type_and_count({:?})", layout),
182-
};
183-
let lane_layout = layout
184-
.field(
185-
&ty::layout::LayoutCx {
186-
tcx,
187-
param_env: ParamEnv::reveal_all(),
188-
},
189-
0,
190-
)
191-
.unwrap();
192-
(lane_layout, lane_count)
193-
}
194-
195174
pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Option<Type> {
196175
let (element, count) = match &layout.abi {
197176
Abi::Vector { element, count } => (element.clone(), *count),
@@ -218,8 +197,10 @@ fn simd_for_each_lane<'tcx, M: Module>(
218197
) {
219198
let layout = val.layout();
220199

221-
let (lane_layout, lane_count) = lane_type_and_count(fx.tcx, layout);
222-
let (ret_lane_layout, ret_lane_count) = lane_type_and_count(fx.tcx, ret.layout());
200+
let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
201+
let lane_layout = fx.layout_of(lane_ty);
202+
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
203+
let ret_lane_layout = fx.layout_of(ret_lane_ty);
223204
assert_eq!(lane_count, ret_lane_count);
224205

225206
for lane_idx in 0..lane_count {
@@ -248,8 +229,10 @@ fn simd_pair_for_each_lane<'tcx, M: Module>(
248229
assert_eq!(x.layout(), y.layout());
249230
let layout = x.layout();
250231

251-
let (lane_layout, lane_count) = lane_type_and_count(fx.tcx, layout);
252-
let (ret_lane_layout, ret_lane_count) = lane_type_and_count(fx.tcx, ret.layout());
232+
let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
233+
let lane_layout = fx.layout_of(lane_ty);
234+
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
235+
let ret_lane_layout = fx.layout_of(ret_lane_ty);
253236
assert_eq!(lane_count, ret_lane_count);
254237

255238
for lane in 0..lane_count {
@@ -269,13 +252,14 @@ fn simd_reduce<'tcx, M: Module>(
269252
ret: CPlace<'tcx>,
270253
f: impl Fn(&mut FunctionCx<'_, 'tcx, M>, TyAndLayout<'tcx>, Value, Value) -> Value,
271254
) {
272-
let (lane_layout, lane_count) = lane_type_and_count(fx.tcx, val.layout());
255+
let (lane_count, lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx);
256+
let lane_layout = fx.layout_of(lane_ty);
273257
assert_eq!(lane_layout, ret.layout());
274258

275259
let mut res_val = val.value_field(fx, mir::Field::new(0)).load_scalar(fx);
276260
for lane_idx in 1..lane_count {
277261
let lane = val
278-
.value_field(fx, mir::Field::new(lane_idx.into()))
262+
.value_field(fx, mir::Field::new(lane_idx.try_into().unwrap()))
279263
.load_scalar(fx);
280264
res_val = f(fx, lane_layout, res_val, lane);
281265
}
@@ -289,14 +273,14 @@ fn simd_reduce_bool<'tcx, M: Module>(
289273
ret: CPlace<'tcx>,
290274
f: impl Fn(&mut FunctionCx<'_, 'tcx, M>, Value, Value) -> Value,
291275
) {
292-
let (_lane_layout, lane_count) = lane_type_and_count(fx.tcx, val.layout());
276+
let (lane_count, _lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx);
293277
assert!(ret.layout().ty.is_bool());
294278

295279
let res_val = val.value_field(fx, mir::Field::new(0)).load_scalar(fx);
296280
let mut res_val = fx.bcx.ins().band_imm(res_val, 1); // mask to boolean
297281
for lane_idx in 1..lane_count {
298282
let lane = val
299-
.value_field(fx, mir::Field::new(lane_idx.into()))
283+
.value_field(fx, mir::Field::new(lane_idx.try_into().unwrap()))
300284
.load_scalar(fx);
301285
let lane = fx.bcx.ins().band_imm(lane, 1); // mask to boolean
302286
res_val = f(fx, res_val, lane);

src/intrinsics/simd.rs

+13-12
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
7373
assert_eq!(x.layout(), y.layout());
7474
let layout = x.layout();
7575

76-
let (lane_type, lane_count) = lane_type_and_count(fx.tcx, layout);
77-
let (ret_lane_type, ret_lane_count) = lane_type_and_count(fx.tcx, ret.layout());
76+
let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
77+
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
7878

79-
assert_eq!(lane_type, ret_lane_type);
80-
assert_eq!(n, ret_lane_count);
79+
assert_eq!(lane_ty, ret_lane_ty);
80+
assert_eq!(u64::from(n), ret_lane_count);
8181

8282
let total_len = lane_count * 2;
8383

@@ -105,14 +105,14 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
105105
};
106106

107107
for &idx in &indexes {
108-
assert!(idx < total_len, "idx {} out of range 0..{}", idx, total_len);
108+
assert!(u64::from(idx) < total_len, "idx {} out of range 0..{}", idx, total_len);
109109
}
110110

111111
for (out_idx, in_idx) in indexes.into_iter().enumerate() {
112-
let in_lane = if in_idx < lane_count {
112+
let in_lane = if u64::from(in_idx) < lane_count {
113113
x.value_field(fx, mir::Field::new(in_idx.into()))
114114
} else {
115-
y.value_field(fx, mir::Field::new((in_idx - lane_count).into()))
115+
y.value_field(fx, mir::Field::new(usize::from(in_idx) - usize::try_from(lane_count).unwrap()))
116116
};
117117
let out_lane = ret.place_field(fx, mir::Field::new(out_idx));
118118
out_lane.write_cvalue(fx, in_lane);
@@ -131,7 +131,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
131131
};
132132

133133
let idx = idx_const.val.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
134-
let (_lane_type, lane_count) = lane_type_and_count(fx.tcx, base.layout());
134+
let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx);
135135
if idx >= lane_count.into() {
136136
fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count));
137137
}
@@ -160,7 +160,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
160160
};
161161

162162
let idx = idx_const.val.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
163-
let (_lane_type, lane_count) = lane_type_and_count(fx.tcx, v.layout());
163+
let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx);
164164
if idx >= lane_count.into() {
165165
fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count));
166166
}
@@ -212,12 +212,13 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
212212
assert_eq!(a.layout(), c.layout());
213213
let layout = a.layout();
214214

215-
let (_lane_layout, lane_count) = lane_type_and_count(fx.tcx, layout);
216-
let (ret_lane_layout, ret_lane_count) = lane_type_and_count(fx.tcx, ret.layout());
215+
let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
216+
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
217217
assert_eq!(lane_count, ret_lane_count);
218+
let ret_lane_layout = fx.layout_of(ret_lane_ty);
218219

219220
for lane in 0..lane_count {
220-
let lane = mir::Field::new(lane.into());
221+
let lane = mir::Field::new(lane.try_into().unwrap());
221222
let a_lane = a.value_field(fx, lane).load_scalar(fx);
222223
let b_lane = b.value_field(fx, lane).load_scalar(fx);
223224
let c_lane = c.value_field(fx, lane).load_scalar(fx);

0 commit comments

Comments
 (0)