Skip to content

Commit 81da1f2

Browse files
committed
Add LLVM and Miri backend support for funnel_sh{l,r}
1 parent 40c14d9 commit 81da1f2

File tree

4 files changed

+52
-1
lines changed

4 files changed

+52
-1
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,9 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
383383
| sym::rotate_left
384384
| sym::rotate_right
385385
| sym::saturating_add
386-
| sym::saturating_sub => {
386+
| sym::saturating_sub
387+
| sym::funnel_shl
388+
| sym::funnel_shr => {
387389
let ty = args[0].layout.ty;
388390
if !ty.is_integral() {
389391
tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
@@ -448,6 +450,19 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
448450
);
449451
self.call_intrinsic(llvm_name, &[llty], &[lhs, rhs])
450452
}
453+
sym::funnel_shl | sym::funnel_shr => {
454+
let is_left = name == sym::funnel_shl;
455+
let lhs = args[0].immediate();
456+
let rhs = args[1].immediate();
457+
let raw_shift = args[2].immediate();
458+
let llvm_name = format!("llvm.fsh{}", if is_left { 'l' } else { 'r' });
459+
460+
// llvm expects shift to be the same type as the values, but rust
461+
// always uses `u32`.
462+
let raw_shift = self.intcast(raw_shift, self.val_ty(lhs), false);
463+
464+
self.call_intrinsic(llvm_name, &[llty], &[lhs, rhs, raw_shift])
465+
}
451466
_ => bug!(),
452467
}
453468
}

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,37 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
302302
let result = Scalar::from_uint(truncated_bits, layout_val.size);
303303
self.write_scalar(result, dest)?;
304304
}
305+
sym::funnel_shl | sym::funnel_shr => {
306+
// funnel_shl: (A << (S % BW)) | (B >> ((BW - S) % BW))
307+
// funnel_shr: (A << ((BW - S) % BW)) | (B >> (S % BW))
308+
let layout_val = self.layout_of(instance_args.type_at(0))?;
309+
310+
let lhs = self.read_scalar(&args[0])?;
311+
let lhs_bits = lhs.to_bits(layout_val.size)?; // sign is ignored here
312+
313+
let rhs = self.read_scalar(&args[1])?;
314+
let rhs_bits = rhs.to_bits(layout_val.size)?; // sign is ignored here
315+
316+
let layout_raw_shift = self.layout_of(self.tcx.types.u32)?;
317+
let raw_shift = self.read_scalar(&args[2])?;
318+
let raw_shift_bits = raw_shift.to_bits(layout_raw_shift.size)?;
319+
320+
let width_bits = u128::from(layout_val.size.bits());
321+
let shift_bits = raw_shift_bits % width_bits;
322+
let inv_shift_bits = (width_bits - shift_bits) % width_bits;
323+
let result_bits = if shift_bits == 0 {
324+
if intrinsic_name == sym::funnel_shl { lhs_bits } else { rhs_bits }
325+
} else {
326+
if intrinsic_name == sym::rotate_left {
327+
(lhs_bits << shift_bits) | (rhs_bits >> inv_shift_bits)
328+
} else {
329+
(rhs_bits >> shift_bits) | (lhs_bits << inv_shift_bits)
330+
}
331+
};
332+
let truncated_bits = layout_val.size.truncate(result_bits);
333+
let result = Scalar::from_uint(truncated_bits, layout_val.size);
334+
self.write_scalar(result, dest)?;
335+
}
305336
sym::copy => {
306337
self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?;
307338
}

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,9 @@ pub(crate) fn check_intrinsic_type(
449449
}
450450
sym::unchecked_shl | sym::unchecked_shr => (2, 0, vec![param(0), param(1)], param(0)),
451451
sym::rotate_left | sym::rotate_right => (1, 0, vec![param(0), tcx.types.u32], param(0)),
452+
sym::funnel_shl | sym::funnel_shr => {
453+
(1, 0, vec![param(0), param(0), tcx.types.u32], param(0))
454+
}
452455
sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => {
453456
(1, 0, vec![param(0), param(0)], param(0))
454457
}

compiler/rustc_span/src/symbol.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,8 @@ symbols! {
10961096
fsub_fast,
10971097
full,
10981098
fundamental,
1099+
funnel_shl,
1100+
funnel_shr,
10991101
fused_iterator,
11001102
future,
11011103
future_drop_poll,

0 commit comments

Comments
 (0)