Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
| sym::ctpop
| sym::bswap
| sym::bitreverse
| sym::rotate_left
| sym::rotate_right
| sym::saturating_add
| sym::saturating_sub
| sym::unchecked_funnel_shl
Expand Down Expand Up @@ -445,11 +447,19 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
sym::bitreverse => {
self.call_intrinsic("llvm.bitreverse", &[llty], &[args[0].immediate()])
}
sym::unchecked_funnel_shl | sym::unchecked_funnel_shr => {
let is_left = name == sym::unchecked_funnel_shl;
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 = args[1].immediate();
let raw_shift = args[2].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
Expand Down
8 changes: 4 additions & 4 deletions tests/codegen-llvm/intrinsics/rotate_left.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@ compile-flags: -O
//@ compile-flags: -C no-prepopulate-passes

#![crate_type = "lib"]
#![feature(core_intrinsics)]
Expand All @@ -9,7 +9,7 @@ use std::intrinsics::rotate_left;
#[no_mangle]
pub unsafe fn rotate_left_u16(x: u16, shift: u32) -> u16 {
// CHECK: %[[tmp:.*]] = trunc i32 %shift to i16
// CHECK: call noundef i16 @llvm.fshl.i16(i16 %x, i16 %x, i16 %[[tmp]])
// CHECK: call i16 @llvm.fshl.i16(i16 %x, i16 %x, i16 %[[tmp]])
rotate_left(x, shift)
}

Expand All @@ -18,14 +18,14 @@ pub unsafe fn rotate_left_u16(x: u16, shift: u32) -> u16 {
pub unsafe fn rotate_left_u32(x: u32, shift: u32) -> u32 {
// CHECK-NOT: trunc
// CHECK-NOT: zext
// CHECK: call noundef i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %shift)
// CHECK: call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %shift)
rotate_left(x, shift)
}

// CHECK-LABEL: @rotate_left_u64
#[no_mangle]
pub unsafe fn rotate_left_u64(x: u64, shift: u32) -> u64 {
// CHECK: %[[tmp:.*]] = zext i32 %shift to i64
// CHECK: call noundef i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 %[[tmp]])
// CHECK: call i64 @llvm.fshl.i64(i64 %x, i64 %x, i64 %[[tmp]])
rotate_left(x, shift)
}
Loading