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