| ; 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 |
| } |
| |