; 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) { ; 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: tst.w r1, #16843009 ; 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 r2, #257 ; V7A-NEXT: tst r0, #1 ; V7A-NEXT: movt r2, #257 ; V7A-NEXT: and r1, r1, r2 ; 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, #0 ; V7A-NEXT: cmp r1, #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: tst.w r1, #16843009 ; 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 r2, .LCPI1_0 ; V6M-NEXT: ands r2, r1 ; V6M-NEXT: lsls r0, r0, #31 ; V6M-NEXT: beq .LBB1_3 ; V6M-NEXT: @ %bb.1: @ %A ; V6M-NEXT: cmp r2, #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: cmp r2, #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 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) { ; 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: tst.w r1, #100663296 ; 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, #0 ; V7A-NEXT: tst r1, #100663296 ; 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: tst.w r1, #100663296 ; 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 r2, #3 ; V6M-NEXT: lsls r2, r2, #25 ; V6M-NEXT: ands r2, r1 ; V6M-NEXT: lsls r0, r0, #31 ; V6M-NEXT: beq .LBB2_3 ; V6M-NEXT: @ %bb.1: @ %A ; V6M-NEXT: cmp r2, #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: cmp r2, #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 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 }