@@ -2,7 +2,7 @@ use either::Either;
2
2
use rustc_abi:: Endian ;
3
3
use rustc_apfloat:: { Float , Round } ;
4
4
use rustc_middle:: mir:: interpret:: { InterpErrorKind , UndefinedBehaviorInfo } ;
5
- use rustc_middle:: ty:: FloatTy ;
5
+ use rustc_middle:: ty:: { FloatTy , ScalarInt } ;
6
6
use rustc_middle:: { bug, err_ub_format, mir, span_bug, throw_unsup_format, ty} ;
7
7
use rustc_span:: { Symbol , sym} ;
8
8
use tracing:: trace;
@@ -710,6 +710,44 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
710
710
} ;
711
711
}
712
712
}
713
+ sym:: simd_funnel_shl | sym:: simd_funnel_shr => {
714
+ let ( left, _) = self . project_to_simd ( & args[ 0 ] ) ?;
715
+ let ( right, _) = self . project_to_simd ( & args[ 1 ] ) ?;
716
+ let ( shift, _) = self . project_to_simd ( & args[ 2 ] ) ?;
717
+ let ( dest, _) = self . project_to_simd ( dest) ?;
718
+
719
+ let ( len, elem_ty) = args[ 0 ] . layout . ty . simd_size_and_type ( tcx) ;
720
+ let ( elem_size, _signed) = elem_ty. int_size_and_signed ( tcx) ;
721
+ let elem_size_bits = elem_size. bits ( ) as u128 ;
722
+
723
+ let is_left = intrinsic_name == sym:: simd_funnel_shl;
724
+
725
+ for i in 0 ..len {
726
+ let left =
727
+ self . read_scalar ( & self . project_index ( & left, i) ?) ?. to_bits ( elem_size) ?;
728
+ let right =
729
+ self . read_scalar ( & self . project_index ( & right, i) ?) ?. to_bits ( elem_size) ?;
730
+ let shift_bits =
731
+ self . read_scalar ( & self . project_index ( & shift, i) ?) ?. to_bits ( elem_size) ?;
732
+
733
+ if shift_bits >= elem_size_bits {
734
+ err_ub_format ! (
735
+ "overflowing shift by {shift_bits} in `{intrinsic_name}` in lane {i}"
736
+ ) ;
737
+ }
738
+ let inv_shift_bits = ( elem_size_bits - shift_bits) as u32 ;
739
+
740
+ let result_bits = if is_left {
741
+ ( left << shift_bits) | right. unbounded_shr ( inv_shift_bits)
742
+ } else {
743
+ left. unbounded_shl ( inv_shift_bits) | ( right >> shift_bits)
744
+ } ;
745
+ let ( result, _overflow) = ScalarInt :: truncate_from_uint ( result_bits, elem_size) ;
746
+
747
+ let dest = self . project_index ( & dest, i) ?;
748
+ self . write_scalar ( result, & dest) ?;
749
+ }
750
+ }
713
751
sym:: simd_fma | sym:: simd_relaxed_fma => {
714
752
// `simd_fma` should always deterministically use `mul_add`, whereas `relaxed_fma`
715
753
// is non-deterministic, and can use either `mul_add` or `a * b + c`
0 commit comments