Skip to content

Commit 3e9b6bd

Browse files
folkertdevsayantn
authored andcommitted
add funnel shifts to the gcc backend
1 parent 3cabdab commit 3e9b6bd

File tree

1 file changed

+49
-0
lines changed
  • compiler/rustc_codegen_gcc/src/intrinsic

1 file changed

+49
-0
lines changed

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
442442
| sym::bitreverse
443443
| sym::rotate_left
444444
| sym::rotate_right
445+
| sym::funnel_shl
446+
| sym::funnel_shr
445447
| sym::saturating_add
446448
| sym::saturating_sub => {
447449
match int_type_width_signed(args[0].layout.ty, self) {
@@ -505,6 +507,53 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
505507
self.rotate_right(val, raw_shift, width)
506508
}
507509
}
510+
sym::funnel_shl => {
511+
let lhs_bits = args[0].immediate();
512+
let rhs_bits = args[1].immediate();
513+
let raw_shift_bits = args[2].immediate();
514+
515+
let width_ty = raw_shift_bits.get_type();
516+
let width_bits = self.cx.gcc_uint(width_ty, width as u64);
517+
let shift_bits = self.gcc_urem(raw_shift_bits, width_bits);
518+
519+
// lhs_bits << shift_bits
520+
let shl = self.gcc_shl(lhs_bits, shift_bits);
521+
522+
// rhs_bits.bounded_shr(inv_shift_bits)
523+
let inv_shift_bits = self.gcc_sub(width_bits, shift_bits);
524+
let inv_shift_bits_mod = self.gcc_urem(inv_shift_bits, width_bits);
525+
let shr = self.gcc_lshr(rhs_bits, inv_shift_bits_mod);
526+
let zero = self.cx.gcc_uint(lhs_bits.get_type(), 0);
527+
let is_zero =
528+
self.gcc_icmp(IntPredicate::IntEQ, inv_shift_bits_mod, zero);
529+
let shr = self.select(is_zero, zero, shr);
530+
531+
self.or(shl, shr)
532+
}
533+
sym::funnel_shr => {
534+
let lhs_bits = args[0].immediate();
535+
let rhs_bits = args[1].immediate();
536+
let raw_shift_bits = args[2].immediate();
537+
538+
let width_ty = raw_shift_bits.get_type();
539+
let width_bits = self.cx.gcc_uint(width_ty, width as u64);
540+
let shift_bits = self.gcc_urem(raw_shift_bits, width_bits);
541+
542+
// rhs_bits >> shift_bits
543+
let shr = self.gcc_lshr(rhs_bits, shift_bits);
544+
545+
let inv_shift_bits = self.gcc_sub(width_bits, shift_bits);
546+
547+
// lhs_bits.bounded_shl(inv_shift_bits)
548+
let inv_shift_bits_mod = self.gcc_urem(inv_shift_bits, width_bits);
549+
let shl = self.gcc_shl(lhs_bits, inv_shift_bits_mod);
550+
let zero = self.cx.gcc_uint(lhs_bits.get_type(), 0);
551+
let is_zero =
552+
self.gcc_icmp(IntPredicate::IntEQ, inv_shift_bits_mod, zero);
553+
let shl = self.select(is_zero, zero, shl);
554+
555+
self.or(shl, shr)
556+
}
508557
sym::saturating_add => self.saturating_add(
509558
args[0].immediate(),
510559
args[1].immediate(),

0 commit comments

Comments
 (0)