| ; RUN: llc -mtriple=aarch64 -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK --check-prefix=OPT %s | |
| ; RUN: llc -mtriple=aarch64 -verify-machineinstrs -O0 -fast-isel=0 -global-isel=false < %s | FileCheck --check-prefix=CHECK --check-prefix=NOOPT %s | |
| declare void @foo() | |
| ; Check that the inverted or doesn't inhibit the splitting of the | |
| ; complex conditional into three branch instructions. | |
| ; CHECK-LABEL: test_and_not: | |
| ; CHECK: cbz w0, [[L:\.LBB[0-9_]+]] | |
| ; OPT: cmp w1, #2 | |
| ; NOOPT: subs w{{[0-9]+}}, w{{[0-9]+}}, #2 | |
| ; CHECK: b.lo [[L]] | |
| ; OPT: cmp w2, #2 | |
| ; NOOPT: subs w{{[0-9]+}}, w{{[0-9]+}}, #2 | |
| ; CHECK: b.hi [[L]] | |
| define void @test_and_not(i32 %a, i32 %b, i32 %c) { | |
| bb1: | |
| %cmp1 = icmp ult i32 %a, 1 | |
| %cmp2 = icmp ult i32 %b, 2 | |
| %cmp3 = icmp ult i32 %c, 3 | |
| %or = or i1 %cmp1, %cmp2 | |
| %not.or = xor i1 %or, -1 | |
| %and = and i1 %not.or, %cmp3 | |
| br i1 %and, label %bb2, label %bb3 | |
| bb2: | |
| ret void | |
| bb3: | |
| call void @foo() | |
| ret void | |
| } | |
| ; Check that non-canonicalized xor not is handled correctly by FindMergedConditions. | |
| ; CHECK-LABEL: test_and_not2: | |
| ; CHECK: cbz w0, [[L:\.LBB[0-9_]+]] | |
| ; OPT: cmp w1, #2 | |
| ; NOOPT: subs w{{[0-9]+}}, w{{[0-9]+}}, #2 | |
| ; CHECK: b.lo [[L]] | |
| ; OPT: cmp w2, #2 | |
| ; NOOPT: subs w{{[0-9]+}}, w{{[0-9]+}}, #2 | |
| ; CHECK: b.hi [[L]] | |
| define void @test_and_not2(i32 %a, i32 %b, i32 %c) { | |
| bb1: | |
| %cmp1 = icmp ult i32 %a, 1 | |
| %cmp2 = icmp ult i32 %b, 2 | |
| %cmp3 = icmp ult i32 %c, 3 | |
| %or = or i1 %cmp1, %cmp2 | |
| %not.or = xor i1 -1, %or | |
| %and = and i1 %not.or, %cmp3 | |
| br i1 %and, label %bb2, label %bb3 | |
| bb2: | |
| ret void | |
| bb3: | |
| call void @foo() | |
| ret void | |
| } | |
| ; Check that cmps in different blocks are handled correctly by FindMergedConditions. | |
| ; CHECK-LABEL: test_cmp_other_block: | |
| ; OPT: cmp w{{[0-9]+}}, #0 | |
| ; OPT: b.gt [[L:\.LBB[0-9_]+]] | |
| ; OPT: tbz w1, #0, [[L]] | |
| ; | |
| ; NOOPT: subs w{{[0-9]+}}, w{{[0-9]+}}, #0 | |
| ; NOOPT: cset [[R1:w[0-9]+]], gt | |
| ; NOOPT: str w1, [sp, #[[SLOT2:[0-9]+]]] | |
| ; NOOPT: str [[R1]], [sp, #[[SLOT1:[0-9]+]]] | |
| ; NOOPT: b .LBB | |
| ; NOOPT: ldr [[R2:w[0-9]+]], [sp, #[[SLOT1]]] | |
| ; NOOPT: tbnz [[R2]], #0, [[L:\.LBB[0-9_]+]] | |
| ; NOOPT: ldr [[R3:w[0-9]+]], [sp, #[[SLOT2]]] | |
| ; NOOPT: tbz [[R3]], #0, [[L]] | |
| define void @test_cmp_other_block(i32* %p, i1 %c) { | |
| entry: | |
| %l = load i32, i32* %p | |
| %cmp = icmp sgt i32 %l, 0 | |
| br label %bb1 | |
| bb1: | |
| %cmp.i = xor i1 %cmp, true | |
| %or.cond1.i = and i1 %cmp.i, %c | |
| br i1 %or.cond1.i, label %bb2, label %bb3 | |
| bb2: | |
| ret void | |
| bb3: | |
| call void @foo() | |
| ret void | |
| } | |