Files
llvm-project/llvm/test/CodeGen/ARM/shift-mod.ll
2026-04-13 13:02:36 -07:00

257 lines
7.5 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=armv7-linux-gnueabihf %s -o - | FileCheck %s --check-prefixes=CHECK-ARM
; RUN: llc -mtriple=armv7eb-linux-gnueabihf %s -o - | FileCheck %s --check-prefixes=CHECK-BE
; RUN: llc -mtriple=thumbv7-linux-gnueabihf %s -o - | FileCheck %s --check-prefixes=CHECK-THUMB
; RUN: llc -mtriple=thumbv7m %s -o - | FileCheck %s --check-prefixes=CHECK-THUMB
; RUN: llc -mtriple=thumbv6m %s -o - | FileCheck %s --check-prefix=CHECK-V6M
declare i32 @llvm.fshl.i32(i32, i32, i32)
declare i32 @llvm.fshr.i32(i32, i32, i32)
; -----------------------
; fshl (funnel-shift left) group
; fshl(x,x, s) == rotate-left(x, s)
; -----------------------
; amt + 32 -> REMOVE ADD (mod 32), expect rotate lowering (ror/lsl/lsr depending on selector)
define i32 @fshl_add_mod(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshl_add_mod:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: rsb r1, r1, #0
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshl_add_mod:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: rsb r1, r1, #0
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshl_add_mod:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: rsbs r1, r1, #0
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshl_add_mod:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: rsbs r1, r1, #0
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = add i32 %amt, 32
%r = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %sa)
ret i32 %r
}
; 32 - amt -> expect RSB/NEG materialization then rotate lowering
define i32 @fshl_sub_rsb(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshl_sub_rsb:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshl_sub_rsb:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshl_sub_rsb:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshl_sub_rsb:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = sub i32 32, %amt
%r = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %sa)
ret i32 %r
}
; 31 - amt -> fshl lowers to sub amt,#31 then ror (mod-32 equivalent); fshr uses MVN+ror
define i32 @fshl_sub_31(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshl_sub_31:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: sub r1, r1, #31
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshl_sub_31:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: sub r1, r1, #31
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshl_sub_31:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: subs r1, #31
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshl_sub_31:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: subs r1, #31
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = sub i32 31, %amt
%r = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %sa)
ret i32 %r
}
; amt & 31 -> AND redundant (hardware masks low 5 bits) -> expect rotate lowering with no AND
define i32 @fshl_and_mask(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshl_and_mask:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: rsb r1, r1, #0
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshl_and_mask:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: rsb r1, r1, #0
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshl_and_mask:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: rsbs r1, r1, #0
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshl_and_mask:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: rsbs r1, r1, #0
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = and i32 %amt, 31
%r = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %sa)
ret i32 %r
}
; -----------------------
; fshr (funnel-shift right) group
; fshr(x,x, s) == rotate-right(x, s)
; -----------------------
; amt + 32 -> REMOVE ADD (mod 32) -> expect rotate lowering
define i32 @fshr_add_mod(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshr_add_mod:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshr_add_mod:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshr_add_mod:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshr_add_mod:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = add i32 %amt, 32
%r = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %sa)
ret i32 %r
}
; 32 - amt -> expect RSB then rotate lowering
define i32 @fshr_sub_rsb(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshr_sub_rsb:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: rsb r1, r1, #0
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshr_sub_rsb:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: rsb r1, r1, #0
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshr_sub_rsb:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: rsbs r1, r1, #0
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshr_sub_rsb:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: rsbs r1, r1, #0
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = sub i32 32, %amt
%r = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %sa)
ret i32 %r
}
; 31 - amt -> expect MVN then rotate lowering
define i32 @fshr_sub_mvn(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshr_sub_mvn:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: mvn r1, r1
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshr_sub_mvn:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: mvn r1, r1
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshr_sub_mvn:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: mvns r1, r1
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshr_sub_mvn:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: mvns r1, r1
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = sub i32 31, %amt
%r = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %sa)
ret i32 %r
}
; amt & 31 -> AND redundant -> expect rotate lowering with no AND
define i32 @fshr_and_mask(i32 %x, i32 %amt) #0 {
; CHECK-ARM-LABEL: fshr_and_mask:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ror r0, r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: fshr_and_mask:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ror r0, r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: fshr_and_mask:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: rors r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-V6M-LABEL: fshr_and_mask:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: rors r0, r1
; CHECK-V6M-NEXT: bx lr
entry:
%sa = and i32 %amt, 31
%r = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %sa)
ret i32 %r
}