Skip to content

Commit 6fd5dc8

Browse files
committed
Prototype using const generic for simd_shuffle IDX array
1 parent f9f8bff commit 6fd5dc8

File tree

1 file changed

+49
-1
lines changed

1 file changed

+49
-1
lines changed

src/intrinsics/simd.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn report_simd_type_validation_error(
2121
pub(super) fn codegen_simd_intrinsic_call<'tcx>(
2222
fx: &mut FunctionCx<'_, '_, 'tcx>,
2323
intrinsic: Symbol,
24-
_args: GenericArgsRef<'tcx>,
24+
generic_args: GenericArgsRef<'tcx>,
2525
args: &[mir::Operand<'tcx>],
2626
ret: CPlace<'tcx>,
2727
target: BasicBlock,
@@ -117,6 +117,54 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
117117
});
118118
}
119119

120+
// simd_shuffle_generic<T, U, const I: &[u32]>(x: T, y: T) -> U
121+
sym::simd_shuffle_generic => {
122+
let [x, y] = args else {
123+
bug!("wrong number of args for intrinsic {intrinsic}");
124+
};
125+
let x = codegen_operand(fx, x);
126+
let y = codegen_operand(fx, y);
127+
128+
if !x.layout().ty.is_simd() {
129+
report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty);
130+
return;
131+
}
132+
133+
let idx = generic_args[2]
134+
.expect_const()
135+
.eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(span))
136+
.unwrap()
137+
.unwrap_branch();
138+
139+
assert_eq!(x.layout(), y.layout());
140+
let layout = x.layout();
141+
142+
let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
143+
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
144+
145+
assert_eq!(lane_ty, ret_lane_ty);
146+
assert_eq!(idx.len() as u64, ret_lane_count);
147+
148+
let total_len = lane_count * 2;
149+
150+
let indexes =
151+
idx.iter().map(|idx| idx.unwrap_leaf().try_to_u16().unwrap()).collect::<Vec<u16>>();
152+
153+
for &idx in &indexes {
154+
assert!(u64::from(idx) < total_len, "idx {} out of range 0..{}", idx, total_len);
155+
}
156+
157+
for (out_idx, in_idx) in indexes.into_iter().enumerate() {
158+
let in_lane = if u64::from(in_idx) < lane_count {
159+
x.value_lane(fx, in_idx.into())
160+
} else {
161+
y.value_lane(fx, u64::from(in_idx) - lane_count)
162+
};
163+
let out_lane = ret.place_lane(fx, u64::try_from(out_idx).unwrap());
164+
out_lane.write_cvalue(fx, in_lane);
165+
}
166+
}
167+
120168
// simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U
121169
sym::simd_shuffle => {
122170
let (x, y, idx) = match args {

0 commit comments

Comments
 (0)