@@ -2,7 +2,7 @@ use either::Either;
22use rustc_abi:: Endian ;
33use rustc_apfloat:: { Float , Round } ;
44use rustc_middle:: mir:: interpret:: { InterpErrorKind , UndefinedBehaviorInfo } ;
5- use rustc_middle:: ty:: FloatTy ;
5+ use rustc_middle:: ty:: { FloatTy , ScalarInt } ;
66use rustc_middle:: { bug, err_ub_format, mir, span_bug, throw_unsup_format, ty} ;
77use rustc_span:: { Symbol , sym} ;
88use tracing:: trace;
@@ -710,6 +710,44 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
710710 } ;
711711 }
712712 }
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+ }
713751 sym:: simd_fma | sym:: simd_relaxed_fma => {
714752 // `simd_fma` should always deterministically use `mul_add`, whereas `relaxed_fma`
715753 // is non-deterministic, and can use either `mul_add` or `a * b + c`
0 commit comments