257 lines
7.5 KiB
LLVM
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
|
|
}
|
|
|