llvm-project/llvm/test/CodeGen/ARM/shift-combine.ll
Craig Topper 6590d0fed5
[DAGCombiner][ARM] Teach reduceLoadWidth to handle (and (srl (load), C, ShiftedMask)) (#80342)
If we have a shifted mask, we may be able to reduce the load width
to the width of the non-zero part of the mask and use an offset
to the base address to remove the srl. The offset is given by
C+trailingzeros(ShiftedMask).
    
Then we add a final shl to restore the trailing zero bits.
    
I've use the ARM test because that's where the existing (and (srl
(load))) tests were.
    
The X86 test was modified to keep the H register.
2024-02-04 16:05:51 -08:00

1393 lines
42 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-COMMON,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-COMMON,CHECK-THUMB
; RUN: llc -mtriple=thumbv7m %s -o - | FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-THUMB
; RUN: llc -mtriple=thumbv7m -mattr=+strict-align %s -o - | FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-ALIGN
; 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) {
; CHECK-COMMON-LABEL: test_lshr_and1:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: 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
;
; CHECK-BE-LABEL: test_lshr_and1:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: movw r1, :lower16:array
; CHECK-BE-NEXT: and r0, r0, #12
; CHECK-BE-NEXT: movt r1, :upper16:array
; CHECK-BE-NEXT: ldr r0, [r1, r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_and1:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: movs r1, #12
; CHECK-V6M-NEXT: ands r1, r0
; CHECK-V6M-NEXT: ldr r0, .LCPI0_0
; CHECK-V6M-NEXT: ldr r0, [r0, r1]
; CHECK-V6M-NEXT: bx lr
; CHECK-V6M-NEXT: .p2align 2
; CHECK-V6M-NEXT: @ %bb.1:
; CHECK-V6M-NEXT: .LCPI0_0:
; CHECK-V6M-NEXT: .long array
entry:
%tmp2 = lshr i32 %x, 2
%tmp3 = and i32 %tmp2, 3
%tmp4 = getelementptr [4 x i32], ptr @array, i32 0, i32 %tmp3
%tmp5 = load i32, ptr %tmp4, align 4
ret i32 %tmp5
}
define i32 @test_lshr_and2(i32 %x) {
; CHECK-ARM-LABEL: test_lshr_and2:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ubfx r0, r0, #1, #15
; CHECK-ARM-NEXT: add r0, r0, r0
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_and2:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ubfx r0, r0, #1, #15
; CHECK-BE-NEXT: add r0, r0, r0
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_lshr_and2:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ubfx r0, r0, #1, #15
; CHECK-THUMB-NEXT: add r0, r0
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_lshr_and2:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ubfx r0, r0, #1, #15
; CHECK-ALIGN-NEXT: add r0, r0
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_and2:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: lsls r0, r0, #16
; CHECK-V6M-NEXT: lsrs r0, r0, #17
; CHECK-V6M-NEXT: adds r0, r0, r0
; CHECK-V6M-NEXT: bx lr
entry:
%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
}
define arm_aapcscc i32 @test_lshr_load1(ptr %a) {
; CHECK-COMMON-LABEL: test_lshr_load1:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldrb r0, [r0, #1]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load1:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrb r0, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load1:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrb r0, [r0, #1]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i16, ptr %a, align 2
%conv1 = zext i16 %0 to i32
%1 = lshr i32 %conv1, 8
ret i32 %1
}
define arm_aapcscc i32 @test_lshr_load1_sext(ptr %a) {
; CHECK-ARM-LABEL: test_lshr_load1_sext:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldrsh r0, [r0]
; CHECK-ARM-NEXT: lsr r0, r0, #8
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load1_sext:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrsh r0, [r0]
; CHECK-BE-NEXT: lsr r0, r0, #8
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_lshr_load1_sext:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldrsh.w r0, [r0]
; CHECK-THUMB-NEXT: lsrs r0, r0, #8
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_lshr_load1_sext:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldrsh.w r0, [r0]
; CHECK-ALIGN-NEXT: lsrs r0, r0, #8
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load1_sext:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: movs r1, #0
; CHECK-V6M-NEXT: ldrsh r0, [r0, r1]
; CHECK-V6M-NEXT: lsrs r0, r0, #8
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i16, ptr %a, align 2
%conv1 = sext i16 %0 to i32
%1 = lshr i32 %conv1, 8
ret i32 %1
}
define arm_aapcscc i32 @test_lshr_load1_fail(ptr %a) {
; CHECK-ARM-LABEL: test_lshr_load1_fail:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldrh r0, [r0]
; CHECK-ARM-NEXT: lsr r0, r0, #9
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load1_fail:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrh r0, [r0]
; CHECK-BE-NEXT: lsr r0, r0, #9
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_lshr_load1_fail:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldrh r0, [r0]
; CHECK-THUMB-NEXT: lsrs r0, r0, #9
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_lshr_load1_fail:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldrh r0, [r0]
; CHECK-ALIGN-NEXT: lsrs r0, r0, #9
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load1_fail:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrh r0, [r0]
; CHECK-V6M-NEXT: lsrs r0, r0, #9
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i16, ptr %a, align 2
%conv1 = zext i16 %0 to i32
%1 = lshr i32 %conv1, 9
ret i32 %1
}
define arm_aapcscc i32 @test_lshr_load32(ptr %a) {
; CHECK-ARM-LABEL: test_lshr_load32:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldr r0, [r0]
; CHECK-ARM-NEXT: lsr r0, r0, #8
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load32:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldr r0, [r0]
; CHECK-BE-NEXT: lsr r0, r0, #8
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_lshr_load32:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldr r0, [r0]
; CHECK-THUMB-NEXT: lsrs r0, r0, #8
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_lshr_load32:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldr r0, [r0]
; CHECK-ALIGN-NEXT: lsrs r0, r0, #8
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load32:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldr r0, [r0]
; CHECK-V6M-NEXT: lsrs r0, r0, #8
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %a, align 4
%1 = lshr i32 %0, 8
ret i32 %1
}
define arm_aapcscc i32 @test_lshr_load32_2(ptr %a) {
; CHECK-COMMON-LABEL: test_lshr_load32_2:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldrh r0, [r0, #2]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load32_2:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrh r0, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load32_2:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrh r0, [r0, #2]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %a, align 4
%1 = lshr i32 %0, 16
ret i32 %1
}
define arm_aapcscc i32 @test_lshr_load32_1(ptr %a) {
; CHECK-COMMON-LABEL: test_lshr_load32_1:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldrb r0, [r0, #3]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load32_1:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrb r0, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load32_1:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrb r0, [r0, #3]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %a, align 4
%1 = lshr i32 %0, 24
ret i32 %1
}
define arm_aapcscc i32 @test_lshr_load32_fail(ptr %a) {
; CHECK-ARM-LABEL: test_lshr_load32_fail:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldr r0, [r0]
; CHECK-ARM-NEXT: lsr r0, r0, #15
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load32_fail:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldr r0, [r0]
; CHECK-BE-NEXT: lsr r0, r0, #15
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_lshr_load32_fail:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldr r0, [r0]
; CHECK-THUMB-NEXT: lsrs r0, r0, #15
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_lshr_load32_fail:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldr r0, [r0]
; CHECK-ALIGN-NEXT: lsrs r0, r0, #15
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load32_fail:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldr r0, [r0]
; CHECK-V6M-NEXT: lsrs r0, r0, #15
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %a, align 4
%1 = lshr i32 %0, 15
ret i32 %1
}
define arm_aapcscc i32 @test_lshr_load64_4_unaligned(ptr %a) {
; CHECK-ARM-LABEL: test_lshr_load64_4_unaligned:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldr r0, [r0, #2]
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load64_4_unaligned:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldr r0, [r0, #2]
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_lshr_load64_4_unaligned:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldr.w r0, [r0, #2]
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_lshr_load64_4_unaligned:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldr r1, [r0, #4]
; CHECK-ALIGN-NEXT: ldrh r0, [r0, #2]
; CHECK-ALIGN-NEXT: orr.w r0, r0, r1, lsl #16
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load64_4_unaligned:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrh r1, [r0, #2]
; CHECK-V6M-NEXT: ldr r0, [r0, #4]
; CHECK-V6M-NEXT: lsls r0, r0, #16
; CHECK-V6M-NEXT: adds r0, r1, r0
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i64, ptr %a, align 8
%1 = lshr i64 %0, 16
%conv = trunc i64 %1 to i32
ret i32 %conv
}
define arm_aapcscc i32 @test_lshr_load64_1_lsb(ptr %a) {
; CHECK-ARM-LABEL: test_lshr_load64_1_lsb:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldr r0, [r0, #3]
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load64_1_lsb:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldr r0, [r0, #1]
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_lshr_load64_1_lsb:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldr.w r0, [r0, #3]
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_lshr_load64_1_lsb:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldr r1, [r0, #4]
; CHECK-ALIGN-NEXT: ldrb r0, [r0, #3]
; CHECK-ALIGN-NEXT: orr.w r0, r0, r1, lsl #8
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load64_1_lsb:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrb r1, [r0, #3]
; CHECK-V6M-NEXT: ldr r0, [r0, #4]
; CHECK-V6M-NEXT: lsls r0, r0, #8
; CHECK-V6M-NEXT: adds r0, r1, r0
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i64, ptr %a, align 8
%1 = lshr i64 %0, 24
%conv = trunc i64 %1 to i32
ret i32 %conv
}
define arm_aapcscc i32 @test_lshr_load64_1_msb(ptr %a) {
; CHECK-COMMON-LABEL: test_lshr_load64_1_msb:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldrb r0, [r0, #7]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load64_1_msb:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrb r0, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load64_1_msb:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrb r0, [r0, #7]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i64, ptr %a, align 8
%1 = lshr i64 %0, 56
%conv = trunc i64 %1 to i32
ret i32 %conv
}
define arm_aapcscc i32 @test_lshr_load64_4(ptr %a) {
; CHECK-COMMON-LABEL: test_lshr_load64_4:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldr r0, [r0, #4]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load64_4:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldr r0, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load64_4:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldr r0, [r0, #4]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i64, ptr %a, align 8
%1 = lshr i64 %0, 32
%conv = trunc i64 %1 to i32
ret i32 %conv
}
define arm_aapcscc i32 @test_lshr_load64_2(ptr %a) {
; CHECK-COMMON-LABEL: test_lshr_load64_2:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldrh r0, [r0, #6]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load64_2:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrh r0, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load64_2:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrh r0, [r0, #6]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i64, ptr %a, align 8
%1 = lshr i64 %0, 48
%conv = trunc i64 %1 to i32
ret i32 %conv
}
define arm_aapcscc i32 @test_lshr_load4_fail(ptr %a) {
; CHECK-ARM-LABEL: test_lshr_load4_fail:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldr r0, [r0, #1]
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_lshr_load4_fail:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldr r0, [r0, #3]
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_lshr_load4_fail:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldr.w r0, [r0, #1]
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_lshr_load4_fail:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldrd r0, r1, [r0]
; CHECK-ALIGN-NEXT: lsrs r0, r0, #8
; CHECK-ALIGN-NEXT: orr.w r0, r0, r1, lsl #24
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_lshr_load4_fail:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldr r1, [r0]
; CHECK-V6M-NEXT: ldr r0, [r0, #4]
; CHECK-V6M-NEXT: lsls r0, r0, #24
; CHECK-V6M-NEXT: lsrs r1, r1, #8
; CHECK-V6M-NEXT: adds r0, r1, r0
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i64, ptr %a, align 8
%1 = lshr i64 %0, 8
%conv = trunc i64 %1 to i32
ret i32 %conv
}
define arm_aapcscc void @test_shift7_mask8(ptr nocapture %p) {
; CHECK-COMMON-LABEL: test_shift7_mask8:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldr r1, [r0]
; CHECK-COMMON-NEXT: ubfx r1, r1, #7, #8
; CHECK-COMMON-NEXT: str r1, [r0]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_shift7_mask8:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldr r1, [r0]
; CHECK-BE-NEXT: ubfx r1, r1, #7, #8
; CHECK-BE-NEXT: str r1, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_shift7_mask8:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldr r1, [r0]
; CHECK-V6M-NEXT: lsrs r1, r1, #7
; CHECK-V6M-NEXT: uxtb r1, r1
; CHECK-V6M-NEXT: str r1, [r0]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %p, align 4
%shl = lshr i32 %0, 7
%and = and i32 %shl, 255
store i32 %and, ptr %p, align 4
ret void
}
define arm_aapcscc void @test_shift8_mask8(ptr nocapture %p) {
; CHECK-COMMON-LABEL: test_shift8_mask8:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldrb r1, [r0, #1]
; CHECK-COMMON-NEXT: str r1, [r0]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_shift8_mask8:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrb r1, [r0, #2]
; CHECK-BE-NEXT: str r1, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_shift8_mask8:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrb r1, [r0, #1]
; CHECK-V6M-NEXT: str r1, [r0]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %p, align 4
%shl = lshr i32 %0, 8
%and = and i32 %shl, 255
store i32 %and, ptr %p, align 4
ret void
}
define arm_aapcscc void @test_shift8_mask7(ptr nocapture %p) {
; CHECK-COMMON-LABEL: test_shift8_mask7:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldr r1, [r0]
; CHECK-COMMON-NEXT: ubfx r1, r1, #8, #7
; CHECK-COMMON-NEXT: str r1, [r0]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_shift8_mask7:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldr r1, [r0]
; CHECK-BE-NEXT: ubfx r1, r1, #8, #7
; CHECK-BE-NEXT: str r1, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_shift8_mask7:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldr r1, [r0]
; CHECK-V6M-NEXT: lsls r1, r1, #17
; CHECK-V6M-NEXT: lsrs r1, r1, #25
; CHECK-V6M-NEXT: str r1, [r0]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %p, align 4
%shl = lshr i32 %0, 8
%and = and i32 %shl, 127
store i32 %and, ptr %p, align 4
ret void
}
define arm_aapcscc void @test_shift9_mask8(ptr nocapture %p) {
; CHECK-COMMON-LABEL: test_shift9_mask8:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldr r1, [r0]
; CHECK-COMMON-NEXT: ubfx r1, r1, #9, #8
; CHECK-COMMON-NEXT: str r1, [r0]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_shift9_mask8:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldr r1, [r0]
; CHECK-BE-NEXT: ubfx r1, r1, #9, #8
; CHECK-BE-NEXT: str r1, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_shift9_mask8:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldr r1, [r0]
; CHECK-V6M-NEXT: lsrs r1, r1, #9
; CHECK-V6M-NEXT: uxtb r1, r1
; CHECK-V6M-NEXT: str r1, [r0]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %p, align 4
%shl = lshr i32 %0, 9
%and = and i32 %shl, 255
store i32 %and, ptr %p, align 4
ret void
}
define arm_aapcscc void @test_shift8_mask16(ptr nocapture %p) {
; CHECK-ARM-LABEL: test_shift8_mask16:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldrh r1, [r0, #1]
; CHECK-ARM-NEXT: str r1, [r0]
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_shift8_mask16:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrh r1, [r0, #1]
; CHECK-BE-NEXT: str r1, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_shift8_mask16:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldrh.w r1, [r0, #1]
; CHECK-THUMB-NEXT: str r1, [r0]
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_shift8_mask16:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldr r1, [r0]
; CHECK-ALIGN-NEXT: ubfx r1, r1, #8, #16
; CHECK-ALIGN-NEXT: str r1, [r0]
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_shift8_mask16:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldr r1, [r0]
; CHECK-V6M-NEXT: lsrs r1, r1, #8
; CHECK-V6M-NEXT: uxth r1, r1
; CHECK-V6M-NEXT: str r1, [r0]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %p, align 4
%shl = lshr i32 %0, 8
%and = and i32 %shl, 65535
store i32 %and, ptr %p, align 4
ret void
}
define arm_aapcscc void @test_shift15_mask16(ptr nocapture %p) {
; CHECK-COMMON-LABEL: test_shift15_mask16:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldr r1, [r0]
; CHECK-COMMON-NEXT: ubfx r1, r1, #15, #16
; CHECK-COMMON-NEXT: str r1, [r0]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_shift15_mask16:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldr r1, [r0]
; CHECK-BE-NEXT: ubfx r1, r1, #15, #16
; CHECK-BE-NEXT: str r1, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_shift15_mask16:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldr r1, [r0]
; CHECK-V6M-NEXT: lsrs r1, r1, #15
; CHECK-V6M-NEXT: uxth r1, r1
; CHECK-V6M-NEXT: str r1, [r0]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %p, align 4
%shl = lshr i32 %0, 15
%and = and i32 %shl, 65535
store i32 %and, ptr %p, align 4
ret void
}
define arm_aapcscc void @test_shift16_mask15(ptr nocapture %p) {
; CHECK-COMMON-LABEL: test_shift16_mask15:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldrh r1, [r0, #2]
; CHECK-COMMON-NEXT: bfc r1, #15, #17
; CHECK-COMMON-NEXT: str r1, [r0]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_shift16_mask15:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrh r1, [r0]
; CHECK-BE-NEXT: bfc r1, #15, #17
; CHECK-BE-NEXT: str r1, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_shift16_mask15:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrh r1, [r0, #2]
; CHECK-V6M-NEXT: ldr r2, .LCPI21_0
; CHECK-V6M-NEXT: ands r2, r1
; CHECK-V6M-NEXT: str r2, [r0]
; CHECK-V6M-NEXT: bx lr
; CHECK-V6M-NEXT: .p2align 2
; CHECK-V6M-NEXT: @ %bb.1:
; CHECK-V6M-NEXT: .LCPI21_0:
; CHECK-V6M-NEXT: .long 32767 @ 0x7fff
entry:
%0 = load i32, ptr %p, align 4
%shl = lshr i32 %0, 16
%and = and i32 %shl, 32767
store i32 %and, ptr %p, align 4
ret void
}
define arm_aapcscc void @test_shift8_mask24(ptr nocapture %p) {
; CHECK-ARM-LABEL: test_shift8_mask24:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldr r1, [r0]
; CHECK-ARM-NEXT: lsr r1, r1, #8
; CHECK-ARM-NEXT: str r1, [r0]
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_shift8_mask24:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldr r1, [r0]
; CHECK-BE-NEXT: lsr r1, r1, #8
; CHECK-BE-NEXT: str r1, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_shift8_mask24:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldr r1, [r0]
; CHECK-THUMB-NEXT: lsrs r1, r1, #8
; CHECK-THUMB-NEXT: str r1, [r0]
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_shift8_mask24:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldr r1, [r0]
; CHECK-ALIGN-NEXT: lsrs r1, r1, #8
; CHECK-ALIGN-NEXT: str r1, [r0]
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_shift8_mask24:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldr r1, [r0]
; CHECK-V6M-NEXT: lsrs r1, r1, #8
; CHECK-V6M-NEXT: str r1, [r0]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %p, align 4
%shl = lshr i32 %0, 8
%and = and i32 %shl, 16777215
store i32 %and, ptr %p, align 4
ret void
}
define arm_aapcscc void @test_shift24_mask16(ptr nocapture %p) {
; CHECK-COMMON-LABEL: test_shift24_mask16:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldrb r1, [r0, #3]
; CHECK-COMMON-NEXT: str r1, [r0]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_shift24_mask16:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrb r1, [r0]
; CHECK-BE-NEXT: str r1, [r0]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_shift24_mask16:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrb r1, [r0, #3]
; CHECK-V6M-NEXT: str r1, [r0]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i32, ptr %p, align 4
%shl = lshr i32 %0, 24
%and = and i32 %shl, 65535
store i32 %and, ptr %p, align 4
ret void
}
define arm_aapcscc void @test_sext_shift8_mask8(ptr %p, ptr %q) {
; CHECK-COMMON-LABEL: test_sext_shift8_mask8:
; CHECK-COMMON: @ %bb.0: @ %entry
; CHECK-COMMON-NEXT: ldrb r0, [r0, #1]
; CHECK-COMMON-NEXT: str r0, [r1]
; CHECK-COMMON-NEXT: bx lr
;
; CHECK-BE-LABEL: test_sext_shift8_mask8:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrb r0, [r0]
; CHECK-BE-NEXT: str r0, [r1]
; CHECK-BE-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_sext_shift8_mask8:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrb r0, [r0, #1]
; CHECK-V6M-NEXT: str r0, [r1]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i16, ptr %p, align 4
%1 = sext i16 %0 to i32
%shl = lshr i32 %1, 8
%and = and i32 %shl, 255
store i32 %and, ptr %q, align 4
ret void
}
define arm_aapcscc void @test_sext_shift8_mask16(ptr %p, ptr %q) {
; CHECK-ARM-LABEL: test_sext_shift8_mask16:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldrsh r0, [r0]
; CHECK-ARM-NEXT: ubfx r0, r0, #8, #16
; CHECK-ARM-NEXT: str r0, [r1]
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_sext_shift8_mask16:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrsh r0, [r0]
; CHECK-BE-NEXT: ubfx r0, r0, #8, #16
; CHECK-BE-NEXT: str r0, [r1]
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_sext_shift8_mask16:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldrsh.w r0, [r0]
; CHECK-THUMB-NEXT: ubfx r0, r0, #8, #16
; CHECK-THUMB-NEXT: str r0, [r1]
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_sext_shift8_mask16:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldrsh.w r0, [r0]
; CHECK-ALIGN-NEXT: ubfx r0, r0, #8, #16
; CHECK-ALIGN-NEXT: str r0, [r1]
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_sext_shift8_mask16:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: movs r2, #0
; CHECK-V6M-NEXT: ldrsh r0, [r0, r2]
; CHECK-V6M-NEXT: lsrs r0, r0, #8
; CHECK-V6M-NEXT: uxth r0, r0
; CHECK-V6M-NEXT: str r0, [r1]
; CHECK-V6M-NEXT: bx lr
entry:
%0 = load i16, ptr %p, align 4
%1 = sext i16 %0 to i32
%shl = lshr i32 %1, 8
%and = and i32 %shl, 65535
store i32 %and, ptr %q, align 4
ret void
}
define i1 @trunc_i64_mask_srl(i32 zeroext %AttrArgNo, ptr %ptr) {
; CHECK-ARM-LABEL: trunc_i64_mask_srl:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldrh r2, [r1, #4]
; CHECK-ARM-NEXT: mov r1, #0
; CHECK-ARM-NEXT: cmp r2, r0
; CHECK-ARM-NEXT: movwhi r1, #1
; CHECK-ARM-NEXT: mov r0, r1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: trunc_i64_mask_srl:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrh r2, [r1, #2]
; CHECK-BE-NEXT: mov r1, #0
; CHECK-BE-NEXT: cmp r2, r0
; CHECK-BE-NEXT: movwhi r1, #1
; CHECK-BE-NEXT: mov r0, r1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: trunc_i64_mask_srl:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldrh r2, [r1, #4]
; CHECK-THUMB-NEXT: movs r1, #0
; CHECK-THUMB-NEXT: cmp r2, r0
; CHECK-THUMB-NEXT: it hi
; CHECK-THUMB-NEXT: movhi r1, #1
; CHECK-THUMB-NEXT: mov r0, r1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: trunc_i64_mask_srl:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldrh r2, [r1, #4]
; CHECK-ALIGN-NEXT: movs r1, #0
; CHECK-ALIGN-NEXT: cmp r2, r0
; CHECK-ALIGN-NEXT: it hi
; CHECK-ALIGN-NEXT: movhi r1, #1
; CHECK-ALIGN-NEXT: mov r0, r1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: trunc_i64_mask_srl:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrh r1, [r1, #4]
; CHECK-V6M-NEXT: cmp r1, r0
; CHECK-V6M-NEXT: bhi .LBB26_2
; CHECK-V6M-NEXT: @ %bb.1: @ %entry
; CHECK-V6M-NEXT: movs r0, #0
; CHECK-V6M-NEXT: bx lr
; CHECK-V6M-NEXT: .LBB26_2:
; CHECK-V6M-NEXT: movs r0, #1
; CHECK-V6M-NEXT: bx lr
entry:
%bf.load.i = load i64, ptr %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
}
define i64 @or_tree_with_shifts_i64(i64 %a, i64 %b, i64 %c, i64 %d) {
; CHECK-ARM-LABEL: or_tree_with_shifts_i64:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: .save {r11, lr}
; CHECK-ARM-NEXT: push {r11, lr}
; CHECK-ARM-NEXT: ldr lr, [sp, #16]
; CHECK-ARM-NEXT: orr r0, r0, r2, lsl #16
; CHECK-ARM-NEXT: ldr r12, [sp, #8]
; CHECK-ARM-NEXT: orr r3, lr, r3
; CHECK-ARM-NEXT: orr r1, r1, r3, lsl #16
; CHECK-ARM-NEXT: orr r1, r1, r2, lsr #16
; CHECK-ARM-NEXT: orr r1, r1, r12
; CHECK-ARM-NEXT: pop {r11, pc}
;
; CHECK-BE-LABEL: or_tree_with_shifts_i64:
; CHECK-BE: @ %bb.0:
; CHECK-BE-NEXT: .save {r11, lr}
; CHECK-BE-NEXT: push {r11, lr}
; CHECK-BE-NEXT: ldr lr, [sp, #20]
; CHECK-BE-NEXT: orr r1, r1, r3, lsl #16
; CHECK-BE-NEXT: ldr r12, [sp, #12]
; CHECK-BE-NEXT: orr r2, lr, r2
; CHECK-BE-NEXT: orr r0, r0, r2, lsl #16
; CHECK-BE-NEXT: orr r0, r0, r3, lsr #16
; CHECK-BE-NEXT: orr r0, r0, r12
; CHECK-BE-NEXT: pop {r11, pc}
;
; CHECK-ALIGN-LABEL: or_tree_with_shifts_i64:
; CHECK-ALIGN: @ %bb.0:
; CHECK-ALIGN-NEXT: ldr.w r12, [sp, #8]
; CHECK-ALIGN-NEXT: orr.w r0, r0, r2, lsl #16
; CHECK-ALIGN-NEXT: orr.w r3, r3, r12
; CHECK-ALIGN-NEXT: orr.w r1, r1, r3, lsl #16
; CHECK-ALIGN-NEXT: orr.w r1, r1, r2, lsr #16
; CHECK-ALIGN-NEXT: ldr r2, [sp]
; CHECK-ALIGN-NEXT: orrs r1, r2
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: or_tree_with_shifts_i64:
; CHECK-V6M: @ %bb.0:
; CHECK-V6M-NEXT: push {r4, lr}
; CHECK-V6M-NEXT: lsls r4, r2, #16
; CHECK-V6M-NEXT: orrs r0, r4
; CHECK-V6M-NEXT: ldr r4, [sp, #16]
; CHECK-V6M-NEXT: orrs r4, r3
; CHECK-V6M-NEXT: lsls r3, r4, #16
; CHECK-V6M-NEXT: orrs r1, r3
; CHECK-V6M-NEXT: lsrs r2, r2, #16
; CHECK-V6M-NEXT: orrs r1, r2
; CHECK-V6M-NEXT: ldr r2, [sp, #8]
; CHECK-V6M-NEXT: orrs r1, r2
; CHECK-V6M-NEXT: pop {r4, pc}
%b.shifted = shl i64 %b, 16
%c.shifted = shl i64 %c, 32
%d.shifted = shl i64 %d, 48
%or.ad = or i64 %a, %d.shifted
%or.adb = or i64 %or.ad, %b.shifted
%or.adbc = or i64 %or.adb, %c.shifted
ret i64 %or.adbc
}
define i32 @or_tree_with_shifts_i32(i32 %a, i32 %b, i32 %c, i32 %d) {
; CHECK-ARM-LABEL: or_tree_with_shifts_i32:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: orr r0, r0, r2
; CHECK-ARM-NEXT: orr r0, r1, r0, lsl #16
; CHECK-ARM-NEXT: orr r0, r0, r3
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: or_tree_with_shifts_i32:
; CHECK-BE: @ %bb.0:
; CHECK-BE-NEXT: orr r0, r0, r2
; CHECK-BE-NEXT: orr r0, r1, r0, lsl #16
; CHECK-BE-NEXT: orr r0, r0, r3
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: or_tree_with_shifts_i32:
; CHECK-THUMB: @ %bb.0:
; CHECK-THUMB-NEXT: orrs r0, r2
; CHECK-THUMB-NEXT: orr.w r0, r1, r0, lsl #16
; CHECK-THUMB-NEXT: orrs r0, r3
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: or_tree_with_shifts_i32:
; CHECK-ALIGN: @ %bb.0:
; CHECK-ALIGN-NEXT: orrs r0, r2
; CHECK-ALIGN-NEXT: orr.w r0, r1, r0, lsl #16
; CHECK-ALIGN-NEXT: orrs r0, r3
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: or_tree_with_shifts_i32:
; CHECK-V6M: @ %bb.0:
; CHECK-V6M-NEXT: orrs r0, r2
; CHECK-V6M-NEXT: lsls r0, r0, #16
; CHECK-V6M-NEXT: orrs r0, r1
; CHECK-V6M-NEXT: orrs r0, r3
; CHECK-V6M-NEXT: bx lr
%a.shifted = shl i32 %a, 16
%c.shifted = shl i32 %c, 16
%or.ab = or i32 %a.shifted, %b
%or.cd = or i32 %c.shifted, %d
%r = or i32 %or.ab, %or.cd
ret i32 %r
}
define i32 @xor_tree_with_shifts_i32(i32 %a, i32 %b, i32 %c, i32 %d) {
; CHECK-ARM-LABEL: xor_tree_with_shifts_i32:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: eor r0, r0, r2
; CHECK-ARM-NEXT: eor r0, r1, r0, lsr #16
; CHECK-ARM-NEXT: eor r0, r0, r3
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: xor_tree_with_shifts_i32:
; CHECK-BE: @ %bb.0:
; CHECK-BE-NEXT: eor r0, r0, r2
; CHECK-BE-NEXT: eor r0, r1, r0, lsr #16
; CHECK-BE-NEXT: eor r0, r0, r3
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: xor_tree_with_shifts_i32:
; CHECK-THUMB: @ %bb.0:
; CHECK-THUMB-NEXT: eors r0, r2
; CHECK-THUMB-NEXT: eor.w r0, r1, r0, lsr #16
; CHECK-THUMB-NEXT: eors r0, r3
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: xor_tree_with_shifts_i32:
; CHECK-ALIGN: @ %bb.0:
; CHECK-ALIGN-NEXT: eors r0, r2
; CHECK-ALIGN-NEXT: eor.w r0, r1, r0, lsr #16
; CHECK-ALIGN-NEXT: eors r0, r3
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: xor_tree_with_shifts_i32:
; CHECK-V6M: @ %bb.0:
; CHECK-V6M-NEXT: eors r0, r2
; CHECK-V6M-NEXT: lsrs r0, r0, #16
; CHECK-V6M-NEXT: eors r0, r1
; CHECK-V6M-NEXT: eors r0, r3
; CHECK-V6M-NEXT: bx lr
%a.shifted = lshr i32 %a, 16
%c.shifted = lshr i32 %c, 16
%xor.ab = xor i32 %a.shifted, %b
%xor.cd = xor i32 %d, %c.shifted
%r = xor i32 %xor.ab, %xor.cd
ret i32 %r
}
define i32 @and_tree_with_shifts_i32(i32 %a, i32 %b, i32 %c, i32 %d) {
; CHECK-ARM-LABEL: and_tree_with_shifts_i32:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: and r0, r0, r2
; CHECK-ARM-NEXT: and r0, r1, r0, asr #16
; CHECK-ARM-NEXT: and r0, r0, r3
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: and_tree_with_shifts_i32:
; CHECK-BE: @ %bb.0:
; CHECK-BE-NEXT: and r0, r0, r2
; CHECK-BE-NEXT: and r0, r1, r0, asr #16
; CHECK-BE-NEXT: and r0, r0, r3
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: and_tree_with_shifts_i32:
; CHECK-THUMB: @ %bb.0:
; CHECK-THUMB-NEXT: ands r0, r2
; CHECK-THUMB-NEXT: and.w r0, r1, r0, asr #16
; CHECK-THUMB-NEXT: ands r0, r3
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: and_tree_with_shifts_i32:
; CHECK-ALIGN: @ %bb.0:
; CHECK-ALIGN-NEXT: ands r0, r2
; CHECK-ALIGN-NEXT: and.w r0, r1, r0, asr #16
; CHECK-ALIGN-NEXT: ands r0, r3
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: and_tree_with_shifts_i32:
; CHECK-V6M: @ %bb.0:
; CHECK-V6M-NEXT: ands r0, r2
; CHECK-V6M-NEXT: asrs r0, r0, #16
; CHECK-V6M-NEXT: ands r0, r1
; CHECK-V6M-NEXT: ands r0, r3
; CHECK-V6M-NEXT: bx lr
%a.shifted = ashr i32 %a, 16
%c.shifted = ashr i32 %c, 16
%and.ab = and i32 %b, %a.shifted
%and.cd = and i32 %c.shifted, %d
%r = and i32 %and.ab, %and.cd
ret i32 %r
}
define i32 @logic_tree_with_shifts_var_i32(i32 %a, i32 %b, i32 %c, i32 %d, i32 %s) {
; CHECK-ARM-LABEL: logic_tree_with_shifts_var_i32:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: ldr r12, [sp]
; CHECK-ARM-NEXT: orr r0, r0, r2
; CHECK-ARM-NEXT: orr r0, r1, r0, lsl r12
; CHECK-ARM-NEXT: orr r0, r0, r3
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: logic_tree_with_shifts_var_i32:
; CHECK-BE: @ %bb.0:
; CHECK-BE-NEXT: ldr r12, [sp]
; CHECK-BE-NEXT: orr r0, r0, r2
; CHECK-BE-NEXT: orr r0, r1, r0, lsl r12
; CHECK-BE-NEXT: orr r0, r0, r3
; CHECK-BE-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: logic_tree_with_shifts_var_i32:
; CHECK-ALIGN: @ %bb.0:
; CHECK-ALIGN-NEXT: orrs r0, r2
; CHECK-ALIGN-NEXT: ldr r2, [sp]
; CHECK-ALIGN-NEXT: lsls r0, r2
; CHECK-ALIGN-NEXT: orrs r0, r1
; CHECK-ALIGN-NEXT: orrs r0, r3
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: logic_tree_with_shifts_var_i32:
; CHECK-V6M: @ %bb.0:
; CHECK-V6M-NEXT: orrs r0, r2
; CHECK-V6M-NEXT: ldr r2, [sp]
; CHECK-V6M-NEXT: lsls r0, r2
; CHECK-V6M-NEXT: orrs r0, r1
; CHECK-V6M-NEXT: orrs r0, r3
; CHECK-V6M-NEXT: bx lr
%a.shifted = shl i32 %a, %s
%c.shifted = shl i32 %c, %s
%or.ab = or i32 %b, %a.shifted
%or.cd = or i32 %d, %c.shifted
%r = or i32 %or.ab, %or.cd
ret i32 %r
}
define i32 @logic_tree_with_mismatching_shifts_i32(i32 %a, i32 %b, i32 %c, i32 %d) {
; CHECK-ARM-LABEL: logic_tree_with_mismatching_shifts_i32:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: orr r2, r3, r2, lsl #16
; CHECK-ARM-NEXT: orr r0, r1, r0, lsl #15
; CHECK-ARM-NEXT: orr r0, r0, r2
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: logic_tree_with_mismatching_shifts_i32:
; CHECK-BE: @ %bb.0:
; CHECK-BE-NEXT: orr r2, r3, r2, lsl #16
; CHECK-BE-NEXT: orr r0, r1, r0, lsl #15
; CHECK-BE-NEXT: orr r0, r0, r2
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: logic_tree_with_mismatching_shifts_i32:
; CHECK-THUMB: @ %bb.0:
; CHECK-THUMB-NEXT: orr.w r2, r3, r2, lsl #16
; CHECK-THUMB-NEXT: orr.w r0, r1, r0, lsl #15
; CHECK-THUMB-NEXT: orrs r0, r2
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: logic_tree_with_mismatching_shifts_i32:
; CHECK-ALIGN: @ %bb.0:
; CHECK-ALIGN-NEXT: orr.w r2, r3, r2, lsl #16
; CHECK-ALIGN-NEXT: orr.w r0, r1, r0, lsl #15
; CHECK-ALIGN-NEXT: orrs r0, r2
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: logic_tree_with_mismatching_shifts_i32:
; CHECK-V6M: @ %bb.0:
; CHECK-V6M-NEXT: lsls r2, r2, #16
; CHECK-V6M-NEXT: orrs r2, r3
; CHECK-V6M-NEXT: lsls r0, r0, #15
; CHECK-V6M-NEXT: orrs r0, r1
; CHECK-V6M-NEXT: orrs r0, r2
; CHECK-V6M-NEXT: bx lr
%a.shifted = shl i32 %a, 15
%c.shifted = shl i32 %c, 16
%or.ab = or i32 %a.shifted, %b
%or.cd = or i32 %c.shifted, %d
%r = or i32 %or.ab, %or.cd
ret i32 %r
}
define i32 @logic_tree_with_mismatching_shifts2_i32(i32 %a, i32 %b, i32 %c, i32 %d) {
; CHECK-ARM-LABEL: logic_tree_with_mismatching_shifts2_i32:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: orr r2, r3, r2, lsr #16
; CHECK-ARM-NEXT: orr r0, r1, r0, lsl #16
; CHECK-ARM-NEXT: orr r0, r0, r2
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: logic_tree_with_mismatching_shifts2_i32:
; CHECK-BE: @ %bb.0:
; CHECK-BE-NEXT: orr r2, r3, r2, lsr #16
; CHECK-BE-NEXT: orr r0, r1, r0, lsl #16
; CHECK-BE-NEXT: orr r0, r0, r2
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: logic_tree_with_mismatching_shifts2_i32:
; CHECK-THUMB: @ %bb.0:
; CHECK-THUMB-NEXT: orr.w r2, r3, r2, lsr #16
; CHECK-THUMB-NEXT: orr.w r0, r1, r0, lsl #16
; CHECK-THUMB-NEXT: orrs r0, r2
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: logic_tree_with_mismatching_shifts2_i32:
; CHECK-ALIGN: @ %bb.0:
; CHECK-ALIGN-NEXT: orr.w r2, r3, r2, lsr #16
; CHECK-ALIGN-NEXT: orr.w r0, r1, r0, lsl #16
; CHECK-ALIGN-NEXT: orrs r0, r2
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: logic_tree_with_mismatching_shifts2_i32:
; CHECK-V6M: @ %bb.0:
; CHECK-V6M-NEXT: lsrs r2, r2, #16
; CHECK-V6M-NEXT: orrs r2, r3
; CHECK-V6M-NEXT: lsls r0, r0, #16
; CHECK-V6M-NEXT: orrs r0, r1
; CHECK-V6M-NEXT: orrs r0, r2
; CHECK-V6M-NEXT: bx lr
%a.shifted = shl i32 %a, 16
%c.shifted = lshr i32 %c, 16
%or.ab = or i32 %a.shifted, %b
%or.cd = or i32 %c.shifted, %d
%r = or i32 %or.ab, %or.cd
ret i32 %r
}
define <4 x i32> @or_tree_with_shifts_vec_i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c, <4 x i32> %d) {
; CHECK-ARM-LABEL: or_tree_with_shifts_vec_i32:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: vorr q8, q0, q2
; CHECK-ARM-NEXT: vshl.i32 q8, q8, #16
; CHECK-ARM-NEXT: vorr q8, q8, q1
; CHECK-ARM-NEXT: vorr q0, q8, q3
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: or_tree_with_shifts_vec_i32:
; CHECK-BE: @ %bb.0:
; CHECK-BE-NEXT: vrev64.32 q8, q2
; CHECK-BE-NEXT: vrev64.32 q9, q0
; CHECK-BE-NEXT: vorr q8, q9, q8
; CHECK-BE-NEXT: vrev64.32 q9, q1
; CHECK-BE-NEXT: vrev64.32 q10, q3
; CHECK-BE-NEXT: vshl.i32 q8, q8, #16
; CHECK-BE-NEXT: vorr q8, q8, q9
; CHECK-BE-NEXT: vorr q8, q8, q10
; CHECK-BE-NEXT: vrev64.32 q0, q8
; CHECK-BE-NEXT: bx lr
%a.shifted = shl <4 x i32> %a, <i32 16, i32 16, i32 16, i32 16>
%c.shifted = shl <4 x i32> %c, <i32 16, i32 16, i32 16, i32 16>
%or.ab = or <4 x i32> %a.shifted, %b
%or.cd = or <4 x i32> %c.shifted, %d
%r = or <4 x i32> %or.ab, %or.cd
ret <4 x i32> %r
}
define <4 x i32> @or_tree_with_mismatching_shifts_vec_i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c, <4 x i32> %d) {
; CHECK-ARM-LABEL: or_tree_with_mismatching_shifts_vec_i32:
; CHECK-ARM: @ %bb.0:
; CHECK-ARM-NEXT: vshl.i32 q8, q2, #17
; CHECK-ARM-NEXT: vshl.i32 q9, q0, #16
; CHECK-ARM-NEXT: vorr q8, q8, q3
; CHECK-ARM-NEXT: vorr q9, q9, q1
; CHECK-ARM-NEXT: vorr q0, q9, q8
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: or_tree_with_mismatching_shifts_vec_i32:
; CHECK-BE: @ %bb.0:
; CHECK-BE-NEXT: vrev64.32 q8, q2
; CHECK-BE-NEXT: vrev64.32 q9, q0
; CHECK-BE-NEXT: vshl.i32 q8, q8, #17
; CHECK-BE-NEXT: vrev64.32 q10, q3
; CHECK-BE-NEXT: vshl.i32 q9, q9, #16
; CHECK-BE-NEXT: vrev64.32 q11, q1
; CHECK-BE-NEXT: vorr q8, q8, q10
; CHECK-BE-NEXT: vorr q9, q9, q11
; CHECK-BE-NEXT: vorr q8, q9, q8
; CHECK-BE-NEXT: vrev64.32 q0, q8
; CHECK-BE-NEXT: bx lr
%a.shifted = shl <4 x i32> %a, <i32 16, i32 16, i32 16, i32 16>
%c.shifted = shl <4 x i32> %c, <i32 17, i32 17, i32 17, i32 17>
%or.ab = or <4 x i32> %a.shifted, %b
%or.cd = or <4 x i32> %c.shifted, %d
%r = or <4 x i32> %or.ab, %or.cd
ret <4 x i32> %r
}
define arm_aapcscc i32 @test_shift15_and510(ptr nocapture %p) {
; CHECK-ARM-LABEL: test_shift15_and510:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldrb r0, [r0, #2]
; CHECK-ARM-NEXT: lsl r0, r0, #1
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_shift15_and510:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrb r0, [r0, #1]
; CHECK-BE-NEXT: lsl r0, r0, #1
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_shift15_and510:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldrb r0, [r0, #2]
; CHECK-THUMB-NEXT: lsls r0, r0, #1
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_shift15_and510:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldrb r0, [r0, #2]
; CHECK-ALIGN-NEXT: lsls r0, r0, #1
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_shift15_and510:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrb r0, [r0, #2]
; CHECK-V6M-NEXT: lsls r0, r0, #1
; CHECK-V6M-NEXT: bx lr
entry:
%load = load i32, ptr %p, align 4
%lshr = lshr i32 %load, 15
%and = and i32 %lshr, 510
ret i32 %and
}
define arm_aapcscc i32 @test_shift22_and1020(ptr nocapture %p) {
; CHECK-ARM-LABEL: test_shift22_and1020:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldrb r0, [r0, #3]
; CHECK-ARM-NEXT: lsl r0, r0, #2
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_shift22_and1020:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrb r0, [r0]
; CHECK-BE-NEXT: lsl r0, r0, #2
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_shift22_and1020:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldrb r0, [r0, #3]
; CHECK-THUMB-NEXT: lsls r0, r0, #2
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_shift22_and1020:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldrb r0, [r0, #3]
; CHECK-ALIGN-NEXT: lsls r0, r0, #2
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_shift22_and1020:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrb r0, [r0, #3]
; CHECK-V6M-NEXT: lsls r0, r0, #2
; CHECK-V6M-NEXT: bx lr
entry:
%load = load i32, ptr %p, align 4
%lshr = lshr i32 %load, 22
%and = and i32 %lshr, 1020
ret i32 %and
}
define arm_aapcscc i32 @test_zext_shift5_and2040(ptr nocapture %p) {
; CHECK-ARM-LABEL: test_zext_shift5_and2040:
; CHECK-ARM: @ %bb.0: @ %entry
; CHECK-ARM-NEXT: ldrb r0, [r0, #1]
; CHECK-ARM-NEXT: lsl r0, r0, #3
; CHECK-ARM-NEXT: bx lr
;
; CHECK-BE-LABEL: test_zext_shift5_and2040:
; CHECK-BE: @ %bb.0: @ %entry
; CHECK-BE-NEXT: ldrb r0, [r0]
; CHECK-BE-NEXT: lsl r0, r0, #3
; CHECK-BE-NEXT: bx lr
;
; CHECK-THUMB-LABEL: test_zext_shift5_and2040:
; CHECK-THUMB: @ %bb.0: @ %entry
; CHECK-THUMB-NEXT: ldrb r0, [r0, #1]
; CHECK-THUMB-NEXT: lsls r0, r0, #3
; CHECK-THUMB-NEXT: bx lr
;
; CHECK-ALIGN-LABEL: test_zext_shift5_and2040:
; CHECK-ALIGN: @ %bb.0: @ %entry
; CHECK-ALIGN-NEXT: ldrb r0, [r0, #1]
; CHECK-ALIGN-NEXT: lsls r0, r0, #3
; CHECK-ALIGN-NEXT: bx lr
;
; CHECK-V6M-LABEL: test_zext_shift5_and2040:
; CHECK-V6M: @ %bb.0: @ %entry
; CHECK-V6M-NEXT: ldrb r0, [r0, #1]
; CHECK-V6M-NEXT: lsls r0, r0, #3
; CHECK-V6M-NEXT: bx lr
entry:
%load = load i16, ptr %p, align 2
%zext = zext i16 %load to i32
%lshr = lshr i32 %zext, 5
%and = and i32 %lshr, 2040
ret i32 %and
}