| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s |
| ; Test implementation of combining br_ccmask for flag output operand, and |
| ; optimizing ipm sequence using conditional branches. |
| |
| declare void @dummy() |
| |
| ; Check a case where the cc is used as an integer. |
| ; Just (srl (ipm)) sequence without optimization. |
| define i32 @test(ptr %a) { |
| ; CHECK-LABEL: test: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: ipm %r2 |
| ; CHECK-NEXT: srl %r2, 28 |
| ; CHECK-NEXT: br %r14 |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| ret i32 %cc |
| } |
| |
| ; Test-1(f1_0_*). Test all 14 valid combinations, where cc is being used for |
| ; branching. |
| |
| ; Check (cc == 0). |
| define void @f1_0_eq_0(ptr %a) { |
| ; CHECK-LABEL: f1_0_eq_0: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jge dummy@PLT |
| ; CHECK-NEXT: .LBB1_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmp = icmp eq i32 %cc, 0 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc != 0). |
| define void @f1_0_ne_0(ptr %a) { |
| ; CHECK-LABEL: f1_0_ne_0: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgne dummy@PLT |
| ; CHECK-NEXT: .LBB2_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmp = icmp ugt i32 %cc, 0 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc == 1). |
| define void @f1_0_eq_1(ptr %a) { |
| ; CHECK-LABEL: f1_0_eq_1: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgl dummy@PLT |
| ; CHECK-NEXT: .LBB3_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmp = icmp eq i32 %cc, 1 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc != 1). |
| define void @f1_0_ne_1(ptr %a) { |
| ; CHECK-LABEL: f1_0_ne_1: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnl dummy@PLT |
| ; CHECK-NEXT: .LBB4_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmp = icmp ne i32 %cc, 1 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc == 2). |
| define void @f1_0_eq_2(ptr %a) { |
| ; CHECK-LABEL: f1_0_eq_2: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgh dummy@PLT |
| ; CHECK-NEXT: .LBB5_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmp = icmp eq i32 %cc, 2 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc != 2). |
| define void @f1_0_ne_2(ptr %a) { |
| ; CHECK-LABEL: f1_0_ne_2: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnh dummy@PLT |
| ; CHECK-NEXT: .LBB6_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmp = icmp ne i32 %cc, 2 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc == 3). |
| define void @f1_0_eq_3(ptr %a) { |
| ; CHECK-LABEL: f1_0_eq_3: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgo dummy@PLT |
| ; CHECK-NEXT: .LBB7_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmp = icmp eq i32 %cc, 3 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc != 3). |
| define void @f1_0_ne_3(ptr %a) { |
| ; CHECK-LABEL: f1_0_ne_3: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgno dummy@PLT |
| ; CHECK-NEXT: .LBB8_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmp = icmp ult i32 %cc, 3 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc == 0|1). |
| define void @f1_0_01(ptr %a) { |
| ; CHECK-LABEL: f1_0_01: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgle dummy@PLT |
| ; CHECK-NEXT: .LBB9_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmp = icmp ult i32 %cc, 2 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc == 0|2). |
| define void @f1_0_02(ptr %a) { |
| ; CHECK-LABEL: f1_0_02: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jghe dummy@PLT |
| ; CHECK-NEXT: .LBB10_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %and = and i32 %cc, 1 |
| %cmp = icmp eq i32 %and, 0 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc == 0|3). |
| define void @f1_0_03(ptr %a) { |
| ; CHECK-LABEL: f1_0_03: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnlh dummy@PLT |
| ; CHECK-NEXT: .LBB11_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmp0 = icmp ne i32 %cc, 0 |
| %cmp3 = icmp ne i32 %cc, 3 |
| %cmp.inv = and i1 %cmp0, %cmp3 |
| br i1 %cmp.inv, label %exit, label %branch |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc == 1|2). |
| define void @f1_0_12(ptr %a) { |
| ; CHECK-LABEL: f1_0_12: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jglh dummy@PLT |
| ; CHECK-NEXT: .LBB12_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmpeq1 = icmp eq i32 %cc, 1 |
| %cmpeq2 = icmp eq i32 %cc, 2 |
| %cmp = or i1 %cmpeq1, %cmpeq2 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc == 1|3). |
| define void @f1_0_13(ptr %a) { |
| ; CHECK-LABEL: f1_0_13: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnhe dummy@PLT |
| ; CHECK-NEXT: .LBB13_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmpeq1 = icmp eq i32 %cc, 1 |
| %cmpeq3 = icmp eq i32 %cc, 3 |
| %cmp = or i1 %cmpeq1, %cmpeq3 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check (cc == 2|3). |
| define void @f1_0_23(ptr %a) { |
| ; CHECK-LABEL: f1_0_23: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnle dummy@PLT |
| ; CHECK-NEXT: .LBB14_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmp = icmp ugt i32 %cc, 1 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Test-2(f1_1_*/f1_2_*/fl_3_*/f1_4_*). |
| ; Test Mixed patterns involving Binary Ops. |
| |
| ; Check 'add' for (cc != 0). |
| define void @f1_1_1(ptr %a) { |
| ; CHECK-LABEL: f1_1_1: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgne dummy@PLT |
| ; CHECK-NEXT: .LBB15_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %add = add nsw i32 %cc, -1 |
| %cmp = icmp ult i32 %add, 3 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check 'add' for (cc == 1|2). |
| define void @f1_1_2(ptr %a) { |
| ; CHECK-LABEL: f1_1_2: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jglh dummy@PLT |
| ; CHECK-NEXT: .LBB16_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %add = add nsw i32 %cc, -1 |
| %cmp = icmp ult i32 %add, 2 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check 'add' for (cc == 1|2). |
| define void @f1_1_3(ptr %a) { |
| ; CHECK-LABEL: f1_1_3: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jglh dummy@PLT |
| ; CHECK-NEXT: .LBB17_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %add = add nsw i32 %cc, -3 |
| %cmp.inv = icmp ult i32 %add, -2 |
| br i1 %cmp.inv, label %exit, label %branch |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check 'and' with one operand cc and other select_ccmask(cc !=1). |
| define void @f1_2_1(ptr %a) { |
| ; CHECK-LABEL: f1_2_1: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnl dummy@PLT |
| ; CHECK-NEXT: .LBB18_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %andcc = and i32 %cc, 1 |
| %cmpne0 = icmp ne i32 %andcc, 0 |
| %cmpne3 = icmp ne i32 %cc, 3 |
| %cmp.inv = and i1 %cmpne3, %cmpne0 |
| br i1 %cmp.inv, label %exit, label %branch |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check 'and' with both operands select_ccmask(cc != 2). |
| define void @f1_2_2(ptr %a) { |
| ; CHECK-LABEL: f1_2_2: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnh dummy@PLT |
| ; CHECK-NEXT: .LBB19_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %ugt1 = icmp samesign ugt i32 %cc, 1 |
| %cmpne3 = icmp ne i32 %cc, 3 |
| %and.cond.inv = and i1 %ugt1, %cmpne3 |
| br i1 %and.cond.inv, label %exit, label %branch |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check 'and/tm' for (cc == 0|2). |
| define void @f1_2_3(ptr %a) { |
| ; CHECK-LABEL: f1_2_3: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jghe dummy@PLT |
| ; CHECK-NEXT: .LBB20_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %and = and i32 %cc, 1 |
| %cmp = icmp eq i32 %and, 0 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check 'and/tm' for (cc == 1|3). |
| define void @f1_2_4(ptr %a) { |
| ; CHECK-LABEL: f1_2_4: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnhe dummy@PLT |
| ; CHECK-NEXT: .LBB21_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %and = and i32 %cc, 1 |
| %cmp = icmp eq i32 %and, 0 |
| br i1 %cmp, label %exit, label %branch |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check 'icmp' with one operand 'and' and other 'select_ccmask'(cc != 1). |
| define void @f1_2_5(ptr %a) { |
| ; CHECK-LABEL: f1_2_5: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnl dummy@PLT |
| ; CHECK-NEXT: .LBB22_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %trunc = trunc i32 %cc to i1 |
| %cmpne3 = icmp ne i32 %cc, 3 |
| %cmp = xor i1 %cmpne3, %trunc |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check nested 'xor' cc with select_ccmask(cc != 1). |
| define void @f1_3_1(ptr %a) { |
| ; CHECK-LABEL: f1_3_1: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnl dummy@PLT |
| ; CHECK-NEXT: .LBB23_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %cmpeq0 = icmp eq i32 %cc, 0 |
| %cmpeq2 = icmp eq i32 %cc, 2 |
| %xor = xor i1 %cmpeq0, %cmpeq2 |
| %cmpne3 = icmp ne i32 %cc, 3 |
| %cmp.inv = xor i1 %cmpne3, %xor |
| br i1 %cmp.inv, label %exit, label %branch |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check branching on 'tm' and 'xor' with one operand cc and the other |
| ; select_ccmask(cc !=1). |
| define void @f1_3_2(ptr %a) { |
| ; CHECK-LABEL: f1_3_2: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnl dummy@PLT |
| ; CHECK-NEXT: .LBB24_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %trunc = trunc i32 %cc to i1 |
| %cmpeq3 = icmp eq i32 %cc, 3 |
| %cmp.inv = xor i1 %cmpeq3, %trunc |
| br i1 %cmp.inv, label %exit, label %branch |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check branching on 'tm' and 'xor' with one operand cc and the other |
| ; select_ccmask(cc !=2). |
| define void @f1_3_3(ptr %a) { |
| ; CHECK-LABEL: f1_3_3: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgnh dummy@PLT |
| ; CHECK-NEXT: .LBB25_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %trunc = trunc i32 %cc to i1 |
| %cmpne0 = icmp ne i32 %cc, 0 |
| %cmp.cond.inv = xor i1 %cmpne0, %trunc |
| br i1 %cmp.cond.inv, label %exit, label %branch |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check 'or' with both operands are select_ccmask one with TM and other with |
| ; ICMP(cc == 1). |
| define void @f1_4_1(ptr %a) { |
| ; CHECK-LABEL: f1_4_1: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgl dummy@PLT |
| ; CHECK-NEXT: .LBB26_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %andcc = and i32 %cc, 1 |
| %cmpeq0 = icmp eq i32 %andcc, 0 |
| %cmpeq3 = icmp eq i32 %cc, 3 |
| %cmp.cond.inv = or i1 %cmpeq3, %cmpeq0 |
| br i1 %cmp.cond.inv, label %exit, label %branch |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check 'or' for (cc == 0|1). |
| define void @f1_4_2(ptr %a) { |
| ; CHECK-LABEL: f1_4_2: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgle dummy@PLT |
| ; CHECK-NEXT: .LBB27_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %or = or disjoint i32 %cc, -4 |
| %cmp.inv = icmp samesign ugt i32 %or, -3 |
| br i1 %cmp.inv, label %exit, label %branch |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Check 'or' for (cc == 0|1). |
| define void @f1_4_3(ptr %a) { |
| ; CHECK-LABEL: f1_4_3: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: alsi 0(%r2), -1 |
| ; CHECK-EMPTY: |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: jgle dummy@PLT |
| ; CHECK-NEXT: .LBB28_1: # %exit |
| ; CHECK-NEXT: br %r14 |
| entry: |
| %cc = tail call i32 asm sideeffect "alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr elementtype(i32) %a, ptr elementtype(i32) %a) |
| %tmp = icmp ult i32 %cc, 4 |
| tail call void @llvm.assume(i1 %tmp) |
| %or = or disjoint i32 %cc, -4 |
| %cmp = icmp samesign ult i32 %or, -2 |
| br i1 %cmp, label %branch, label %exit |
| branch: |
| tail call void @dummy() |
| br label %exit |
| exit: |
| ret void |
| } |
| |
| ; Test INLINEASM defines CC. |
| @wait_fence = global i32 0, align 4 |
| @bit_cc = global i32 0, align 4 |
| define void @test_inlineasm_define_cc() { |
| ; CHECK-LABEL: test_inlineasm_define_cc: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: lgrl %r1, wait_fence@GOT |
| ; CHECK-NEXT: chsi 0(%r1), 0 |
| ; CHECK-NEXT: ber %r14 |
| ; CHECK-NEXT: .LBB29_1: # %while.body.lr.ph |
| ; CHECK-NEXT: lgrl %r1, bit_cc@GOT |
| ; CHECK-NEXT: #APP |
| ; CHECK-NEXT: #NO_APP |
| ; CHECK-NEXT: ipm %r0 |
| ; CHECK-NEXT: srl %r0, 28 |
| ; CHECK-NEXT: st %r0, 0(%r1) |
| ; CHECK-NEXT: .LBB29_2: # %while.body |
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: j .LBB29_2 |
| entry: |
| %0 = load i32, ptr @wait_fence, align 4 |
| %tobool.not = icmp eq i32 %0, 0 |
| br i1 %tobool.not, label %while.end, label %while.body.lr.ph |
| |
| while.body.lr.ph: |
| %1 = tail call i32 asm "", "={@cc}"() |
| %2 = icmp ult i32 %1, 4 |
| tail call void @llvm.assume(i1 %2) |
| store i32 %1, ptr @bit_cc, align 4 |
| br label %while.body |
| |
| while.body: |
| br label %while.body |
| |
| while.end: |
| ret void |
| } |