@@ -442,6 +442,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
442
442
| sym:: bitreverse
443
443
| sym:: rotate_left
444
444
| sym:: rotate_right
445
+ | sym:: funnel_shl
446
+ | sym:: funnel_shr
445
447
| sym:: saturating_add
446
448
| sym:: saturating_sub => {
447
449
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
505
507
self . rotate_right ( val, raw_shift, width)
506
508
}
507
509
}
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
+ }
508
557
sym:: saturating_add => self . saturating_add (
509
558
args[ 0 ] . immediate ( ) ,
510
559
args[ 1 ] . immediate ( ) ,
0 commit comments