blob: a86420ef6ffa6b8f5ee75b71a273bfaf4361587b [file] [log] [blame] [edit]
; 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
}