; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=thumbv7m-eabi %s -o - | FileCheck %s --check-prefix V7M
; RUN: llc -mtriple=armv7a-eabi %s -o - | FileCheck %s --check-prefix V7A
; RUN: llc -mtriple=thumbv7a-eabi %s -o - | FileCheck %s --check-prefix V7A-T
; RUN: llc -mtriple=armv6m-eabi %s -o - | FileCheck %s --check-prefix V6M
target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
; Test sink of `and` instructions to fold in to `tst`, `lsls`, do cmov-bfi combine, etc.
define void @f(i32 %v, ptr noalias %outp) {
; V7M-LABEL: f:
; V7M: @ %bb.0: @ %entry
; V7M-NEXT: movs r2, #0
; V7M-NEXT: str r2, [r1]
; V7M-NEXT: lsls r2, r0, #31
; V7M-NEXT: bne .LBB0_3
; V7M-NEXT: @ %bb.1: @ %if.then
; V7M-NEXT: tst.w r0, #14
; V7M-NEXT: beq .LBB0_6
; V7M-NEXT: @ %bb.2:
; V7M-NEXT: lsls r2, r0, #30
; V7M-NEXT: mov.w r3, #33024
; V7M-NEXT: and.w r2, r3, r2, asr #31
; V7M-NEXT: lsrs r0, r0, #2
; V7M-NEXT: bfi r2, r0, #7, #1
; V7M-NEXT: bfi r2, r0, #14, #1
; V7M-NEXT: b .LBB0_5
; V7M-NEXT: .LBB0_3: @ %if.else
; V7M-NEXT: tst.w r0, #14
; V7M-NEXT: it eq
; V7M-NEXT: bxeq lr
; V7M-NEXT: .LBB0_4:
; V7M-NEXT: lsls r2, r0, #30
; V7M-NEXT: mov.w r3, #8256
; V7M-NEXT: and.w r2, r3, r2, asr #31
; V7M-NEXT: lsrs r0, r0, #2
; V7M-NEXT: bfi r2, r0, #5, #1
; V7M-NEXT: bfi r2, r0, #12, #1
; V7M-NEXT: .LBB0_5: @ %if.end
; V7M-NEXT: str r2, [r1]
; V7M-NEXT: .LBB0_6: @ %exit
; V7M-NEXT: bx lr
;
; V7A-LABEL: f:
; V7A: @ %bb.0: @ %entry
; V7A-NEXT: mov r2, #0
; V7A-NEXT: tst r0, #1
; V7A-NEXT: str r2, [r1]
; V7A-NEXT: bne .LBB0_3
; V7A-NEXT: @ %bb.1: @ %if.then
; V7A-NEXT: tst r0, #14
; V7A-NEXT: beq .LBB0_6
; V7A-NEXT: @ %bb.2:
; V7A-NEXT: lsl r2, r0, #30
; V7A-NEXT: mov r3, #33024
; V7A-NEXT: and r2, r3, r2, asr #31
; V7A-NEXT: lsr r0, r0, #2
; V7A-NEXT: bfi r2, r0, #7, #1
; V7A-NEXT: bfi r2, r0, #14, #1
; V7A-NEXT: b .LBB0_5
; V7A-NEXT: .LBB0_3: @ %if.else
; V7A-NEXT: tst r0, #14
; V7A-NEXT: bxeq lr
; V7A-NEXT: .LBB0_4:
; V7A-NEXT: lsl r2, r0, #30
; V7A-NEXT: mov r3, #8256
; V7A-NEXT: and r2, r3, r2, asr #31
; V7A-NEXT: lsr r0, r0, #2
; V7A-NEXT: bfi r2, r0, #5, #1
; V7A-NEXT: bfi r2, r0, #12, #1
; V7A-NEXT: .LBB0_5: @ %if.end
; V7A-NEXT: str r2, [r1]
; V7A-NEXT: .LBB0_6: @ %exit
; V7A-NEXT: bx lr
;
; V7A-T-LABEL: f:
; V7A-T: @ %bb.0: @ %entry
; V7A-T-NEXT: movs r2, #0
; V7A-T-NEXT: str r2, [r1]
; V7A-T-NEXT: lsls r2, r0, #31
; V7A-T-NEXT: bne .LBB0_3
; V7A-T-NEXT: @ %bb.1: @ %if.then
; V7A-T-NEXT: tst.w r0, #14
; V7A-T-NEXT: beq .LBB0_6
; V7A-T-NEXT: @ %bb.2:
; V7A-T-NEXT: lsls r2, r0, #30
; V7A-T-NEXT: mov.w r3, #33024
; V7A-T-NEXT: and.w r2, r3, r2, asr #31
; V7A-T-NEXT: lsrs r0, r0, #2
; V7A-T-NEXT: bfi r2, r0, #7, #1
; V7A-T-NEXT: bfi r2, r0, #14, #1
; V7A-T-NEXT: b .LBB0_5
; V7A-T-NEXT: .LBB0_3: @ %if.else
; V7A-T-NEXT: tst.w r0, #14
; V7A-T-NEXT: it eq
; V7A-T-NEXT: bxeq lr
; V7A-T-NEXT: .LBB0_4:
; V7A-T-NEXT: lsls r2, r0, #30
; V7A-T-NEXT: mov.w r3, #8256
; V7A-T-NEXT: and.w r2, r3, r2, asr #31
; V7A-T-NEXT: lsrs r0, r0, #2
; V7A-T-NEXT: bfi r2, r0, #5, #1
; V7A-T-NEXT: bfi r2, r0, #12, #1
; V7A-T-NEXT: .LBB0_5: @ %if.end
; V7A-T-NEXT: str r2, [r1]
; V7A-T-NEXT: .LBB0_6: @ %exit
; V7A-T-NEXT: bx lr
;
; V6M-LABEL: f:
; V6M: @ %bb.0: @ %entry
; V6M-NEXT: .save {r4, lr}
; V6M-NEXT: push {r4, lr}
; V6M-NEXT: movs r2, #0
; V6M-NEXT: str r2, [r1]
; V6M-NEXT: movs r3, #14
; V6M-NEXT: ands r3, r0
; V6M-NEXT: movs r4, #4
; V6M-NEXT: ands r4, r0
; V6M-NEXT: movs r2, #2
; V6M-NEXT: ands r2, r0
; V6M-NEXT: lsls r0, r0, #31
; V6M-NEXT: bne .LBB0_5
; V6M-NEXT: @ %bb.1: @ %if.then
; V6M-NEXT: movs r0, #129
; V6M-NEXT: cmp r2, #0
; V6M-NEXT: beq .LBB0_3
; V6M-NEXT: @ %bb.2:
; V6M-NEXT: lsls r2, r0, #8
; V6M-NEXT: .LBB0_3: @ %if.then
; V6M-NEXT: cmp r4, #0
; V6M-NEXT: beq .LBB0_10
; V6M-NEXT: @ %bb.4: @ %if.then
; V6M-NEXT: lsls r0, r0, #7
; V6M-NEXT: b .LBB0_9
; V6M-NEXT: .LBB0_5: @ %if.else
; V6M-NEXT: movs r0, #129
; V6M-NEXT: cmp r2, #0
; V6M-NEXT: beq .LBB0_7
; V6M-NEXT: @ %bb.6:
; V6M-NEXT: lsls r2, r0, #6
; V6M-NEXT: .LBB0_7: @ %if.else
; V6M-NEXT: cmp r4, #0
; V6M-NEXT: beq .LBB0_10
; V6M-NEXT: @ %bb.8: @ %if.else
; V6M-NEXT: lsls r0, r0, #5
; V6M-NEXT: .LBB0_9: @ %if.else
; V6M-NEXT: adds r2, r2, r0
; V6M-NEXT: .LBB0_10: @ %if.else
; V6M-NEXT: cmp r3, #0
; V6M-NEXT: beq .LBB0_12
; V6M-NEXT: @ %bb.11: @ %if.end
; V6M-NEXT: str r2, [r1]
; V6M-NEXT: .LBB0_12: @ %exit
; V6M-NEXT: pop {r4, pc}
entry:
store i32 0, ptr %outp, align 4
%and = and i32 %v, 1
%cmp = icmp eq i32 %and, 0
%and1 = and i32 %v, 2
%tobool.not = icmp eq i32 %and1, 0
%and2 = and i32 %v, 4
%tobool1.not = icmp eq i32 %and2, 0
%and3 = and i32 %v, 14
%tobool2.not = icmp eq i32 %and3, 0
br i1 %cmp, label %if.then, label %if.else
if.then:
%select = select i1 %tobool.not, i32 0, i32 33024
%or = or i32 %select, 16512
%spec.select = select i1 %tobool1.not, i32 %select, i32 %or
br i1 %tobool2.not, label %exit, label %if.end
if.else:
%select1 = select i1 %tobool.not, i32 0, i32 8256
%or1 = or i32 %select1, 4128
%spec.select1 = select i1 %tobool1.not, i32 %select1, i32 %or1
br i1 %tobool2.not, label %exit, label %if.end
if.end:
%spec.select.sink = phi i32 [ %spec.select, %if.then ], [ %spec.select1, %if.else ]
store i32 %spec.select.sink, ptr %outp, align 4
br label %exit
exit:
ret void
}
; Test with a mask that can be encoded with T32 instruction set, but not with A32.
define i32 @f0(i1 %c0, i32 %v, ptr %p) {
; V7M-LABEL: f0:
; V7M: @ %bb.0: @ %E
; V7M-NEXT: lsls r0, r0, #31
; V7M-NEXT: beq .LBB1_2
; V7M-NEXT: @ %bb.1: @ %A
; V7M-NEXT: tst.w r1, #16843009
; V7M-NEXT: itt eq
; V7M-NEXT: moveq r0, #0
; V7M-NEXT: bxeq lr
; V7M-NEXT: b .LBB1_3
; V7M-NEXT: .LBB1_2: @ %B
; V7M-NEXT: movs r0, #1
; V7M-NEXT: tst.w r1, #16843009
; V7M-NEXT: str r0, [r2]
; V7M-NEXT: itt ne
; V7M-NEXT: movne r0, #0
; V7M-NEXT: bxne lr
; V7M-NEXT: .LBB1_3: @ %D
; V7M-NEXT: movs r0, #1
; V7M-NEXT: bx lr
;
; V7A-LABEL: f0:
; V7A: @ %bb.0: @ %E
; V7A-NEXT: movw r3, #257
; V7A-NEXT: tst r0, #1
; V7A-NEXT: movt r3, #257
; V7A-NEXT: and r1, r1, r3
; V7A-NEXT: beq .LBB1_3
; V7A-NEXT: @ %bb.1: @ %A
; V7A-NEXT: cmp r1, #0
; V7A-NEXT: moveq r0, #0
; V7A-NEXT: bxeq lr
; V7A-NEXT: .LBB1_2: @ %D
; V7A-NEXT: mov r0, #1
; V7A-NEXT: bx lr
; V7A-NEXT: .LBB1_3: @ %B
; V7A-NEXT: mov r0, #1
; V7A-NEXT: cmp r1, #0
; V7A-NEXT: str r0, [r2]
; V7A-NEXT: mov r0, #0
; V7A-NEXT: moveq r0, #1
; V7A-NEXT: bx lr
;
; V7A-T-LABEL: f0:
; V7A-T: @ %bb.0: @ %E
; V7A-T-NEXT: lsls r0, r0, #31
; V7A-T-NEXT: beq .LBB1_2
; V7A-T-NEXT: @ %bb.1: @ %A
; V7A-T-NEXT: tst.w r1, #16843009
; V7A-T-NEXT: itt eq
; V7A-T-NEXT: moveq r0, #0
; V7A-T-NEXT: bxeq lr
; V7A-T-NEXT: b .LBB1_3
; V7A-T-NEXT: .LBB1_2: @ %B
; V7A-T-NEXT: movs r0, #1
; V7A-T-NEXT: tst.w r1, #16843009
; V7A-T-NEXT: str r0, [r2]
; V7A-T-NEXT: itt ne
; V7A-T-NEXT: movne r0, #0
; V7A-T-NEXT: bxne lr
; V7A-T-NEXT: .LBB1_3: @ %D
; V7A-T-NEXT: movs r0, #1
; V7A-T-NEXT: bx lr
;
; V6M-LABEL: f0:
; V6M: @ %bb.0: @ %E
; V6M-NEXT: ldr r3, .LCPI1_0
; V6M-NEXT: ands r3, r1
; V6M-NEXT: lsls r0, r0, #31
; V6M-NEXT: beq .LBB1_3
; V6M-NEXT: @ %bb.1: @ %A
; V6M-NEXT: cmp r3, #0
; V6M-NEXT: bne .LBB1_5
; V6M-NEXT: @ %bb.2:
; V6M-NEXT: movs r0, #0
; V6M-NEXT: bx lr
; V6M-NEXT: .LBB1_3: @ %B
; V6M-NEXT: movs r0, #1
; V6M-NEXT: str r0, [r2]
; V6M-NEXT: cmp r3, #0
; V6M-NEXT: beq .LBB1_5
; V6M-NEXT: @ %bb.4:
; V6M-NEXT: movs r0, #0
; V6M-NEXT: bx lr
; V6M-NEXT: .LBB1_5: @ %D
; V6M-NEXT: movs r0, #1
; V6M-NEXT: bx lr
; V6M-NEXT: .p2align 2
; V6M-NEXT: @ %bb.6:
; V6M-NEXT: .LCPI1_0:
; V6M-NEXT: .long 16843009 @ 0x1010101
E:
%a = and i32 %v, 16843009
br i1 %c0, label %A, label %B
A:
%c1 = icmp eq i32 %a, 0
br i1 %c1, label %C, label %D
B:
%c2 = icmp eq i32 %a, 0
store i32 1, ptr %p, align 4
br i1 %c2, label %D, label %C
C:
br label %X
D:
br label %X
X:
%x = phi i32 [0, %C], [1, %D]
ret i32 %x
}
; Test with a mask that can be encoded both with T32 and A32 instruction sets.
define i32 @f1(i1 %c0, i32 %v, ptr %p) {
; V7M-LABEL: f1:
; V7M: @ %bb.0: @ %E
; V7M-NEXT: lsls r0, r0, #31
; V7M-NEXT: beq .LBB2_2
; V7M-NEXT: @ %bb.1: @ %A
; V7M-NEXT: tst.w r1, #100663296
; V7M-NEXT: itt eq
; V7M-NEXT: moveq r0, #0
; V7M-NEXT: bxeq lr
; V7M-NEXT: b .LBB2_3
; V7M-NEXT: .LBB2_2: @ %B
; V7M-NEXT: movs r0, #1
; V7M-NEXT: tst.w r1, #100663296
; V7M-NEXT: str r0, [r2]
; V7M-NEXT: itt ne
; V7M-NEXT: movne r0, #0
; V7M-NEXT: bxne lr
; V7M-NEXT: .LBB2_3: @ %D
; V7M-NEXT: movs r0, #1
; V7M-NEXT: bx lr
;
; V7A-LABEL: f1:
; V7A: @ %bb.0: @ %E
; V7A-NEXT: tst r0, #1
; V7A-NEXT: beq .LBB2_3
; V7A-NEXT: @ %bb.1: @ %A
; V7A-NEXT: tst r1, #100663296
; V7A-NEXT: moveq r0, #0
; V7A-NEXT: bxeq lr
; V7A-NEXT: .LBB2_2: @ %D
; V7A-NEXT: mov r0, #1
; V7A-NEXT: bx lr
; V7A-NEXT: .LBB2_3: @ %B
; V7A-NEXT: mov r0, #1
; V7A-NEXT: tst r1, #100663296
; V7A-NEXT: str r0, [r2]
; V7A-NEXT: mov r0, #0
; V7A-NEXT: moveq r0, #1
; V7A-NEXT: bx lr
;
; V7A-T-LABEL: f1:
; V7A-T: @ %bb.0: @ %E
; V7A-T-NEXT: lsls r0, r0, #31
; V7A-T-NEXT: beq .LBB2_2
; V7A-T-NEXT: @ %bb.1: @ %A
; V7A-T-NEXT: tst.w r1, #100663296
; V7A-T-NEXT: itt eq
; V7A-T-NEXT: moveq r0, #0
; V7A-T-NEXT: bxeq lr
; V7A-T-NEXT: b .LBB2_3
; V7A-T-NEXT: .LBB2_2: @ %B
; V7A-T-NEXT: movs r0, #1
; V7A-T-NEXT: tst.w r1, #100663296
; V7A-T-NEXT: str r0, [r2]
; V7A-T-NEXT: itt ne
; V7A-T-NEXT: movne r0, #0
; V7A-T-NEXT: bxne lr
; V7A-T-NEXT: .LBB2_3: @ %D
; V7A-T-NEXT: movs r0, #1
; V7A-T-NEXT: bx lr
;
; V6M-LABEL: f1:
; V6M: @ %bb.0: @ %E
; V6M-NEXT: movs r3, #3
; V6M-NEXT: lsls r3, r3, #25
; V6M-NEXT: ands r3, r1
; V6M-NEXT: lsls r0, r0, #31
; V6M-NEXT: beq .LBB2_3
; V6M-NEXT: @ %bb.1: @ %A
; V6M-NEXT: cmp r3, #0
; V6M-NEXT: bne .LBB2_5
; V6M-NEXT: @ %bb.2:
; V6M-NEXT: movs r0, #0
; V6M-NEXT: bx lr
; V6M-NEXT: .LBB2_3: @ %B
; V6M-NEXT: movs r0, #1
; V6M-NEXT: str r0, [r2]
; V6M-NEXT: cmp r3, #0
; V6M-NEXT: beq .LBB2_5
; V6M-NEXT: @ %bb.4:
; V6M-NEXT: movs r0, #0
; V6M-NEXT: bx lr
; V6M-NEXT: .LBB2_5: @ %D
; V6M-NEXT: movs r0, #1
; V6M-NEXT: bx lr
E:
%a = and i32 %v, 100663296
br i1 %c0, label %A, label %B
A:
%c1 = icmp eq i32 %a, 0
br i1 %c1, label %C, label %D
B:
%c2 = icmp eq i32 %a, 0
store i32 1, ptr %p, align 4
br i1 %c2, label %D, label %C
C:
br label %X
D:
br label %X
X:
%x = phi i32 [0, %C], [1, %D]
ret i32 %x
}