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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user