Skip to content

Commit 3947340

Browse files
committed
implement SIMD funnel shifts in const-eval
1 parent acf2437 commit 3947340

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;
@@ -701,6 +701,44 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
701701
};
702702
}
703703
}
704+
sym::simd_funnel_shl | sym::simd_funnel_shr => {
705+
let (left, _) = self.project_to_simd(&args[0])?;
706+
let (right, _) = self.project_to_simd(&args[1])?;
707+
let (shift, _) = self.project_to_simd(&args[2])?;
708+
let (dest, _) = self.project_to_simd(&dest)?;
709+
710+
let (len, elem_ty) = args[0].layout.ty.simd_size_and_type(*self.tcx);
711+
let (elem_size, _signed) = elem_ty.int_size_and_signed(*self.tcx);
712+
let elem_size_bits = elem_size.bits() as u128;
713+
714+
let is_left = intrinsic_name == sym::simd_funnel_shl;
715+
716+
for i in 0..len {
717+
let left =
718+
self.read_scalar(&self.project_index(&left, i)?)?.to_bits(elem_size)?;
719+
let right =
720+
self.read_scalar(&self.project_index(&right, i)?)?.to_bits(elem_size)?;
721+
let shift_bits =
722+
self.read_scalar(&self.project_index(&shift, i)?)?.to_bits(elem_size)?;
723+
724+
if shift_bits >= elem_size_bits {
725+
err_ub_format!(
726+
"overflowing shift by {shift_bits} in `{intrinsic_name}` in lane {i}"
727+
);
728+
}
729+
let inv_shift_bits = (elem_size_bits - shift_bits) as u32;
730+
731+
let result_bits = if is_left {
732+
(left << shift_bits) | right.unbounded_shr(inv_shift_bits)
733+
} else {
734+
left.unbounded_shl(inv_shift_bits) | (right >> shift_bits)
735+
};
736+
let (result, _overflow) = ScalarInt::truncate_from_uint(result_bits, elem_size);
737+
738+
let dest = self.project_index(&dest, i)?;
739+
self.write_scalar(result, &dest)?;
740+
}
741+
}
704742

705743
// Unsupported intrinsic: skip the return_to_block below.
706744
_ => return interp_ok(false),

0 commit comments

Comments
 (0)