@@ -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