@@ -655,6 +655,66 @@ fn codegen_regular_intrinsic_call<'tcx>(
655
655
let res = fx. bcx . ins ( ) . rotr ( x, y) ;
656
656
ret. write_cvalue ( fx, CValue :: by_val ( res, layout) ) ;
657
657
}
658
+ sym:: funnel_shl => {
659
+ intrinsic_args ! ( fx, args => ( x, y, z) ; intrinsic) ;
660
+ let layout = x. layout ( ) ;
661
+
662
+ let width_bits = layout. size . bits ( ) as u64 ;
663
+ let width_bits = fx. bcx . ins ( ) . iconst ( types:: I32 , width_bits as i64 ) ;
664
+
665
+ let lhs_bits = x. load_scalar ( fx) ;
666
+ let rhs_bits = y. load_scalar ( fx) ;
667
+ let raw_shift_bits = z. load_scalar ( fx) ;
668
+
669
+ let ty = fx. bcx . func . dfg . value_type ( lhs_bits) ;
670
+ let zero = fx. bcx . ins ( ) . iconst ( ty, 0 ) ;
671
+
672
+ let shift_bits = fx. bcx . ins ( ) . urem ( raw_shift_bits, width_bits) ;
673
+
674
+ // lhs_bits << shift_bits
675
+ let shl = fx. bcx . ins ( ) . ishl ( lhs_bits, shift_bits) ;
676
+
677
+ let inv_shift_bits = fx. bcx . ins ( ) . isub ( width_bits, shift_bits) ;
678
+
679
+ // rhs_bits.bounded_shr(inv_shift_bits)
680
+ let inv_shift_bits_mod = fx. bcx . ins ( ) . urem ( inv_shift_bits, width_bits) ;
681
+ let shr = fx. bcx . ins ( ) . ushr ( rhs_bits, inv_shift_bits_mod) ;
682
+ let is_zero = fx. bcx . ins ( ) . icmp ( IntCC :: Equal , inv_shift_bits_mod, zero) ;
683
+ let shr = fx. bcx . ins ( ) . select ( is_zero, zero, shr) ;
684
+
685
+ let res = fx. bcx . ins ( ) . bor ( shr, shl) ;
686
+ ret. write_cvalue ( fx, CValue :: by_val ( res, layout) ) ;
687
+ }
688
+ sym:: funnel_shr => {
689
+ intrinsic_args ! ( fx, args => ( x, y, z) ; intrinsic) ;
690
+ let layout = x. layout ( ) ;
691
+
692
+ let width_bits = layout. size . bits ( ) as u64 ;
693
+ let width_bits = fx. bcx . ins ( ) . iconst ( types:: I32 , width_bits as i64 ) ;
694
+
695
+ let lhs_bits = x. load_scalar ( fx) ;
696
+ let rhs_bits = y. load_scalar ( fx) ;
697
+ let raw_shift_bits = z. load_scalar ( fx) ;
698
+
699
+ let ty = fx. bcx . func . dfg . value_type ( lhs_bits) ;
700
+ let zero = fx. bcx . ins ( ) . iconst ( ty, 0 ) ;
701
+
702
+ let shift_bits = fx. bcx . ins ( ) . urem ( raw_shift_bits, width_bits) ;
703
+
704
+ // rhs_bits >> shift_bits
705
+ let shr = fx. bcx . ins ( ) . ushr ( rhs_bits, shift_bits) ;
706
+
707
+ let inv_shift_bits = fx. bcx . ins ( ) . isub ( width_bits, shift_bits) ;
708
+
709
+ // lhs_bits.bounded_shl(inv_shift_bits)
710
+ let inv_shift_bits_mod = fx. bcx . ins ( ) . urem ( inv_shift_bits, width_bits) ;
711
+ let shl = fx. bcx . ins ( ) . ishl ( lhs_bits, inv_shift_bits_mod) ;
712
+ let is_zero = fx. bcx . ins ( ) . icmp ( IntCC :: Equal , inv_shift_bits_mod, zero) ;
713
+ let shl = fx. bcx . ins ( ) . select ( is_zero, zero, shl) ;
714
+
715
+ let res = fx. bcx . ins ( ) . bor ( shr, shl) ;
716
+ ret. write_cvalue ( fx, CValue :: by_val ( res, layout) ) ;
717
+ }
658
718
659
719
// The only difference between offset and arith_offset is regarding UB. Because Cranelift
660
720
// doesn't have UB both are codegen'ed the same way
0 commit comments