Add funnel_sh{l,r} functions and intrinsics

- Add a fallback implementation for the intrinsics
 - Add LLVM backend support for funnel shifts

Co-Authored-By: folkertdev <folkert@folkertdev.nl>
This commit is contained in:
sayantn
2025-08-21 04:47:05 +05:30
parent f5703d5dd3
commit 62b4347e80
16 changed files with 338 additions and 9 deletions

View File

@@ -383,7 +383,9 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
| sym::rotate_left
| sym::rotate_right
| sym::saturating_add
| sym::saturating_sub => {
| sym::saturating_sub
| sym::unchecked_funnel_shl
| sym::unchecked_funnel_shr => {
let ty = args[0].layout.ty;
if !ty.is_integral() {
tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
@@ -424,18 +426,26 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
sym::bitreverse => {
self.call_intrinsic("llvm.bitreverse", &[llty], &[args[0].immediate()])
}
sym::rotate_left | sym::rotate_right => {
let is_left = name == sym::rotate_left;
let val = args[0].immediate();
let raw_shift = args[1].immediate();
// rotate = funnel shift with first two args the same
sym::rotate_left
| sym::rotate_right
| sym::unchecked_funnel_shl
| sym::unchecked_funnel_shr => {
let is_left = name == sym::rotate_left || name == sym::unchecked_funnel_shl;
let lhs = args[0].immediate();
let (rhs, raw_shift) =
if name == sym::rotate_left || name == sym::rotate_right {
// rotate = funnel shift with first two args the same
(lhs, args[1].immediate())
} else {
(args[1].immediate(), args[2].immediate())
};
let llvm_name = format!("llvm.fsh{}", if is_left { 'l' } else { 'r' });
// llvm expects shift to be the same type as the values, but rust
// always uses `u32`.
let raw_shift = self.intcast(raw_shift, self.val_ty(val), false);
let raw_shift = self.intcast(raw_shift, self.val_ty(lhs), false);
self.call_intrinsic(llvm_name, &[llty], &[val, val, raw_shift])
self.call_intrinsic(llvm_name, &[llty], &[lhs, rhs, raw_shift])
}
sym::saturating_add | sym::saturating_sub => {
let is_add = name == sym::saturating_add;