Files
clang-p2996/llvm/test/CodeGen/ARM/shift-combine.ll
Sam Parker 1f4f4d9a08 [DAGCombine] Improve ReduceLoad for SRL
Recommitting r329283, third time lucky...

If the SRL node is only used by an AND, we may be able to set the
ExtVT to the width of the mask, making the AND redundant. To support
this, another check has been added in isLegalNarrowLoad which queries
whether the load is valid.

Differential Revision: https://reviews.llvm.org/D41350

llvm-svn: 329551
2018-04-09 08:16:11 +00:00

388 lines
11 KiB
LLVM

; RUN: llc -mtriple=armv7-linux-gnueabihf %s -o - | FileCheck %s --check-prefix=CHECK-ARM --check-prefix=CHECK-COMMON
; RUN: llc -mtriple=armv7eb-linux-gnueabihf %s -o - | FileCheck %s --check-prefix=CHECK-BE
; RUN: llc -mtriple=thumbv7-linux-gnueabihf %s -o - | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-COMMON
; RUN: llc -mtriple=thumbv7m %s -o - | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-COMMON
; RUN: llc -mtriple=thumbv7m -mattr=+strict-align %s -o - | FileCheck %s --check-prefix=CHECK-ALIGN --check-prefix=CHECK-COMMON
; RUN: llc -mtriple=thumbv6m %s -o - | FileCheck %s --check-prefix=CHECK-V6M
@array = weak global [4 x i32] zeroinitializer
define i32 @test_lshr_and1(i32 %x) {
entry:
;CHECK-LABLE: test_lshr_and1:
;CHECK-COMMON: movw r1, :lower16:array
;CHECK-COMMON-NEXT: and r0, r0, #12
;CHECK-COMMON-NEXT: movt r1, :upper16:array
;CHECK-COMMON-NEXT: ldr r0, [r1, r0]
;CHECK-COMMON-NEXT: bx lr
%tmp2 = lshr i32 %x, 2
%tmp3 = and i32 %tmp2, 3
%tmp4 = getelementptr [4 x i32], [4 x i32]* @array, i32 0, i32 %tmp3
%tmp5 = load i32, i32* %tmp4, align 4
ret i32 %tmp5
}
define i32 @test_lshr_and2(i32 %x) {
entry:
;CHECK-LABEL: test_lshr_and2:
;CHECK-COMMON: ubfx r0, r0, #1, #15
;CHECK-ARM: add r0, r0, r0
;CHECK-THUMB: add r0, r0
;CHECK-COMMON: bx lr
%a = and i32 %x, 65534
%b = lshr i32 %a, 1
%c = and i32 %x, 65535
%d = lshr i32 %c, 1
%e = add i32 %b, %d
ret i32 %e
}
; CHECK-LABEL: test_lshr_load1
; CHECK-BE: ldrb r0, [r0]
; CHECK-COMMON: ldrb r0, [r0, #1]
; CHECK-COMMON-NEXT: bx
define arm_aapcscc i32 @test_lshr_load1(i16* %a) {
entry:
%0 = load i16, i16* %a, align 2
%conv1 = zext i16 %0 to i32
%1 = lshr i32 %conv1, 8
ret i32 %1
}
; CHECK-LABEL: test_lshr_load1_sext
; CHECK-ARM: ldrsh r0, [r0]
; CHECK-ARM-NEXT: lsr r0, r0, #8
; CHECK-THUMB: ldrsh.w r0, [r0]
; CHECK-THUMB-NEXT: lsrs r0, r0, #8
; CHECK-COMMON: bx
define arm_aapcscc i32 @test_lshr_load1_sext(i16* %a) {
entry:
%0 = load i16, i16* %a, align 2
%conv1 = sext i16 %0 to i32
%1 = lshr i32 %conv1, 8
ret i32 %1
}
; CHECK-LABEL: test_lshr_load1_fail
; CHECK-COMMON: ldrh r0, [r0]
; CHECK-ARM: lsr r0, r0, #9
; CHECK-THUMB: lsrs r0, r0, #9
; CHECK-COMMON: bx
define arm_aapcscc i32 @test_lshr_load1_fail(i16* %a) {
entry:
%0 = load i16, i16* %a, align 2
%conv1 = zext i16 %0 to i32
%1 = lshr i32 %conv1, 9
ret i32 %1
}
; CHECK-LABEL: test_lshr_load32
; CHECK-COMMON: ldr r0, [r0]
; CHECK-ARM: lsr r0, r0, #8
; CHECK-THUMB: lsrs r0, r0, #8
; CHECK-COMMON: bx
define arm_aapcscc i32 @test_lshr_load32(i32* %a) {
entry:
%0 = load i32, i32* %a, align 4
%1 = lshr i32 %0, 8
ret i32 %1
}
; CHECK-LABEL: test_lshr_load32_2
; CHECK-BE: ldrh r0, [r0]
; CHECK-COMMON: ldrh r0, [r0, #2]
; CHECK-COMMON-NEXT: bx
define arm_aapcscc i32 @test_lshr_load32_2(i32* %a) {
entry:
%0 = load i32, i32* %a, align 4
%1 = lshr i32 %0, 16
ret i32 %1
}
; CHECK-LABEL: test_lshr_load32_1
; CHECK-BE: ldrb r0, [r0]
; CHECK-COMMON: ldrb r0, [r0, #3]
; CHECK-COMMON-NEXT: bx
define arm_aapcscc i32 @test_lshr_load32_1(i32* %a) {
entry:
%0 = load i32, i32* %a, align 4
%1 = lshr i32 %0, 24
ret i32 %1
}
; CHECK-LABEL: test_lshr_load32_fail
; CHECK-BE: ldr r0, [r0]
; CHECK-BE-NEXT: lsr r0, r0, #15
; CHECK-COMMON: ldr r0, [r0]
; CHECK-ARM: lsr r0, r0, #15
; CHECK-THUMB: lsrs r0, r0, #15
; CHECK-COMMON: bx
define arm_aapcscc i32 @test_lshr_load32_fail(i32* %a) {
entry:
%0 = load i32, i32* %a, align 4
%1 = lshr i32 %0, 15
ret i32 %1
}
; CHECK-LABEL: test_lshr_load64_4_unaligned
; CHECK-BE: ldr [[HIGH:r[0-9]+]], [r0]
; CHECK-BE-NEXT: ldrh [[LOW:r[0-9]+]], [r0, #4]
; CHECK-BE-NEXT: orr r0, [[LOW]], [[HIGH]], lsl #16
; CHECK-V6M: ldrh [[LOW:r[0-9]+]], [r0, #2]
; CHECK-V6M: ldr [[HIGH:r[0-9]+]], [r0, #4]
; CHECK-V6M-NEXT: lsls [[HIGH]], [[HIGH]], #16
; CHECK-V6M-NEXT: orrs r0, r1
; CHECK-ALIGN: ldr [[HIGH:r[0-9]+]], [r0, #4]
; CHECK-ALIGN-NEXT: ldrh [[LOW:r[0-9]+]], [r0, #2]
; CHECK-ALIGN-NEXT: orr.w r0, [[LOW]], [[HIGH]], lsl #16
; CHECK-ARM: ldr r0, [r0, #2]
; CHECK-THUMB: ldr.w r0, [r0, #2]
; CHECK-COMMON: bx
define arm_aapcscc i32 @test_lshr_load64_4_unaligned(i64* %a) {
entry:
%0 = load i64, i64* %a, align 8
%1 = lshr i64 %0, 16
%conv = trunc i64 %1 to i32
ret i32 %conv
}
; CHECK-LABEL: test_lshr_load64_1_lsb
; CHECK-BE: ldr r1, [r0]
; CHECK-BE-NEXT: ldrb r0, [r0, #4]
; CHECK-BE-NEXT: orr r0, r0, r1, lsl #8
; CHECK-ARM: ldr r0, [r0, #3]
; CHECK-THUMB: ldr.w r0, [r0, #3]
; CHECK-ALIGN: ldr [[HIGH:r[0-9]+]], [r0, #4]
; CHECK-ALIGN-NEXT: ldrb [[LOW:r[0-9]+]], [r0, #3]
; CHECK-ALIGN-NEXT: orr.w r0, [[LOW]], [[HIGH]], lsl #8
; CHECK-COMMON: bx
define arm_aapcscc i32 @test_lshr_load64_1_lsb(i64* %a) {
entry:
%0 = load i64, i64* %a, align 8
%1 = lshr i64 %0, 24
%conv = trunc i64 %1 to i32
ret i32 %conv
}
; CHECK-LABEL: test_lshr_load64_1_msb
; CHECK-BE: ldrb r0, [r0]
; CHECK-BE-NEXT: bx
; CHECK-COMMON: ldrb r0, [r0, #7]
; CHECK-COMMON-NEXT: bx
define arm_aapcscc i32 @test_lshr_load64_1_msb(i64* %a) {
entry:
%0 = load i64, i64* %a, align 8
%1 = lshr i64 %0, 56
%conv = trunc i64 %1 to i32
ret i32 %conv
}
; CHECK-LABEL: test_lshr_load64_4
; CHECK-BE: ldr r0, [r0]
; CHECK-BE-NEXT: bx
; CHECK-COMMON: ldr r0, [r0, #4]
; CHECK-COMMON-NEXT: bx
define arm_aapcscc i32 @test_lshr_load64_4(i64* %a) {
entry:
%0 = load i64, i64* %a, align 8
%1 = lshr i64 %0, 32
%conv = trunc i64 %1 to i32
ret i32 %conv
}
; CHECK-LABEL: test_lshr_load64_2
; CHECK-BE: ldrh r0, [r0]
; CHECK-BE-NEXT: bx
; CHECK-COMMON: ldrh r0, [r0, #6]
; CHECK-COMMON-NEXT:bx
define arm_aapcscc i32 @test_lshr_load64_2(i64* %a) {
entry:
%0 = load i64, i64* %a, align 8
%1 = lshr i64 %0, 48
%conv = trunc i64 %1 to i32
ret i32 %conv
}
; CHECK-LABEL: test_lshr_load4_fail
; CHECK-COMMON: ldrd r0, r1, [r0]
; CHECK-ARM: lsr r0, r0, #8
; CHECK-ARM-NEXT: orr r0, r0, r1, lsl #24
; CHECK-THUMB: lsrs r0, r0, #8
; CHECK-THUMB-NEXT: orr.w r0, r0, r1, lsl #24
; CHECK-COMMON: bx
define arm_aapcscc i32 @test_lshr_load4_fail(i64* %a) {
entry:
%0 = load i64, i64* %a, align 8
%1 = lshr i64 %0, 8
%conv = trunc i64 %1 to i32
ret i32 %conv
}
; CHECK-LABEL: test_shift7_mask8
; CHECK-BE: ldr r1, [r0]
; CHECK-COMMON: ldr r1, [r0]
; CHECK-COMMON: ubfx r1, r1, #7, #8
; CHECK-COMMON: str r1, [r0]
define arm_aapcscc void @test_shift7_mask8(i32* nocapture %p) {
entry:
%0 = load i32, i32* %p, align 4
%shl = lshr i32 %0, 7
%and = and i32 %shl, 255
store i32 %and, i32* %p, align 4
ret void
}
; CHECK-LABEL: test_shift8_mask8
; CHECK-BE: ldrb r1, [r0, #2]
; CHECK-COMMON: ldrb r1, [r0, #1]
; CHECK-COMMON: str r1, [r0]
define arm_aapcscc void @test_shift8_mask8(i32* nocapture %p) {
entry:
%0 = load i32, i32* %p, align 4
%shl = lshr i32 %0, 8
%and = and i32 %shl, 255
store i32 %and, i32* %p, align 4
ret void
}
; CHECK-LABEL: test_shift8_mask7
; CHECK-BE: ldr r1, [r0]
; CHECK-COMMON: ldr r1, [r0]
; CHECK-COMMON: ubfx r1, r1, #8, #7
; CHECK-COMMON: str r1, [r0]
define arm_aapcscc void @test_shift8_mask7(i32* nocapture %p) {
entry:
%0 = load i32, i32* %p, align 4
%shl = lshr i32 %0, 8
%and = and i32 %shl, 127
store i32 %and, i32* %p, align 4
ret void
}
; CHECK-LABEL: test_shift9_mask8
; CHECK-BE: ldr r1, [r0]
; CHECK-COMMON: ldr r1, [r0]
; CHECK-COMMON: ubfx r1, r1, #9, #8
; CHECK-COMMON: str r1, [r0]
define arm_aapcscc void @test_shift9_mask8(i32* nocapture %p) {
entry:
%0 = load i32, i32* %p, align 4
%shl = lshr i32 %0, 9
%and = and i32 %shl, 255
store i32 %and, i32* %p, align 4
ret void
}
; CHECK-LABEL: test_shift8_mask16
; CHECK-ALIGN: ldr r1, [r0]
; CHECK-ALIGN: ubfx r1, r1, #8, #16
; CHECK-BE: ldrh r1, [r0, #1]
; CHECK-ARM: ldrh r1, [r0, #1]
; CHECK-THUMB: ldrh.w r1, [r0, #1]
; CHECK-COMMON: str r1, [r0]
define arm_aapcscc void @test_shift8_mask16(i32* nocapture %p) {
entry:
%0 = load i32, i32* %p, align 4
%shl = lshr i32 %0, 8
%and = and i32 %shl, 65535
store i32 %and, i32* %p, align 4
ret void
}
; CHECK-LABEL: test_shift15_mask16
; CHECK-COMMON: ldr r1, [r0]
; CHECK-COMMON: ubfx r1, r1, #15, #16
; CHECK-COMMON: str r1, [r0]
define arm_aapcscc void @test_shift15_mask16(i32* nocapture %p) {
entry:
%0 = load i32, i32* %p, align 4
%shl = lshr i32 %0, 15
%and = and i32 %shl, 65535
store i32 %and, i32* %p, align 4
ret void
}
; CHECK-LABEL: test_shift16_mask15
; CHECK-BE: ldrh r1, [r0]
; CHECK-COMMON: ldrh r1, [r0, #2]
; CHECK-COMMON: bfc r1, #15, #17
; CHECK-COMMON: str r1, [r0]
define arm_aapcscc void @test_shift16_mask15(i32* nocapture %p) {
entry:
%0 = load i32, i32* %p, align 4
%shl = lshr i32 %0, 16
%and = and i32 %shl, 32767
store i32 %and, i32* %p, align 4
ret void
}
; CHECK-LABEL: test_shift8_mask24
; CHECK-BE: ldr r1, [r0]
; CHECK-COMMON: ldr r1, [r0]
; CHECK-ARM: lsr r1, r1, #8
; CHECK-THUMB: lsrs r1, r1, #8
; CHECK-COMMON: str r1, [r0]
define arm_aapcscc void @test_shift8_mask24(i32* nocapture %p) {
entry:
%0 = load i32, i32* %p, align 4
%shl = lshr i32 %0, 8
%and = and i32 %shl, 16777215
store i32 %and, i32* %p, align 4
ret void
}
; CHECK-LABEL: test_shift24_mask16
; CHECK-BE: ldrb r1, [r0]
; CHECK-COMMON: ldrb r1, [r0, #3]
; CHECK-COMMON: str r1, [r0]
define arm_aapcscc void @test_shift24_mask16(i32* nocapture %p) {
entry:
%0 = load i32, i32* %p, align 4
%shl = lshr i32 %0, 24
%and = and i32 %shl, 65535
store i32 %and, i32* %p, align 4
ret void
}
; CHECK-LABEL: test_sext_shift8_mask8
; CHECK-BE: ldrb r0, [r0]
; CHECK-COMMON: ldrb r0, [r0, #1]
; CHECK-COMMON: str r0, [r1]
define arm_aapcscc void @test_sext_shift8_mask8(i16* %p, i32* %q) {
entry:
%0 = load i16, i16* %p, align 4
%1 = sext i16 %0 to i32
%shl = lshr i32 %1, 8
%and = and i32 %shl, 255
store i32 %and, i32* %q, align 4
ret void
}
; CHECK-LABEL: test_sext_shift8_mask16
; CHECK-ARM: ldrsh r0, [r0]
; CHECK-BE: ldrsh r0, [r0]
; CHECK-THUMB: ldrsh.w r0, [r0]
; CHECK-COMMON: ubfx r0, r0, #8, #16
; CHECK-COMMON: str r0, [r1]
define arm_aapcscc void @test_sext_shift8_mask16(i16* %p, i32* %q) {
entry:
%0 = load i16, i16* %p, align 4
%1 = sext i16 %0 to i32
%shl = lshr i32 %1, 8
%and = and i32 %shl, 65535
store i32 %and, i32* %q, align 4
ret void
}
; CHECK-LABEL: trunc_i64_mask_srl
; CHECK-ARM: ldrh r2, [r1, #4]
; CHECK-BE: ldrh r2, [r1, #2]
define i1 @trunc_i64_mask_srl(i32 zeroext %AttrArgNo, i64* %ptr) {
entry:
%bf.load.i = load i64, i64* %ptr, align 8
%bf.lshr.i = lshr i64 %bf.load.i, 32
%0 = trunc i64 %bf.lshr.i to i32
%bf.cast.i = and i32 %0, 65535
%cmp.i = icmp ugt i32 %bf.cast.i, %AttrArgNo
ret i1 %cmp.i
}