Skip to content

Commit 344e3dc

Browse files
committed
implement SIMD funnel shifts in const-eval
1 parent f3f604b commit 344e3dc

File tree

1 file changed

+39
-1
lines changed
  • compiler/rustc_const_eval/src/interpret/intrinsics

1 file changed

+39
-1
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use either::Either;
22
use rustc_abi::Endian;
33
use rustc_apfloat::{Float, Round};
44
use rustc_middle::mir::interpret::{InterpErrorKind, UndefinedBehaviorInfo};
5-
use rustc_middle::ty::FloatTy;
5+
use rustc_middle::ty::{FloatTy, ScalarInt};
66
use rustc_middle::{bug, err_ub_format, mir, span_bug, throw_unsup_format, ty};
77
use rustc_span::{Symbol, sym};
88
use 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

Comments
 (0)