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