[clang] [llvm] Add support for flag output operand "=@cc" for SystemZ. (PR #125970)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 21 16:03:09 PDT 2025
https://github.com/anoopkg6 updated https://github.com/llvm/llvm-project/pull/125970
>From 8a07b3dd922c11e27d922c0db7b08be449167c09 Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoop.kumar6 at ibm.com>
Date: Wed, 5 Feb 2025 23:57:13 +0100
Subject: [PATCH 1/8] Add support for flag output operand "=@cc" for SystemZ
and optimizing conditional branch for 14 possible combinations of CC mask.
---
clang/lib/Basic/Targets/SystemZ.cpp | 11 +
clang/lib/Basic/Targets/SystemZ.h | 5 +
clang/lib/CodeGen/CGStmt.cpp | 10 +-
.../CodeGen/inline-asm-systemz-flag-output.c | 149 +
llvm/include/llvm/CodeGen/TargetLowering.h | 3 +
.../SelectionDAG/SelectionDAGBuilder.cpp | 70 +-
.../CodeGen/SelectionDAG/TargetLowering.cpp | 4 +
.../Target/SystemZ/SystemZISelLowering.cpp | 600 +-
llvm/lib/Target/SystemZ/SystemZISelLowering.h | 14 +
.../SystemZ/flag_output_operand_ccand.ll | 500 ++
.../flag_output_operand_ccand_eq_noteq.ll | 939 +++
.../SystemZ/flag_output_operand_ccand_not.ll | 779 +++
.../SystemZ/flag_output_operand_ccmixed.ll | 2427 ++++++++
.../flag_output_operand_ccmixed_eq_noteq.ll | 5248 +++++++++++++++++
.../flag_output_operand_ccmixed_not.ll | 2543 ++++++++
.../SystemZ/flag_output_operand_ccor.ll | 1047 ++++
.../flag_output_operand_ccor_eq_noteq.ll | 854 +++
.../SystemZ/flag_output_operand_ccor_not.ll | 806 +++
.../SystemZ/flag_output_operand_ccxor.ll | 784 +++
.../flag_output_operand_ccxor_eq_noteq.ll | 1083 ++++
.../SystemZ/flag_output_operand_ccxor_not.ll | 778 +++
21 files changed, 18641 insertions(+), 13 deletions(-)
create mode 100644 clang/test/CodeGen/inline-asm-systemz-flag-output.c
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccand.ll
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_eq_noteq.ll
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_not.ll
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed.ll
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_eq_noteq.ll
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_not.ll
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccor.ll
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccor_eq_noteq.ll
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccor_not.ll
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor.ll
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_eq_noteq.ll
create mode 100644 llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_not.ll
diff --git a/clang/lib/Basic/Targets/SystemZ.cpp b/clang/lib/Basic/Targets/SystemZ.cpp
index 06f08db2eadd4..49f88b45220d0 100644
--- a/clang/lib/Basic/Targets/SystemZ.cpp
+++ b/clang/lib/Basic/Targets/SystemZ.cpp
@@ -90,6 +90,14 @@ bool SystemZTargetInfo::validateAsmConstraint(
case 'T': // Likewise, plus an index
Info.setAllowsMemory();
return true;
+ case '@':
+ // CC condition changes.
+ if (strlen(Name) >= 3 && *(Name + 1) == 'c' && *(Name + 2) == 'c') {
+ Name += 2;
+ Info.setAllowsRegister();
+ return true;
+ }
+ return false;
}
}
@@ -150,6 +158,9 @@ unsigned SystemZTargetInfo::getMinGlobalAlign(uint64_t Size,
void SystemZTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
+ // Inline assembly supports SystemZ flag outputs.
+ Builder.defineMacro("__GCC_ASM_FLAG_OUTPUTS__");
+
Builder.defineMacro("__s390__");
Builder.defineMacro("__s390x__");
Builder.defineMacro("__zarch__");
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index ef9a07033a6e4..a6909ababdec0 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -118,6 +118,11 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
TargetInfo::ConstraintInfo &info) const override;
std::string convertConstraint(const char *&Constraint) const override {
+ if (strncmp(Constraint, "@cc", 3) == 0) {
+ std::string Converted = "{" + std::string(Constraint, 3) + "}";
+ Constraint += 3;
+ return Converted;
+ }
switch (Constraint[0]) {
case 'p': // Keep 'p' constraint.
return std::string("p");
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 41dc91c578c80..27f7bb6528958 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2563,9 +2563,15 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
// Target must guarantee the Value `Tmp` here is lowered to a boolean
// value.
- llvm::Constant *Two = llvm::ConstantInt::get(Tmp->getType(), 2);
+ unsigned CCUpperBound = 2;
+ if (CGF.getTarget().getTriple().getArch() == llvm::Triple::systemz) {
+ // On this target CC value can be in range [0, 3].
+ CCUpperBound = 4;
+ }
+ llvm::Constant *CCUpperBoundConst =
+ llvm::ConstantInt::get(Tmp->getType(), CCUpperBound);
llvm::Value *IsBooleanValue =
- Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, Two);
+ Builder.CreateCmp(llvm::CmpInst::ICMP_ULT, Tmp, CCUpperBoundConst);
llvm::Function *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume);
Builder.CreateCall(FnAssume, IsBooleanValue);
}
diff --git a/clang/test/CodeGen/inline-asm-systemz-flag-output.c b/clang/test/CodeGen/inline-asm-systemz-flag-output.c
new file mode 100644
index 0000000000000..ab90e031df1f2
--- /dev/null
+++ b/clang/test/CodeGen/inline-asm-systemz-flag-output.c
@@ -0,0 +1,149 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple s390x-linux -emit-llvm -o - %s | FileCheck %s
+// CHECK-LABEL: define dso_local signext i32 @foo_012(
+// CHECK-SAME: i32 noundef signext [[X:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*]]:
+// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[CC:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 [[TMP0]]) #[[ATTR2:[0-9]+]], !srcloc [[META2:![0-9]+]]
+// CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT: [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT: store i32 [[ASMRESULT]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[ASMRESULT1]], 4
+// CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
+// CHECK-NEXT: store i32 [[ASMRESULT1]], ptr [[CC]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 0
+// CHECK-NEXT: br i1 [[CMP]], label %[[LOR_END:.*]], label %[[LOR_LHS_FALSE:.*]]
+// CHECK: [[LOR_LHS_FALSE]]:
+// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[TMP4]], 1
+// CHECK-NEXT: br i1 [[CMP2]], label %[[LOR_END]], label %[[LOR_RHS:.*]]
+// CHECK: [[LOR_RHS]]:
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[TMP5]], 2
+// CHECK-NEXT: br label %[[LOR_END]]
+// CHECK: [[LOR_END]]:
+// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ true, %[[LOR_LHS_FALSE]] ], [ true, %[[ENTRY]] ], [ [[CMP3]], %[[LOR_RHS]] ]
+// CHECK-NEXT: [[TMP7:%.*]] = zext i1 [[TMP6]] to i64
+// CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP6]], i32 42, i32 0
+// CHECK-NEXT: ret i32 [[COND]]
+//
+int foo_012(int x) {
+ int cc;
+ asm volatile ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
+ return cc == 0 || cc == 1 || cc == 2 ? 42 : 0;
+}
+
+// CHECK-LABEL: define dso_local signext i32 @foo_013(
+// CHECK-SAME: i32 noundef signext [[X:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*]]:
+// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[CC:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 [[TMP0]]) #[[ATTR2]], !srcloc [[META3:![0-9]+]]
+// CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT: [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT: store i32 [[ASMRESULT]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[ASMRESULT1]], 4
+// CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
+// CHECK-NEXT: store i32 [[ASMRESULT1]], ptr [[CC]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 0
+// CHECK-NEXT: br i1 [[CMP]], label %[[LOR_END:.*]], label %[[LOR_LHS_FALSE:.*]]
+// CHECK: [[LOR_LHS_FALSE]]:
+// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[TMP4]], 1
+// CHECK-NEXT: br i1 [[CMP2]], label %[[LOR_END]], label %[[LOR_RHS:.*]]
+// CHECK: [[LOR_RHS]]:
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[TMP5]], 3
+// CHECK-NEXT: br label %[[LOR_END]]
+// CHECK: [[LOR_END]]:
+// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ true, %[[LOR_LHS_FALSE]] ], [ true, %[[ENTRY]] ], [ [[CMP3]], %[[LOR_RHS]] ]
+// CHECK-NEXT: [[TMP7:%.*]] = zext i1 [[TMP6]] to i64
+// CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP6]], i32 42, i32 0
+// CHECK-NEXT: ret i32 [[COND]]
+//
+int foo_013(int x) {
+ int cc;
+ asm volatile ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
+ return cc == 0 || cc == 1 || cc == 3 ? 42 : 0;
+}
+
+// CHECK-LABEL: define dso_local signext i32 @foo_023(
+// CHECK-SAME: i32 noundef signext [[X:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*]]:
+// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[CC:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 [[TMP0]]) #[[ATTR2]], !srcloc [[META4:![0-9]+]]
+// CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT: [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT: store i32 [[ASMRESULT]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[ASMRESULT1]], 4
+// CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
+// CHECK-NEXT: store i32 [[ASMRESULT1]], ptr [[CC]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 0
+// CHECK-NEXT: br i1 [[CMP]], label %[[LOR_END:.*]], label %[[LOR_LHS_FALSE:.*]]
+// CHECK: [[LOR_LHS_FALSE]]:
+// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[TMP4]], 2
+// CHECK-NEXT: br i1 [[CMP2]], label %[[LOR_END]], label %[[LOR_RHS:.*]]
+// CHECK: [[LOR_RHS]]:
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[TMP5]], 3
+// CHECK-NEXT: br label %[[LOR_END]]
+// CHECK: [[LOR_END]]:
+// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ true, %[[LOR_LHS_FALSE]] ], [ true, %[[ENTRY]] ], [ [[CMP3]], %[[LOR_RHS]] ]
+// CHECK-NEXT: [[TMP7:%.*]] = zext i1 [[TMP6]] to i64
+// CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP6]], i32 42, i32 0
+// CHECK-NEXT: ret i32 [[COND]]
+//
+int foo_023(int x) {
+ int cc;
+ asm volatile ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
+ return cc == 0 || cc == 2 || cc == 3 ? 42 : 0;
+}
+
+// CHECK-LABEL: define dso_local signext i32 @foo_123(
+// CHECK-SAME: i32 noundef signext [[X:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*]]:
+// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[CC:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 [[TMP0]]) #[[ATTR2]], !srcloc [[META5:![0-9]+]]
+// CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT: [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT: store i32 [[ASMRESULT]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[ASMRESULT1]], 4
+// CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
+// CHECK-NEXT: store i32 [[ASMRESULT1]], ptr [[CC]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 1
+// CHECK-NEXT: br i1 [[CMP]], label %[[LOR_END:.*]], label %[[LOR_LHS_FALSE:.*]]
+// CHECK: [[LOR_LHS_FALSE]]:
+// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[TMP4]], 2
+// CHECK-NEXT: br i1 [[CMP2]], label %[[LOR_END]], label %[[LOR_RHS:.*]]
+// CHECK: [[LOR_RHS]]:
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[CC]], align 4
+// CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[TMP5]], 3
+// CHECK-NEXT: br label %[[LOR_END]]
+// CHECK: [[LOR_END]]:
+// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ true, %[[LOR_LHS_FALSE]] ], [ true, %[[ENTRY]] ], [ [[CMP3]], %[[LOR_RHS]] ]
+// CHECK-NEXT: [[TMP7:%.*]] = zext i1 [[TMP6]] to i64
+// CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP6]], i32 42, i32 0
+// CHECK-NEXT: ret i32 [[COND]]
+//
+int foo_123(int x) {
+ int cc;
+ asm volatile ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
+ return cc == 1 || cc == 2 || cc == 3 ? 42 : 0;
+}
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index e0b638201a047..cb136fe2f446b 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -5071,6 +5071,9 @@ class TargetLowering : public TargetLoweringBase {
std::vector<SDValue> &Ops,
SelectionDAG &DAG) const;
+ // Lower switch statement for flag output operand with SRL/IPM Sequence.
+ virtual bool canLowerSRL_IPM_Switch(SDValue Cond) const;
+
// Lower custom output constraints. If invalid, return SDValue().
virtual SDValue LowerAsmOutputForConstraint(SDValue &Chain, SDValue &Glue,
const SDLoc &DL,
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 3b046aa25f544..a32787bc882f1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2831,8 +2831,37 @@ void SelectionDAGBuilder::visitBr(const BranchInst &I) {
Opcode = Instruction::And;
else if (match(BOp, m_LogicalOr(m_Value(BOp0), m_Value(BOp1))))
Opcode = Instruction::Or;
-
- if (Opcode &&
+ auto &TLI = DAG.getTargetLoweringInfo();
+ bool BrSrlIPM = FuncInfo.MF->getTarget().getTargetTriple().getArch() ==
+ Triple::ArchType::systemz;
+ // For Flag output operands SRL/IPM sequence, we want to avoid
+ // creating switch case, as it creates Basic Block and inhibits
+ // optimization in DAGCombiner for flag output operands.
+ const auto checkSRLIPM = [&TLI](const SDValue &Op) {
+ if (!Op.getNumOperands())
+ return false;
+ SDValue OpVal = Op.getOperand(0);
+ SDNode *N = OpVal.getNode();
+ if (N && N->getOpcode() == ISD::SRL)
+ return TLI.canLowerSRL_IPM_Switch(OpVal);
+ else if (N && OpVal.getNumOperands() &&
+ (N->getOpcode() == ISD::AND || N->getOpcode() == ISD::OR)) {
+ SDValue OpVal1 = OpVal.getOperand(0);
+ SDNode *N1 = OpVal1.getNode();
+ if (N1 && N1->getOpcode() == ISD::SRL)
+ return TLI.canLowerSRL_IPM_Switch(OpVal1);
+ }
+ return false;
+ };
+ if (BrSrlIPM) {
+ if (NodeMap.count(BOp0) && NodeMap[BOp0].getNode()) {
+ BrSrlIPM &= checkSRLIPM(getValue(BOp0));
+ if (NodeMap.count(BOp1) && NodeMap[BOp1].getNode())
+ BrSrlIPM &= checkSRLIPM(getValue(BOp1));
+ } else
+ BrSrlIPM = false;
+ }
+ if (Opcode && !BrSrlIPM &&
!(match(BOp0, m_ExtractElt(m_Value(Vec), m_Value())) &&
match(BOp1, m_ExtractElt(m_Specific(Vec), m_Value()))) &&
!shouldKeepJumpConditionsTogether(
@@ -12043,18 +12072,41 @@ void SelectionDAGBuilder::lowerWorkItem(SwitchWorkListItem W, Value *Cond,
const APInt &SmallValue = Small.Low->getValue();
const APInt &BigValue = Big.Low->getValue();
+ // Creating switch cases optimizing tranformation inhibits DAGCombiner
+ // for SystemZ for flag output operands. DAGCobiner compute cumulative
+ // CCMask for flag output operands SRL/IPM sequence, we want to avoid
+ // creating switch case, as it creates Basic Block and inhibits
+ // optimization in DAGCombiner for flag output operands.
+ // cases like (CC == 0) || (CC == 2) || (CC == 3), or
+ // (CC == 0) || (CC == 1) ^ (CC == 3), there could potentially be
+ // more cases like this.
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ bool IsSrlIPM = false;
+ if (NodeMap.count(Cond) && NodeMap[Cond].getNode())
+ IsSrlIPM = CurMF->getTarget().getTargetTriple().getArch() ==
+ Triple::ArchType::systemz &&
+ TLI.canLowerSRL_IPM_Switch(getValue(Cond));
// Check that there is only one bit different.
APInt CommonBit = BigValue ^ SmallValue;
- if (CommonBit.isPowerOf2()) {
+ if (CommonBit.isPowerOf2() || IsSrlIPM) {
SDValue CondLHS = getValue(Cond);
EVT VT = CondLHS.getValueType();
SDLoc DL = getCurSDLoc();
-
- SDValue Or = DAG.getNode(ISD::OR, DL, VT, CondLHS,
- DAG.getConstant(CommonBit, DL, VT));
- SDValue Cond = DAG.getSetCC(
- DL, MVT::i1, Or, DAG.getConstant(BigValue | SmallValue, DL, VT),
- ISD::SETEQ);
+ SDValue Cond;
+
+ if (CommonBit.isPowerOf2()) {
+ SDValue Or = DAG.getNode(ISD::OR, DL, VT, CondLHS,
+ DAG.getConstant(CommonBit, DL, VT));
+ Cond = DAG.getSetCC(DL, MVT::i1, Or,
+ DAG.getConstant(BigValue | SmallValue, DL, VT),
+ ISD::SETEQ);
+ } else if (IsSrlIPM && BigValue == 3 && SmallValue == 0) {
+ SDValue SetCC =
+ DAG.getSetCC(DL, MVT::i32, CondLHS,
+ DAG.getConstant(SmallValue, DL, VT), ISD::SETEQ);
+ Cond = DAG.getSetCC(DL, MVT::i32, SetCC,
+ DAG.getConstant(BigValue, DL, VT), ISD::SETEQ);
+ }
// Update successor info.
// Both Small and Big will jump to Small.BB, so we sum up the
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 8287565336b54..3d48adac509cb 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -5563,6 +5563,10 @@ const char *TargetLowering::LowerXConstraint(EVT ConstraintVT) const {
return nullptr;
}
+bool TargetLowering::canLowerSRL_IPM_Switch(SDValue Cond) const {
+ return false;
+}
+
SDValue TargetLowering::LowerAsmOutputForConstraint(
SDValue &Chain, SDValue &Glue, const SDLoc &DL,
const AsmOperandInfo &OpInfo, SelectionDAG &DAG) const {
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 3999b54de81b6..259da48a3b223 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -1207,6 +1207,9 @@ SystemZTargetLowering::getConstraintType(StringRef Constraint) const {
default:
break;
}
+ } else if (Constraint.size() == 5 && Constraint.starts_with("{")) {
+ if (StringRef("{@cc}").compare(Constraint) == 0)
+ return C_Other;
}
return TargetLowering::getConstraintType(Constraint);
}
@@ -1389,6 +1392,10 @@ SystemZTargetLowering::getRegForInlineAsmConstraint(
return parseRegisterNumber(Constraint, &SystemZ::VR128BitRegClass,
SystemZMC::VR128Regs, 32);
}
+ if (Constraint[1] == '@') {
+ if (StringRef("{@cc}").compare(Constraint) == 0)
+ return std::make_pair(0u, &SystemZ::GR32BitRegClass);
+ }
}
return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
}
@@ -1421,6 +1428,35 @@ Register SystemZTargetLowering::getExceptionSelectorRegister(
return Subtarget.isTargetXPLINK64() ? SystemZ::R2D : SystemZ::R7D;
}
+// Lower @cc targets via setcc.
+SDValue SystemZTargetLowering::LowerAsmOutputForConstraint(
+ SDValue &Chain, SDValue &Glue, const SDLoc &DL,
+ const AsmOperandInfo &OpInfo, SelectionDAG &DAG) const {
+ if (StringRef("{@cc}").compare(OpInfo.ConstraintCode) != 0)
+ return SDValue();
+
+ // Check that return type is valid.
+ if (OpInfo.ConstraintVT.isVector() || !OpInfo.ConstraintVT.isInteger() ||
+ OpInfo.ConstraintVT.getSizeInBits() < 8)
+ report_fatal_error("Glue output operand is of invalid type");
+
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+ MRI.addLiveIn(SystemZ::CC);
+
+ if (Glue.getNode()) {
+ Glue = DAG.getCopyFromReg(Chain, DL, SystemZ::CC, MVT::i32, Glue);
+ Chain = Glue.getValue(1);
+ } else
+ Glue = DAG.getCopyFromReg(Chain, DL, SystemZ::CC, MVT::i32);
+
+ SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, Glue);
+ SDValue CC = DAG.getNode(ISD::SRL, DL, MVT::i32, IPM,
+ DAG.getConstant(SystemZ::IPM_CC, DL, MVT::i32));
+
+ return CC;
+}
+
void SystemZTargetLowering::LowerAsmOperandForConstraint(
SDValue Op, StringRef Constraint, std::vector<SDValue> &Ops,
SelectionDAG &DAG) const {
@@ -2485,6 +2521,21 @@ static unsigned CCMaskForCondCode(ISD::CondCode CC) {
#undef CONV
}
+static unsigned CCMaskForSystemZCCVal(unsigned CC) {
+ switch (CC) {
+ default:
+ llvm_unreachable("invalid integer condition!");
+ case 0:
+ return SystemZ::CCMASK_CMP_EQ;
+ case 1:
+ return SystemZ::CCMASK_CMP_LT;
+ case 2:
+ return SystemZ::CCMASK_CMP_GT;
+ case 3:
+ return SystemZ::CCMASK_CMP_UO;
+ }
+}
+
// If C can be converted to a comparison against zero, adjust the operands
// as necessary.
static void adjustZeroCmp(SelectionDAG &DAG, const SDLoc &DL, Comparison &C) {
@@ -7657,6 +7708,413 @@ SDValue SystemZTargetLowering::combineBSWAP(
return SDValue();
}
+// Combine IPM sequence for flag output operands.
+static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
+ // Convert CCVal to CCMask and update it along with CCValid.
+ const auto convertCCValToCCMask = [&CCMask, &CCValid](int CCVal) {
+ bool Invert = false;
+ if (CCMask == SystemZ::CCMASK_CMP_NE)
+ Invert = !Invert;
+ if (CCMask == SystemZ::CCMASK_CMP_EQ || CCMask == SystemZ::CCMASK_CMP_NE) {
+ CCMask = CCMaskForSystemZCCVal(CCVal);
+ if (Invert)
+ CCMask ^= SystemZ::CCMASK_ANY;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ } else if (CCMask == SystemZ::CCMASK_CMP_LT) {
+ // CC in range [0, CCVal).
+ CCMask = ((~0U << (4 - CCVal)) & SystemZ::CCMASK_ANY);
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ } else if (CCMask == SystemZ::CCMASK_CMP_GT) {
+ // CC in range (CCVal, 3].
+ CCMask = (~(~0U << (3 - CCVal))) & SystemZ::CCMASK_ANY;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ }
+ return false;
+ };
+ // Check (SRL (IPM (CC))) and update CCReg to combine.
+ const auto isSRL_IPM_CCSequence = [&CCReg](SDNode *N) {
+ if (!N || N->getOpcode() != ISD::SRL)
+ return false;
+ auto *SRLCount = dyn_cast<ConstantSDNode>(N->getOperand(1));
+ if (!SRLCount || SRLCount->getZExtValue() != SystemZ::IPM_CC)
+ return false;
+ auto *IPM = N->getOperand(0).getNode();
+ if (!IPM || IPM->getOpcode() != SystemZISD::IPM)
+ return false;
+ auto *IPMOp0 = IPM->getOperand(0).getNode();
+ if (!IPMOp0 || IPMOp0->getNumOperands() < 2)
+ return false;
+ auto *RN = dyn_cast<RegisterSDNode>(IPMOp0->getOperand(1));
+ if (!RN || !RN->getReg().isPhysical() || RN->getReg() != SystemZ::CC)
+ return false;
+ // Return the updated CCReg link.
+ CCReg = IPM->getOperand(0);
+ return true;
+ };
+ // Check if N has SystemZ::CC operand.
+ const auto isCCOperand = [](SDNode *N) {
+ if (!N || N->getNumOperands() < 2)
+ return false;
+ auto *RN = dyn_cast<RegisterSDNode>(N->getOperand(1));
+ if (!RN || !RN->getReg().isPhysical() || RN->getReg() != SystemZ::CC)
+ return false;
+ return true;
+ };
+
+ auto *CCNode = CCReg.getNode();
+ if (!CCNode)
+ return false;
+
+ int RestoreCCValid = CCValid;
+ // Optimize (TM (IPM (CC)))
+ if (CCNode->getOpcode() == SystemZISD::TM) {
+ bool Invert = false;
+ if (CCMask == SystemZ::CCMASK_TM_SOME_1)
+ Invert = !Invert;
+ auto *N = CCNode->getOperand(0).getNode();
+ auto Shift = dyn_cast<ConstantSDNode>(CCNode->getOperand(1));
+ if (!N || !Shift)
+ return false;
+ if (N->getOpcode() == SystemZISD::IPM) {
+ auto ShiftVal = Shift->getZExtValue();
+ if (ShiftVal == (1 << SystemZ::IPM_CC))
+ CCMask = SystemZ::CCMASK_CMP_GE;
+ if (Invert)
+ CCMask ^= CCValid;
+ // Return the updated CCReg link.
+ CCReg = N->getOperand(0);
+ return true;
+ } else if (N->getOpcode() == ISD::XOR) {
+ // Optimize (TM (XOR (OP1 OP2))).
+ auto *XOROp1 = N->getOperand(0).getNode();
+ auto *XOROp2 = N->getOperand(1).getNode();
+ if (!XOROp1 || !XOROp2)
+ return false;
+ // OP1. (SELECT_CCMASK (ICMP (SRL (IPM (CC))))).
+ // OP2. (SRL (IPM (CC))).
+ if (XOROp1->getOpcode() == SystemZISD::SELECT_CCMASK &&
+ isSRL_IPM_CCSequence(XOROp2)) {
+ auto *CCValid1 = dyn_cast<ConstantSDNode>(XOROp1->getOperand(2));
+ auto *CCMask1 = dyn_cast<ConstantSDNode>(XOROp1->getOperand(3));
+ SDValue XORReg = XOROp1->getOperand(4);
+ if (!CCValid1 || !CCMask1)
+ return false;
+ int CCValidVal = CCValid1->getZExtValue();
+ int CCMaskVal = CCMask1->getZExtValue();
+ if (combineCCIPMMask(XORReg, CCValidVal, CCMaskVal)) {
+ // CC == 0 || CC == 2 for bit 28 Test Under Mask.
+ CCMask = SystemZ::CCMASK_CMP_GE;
+ CCMask ^= CCMaskVal;
+ if (Invert)
+ CCMask ^= CCValid;
+ CCReg = XORReg;
+ return true;
+ }
+ }
+ }
+ }
+ // Optimize (AND (SRL (IPM (CC)))).
+ if (CCNode->getOpcode() == ISD::AND) {
+ auto *N = CCNode->getOperand(0).getNode();
+ if (!isSRL_IPM_CCSequence(N))
+ return false;
+ auto *ANDConst = dyn_cast<ConstantSDNode>(CCNode->getOperand(1));
+ if (!ANDConst)
+ return false;
+ // Bit 28 false (CC == 0) || (CC == 2).
+ // Caller can invert it depending on CCmask there.
+ if (ANDConst->getZExtValue() == 1) {
+ CCMask = SystemZ::CCMASK_0 | SystemZ::CCMASK_2;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ }
+ CCValid = RestoreCCValid;
+ return false;
+ }
+ // (SELECT_CCMASK (CC)) or (SELECT_CCMASK (ICMP (SRL (IPM (CC)))))
+ if (CCNode->getOpcode() == SystemZISD::SELECT_CCMASK) {
+ auto *CCValidNode = dyn_cast<ConstantSDNode>(CCNode->getOperand(2));
+ auto *CCMaskNode = dyn_cast<ConstantSDNode>(CCNode->getOperand(3));
+ if (!CCValidNode || !CCMaskNode)
+ return false;
+
+ int CCValidVal = CCValidNode->getZExtValue();
+ int CCMaskVal = CCMaskNode->getZExtValue();
+ SDValue CCRegOp = CCNode->getOperand(4);
+ if (combineCCIPMMask(CCRegOp, CCValidVal, CCMaskVal) ||
+ isCCOperand(CCRegOp.getNode())) {
+ CCMask = CCMaskVal;
+ CCValid = SystemZ::CCMASK_ANY;
+ CCReg = CCRegOp;
+ return true;
+ }
+ CCValid = RestoreCCValid;
+ return false;
+ }
+
+ // Both oerands of XOR are (SELECT_CCMASK (ICMP (SRL (IPM (CC))))).
+ if (CCNode->getOpcode() == ISD::XOR) {
+ if (isa<ConstantSDNode>(CCNode->getOperand(0)) ||
+ isa<ConstantSDNode>(CCNode->getOperand(1)))
+ return false;
+ auto *XOROp1 = CCNode->getOperand(0).getNode();
+ auto *XOROp2 = CCNode->getOperand(1).getNode();
+ if (!XOROp1 || !XOROp2)
+ return false;
+ // Both Operands are select_cc.
+ if (XOROp1->getOpcode() == SystemZISD::SELECT_CCMASK &&
+ XOROp2->getOpcode() == SystemZISD::SELECT_CCMASK) {
+ auto *CCValid1 = dyn_cast<ConstantSDNode>(XOROp1->getOperand(2));
+ auto *CCMask1 = dyn_cast<ConstantSDNode>(XOROp1->getOperand(3));
+ auto *CCValid2 = dyn_cast<ConstantSDNode>(XOROp2->getOperand(2));
+ auto *CCMask2 = dyn_cast<ConstantSDNode>(XOROp2->getOperand(3));
+ if (!CCValid1 || !CCMask1 || !CCValid2 || !CCMask2)
+ return false;
+ int CCValidVal1 = CCValid1->getZExtValue();
+ int CCMaskVal1 = CCMask1->getZExtValue();
+ int CCValidVal2 = CCValid2->getZExtValue();
+ int CCMaskVal2 = CCMask2->getZExtValue();
+ SDValue CCReg1 = XOROp1->getOperand(4);
+ SDValue CCReg2 = XOROp2->getOperand(4);
+ if (!combineCCIPMMask(CCReg1, CCValidVal1, CCMaskVal1) ||
+ !combineCCIPMMask(CCReg2, CCValidVal2, CCMaskVal2))
+ return false;
+ CCMask = CCMaskVal1 ^ CCMaskVal2;
+ CCReg = CCReg1;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ }
+ CCValid = RestoreCCValid;
+ return false;
+ }
+
+ // Rest of the code handle ICMP cases.
+ // Handle the case (ICMP (OP (SRL (IPM (CC)))))
+ if (!CCNode || CCNode->getOpcode() != SystemZISD::ICMP)
+ return false;
+ auto *LHS = CCNode->getOperand(0).getNode();
+ auto *RHS = dyn_cast<ConstantSDNode>(CCNode->getOperand(1));
+ if (!LHS || LHS->getOpcode() == ISD::Constant)
+ return false;
+
+ // (BR_CC (ICMP (Op1 Op2))), Op1 Op2 will have (SRL (IPM (CC))) sequence.
+ // SystemZ::ICMP second operand is not constant.
+ if (!RHS) {
+ SDValue CmpOp1 = CCNode->getOperand(0);
+ SDValue CmpOp2 = CCNode->getOperand(1);
+ int CCValid1 = CCValid, CCValid2 = CCValid;
+ int CCMask1 = CCMask, CCMask2 = CCMask;
+ bool IsOp1 = combineCCIPMMask(CmpOp1, CCValid1, CCMask1);
+ bool IsOp2 = combineCCIPMMask(CmpOp2, CCValid2, CCMask2);
+ if (IsOp1 && IsOp2) {
+ CCMask = CCMask1 ^ CCMask2;
+ CCReg = CmpOp1;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ }
+ CCValid = RestoreCCValid;
+ return false;
+ }
+ int CmpVal = RHS->getZExtValue();
+ // (BR_CC (ICMP (SELECT_CCMASK (CC))))
+ if (LHS->getOpcode() == SystemZISD::SELECT_CCMASK) {
+ int CCVal = RHS->getZExtValue();
+ int Mask = CCMaskForSystemZCCVal(CCVal);
+ bool Invert = false;
+ if (CCMask == SystemZ::CCMASK_CMP_NE)
+ Invert = !Invert;
+ SDValue NewCCReg = CCNode->getOperand(0);
+ if (combineCCIPMMask(NewCCReg, CCValid, CCMask)) {
+ CCMask |= Mask;
+ if (Invert)
+ CCMask ^= SystemZ::CCMASK_ANY;
+ CCReg = NewCCReg;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ }
+ CCValid = RestoreCCValid;
+ return false;
+ }
+ // (BR_CC (ICMP OR ((SRL (IPM (CC))) (SELECT_CCMASK (CC)))))
+ if (LHS->getOpcode() == ISD::OR) {
+ bool Invert = false;
+ if (CCMask == SystemZ::CCMASK_CMP_NE)
+ Invert = !Invert;
+ SDValue OrOp1 = LHS->getOperand(0);
+ SDValue OrOp2 = LHS->getOperand(1);
+ int NewCCMask1 = CCMask, NewCCMask2 = CCMask, NewCCMask = CCMask;
+ if (!isa<ConstantSDNode>(OrOp1) && !isa<ConstantSDNode>(OrOp2)) {
+ bool IsOp1 = combineCCIPMMask(OrOp1, CCValid, NewCCMask1);
+ bool IsOp2 = combineCCIPMMask(OrOp2, CCValid, NewCCMask2);
+ if (!IsOp1 && !IsOp2) {
+ CCValid = RestoreCCValid;
+ return false;
+ }
+ if (IsOp1 && IsOp2) {
+ NewCCMask = NewCCMask1 | NewCCMask2;
+ bool IsEqualCmpVal = NewCCMask == CmpVal;
+ if ((CCMask == SystemZ::CCMASK_CMP_NE && IsEqualCmpVal) ||
+ (CCMask == SystemZ::CCMASK_CMP_EQ && !IsEqualCmpVal))
+ NewCCMask ^= SystemZ::CCMASK_ANY;
+ CCReg = OrOp1;
+ CCMask = NewCCMask;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ }
+ } else if (isa<ConstantSDNode>(OrOp2)) {
+ if (isSRL_IPM_CCSequence(OrOp1.getNode())) {
+ auto *OrConst = dyn_cast<ConstantSDNode>(OrOp2);
+ int OrConstVal = OrConst->getZExtValue();
+ if (!OrConst || (OrConstVal & 0x3))
+ return false;
+ // setullt unsigned(-2), mask = 0x1100
+ // setugt unsigned(-4), mask = 0x0011
+ CmpVal &= 0x3;
+ if (convertCCValToCCMask(CmpVal))
+ return true;
+ }
+ }
+ CCValid = RestoreCCValid;
+ return false;
+ }
+ // (BR_CC (ICMP AND ((SRL (IPM (CC))) (SELECT_CCMASK (CC)))))
+ if (LHS->getOpcode() == ISD::AND) {
+ bool Invert = false;
+ if (CCMask == SystemZ::CCMASK_CMP_NE)
+ Invert = !Invert;
+ SDValue AndOp1 = LHS->getOperand(0);
+ SDValue AndOp2 = LHS->getOperand(1);
+ int NewCCMask1 = CCMask;
+ int NewCCMask2 = CCMask;
+ int NewCCMask;
+ if (!isa<ConstantSDNode>(AndOp1) && !isa<ConstantSDNode>(AndOp2)) {
+ bool IsOp1 = combineCCIPMMask(AndOp1, CCValid, NewCCMask1);
+ bool IsOp2 = combineCCIPMMask(AndOp2, CCValid, NewCCMask2);
+ if (!IsOp1 && !IsOp2) {
+ CCValid = RestoreCCValid;
+ return false;
+ }
+ if (IsOp1 && IsOp2) {
+ NewCCMask = NewCCMask1 & NewCCMask2;
+ bool IsEqualCmpVal = NewCCMask == CmpVal;
+ if ((CCMask == SystemZ::CCMASK_CMP_NE && IsEqualCmpVal) ||
+ (CCMask == SystemZ::CCMASK_CMP_EQ && !IsEqualCmpVal))
+ NewCCMask ^= SystemZ::CCMASK_ANY;
+ CCMask = NewCCMask;
+ CCReg = AndOp1;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ } else {
+ if (IsOp1 && isSRL_IPM_CCSequence(AndOp2.getNode()))
+ NewCCMask = NewCCMask1;
+ else if (isSRL_IPM_CCSequence(AndOp2.getNode()) && IsOp2)
+ NewCCMask = NewCCMask2;
+ // Bit 29 set => CC == 2 || CC == 3.
+ if ((NewCCMask & 0x3) == 2)
+ NewCCMask = SystemZ::CCMASK_2 | SystemZ::CCMASK_3;
+ // Bit 28 set => CC == 1 || CC == 3.
+ else if ((NewCCMask & 0x3) == 1)
+ NewCCMask = SystemZ::CCMASK_1 | SystemZ::CCMASK_3;
+ int CCVal = RHS->getZExtValue();
+ int Mask = CCMaskForSystemZCCVal(CCVal);
+ CCMask = Mask | NewCCMask;
+ if (Invert ^ CmpVal)
+ CCMask ^= SystemZ::CCMASK_ANY;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ }
+ }
+ CCValid = RestoreCCValid;
+ return false;
+ }
+ // Optimize the case where LHS is (ICMP (SRL (IPM))).
+ if (isSRL_IPM_CCSequence(LHS)) {
+ unsigned CCVal = RHS->getZExtValue();
+ if (convertCCValToCCMask(CCVal))
+ return true;
+ CCValid = RestoreCCValid;
+ return false;
+ }
+ if (LHS->getOpcode() == ISD::ADD) {
+ if (isSRL_IPM_CCSequence(LHS->getOperand(0).getNode())) {
+ int CCVal = RHS->getZExtValue();
+ // (unsigned) CCVal - 1 or (unsigned) CCVal - 3 Inverted.
+ // CCMask == SystemZ::CCMASK_CMP_LT, CCVal <= 2 => CC == 1 || CC == 2.
+ // CCMask == SystemZ::CCMASK_CMP_LT and CCVal <= 3 =>
+ // CC == 1 || CC == 2 || CC == 3.
+ auto *AddConstOp = dyn_cast<ConstantSDNode>((LHS->getOperand(1)));
+ int AddConst = AddConstOp->getZExtValue();
+ bool Invert = false;
+ if (CCVal < 0) {
+ Invert = !Invert;
+ // setult unsigned(-2), AddConst == -3.
+ AddConst = AddConst & 0x3;
+ } else
+ AddConst = ~AddConst + 1;
+ // As original CCMask of of SELECT_CCMASK/BR_CCMASK does not have
+ // <= or >=.
+ CCVal &= 0x3;
+ CCVal += AddConst;
+ if (convertCCValToCCMask(CCVal)) {
+ // CCVal can not zero here.
+ CCMask ^= SystemZ::CCMASK_CMP_EQ;
+ if (Invert)
+ CCMask ^= SystemZ::CCMASK_ANY;
+ return true;
+ }
+ }
+ CCValid = RestoreCCValid;
+ return false;
+ }
+
+ // Optimize (ICMP (XOR (OP1 OP2))), OP1 or OP2 could be XOR again.
+ // One or both of operands could be (SELECT_CCMASK (ICMP (SRL (IPM (CC))))).
+ if (LHS->getOpcode() == ISD::XOR) {
+ SDValue XORReg = CCReg->getOperand(0);
+ bool Invert = false;
+ if (CCMask == SystemZ::CCMASK_CMP_NE)
+ Invert = !Invert;
+ // If both the operands are select_cc.
+ if (combineCCIPMMask(XORReg, CCValid, CCMask)) {
+ CCReg = XORReg;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ }
+ // Handle the case when one of the operand is select_cc and other operand
+ // could be xor again having both operands as select_cc.
+ auto *XOROp1 = LHS->getOperand(0).getNode();
+ auto *XOROp2 = LHS->getOperand(1).getNode();
+ if (!XOROp1 || !XOROp2)
+ return false;
+ if (XOROp1->getOpcode() == SystemZISD::SELECT_CCMASK ||
+ XOROp2->getOpcode() == SystemZISD::SELECT_CCMASK) {
+ auto *XOROp =
+ XOROp1->getOpcode() == SystemZISD::SELECT_CCMASK ? XOROp1 : XOROp2;
+ auto *CCMaskNode = dyn_cast<ConstantSDNode>(XOROp->getOperand(3));
+ auto *CCValidNode = dyn_cast<ConstantSDNode>(XOROp->getOperand(2));
+ if (!CCValidNode || !CCMaskNode)
+ return false;
+ int CCValidVal = CCValidNode->getZExtValue();
+ int CCMaskVal = CCMaskNode->getZExtValue();
+ SDValue XORReg1 = XOROp->getOperand(4);
+ SDValue XORReg2 = LHS->getOperand(1);
+ int CCMaskVal1 = CCMaskVal, CCMaskVal2 = CCMaskVal;
+ if (combineCCIPMMask(XORReg1, CCValidVal, CCMaskVal1) &&
+ combineCCIPMMask(XORReg2, CCValidVal, CCMaskVal2)) {
+ CCMask = CCMaskVal1 ^ CCMaskVal2;
+ CCReg = XORReg1;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ }
+ }
+ }
+ CCValid = RestoreCCValid;
+ return false;
+}
+
static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
// We have a SELECT_CCMASK or BR_CCMASK comparing the condition code
// set by the CCReg instruction using the CCValid / CCMask masks,
@@ -7744,6 +8202,134 @@ static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
return false;
}
+std::optional<SDValue>
+SystemZTargetLowering::combineSELECT_CC_CCIPMMask(SDNode *N,
+ DAGCombinerInfo &DCI) const {
+ SelectionDAG &DAG = DCI.DAG;
+ // Check if N has SystemZ::CC operand.
+ const auto isCCOperand = [](SDNode *N) {
+ if (!N || N->getNumOperands() < 2)
+ return false;
+ auto *RN = dyn_cast<RegisterSDNode>(N->getOperand(1));
+ if (!RN || !RN->getReg().isPhysical() || RN->getReg() != SystemZ::CC)
+ return false;
+ return true;
+ };
+
+ auto *TrueVal = dyn_cast<ConstantSDNode>(N->getOperand(0));
+ auto *FalseVal = dyn_cast<ConstantSDNode>(N->getOperand(1));
+ // Already handled the case both operands constant in combineCCMask.
+ // Not yet encountered the case where both operands not constants,
+ // that case can be handled by removing this condition.
+ if (!((TrueVal != nullptr) ^ (FalseVal != nullptr)))
+ return std::nullopt;
+
+ SDValue CCOp = TrueVal ? N->getOperand(1) : N->getOperand(0);
+ auto *CCOpNode = CCOp.getNode();
+ if (!CCOpNode || CCOpNode->getOpcode() != SystemZISD::SELECT_CCMASK)
+ return std::nullopt;
+
+ auto *TrueValOp = dyn_cast<ConstantSDNode>(CCOpNode->getOperand(0));
+ auto *FalseValOp = dyn_cast<ConstantSDNode>(CCOpNode->getOperand(1));
+ bool InvertOp1 = false, InvertOp2 = false;
+ // Check if outer select_cc and inner select_cc True/False matching or
+ // inverted.
+ if (TrueVal) {
+ if (FalseValOp && TrueVal->getZExtValue() == FalseValOp->getZExtValue())
+ InvertOp2 = !InvertOp2;
+ else if (!TrueValOp || TrueVal->getZExtValue() != TrueValOp->getZExtValue())
+ return std::nullopt;
+ } else if (FalseVal) {
+ if (TrueValOp && FalseVal->getZExtValue() == TrueValOp->getZExtValue())
+ InvertOp1 = !InvertOp1;
+ else if (!FalseValOp ||
+ FalseVal->getZExtValue() != FalseValOp->getZExtValue())
+ return std::nullopt;
+ }
+
+ auto *CCValidNode = dyn_cast<ConstantSDNode>(N->getOperand(2));
+ auto *CCMaskNode = dyn_cast<ConstantSDNode>(N->getOperand(3));
+ auto *CCValidOp = dyn_cast<ConstantSDNode>(CCOpNode->getOperand(2));
+ auto *CCMaskOp = dyn_cast<ConstantSDNode>(CCOpNode->getOperand(3));
+ if (!CCValidNode || !CCMaskNode || !CCMaskOp || !CCValidOp)
+ return std::nullopt;
+
+ int CCValid = CCValidNode->getZExtValue();
+ int CCMaskValOp = CCMaskOp->getZExtValue();
+ int CCValidValOp = CCValidOp->getZExtValue();
+ int CCMask = CCMaskNode->getZExtValue();
+ bool IsUnionMask = CCMask == SystemZ::CCMASK_CMP_EQ;
+ if (CCValid != SystemZ::CCMASK_ICMP)
+ return std::nullopt;
+
+ SDValue CCReg = N->getOperand(4);
+ SDValue CCRegOp = CCOpNode->getOperand(4);
+ // Combine current select_cc.
+ if (combineCCIPMMask(CCReg, CCValid, CCMask)) {
+ if (InvertOp1)
+ CCMask ^= SystemZ::CCMASK_ANY;
+ // There are two scenarios here.
+ // Case 1. Inner (ICMP (SELECT_CCMASK)) has not already been combined into
+ // SELECT_CCMASK. Compute CCMask after optimization.
+ // Case 2. Inner (ICMP (SELECT_CCMASK)) already been combined into
+ // SELECT_CCMASK. Check for isCCOperand. In this case we will not know
+ // original CCMask, but if only one bit is set in CCMaskValOp, that means
+ // original CCMask was SystemZ::CCMASK_CMP_EQ.
+ if (!combineCCIPMMask(CCRegOp, CCValidValOp, CCMaskValOp) &&
+ !isCCOperand(CCRegOp.getNode()))
+ return std::nullopt;
+ // If outer SELECT_CCMASK is CCMASK_CMP_EQ or single bit is set in
+ // CCMaskValOp(inner SELECT_CCMASK is CCMASK_CMP_EQ).
+ bool OnlyOneBitSet = CCMaskValOp && !(CCMaskValOp & (CCMaskValOp - 1));
+ // Original CCMask of current SELECT_CCMASK is SystemZ::CCMASK_CMP_EQ,
+ // or Original CCMask of inner SELECT_CCMASK before actual CCMask
+ // computation is SystemZ::CCMASK_CMP_EQ.
+ IsUnionMask =
+ IsUnionMask || CCMaskValOp == SystemZ::CCMASK_CMP_EQ || OnlyOneBitSet;
+ if (InvertOp2)
+ CCMaskValOp ^= SystemZ::CCMASK_ANY;
+ if (IsUnionMask)
+ CCMask |= CCMaskValOp;
+ // Original outer SELECT_CCMASK has CCMask one of SystemZ::CCMASK_CMP_LT,
+ // SystemZ::CCMASK_CMP_LT, SystemZ::CCMASK_CMP_NE,
+ // and inner CCMaskValOP is also not SystemZ::CCMASK_CMP_EQ,
+ // Taking intersection. In case of outer SystemZ::CCMASK_CMP_NE and inner
+ // as well, !(!a || !b) => (a & b).
+ else
+ CCMask &= CCMaskValOp;
+ auto Op0 = CCOpNode->getOperand(0);
+ auto Op1 = CCOpNode->getOperand(1);
+ // Inner select_cc True/False is inverted w.r.t outer. We are using inner
+ // select_cc to get CCRegOp and CCOpNode.
+ if (InvertOp2)
+ std::swap(Op0, Op1);
+ return DAG.getNode(
+ SystemZISD::SELECT_CCMASK, SDLoc(N), N->getValueType(0), Op0, Op1,
+ DAG.getTargetConstant(CCValid, SDLoc(N), MVT::i32),
+ DAG.getTargetConstant(CCMask, SDLoc(N), MVT::i32), CCRegOp);
+ }
+ return std::nullopt;
+}
+
+bool SystemZTargetLowering::canLowerSRL_IPM_Switch(SDValue Cond) const {
+ auto *SRL = Cond.getNode();
+ if (!SRL || SRL->getOpcode() != ISD::SRL)
+ return false;
+ auto *SRLCount = dyn_cast<ConstantSDNode>(SRL->getOperand(1));
+ if (!SRLCount || SRLCount->getZExtValue() != SystemZ::IPM_CC)
+ return false;
+ auto *IPM = SRL->getOperand(0).getNode();
+ if (!IPM || IPM->getOpcode() != SystemZISD::IPM)
+ return false;
+ auto IPMOp0 = IPM->getOperand(0).getNode();
+ if (!IPMOp0 || IPMOp0->getNumOperands() < 2)
+ return false;
+ auto RN = dyn_cast<RegisterSDNode>(IPMOp0->getOperand(1));
+ if (!RN || !RN->getReg().isPhysical() || RN->getReg() != SystemZ::CC)
+ return false;
+ return true;
+}
+
SDValue SystemZTargetLowering::combineBR_CCMASK(
SDNode *N, DAGCombinerInfo &DCI) const {
SelectionDAG &DAG = DCI.DAG;
@@ -7759,7 +8345,9 @@ SDValue SystemZTargetLowering::combineBR_CCMASK(
SDValue Chain = N->getOperand(0);
SDValue CCReg = N->getOperand(4);
- if (combineCCMask(CCReg, CCValidVal, CCMaskVal))
+ // combineCCIPMMask tries to combine srl/ipm sequence for flag output operand.
+ if (combineCCIPMMask(CCReg, CCValidVal, CCMaskVal) ||
+ combineCCMask(CCReg, CCValidVal, CCMaskVal))
return DAG.getNode(SystemZISD::BR_CCMASK, SDLoc(N), N->getValueType(0),
Chain,
DAG.getTargetConstant(CCValidVal, SDLoc(N), MVT::i32),
@@ -7770,6 +8358,12 @@ SDValue SystemZTargetLowering::combineBR_CCMASK(
SDValue SystemZTargetLowering::combineSELECT_CCMASK(
SDNode *N, DAGCombinerInfo &DCI) const {
+ // Try to combine select_cc with select_cc for flag output operand.
+ // select_cc may have one of True/Flase Operand SDValue.
+ std::optional<SDValue> Res = combineSELECT_CC_CCIPMMask(N, DCI);
+ if (Res.has_value())
+ return Res.value();
+
SelectionDAG &DAG = DCI.DAG;
// Combine SELECT_CCMASK (ICMP (SELECT_CCMASK)) into a single SELECT_CCMASK.
@@ -7782,7 +8376,9 @@ SDValue SystemZTargetLowering::combineSELECT_CCMASK(
int CCMaskVal = CCMask->getZExtValue();
SDValue CCReg = N->getOperand(4);
- if (combineCCMask(CCReg, CCValidVal, CCMaskVal))
+ // combineCCIPMMask tries to combine srl/ipm sequence for flag output operand.
+ if (combineCCIPMMask(CCReg, CCValidVal, CCMaskVal) ||
+ combineCCMask(CCReg, CCValidVal, CCMaskVal))
return DAG.getNode(SystemZISD::SELECT_CCMASK, SDLoc(N), N->getValueType(0),
N->getOperand(0), N->getOperand(1),
DAG.getTargetConstant(CCValidVal, SDLoc(N), MVT::i32),
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 3c06c1fdf2b1b..0bf103a5ceae5 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -510,6 +510,16 @@ class SystemZTargetLowering : public TargetLowering {
bool shouldExpandCmpUsingSelects(EVT VT) const override { return true; }
const char *getTargetNodeName(unsigned Opcode) const override;
+
+ // Check for if flag output operands has SRL/IPM Sequence.
+ bool canLowerSRL_IPM_Switch(SDValue Cond) const override;
+
+ // Handle Lowering flag assembly outputs.
+ SDValue LowerAsmOutputForConstraint(SDValue &Chain, SDValue &Flag,
+ const SDLoc &DL,
+ const AsmOperandInfo &Constraint,
+ SelectionDAG &DAG) const override;
+
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
StringRef Constraint, MVT VT) const override;
@@ -744,7 +754,11 @@ class SystemZTargetLowering : public TargetLowering {
SDValue combineINT_TO_FP(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue combineBSWAP(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue combineBR_CCMASK(SDNode *N, DAGCombinerInfo &DCI) const;
+ std::optional<SDValue> combineBR_CCJoinIPMMask(SDNode *N,
+ DAGCombinerInfo &DCI) const;
SDValue combineSELECT_CCMASK(SDNode *N, DAGCombinerInfo &DCI) const;
+ std::optional<SDValue> combineSELECT_CC_CCIPMMask(SDNode *N,
+ DAGCombinerInfo &DCI) const;
SDValue combineGET_CCMASK(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue combineIntDIVREM(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue combineINTRINSIC(SDNode *N, DAGCombinerInfo &DCI) const;
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand.ll
new file mode 100644
index 0000000000000..a816b560e99e4
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand.ll
@@ -0,0 +1,500 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations
+; for AND for 3 three different functions, including two test cases from heiko.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
+
+; Test CC == 0 && CC == 1.
+define signext i32 @foo_01(i32 noundef signext %x) {
+; CHECK-LABEL: foo_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+declare void @llvm.assume(i1 noundef) #1
+
+; Test CC == 0 && CC == 2.
+define signext i32 @foo_02(i32 noundef signext %x) {
+; CHECK-LABEL: foo_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test CC == 0 && CC == 3.
+define signext i32 @foo_03(i32 noundef signext %x) {
+; CHECK-LABEL: foo_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test CC == 1 && CC == 2.
+define signext i32 @foo_12(i32 noundef signext %x) {
+; CHECK-LABEL: foo_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test CC == 1 && CC == 3.
+define signext i32 @foo_13(i32 noundef signext %x) {
+; CHECK-LABEL: foo_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test CC == 2 && CC == 3.
+define signext i32 @foo_23(i32 noundef signext %x) {
+; CHECK-LABEL: foo_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test CC == 0 && CC == 1 && CC == 2.
+define signext i32 @foo_012(i32 noundef signext %x) {
+; CHECK-LABEL: foo_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test CC == 0 && CC == 1 && CC == 3.
+define signext i32 @foo_013(i32 noundef signext %x) {
+; CHECK-LABEL: foo_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test CC == 0 && CC == 2 && CC == 3.
+define signext i32 @foo_023(i32 noundef signext %x) {
+; CHECK-LABEL: foo_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test CC == 1 && CC == 2 && CC == 3.
+define signext i32 @foo_123(i32 noundef signext %x) {
+; CHECK-LABEL: foo_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+
+ at a = global i32 0, align 4
+
+; Test CC == 0 && CC == 1.
+define i64 @fu_01() {
+; CHECK-LABEL: fu_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test CC == 0 && CC == 2.
+define i64 @fu_02() {
+; CHECK-LABEL: fu_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test CC == 0 && CC == 3.
+define i64 @fu_03() {
+; CHECK-LABEL: fu_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test CC == 1 && CC == 2.
+define i64 @fu_12() {
+; CHECK-LABEL: fu_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test CC == 1 && CC == 3.
+define i64 @fu_13() {
+; CHECK-LABEL: fu_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test CC == 2 && CC == 3.
+define i64 @fu_23() {
+; CHECK-LABEL: fu_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test CC == 0 && CC == 1 && CC == 2.
+define i64 @fu_012() {
+; CHECK-LABEL: fu_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test CC == 0 && CC == 1 && CC == 3.
+define i64 @fu_013() {
+; CHECK-LABEL: fu_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test CC == 0 && CC == 2 && CC == 3.
+define i64 @fu_023() {
+; CHECK-LABEL: fu_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test CC == 1 && CC == 2 && CC == 3.
+define i64 @fu_123() {
+; CHECK-LABEL: fu_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test CC == 0 && CC == 1.
+define void @bar_01() {
+; CHECK-LABEL: bar_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 0 && CC == 2.
+define void @bar_02() {
+; CHECK-LABEL: bar_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 0 && CC == 3.
+define void @bar_03() {
+; CHECK-LABEL: bar_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 1 && CC == 2.
+define void @bar_12() {
+; CHECK-LABEL: bar_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 1 && CC == 3.
+define void @bar_13() {
+; CHECK-LABEL: bar_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 2 && CC == 3.
+define void @bar_23() {
+; CHECK-LABEL: bar_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 0 && CC == 1 && CC == 2.
+define void @bar_012() {
+; CHECK-LABEL: bar_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 0 && CC == 1 && CC == 3.
+define void @bar_013() {
+; CHECK-LABEL: bar_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 0 && CC == 2 && CC == 3.
+define void @bar_023() {
+; CHECK-LABEL: bar_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 1 && CC == 2 && CC == 3.
+define void @bar_123() {
+; CHECK-LABEL: bar_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_eq_noteq.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_eq_noteq.ll
new file mode 100644
index 0000000000000..c9c7e7c5ed418
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_eq_noteq.ll
@@ -0,0 +1,939 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations
+; for AND for 3 three different functions, including two tests from heiko.
+; This test checks combinations of EQUAL(==) and NOT EQUAL (!=) operator. e.g.
+; CC == 0 && CC != 1 && CC != 2 and CC == 0 && CC == 2 && CC != 3.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
+
+; Test CC == 0 && CC != 1.
+define signext range(i32 0, 43) i32 @foo_01(i32 noundef signext %x) {
+; CHECK-LABEL: foo_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB0_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %cond = select i1 %cmp, i32 42, i32 0
+ ret i32 %cond
+}
+
+declare void @llvm.assume(i1 noundef) #1
+
+; Test CC == 0 && CC != 2
+define signext range(i32 0, 43) i32 @foo_02(i32 noundef signext %x) {
+; CHECK-LABEL: foo_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB1_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %cond = select i1 %cmp, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 && CC != 3.
+define signext range(i32 0, 43) i32 @foo_03(i32 noundef signext %x) {
+; CHECK-LABEL: foo_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB2_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %cond = select i1 %cmp, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 1 && CC != 2
+define signext range(i32 0, 43) i32 @foo_12(i32 noundef signext %x) {
+; CHECK-LABEL: foo_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB3_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 1
+ %cond = select i1 %cmp, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 1 && CC != 3
+define signext range(i32 0, 43) i32 @foo_13(i32 noundef signext %x) {
+; CHECK-LABEL: foo_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB4_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 1
+ %cond = select i1 %cmp, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 2 && CC != 3.
+define signext range(i32 0, 43) i32 @foo_23(i32 noundef signext %x) {
+; CHECK-LABEL: foo_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB5_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 && CC != 1 && CC != 2.
+define signext range(i32 0, 43) i32 @foo_012(i32 noundef signext %x) {
+; CHECK-LABEL: foo_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB6_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %spec.select = select i1 %cmp, i32 42, i32 0
+ ret i32 %spec.select
+}
+
+; Test CC == 0 && CC != 1 && CC != 3.
+define signext range(i32 0, 43) i32 @foo_013(i32 noundef signext %x) {
+; CHECK-LABEL: foo_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB7_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %spec.select = select i1 %cmp, i32 42, i32 0
+ ret i32 %spec.select
+}
+
+; Test CC == 0 && CC != 2 && CC != 3.
+define signext range(i32 0, 43) i32 @foo_023(i32 noundef signext %x) {
+; CHECK-LABEL: foo_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB8_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %spec.select = select i1 %cmp, i32 42, i32 0
+ ret i32 %spec.select
+}
+
+; Test CC == 1 && CC != 2 && CC != 3.
+define signext range(i32 0, 43) i32 @foo_123(i32 noundef signext %x) {
+; CHECK-LABEL: foo_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB9_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 1
+ %spec.select = select i1 %cmp, i32 42, i32 0
+ ret i32 %spec.select
+}
+
+; Test CC == 0 && CC == 1 && CC != 2.
+define noundef signext i32 @foo1_012(i32 noundef signext %x) {
+; CHECK-LABEL: foo1_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test CC == 0 && CC == 1 && CC != 3.
+define noundef signext i32 @foo1_013(i32 noundef signext %x) {
+; CHECK-LABEL: foo1_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test CC == 0 && CC == 2 && CC != 3
+define noundef signext i32 @foo1_023(i32 noundef signext %x) {
+; CHECK-LABEL: foo1_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test CC == 1 && CC == 2 && CC != 3.
+define noundef signext i32 @foo1_123(i32 noundef signext %x) {
+; CHECK-LABEL: foo1_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+ at a = global i32 0, align 4
+
+; Test CC == 0 && CC != 1.
+define range(i64 5, 9) i64 @fu_01() {
+; CHECK-LABEL: fu_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB14_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 0 || CC != 2.
+define range(i64 5, 9) i64 @fu_02() {
+; CHECK-LABEL: fu_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB15_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 0 || CC != 3.
+define range(i64 5, 9) i64 @fu_03() {
+; CHECK-LABEL: fu_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB16_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 1 || CC != 2.
+define range(i64 5, 9) i64 @fu_12() {
+; CHECK-LABEL: fu_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB17_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 1 || CC != 3.
+define range(i64 5, 9) i64 @fu_13() {
+; CHECK-LABEL: fu_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB18_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 2 || CC != 3.
+define range(i64 5, 9) i64 @fu_23() {
+; CHECK-LABEL: fu_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB19_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 0 || CC != 1 || CC != 2.
+define range(i64 5, 9) i64 @fu_012() {
+; CHECK-LABEL: fu_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB20_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 0 || CC != 1 || CC != 3.
+define range(i64 5, 9) i64 @fu_013() {
+; CHECK-LABEL: fu_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB21_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 0 || CC != 2 || CC != 3.
+define range(i64 5, 9) i64 @fu_023() {
+; CHECK-LABEL: fu_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB22_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 1 || CC != 2 || CC != 3.
+define range(i64 5, 9) i64 @fu_123() {
+; CHECK-LABEL: fu_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB23_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+; Test CC == 0 && CC != 1.
+define void @bar_01() {
+; CHECK-LABEL: bar_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB24_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Tset CC == 0 || CC == 1 || CC != 2.
+define noundef i64 @fu1_012() {
+; CHECK-LABEL: fu1_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Tset CC == 0 || CC == 1 || CC != 3.
+define noundef i64 @fu1_013() {
+; CHECK-LABEL: fu1_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Tset CC == 0 || CC == 2 || CC != 3.
+define noundef i64 @fu1_023() {
+; CHECK-LABEL: fu1_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Tset CC == 1 || CC == 2 || CC != 3.
+define noundef i64 @fu1_123() {
+; CHECK-LABEL: fu1_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+declare void @dummy() local_unnamed_addr #1
+
+; Test CC == 0 && CC != 2
+define void @bar_02() {
+; CHECK-LABEL: bar_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB29_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 && CC != 3.
+define void @bar_03() {
+; CHECK-LABEL: bar_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB30_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 && CC != 2
+define void @bar_12() {
+; CHECK-LABEL: bar_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB31_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 && CC != 3.
+define void @bar_13() {
+; CHECK-LABEL: bar_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB32_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 2 && CC != 3.
+define void @bar_23() {
+; CHECK-LABEL: bar_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgh dummy at PLT
+; CHECK-NEXT: .LBB33_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 2
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 && CC != 1 && CC != 3.
+define void @bar_012() {
+; CHECK-LABEL: bar_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB34_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 && CC != 1 && CC != 3.
+define void @bar_013() {
+; CHECK-LABEL: bar_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB35_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 && CC != 2 && CC != 3.
+define void @bar_023() {
+; CHECK-LABEL: bar_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB36_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 && CC != 2 && CC != 3.
+define void @bar_123() {
+; CHECK-LABEL: bar_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB37_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 && CC == 1 && CC != 2.
+define void @bar1_012() {
+; CHECK-LABEL: bar1_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 0 && CC == 1 && CC != 3.
+define void @bar1_013() {
+; CHECK-LABEL: bar1_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 0 && CC == 2 && CC != 3.
+define void @bar1_023() {
+; CHECK-LABEL: bar1_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
+; Test CC == 1 && CC == 2 && CC !=3.
+define void @bar1_123() {
+; CHECK-LABEL: bar1_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret void
+}
+
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_not.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_not.ll
new file mode 100644
index 0000000000000..766bb07eef209
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_not.ll
@@ -0,0 +1,779 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations.
+; This test negate of flag_output_operand_ccand, e.g
+; CC != 0 && cc !- 1 && cc != 2 for AND for 3 three different functions,
+; including two test cases from heiko.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
+
+; Test CC != 0 && CC != 1.
+define signext range(i32 0, 43) i32 @foo_01(i32 noundef signext %x) {
+; CHECK-LABEL: foo_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB0_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ugt i32 %asmresult1, 1
+ %cond = select i1 %2, i32 42, i32 0
+ ret i32 %cond
+}
+
+declare void @llvm.assume(i1 noundef) #1
+
+; Test CC != 0 && CC != 2.
+define signext range(i32 0, 43) i32 @foo_02(i32 noundef signext %x) {
+; CHECK-LABEL: foo_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB1_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %.not = icmp eq i32 %2, 0
+ %cond = select i1 %.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC != 0 && CC != 3.
+define signext range(i32 0, 43) i32 @foo_03(i32 noundef signext %x) {
+; CHECK-LABEL: foo_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB2_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp ne i32 %asmresult1, 0
+ %cmp2 = icmp ne i32 %asmresult1, 3
+ %2 = and i1 %cmp, %cmp2
+ %cond = select i1 %2, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 1 && CC != 2.
+define signext range(i32 0, 43) i32 @foo_12(i32 noundef signext %x) {
+; CHECK-LABEL: foo_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB3_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -3
+ %3 = icmp ult i32 %2, -2
+ %cond = select i1 %3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 1 && CC != 3.
+define signext range(i32 0, 43) i32 @foo_13(i32 noundef signext %x) {
+; CHECK-LABEL: foo_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB4_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %.not.not = icmp eq i32 %2, 0
+ %cond = select i1 %.not.not, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 2 && CC != 3.
+define signext range(i32 0, 43) i32 @foo_23(i32 noundef signext %x) {
+; CHECK-LABEL: foo_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB5_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %asmresult1, -4
+ %3 = icmp samesign ult i32 %2, -2
+ %cond = select i1 %3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 0 && CC != 1 && CC != 2
+define signext range(i32 0, 43) i32 @foo_012(i32 noundef signext %x) {
+; CHECK-LABEL: foo_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bnor %r14
+; CHECK-NEXT: .LBB6_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %or.cond = icmp samesign ugt i32 %asmresult1, 1
+ %cmp3.not = icmp eq i32 %asmresult1, 2
+ %2 = select i1 %cmp3.not, i32 0, i32 42
+ %cond = select i1 %or.cond, i32 %2, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 0 && CC != 1 && CC != 3.
+define signext range(i32 0, 43) i32 @foo_013(i32 noundef signext %x) {
+; CHECK-LABEL: foo_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB7_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %or.cond = icmp samesign ugt i32 %asmresult1, 1
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %2 = select i1 %cmp3.not, i32 0, i32 42
+ %cond = select i1 %or.cond, i32 %2, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 0 && CC != 2 && CC != 3.
+define signext range(i32 0, 43) i32 @foo_023(i32 noundef signext %x) {
+; CHECK-LABEL: foo_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bnlr %r14
+; CHECK-NEXT: .LBB8_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %or.cond.not = icmp eq i32 %2, 0
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %3 = or i1 %cmp3.not, %or.cond.not
+ %cond = select i1 %3, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC != 1 && CC != 2 && CC != 3.
+define signext range(i32 0, 43) i32 @foo_123(i32 noundef signext %x) {
+; CHECK-LABEL: foo_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bner %r14
+; CHECK-NEXT: .LBB9_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -3
+ %or.cond = icmp ult i32 %2, -2
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %3 = select i1 %cmp3.not, i32 0, i32 42
+ %cond = select i1 %or.cond, i32 %3, i32 0
+ ret i32 %cond
+}
+
+ at a = dso_local global i32 0, align 4
+
+; Test CC != 0 && CC != 1.
+define dso_local range(i64 5, 9) i64 @fu_01() local_unnamed_addr #0 {
+; CHECK-LABEL: fu_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB10_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ult i32 %0, 2
+ %. = select i1 %2, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 0 && CC != 2.
+define dso_local range(i64 5, 9) i64 @fu_02() local_unnamed_addr #0 {
+; CHECK-LABEL: fu_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB11_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 0 && CC != 3.
+define dso_local range(i64 5, 9) i64 @fu_03() local_unnamed_addr #0 {
+; CHECK-LABEL: fu_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB12_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp eq i32 %0, 0
+ %cmp1.i = icmp eq i32 %0, 3
+ %.not = or i1 %cmp.i, %cmp1.i
+ %. = select i1 %.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 1 && CC != 2.
+define dso_local range(i64 5, 9) i64 @fu_12() local_unnamed_addr #0 {
+; CHECK-LABEL: fu_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB13_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -1
+ %3 = icmp ult i32 %2, 2
+ %. = select i1 %3, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 1 && CC != 3.
+define dso_local range(i64 5, 9) i64 @fu_13() local_unnamed_addr #0 {
+; CHECK-LABEL: fu_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB14_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC != 2 && CC != 3.
+define dso_local range(i64 5, 9) i64 @fu_23() local_unnamed_addr #0 {
+; CHECK-LABEL: fu_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB15_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %3 = icmp samesign ugt i32 %2, -3
+ %. = select i1 %3, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 0 && CC != 1 && CC != 2.
+define dso_local range(i64 5, 9) i64 @fu_012() local_unnamed_addr #0 {
+; CHECK-LABEL: fu_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB16_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %narrow.not = icmp eq i32 %0, 3
+ %. = select i1 %narrow.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC != 0 && CC != 1 && CC != 3.
+define dso_local range(i64 5, 9) i64 @fu_013() local_unnamed_addr #0 {
+; CHECK-LABEL: fu_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB17_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %or.cond.i = icmp samesign ult i32 %0, 2
+ %cmp2.i = icmp eq i32 %0, 3
+ %narrow.not = or i1 %or.cond.i, %cmp2.i
+ %. = select i1 %narrow.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 0 && CC != 2 && CC != 3.
+define dso_local range(i64 5, 9) i64 @fu_023() local_unnamed_addr #0 {
+; CHECK-LABEL: fu_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlr %r14
+; CHECK-NEXT: .LBB18_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %or.cond.not.i = icmp eq i32 %2, 0
+ %cmp2.i = icmp eq i32 %0, 3
+ %narrow.not = or i1 %cmp2.i, %or.cond.not.i
+ %. = select i1 %narrow.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 1 && CC != 2 && CC != 3.
+define dso_local range(i64 5, 9) i64 @fu_123() local_unnamed_addr #0 {
+; CHECK-LABEL: fu_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB19_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %narrow.not = icmp eq i32 %0, 0
+ %. = select i1 %narrow.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC != 0 && CC != 1.
+define void @bar_01(){
+; CHECK-LABEL: bar_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnle dummy at PLT
+; CHECK-NEXT: .LBB20_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ult i32 %0, 2
+ br i1 %2, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+declare void @dummy() local_unnamed_addr #1
+
+; Test CC != 0 && CC != 2.
+define void @bar_02(){
+; CHECK-LABEL: bar_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnhe dummy at PLT
+; CHECK-NEXT: .LBB21_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not = icmp eq i32 %2, 0
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 0 && CC != 3.
+define void @bar_03(){
+; CHECK-LABEL: bar_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB22_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ switch i32 %0, label %if.then [
+ i32 3, label %if.end
+ i32 0, label %if.end
+ ]
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %entry, %if.then
+ ret void
+}
+
+; Test CC != 1 && CC != 2.
+define void @bar_12(){
+; CHECK-LABEL: bar_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnlh dummy at PLT
+; CHECK-NEXT: .LBB23_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -1
+ %3 = icmp ult i32 %2, 2
+ br i1 %3, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 1 && CC != 3.
+define void @bar_13(){
+; CHECK-LABEL: bar_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jghe dummy at PLT
+; CHECK-NEXT: .LBB24_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 2 && CC != 3.
+define void @bar_23(){
+; CHECK-LABEL: bar_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB25_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %3 = icmp samesign ugt i32 %2, -3
+ br i1 %3, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 0 && CC != 1 && CC != 2.
+define void @bar_012(){
+; CHECK-LABEL: bar_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB26_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %narrow.not = icmp eq i32 %0, 3
+ br i1 %narrow.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 0 && CC != 1 && CC != 3.
+define void @bar_013(){
+; CHECK-LABEL: bar_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgh dummy at PLT
+; CHECK-NEXT: .LBB27_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %switch = icmp eq i32 %0, 2
+ br i1 %switch, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+; Test CC != 0 && CC != 2 && CC != 3.
+define void @bar_023(){
+; CHECK-LABEL: bar_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB28_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %or.cond.not.i = icmp eq i32 %2, 0
+ %cmp2.i = icmp eq i32 %0, 3
+ %narrow.not = or i1 %cmp2.i, %or.cond.not.i
+ br i1 %narrow.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 1 && CC != 2 && CC != 3.
+define void @bar_123(){
+; CHECK-LABEL: bar_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB29_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %narrow.not = icmp eq i32 %0, 0
+ br i1 %narrow.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed.ll
new file mode 100644
index 0000000000000..46e162f697a73
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed.ll
@@ -0,0 +1,2427 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations.
+; This tests mixing XOR wirh OR, XOR with AND and OR with AND with
+; different ways of parenthesizing with == operator.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O3 | FileCheck %s
+
+declare void @llvm.assume(i1 noundef)
+
+ at a = dso_local global i32 0, align 4
+
+; Test ((cc == 0) || (cc == 1)) ^ (cc == 2)
+define signext range(i32 0, 43) i32 @bar_012_OR_XOR(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB0_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %xor6.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+
+; Test ((cc == 0) || (cc == 1)) ^ (cc == 3)
+define signext range(i32 0, 43) i32 @bar_013_OR_XOR(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB1_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ult i32 %asmresult1, 2
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %xor6 = xor i1 %2, %cmp3
+ %cond = select i1 %xor6, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 0) || (cc == 2)) ^ (cc == 3)
+define signext range(i32 0, 43) i32 @bar_023_OR_XOR(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnlr %r14
+; CHECK-NEXT: .LBB2_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %asmresult1 to i1
+ %3 = icmp ne i32 %asmresult1, 3
+ %tobool.not.not = xor i1 %3, %2
+ %cond = select i1 %tobool.not.not, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 1) || (cc == 2)) ^ (cc == 3)
+define signext range(i32 0, 43) i32 @bar_123_OR_XOR(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bner %r14
+; CHECK-NEXT: .LBB3_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %3 = icmp ult i32 %2, 2
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %xor6 = xor i1 %cmp3, %3
+ %cond = select i1 %xor6, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc == 2)
+define signext range(i32 0, 43) i32 @foo_012_XOR_OR(i32 noundef signext %x) {
+; CHECK-LABEL: foo_012_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB4_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc == 3)
+define signext range(i32 0, 43) i32 @foo_013_XOR_OR(i32 noundef signext %x) {
+; CHECK-LABEL: foo_013_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB5_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor8 = icmp samesign ult i32 %asmresult1, 2
+ %cmp4 = icmp eq i32 %asmresult1, 3
+ %2 = or i1 %xor8, %cmp4
+ %cond = select i1 %2, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 0) ^ (cc == 2)) || (cc == 3)
+define signext range(i32 0, 43) i32 @foo_023_XOR_OR(i32 noundef signext %x) {
+; CHECK-LABEL: foo_023_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnlr %r14
+; CHECK-NEXT: .LBB6_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %cmp2 = icmp eq i32 %asmresult1, 2
+ %xor8 = xor i1 %cmp, %cmp2
+ %cmp4 = icmp eq i32 %asmresult1, 3
+ %2 = or i1 %cmp4, %xor8
+ %cond = select i1 %2, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 1) ^ (cc == 2)) || (cc == 3)
+define signext range(i32 0, 43) i32 @foo_123_XOR_OR(i32 noundef signext %x) {
+; CHECK-LABEL: foo_123_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bner %r14
+; CHECK-NEXT: .LBB7_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %3 = icmp ult i32 %2, 3
+ %cond = select i1 %3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (cc == 0) || ((cc == 1) ^ (cc == 2))
+define range(i64 5, 9) i64 @fu_012_OR_XOR_a() {
+; CHECK-LABEL: fu_012_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB8_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 3
+ %. = select i1 %xor6.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc == 1)) ^ (cc == 2)
+define range(i64 5, 9) i64 @fu_012_OR_XOR_c() {
+; CHECK-LABEL: fu_012_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB9_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i.not = icmp eq i32 %0, 3
+ %. = select i1 %xor5.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) ^ ((cc == 1) || (cc == 2))
+define range(i64 5, 9) i64 @fu_012_XOR_OR_a() {
+; CHECK-LABEL: fu_012_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB10_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %tobool.not = icmp eq i32 %0, 3
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc == 2)
+define range(i64 5, 9) i64 @fu_012_XOR_OR_c() {
+; CHECK-LABEL: fu_012_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB11_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %.not = icmp eq i32 %0, 3
+ %. = select i1 %.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) || ((cc == 1) ^ (cc == 3))
+define range(i64 5, 9) i64 @fu_013_OR_XOR_a() {
+; CHECK-LABEL: fu_013_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB12_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp ne i32 %0, 0
+ %2 = and i32 %0, 1
+ %xor6.i.not = icmp eq i32 %2, 0
+ %narrow.not = and i1 %cmp.i, %xor6.i.not
+ %. = select i1 %narrow.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc == 1)) ^ (cc == 3)
+define range(i64 5, 9) i64 @fu_013_OR_XOR_c() {
+; CHECK-LABEL: fu_013_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB13_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ugt i32 %0, 1
+ %3 = icmp ne i32 %0, 3
+ %tobool.not = and i1 %2, %3
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) ^ ((cc == 1) || (cc == 3))
+define range(i64 5, 9) i64 @fu_013_XOR_OR_a() {
+; CHECK-LABEL: fu_013_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB14_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp ne i32 %0, 0
+ %tobool.not = xor i1 %3, %2
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc == 3)
+define range(i64 5, 9) i64 @fu_013_XOR_OR_c() {
+; CHECK-LABEL: fu_013_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB15_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i = icmp samesign ugt i32 %0, 1
+ %cmp3.i = icmp ne i32 %0, 3
+ %.not = and i1 %xor7.i, %cmp3.i
+ %. = select i1 %.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) || ((cc == 2) ^ (cc == 3))
+define range(i64 5, 9) i64 @fu_023_OR_XOR_a() {
+; CHECK-LABEL: fu_023_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB16_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 1
+ %. = select i1 %xor6.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc == 2)) ^ (cc == 3)
+define range(i64 5, 9) i64 @fu_023_OR_XOR_c() {
+; CHECK-LABEL: fu_023_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bnlr %r14
+; CHECK-NEXT: .LBB17_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp ne i32 %0, 3
+ %tobool.not.not = xor i1 %3, %2
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 0) ^ ((cc == 2) || (cc == 3)).
+define range(i64 5, 9) i64 @fu_023_XOR_OR_a() {
+; CHECK-LABEL: fu_023_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB18_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i.not = icmp eq i32 %0, 1
+ %. = select i1 %xor7.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; ((cc == 0) ^ (cc == 2)) || (cc == 3)
+define range(i64 5, 9) i64 @fu_023_XOR_OR_c() {
+; CHECK-LABEL: fu_023_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB19_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %xor7.i.not = icmp ne i32 %2, 0
+ %cmp3.i = icmp ne i32 %0, 3
+ %.not = and i1 %cmp3.i, %xor7.i.not
+ %. = select i1 %.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 1) || ((cc == 2) ^ (cc == 3))
+define range(i64 5, 9) i64 @fu_123_OR_XOR_a() {
+; CHECK-LABEL: fu_123_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB20_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 0
+ %. = select i1 %xor6.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 1) || (cc == 2)) ^ (cc == 3)
+define range(i64 5, 9) i64 @fu_123_OR_XOR_c() {
+; CHECK-LABEL: fu_123_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB21_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %tobool.not = icmp eq i32 %0, 0
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 1 ) ^ ((cc == 2) || (cc == 3)).
+define range(i64 5, 9) i64 @fu_123_XOR_OR_a() {
+; CHECK-LABEL: fu_123_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB22_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i.not = icmp eq i32 %0, 0
+ %. = select i1 %xor7.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 1) ^ (cc == 2)) || (cc == 3)
+define range(i64 5, 9) i64 @fu_123_XOR_OR_c() {
+; CHECK-LABEL: fu_123_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB23_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp eq i32 %0, 0
+ %. = select i1 %2, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) || ((cc == 1) ^ (cc == 2))
+define i64 @bar_012_OR_XOR_a() {
+; CHECK-LABEL: bar_012_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB24_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 3
+ br i1 %xor6.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 1)) ^ (cc == 2)
+define i64 @bar_012_OR_XOR_c() {
+; CHECK-LABEL: bar_012_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB25_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i.not = icmp eq i32 %0, 3
+ br i1 %xor5.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) ^ ((cc == 1) || (cc == 2))
+define i64 @bar_012_XOR_OR_a() {
+; CHECK-LABEL: bar_012_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB26_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %tobool.not = icmp eq i32 %0, 3
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc == 2)
+define i64 @bar_012_XOR_OR_c() {
+; CHECK-LABEL: bar_012_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB27_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %.not = icmp eq i32 %0, 3
+ br i1 %.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) || ((cc == 1) ^ (cc == 3))
+define i64 @bar_013_OR_XOR_a() {
+; CHECK-LABEL: bar_013_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB28_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp ne i32 %0, 0
+ %2 = and i32 %0, 1
+ %xor6.i.not = icmp eq i32 %2, 0
+ %narrow.not = and i1 %cmp.i, %xor6.i.not
+ br i1 %narrow.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 1)) ^ (cc == 3)
+define i64 @bar_013_OR_XOR_c() {
+; CHECK-LABEL: bar_013_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB29_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %switch = icmp eq i32 %0, 2
+ br i1 %switch, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret i64 undef
+}
+
+; Test (cc == 0) ^ ((cc == 1) || (cc == 3))
+define i64 @bar_013_XOR_OR_a() {
+; CHECK-LABEL: bar_013_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB30_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp ne i32 %0, 0
+ %tobool.not = xor i1 %3, %2
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc == 3)
+define i64 @bar_013_XOR_OR_c() {
+; CHECK-LABEL: bar_013_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB31_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %switch = icmp eq i32 %0, 2
+ br i1 %switch, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret i64 undef
+}
+
+; Test (cc == 0) || ((cc == 2) ^ (cc == 3))
+define i64 @bar_023_OR_XOR_a() {
+; CHECK-LABEL: bar_023_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB32_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 1
+ br i1 %xor6.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 2)) ^ (cc == 3)
+define i64 @bar_023_OR_XOR_c() {
+; CHECK-LABEL: bar_023_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB33_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp ne i32 %0, 3
+ %tobool.not.not = xor i1 %3, %2
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) ^ ((cc == 2) || (cc == 3))
+define i64 @bar_023_XOR_OR_a() {
+; CHECK-LABEL: bar_023_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB34_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i.not = icmp eq i32 %0, 1
+ br i1 %xor7.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc == 2)) || (cc == 3)
+define i64 @bar_023_XOR_OR_c() {
+; CHECK-LABEL: bar_023_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB35_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %xor7.i.not = icmp ne i32 %2, 0
+ %cmp3.i = icmp ne i32 %0, 3
+ %.not = and i1 %cmp3.i, %xor7.i.not
+ br i1 %.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1) || ((cc == 2) ^ (cc == 3))
+define i64 @bar_123_OR_XOR_a() {
+; CHECK-LABEL: bar_123_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB36_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 0
+ br i1 %xor6.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) || (cc == 2)) ^ (cc == 3)
+define i64 @bar_123_OR_XOR_c() {
+; CHECK-LABEL: bar_123_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB37_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %tobool.not = icmp eq i32 %0, 0
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1 ) ^ ((cc == 2) || (cc == 3))
+define i64 @bar_123_XOR_OR_a() {
+; CHECK-LABEL: bar_123_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB38_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i.not = icmp eq i32 %0, 0
+ br i1 %xor7.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) ^ (cc == 2)) || (cc == 3)
+define i64 @bar_123_XOR_OR_c() {
+; CHECK-LABEL: bar_123_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB39_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp eq i32 %0, 0
+ br i1 %2, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test OR_AND and AND_OR
+; Test (((cc == 0) || (cc == 1)) && (cc == 3))
+define noundef signext range(i32 0, 43) i32 @bar_013_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test (((cc == 0) || (cc == 2)) && (cc == 3))
+define noundef signext range(i32 0, 43) i32 @bar_023_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test (((cc == 1) || (cc == 2)) && (cc == 3))
+define noundef signext range(i32 0, 43) i32 @bar_123_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test (((cc == 0) && (cc == 1)) || (cc == 2))
+define signext range(i32 0, 43) i32 @bar_012_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB43_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc == 1)) || (cc == 3))
+define signext range(i32 0, 43) i32 @bar_013_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB44_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc == 2)) || (cc == 3))
+define signext range(i32 0, 43) i32 @bar_023_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB45_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 1) && (cc == 2)) || (cc == 3))
+define signext range(i32 0, 43) i32 @bar_123_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB46_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 0) && ((cc == 1)) || (cc == 2))
+define signext range(i32 0, 43) i32 @bar_012_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB47_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 0) && ((cc == 1)) || (cc == 3))
+define signext range(i32 0, 43) i32 @bar_013_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB48_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 0) && ((cc == 2)) || (cc == 3))
+define signext range(i32 0, 43) i32 @bar_023_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB49_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 1) && ((cc == 2)) || (cc == 3))
+define signext range(i32 0, 43) i32 @bar_123_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB50_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) ^ (cc == 1)) && (cc == 2))
+define noundef signext range(i32 0, 43) i32 @bar_012_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test (((cc == 0) ^ (cc == 1)) && (cc == 3))
+define noundef signext range(i32 0, 43) i32 @bar_013_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test (((cc == 0) ^ (cc == 2)) && (cc == 3))
+define noundef signext range(i32 0, 43) i32 @bar_023_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test (((cc == 1) ^ (cc == 2)) && (cc == 3))
+define noundef signext range(i32 0, 43) i32 @bar_123_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test ((cc == 0) && (cc == 1)) ^ (cc == 2))
+define signext range(i32 0, 43) i32 @bar_012_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB55_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 0) && (cc == 1)) ^ (cc == 3))
+define signext range(i32 0, 43) i32 @bar_013_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB56_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 0) && (cc == 2)) ^ (cc == 3))
+define signext range(i32 0, 43) i32 @bar_023_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB57_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 1) && (cc == 2)) ^ (cc == 3))
+define signext range(i32 0, 43) i32 @bar_123_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB58_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 0) && ((cc == 1)) ^ (cc == 2))
+define noundef signext i32 @bar_012_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test ((cc == 0) && ((cc == 1)) ^ (cc == 3))
+define noundef signext i32 @bar_013_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test ((cc == 0) && ((cc == 2)) ^ (cc == 3))
+define noundef signext i32 @bar_023_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test ((cc == 1) && ((cc == 2)) ^ (cc == 3))
+define noundef signext i32 @bar_123_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test ((cc == 0) || (cc == 1)) && (cc == 2)
+define noundef range(i64 5, 9) i64 @fu_012_OR_AND() {
+; CHECK-LABEL: fu_012_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) && (cc == 1)) || (cc == 2)
+define range(i64 5, 9) i64 @fu_012_AND_OR_a() {
+; CHECK-LABEL: fu_012_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB64_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc == 1) || (cc == 2)
+define noundef i64 @fu_012_AND_OR_b() {
+; CHECK-LABEL: fu_012_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) || (cc == 1)) && (cc == 3)
+define noundef range(i64 5, 9) i64 @fu_013_OR_AND() {
+; CHECK-LABEL: fu_013_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) && (cc == 1)) || (cc == 3)
+define range(i64 5, 9) i64 @fu_013_XOR_AND_OR_a() {
+; CHECK-LABEL: fu_013_XOR_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB67_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc == 1) || (cc == 3))
+define noundef i64 @fu_013_AND_OR_b() {
+; CHECK-LABEL: fu_013_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) || (cc == 2)) && (cc == 3)
+define noundef range(i64 5, 9) i64 @fu_023_OR_AND() {
+; CHECK-LABEL: fu_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) && (cc == 2)) || (cc == 3)
+define range(i64 5, 9) i64 @fu_023_AND_OR_a() {
+; CHECK-LABEL: fu_023_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB70_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc == 2) || (cc == 3)
+define noundef i64 @fu_023_AND_OR_b() {
+; CHECK-LABEL: fu_023_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 1) || (cc == 2)) && (cc == 3)
+define noundef range(i64 5, 9) i64 @fu_123_OR_AND() {
+; CHECK-LABEL: fu_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 1) && (cc == 2)) || (cc == 3)
+define range(i64 5, 9) i64 @fu_123_AND_OR_a() {
+; CHECK-LABEL: fu_123_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB73_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 1) && ((cc == 2) || (cc == 3))
+define noundef i64 @fu_123_AND_OR_b() {
+; CHECK-LABEL: fu_123_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) ^ (cc == 1)) && (cc == 2)
+define noundef range(i64 5, 9) i64 @fu_012_XOR_AND() {
+; CHECK-LABEL: fu_012_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) && (cc == 1)) ^ (cc == 2)
+define range(i64 5, 9) i64 @fu_012_AND_XOR_a() {
+; CHECK-LABEL: fu_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB76_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc == 1) ^ (cc == 2))
+define noundef i64 @fu_012_AND_XOR_b() {
+; CHECK-LABEL: fu_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) ^ (cc == 1)) && (cc == 3)
+define noundef range(i64 5, 9) i64 @fu_013_XOR_AND() {
+; CHECK-LABEL: fu_013_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) ^ (cc == 1)) && (cc == 3)
+define range(i64 5, 9) i64 @fu_013_XOR_AND_XOR_a() {
+; CHECK-LABEL: fu_013_XOR_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB79_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc == 1)) ^ (cc == 3)
+define noundef i64 @fu_013_AND_XOR_b() {
+; CHECK-LABEL: fu_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) || (cc == 2)) ^ (cc == 3)
+define range(i64 5, 9) i64 @fu_023_XOR_AND() {
+; CHECK-LABEL: fu_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) && (cc == 2)) ^ (cc == 3)
+define range(i64 5, 9) i64 @fu_023_AND_XOR_a() {
+; CHECK-LABEL: fu_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB82_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc == 2) ^ (cc == 3))
+define noundef i64 @fu_023_AND_XOR_b() {
+; CHECK-LABEL: fu_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 1) ^ (cc == 2)) && (cc == 3)
+define noundef range(i64 5, 9) i64 @fu_123_XOR_AND() {
+; CHECK-LABEL: fu_123_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 1) && (cc == 2)) ^ (cc == 3)
+define range(i64 5, 9) i64 @fu_123_AND_XOR_a() {
+; CHECK-LABEL: fu_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB85_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 1) && ((cc == 2) ^ (cc == 3))
+define noundef i64 @fu_123_AND_XOR_b() {
+; CHECK-LABEL: fu_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) || (cc == 1)) && (cc == 2
+define i64 @bar1_012_OR_AND() {
+; CHECK-LABEL: bar1_012_OR_AND:
+; CHECK: # %bb.0: # %if.end
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+if.end:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+declare void @dummy() local_unnamed_addr #1
+
+; Test ((cc == 0) && (cc == 1)) || (cc == 2)
+define i64 @bar1_012_AND_OR_a() {
+; CHECK-LABEL: bar1_012_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgh dummy at PLT
+; CHECK-NEXT: .LBB88_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc == 1) || (cc == 2)
+define i64 @bar1_012_AND_OR_b() {
+; CHECK-LABEL: bar1_012_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 1)) && (cc == 3)
+define i64 @bar1_013_OR_AND() {
+; CHECK-LABEL: bar1_013_OR_AND:
+; CHECK: # %bb.0: # %if.end
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+if.end:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 1)) || (cc == 3)
+define i64 @bar1_013_XOR_AND_OR_a() {
+; CHECK-LABEL: bar1_013_XOR_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB91_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc == 1) || (cc == 3))
+define i64 @bar1_013_AND_OR_b() {
+; CHECK-LABEL: bar1_013_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 2)) && (cc == 3)
+define i64 @bar1_023_OR_AND() {
+; CHECK-LABEL: bar1_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 2)) || (cc == 3)
+define i64 @bar1_023_AND_OR_a() {
+; CHECK-LABEL: bar1_023_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB94_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc == 2) || (cc == 3)
+define i64 @bar1_023_AND_OR_b() {
+; CHECK-LABEL: bar1_023_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 1) || (cc == 2)) && (cc == 3)
+define i64 @bar1_123_OR_AND() {
+; CHECK-LABEL: bar1_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 1) && (cc == 2)) || (cc == 3)
+define i64 @bar1_123_AND_OR_a() {
+; CHECK-LABEL: bar1_123_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB97_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1) && ((cc == 2) || (cc == 3))
+define i64 @bar1_123_AND_OR_b() {
+; CHECK-LABEL: bar1_123_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc == 1)) && (cc == 2)
+define i64 @bar1_012_XOR_AND() {
+; CHECK-LABEL: bar1_012_XOR_AND:
+; CHECK: # %bb.0: # %if.end
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+if.end:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 1)) ^ (cc == 2)
+define i64 @bar1_012_AND_XOR_a() {
+; CHECK-LABEL: bar1_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgh dummy at PLT
+; CHECK-NEXT: .LBB100_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc == 1) ^ (cc == 2))
+define i64 @bar1_012_AND_XOR_b() {
+; CHECK-LABEL: bar1_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc == 1)) && (cc == 3)
+define i64 @bar1_013_XOR_AND() {
+; CHECK-LABEL: bar1_013_XOR_AND:
+; CHECK: # %bb.0: # %if.end
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+if.end:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc == 1)) && (cc == 3)
+define i64 @bar1_013_XOR_AND_XOR_a() {
+; CHECK-LABEL: bar1_013_XOR_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB103_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 1)) ^ (cc == 3)
+define i64 @bar1_013_AND_XOR_b() {
+; CHECK-LABEL: bar1_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 2)) ^ (cc == 3)
+define i64 @bar1_023_XOR_AND() {
+; CHECK-LABEL: bar1_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 2)) ^ (cc == 3)
+define i64 @bar1_023_AND_XOR_a() {
+; CHECK-LABEL: bar1_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB106_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 2)) ^ (cc == 3)
+define i64 @bar1_023_AND_XOR_b() {
+; CHECK-LABEL: bar1_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 1) ^ (cc == 2)) && (cc == 3)
+define i64 @bar1_123_XOR_AND() {
+; CHECK-LABEL: bar1_123_XOR_AND:
+; CHECK: # %bb.0: # %if.end
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+if.end:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 1) && (cc == 2)) ^ (cc == 3)
+define i64 @bar1_123_AND_XOR_a() {
+; CHECK-LABEL: bar1_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB109_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1) && ((cc == 2) ^ (cc == 3))
+define i64 @bar1_123_AND_XOR_b() {
+; CHECK-LABEL: bar1_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_eq_noteq.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_eq_noteq.ll
new file mode 100644
index 0000000000000..3c071709b2e2a
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_eq_noteq.ll
@@ -0,0 +1,5248 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations.
+; Different ways of parenthesizing with mix of == and != operator for
+; AND/OR/XOR combinations.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O3 | FileCheck %s
+
+; Test ((cc == 0) || (cc != 1)) ^ (cc != 2)
+define signext range(i32 0, 43) i32 @bar_012_OR_XOR(i32 noundef signext %x){
+; CHECK-LABEL: bar_012_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB0_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %xor6 = icmp ult i32 %2, 2
+ %cond = select i1 %xor6, i32 42, i32 0
+ ret i32 %cond
+}
+
+declare void @llvm.assume(i1 noundef) #1
+
+; Test ((cc == 0) || (cc != 1)) ^ (cc != 3)
+define signext range(i32 0, 43) i32 @bar_013_OR_XOR(i32 noundef signext %x){
+; CHECK-LABEL: bar_013_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnher %r14
+; CHECK-NEXT: .LBB1_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2 = icmp ne i32 %asmresult1, 1
+ %cmp3 = icmp ne i32 %asmresult1, 3
+ %xor6 = xor i1 %cmp2, %cmp3
+ %cond = select i1 %xor6, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 0) || (cc != 2)) ^ (cc != 3)
+define signext range(i32 0, 43) i32 @bar_023_OR_XOR(i32 noundef signext %x){
+; CHECK-LABEL: bar_023_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB2_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6 = icmp samesign ugt i32 %asmresult1, 1
+ %cond = select i1 %xor6, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 1) || (cc != 2)) ^ (cc != 3)
+define signext range(i32 0, 43) i32 @bar_123_OR_XOR(i32 noundef signext %x){
+; CHECK-LABEL: bar_123_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB3_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6 = icmp samesign ugt i32 %asmresult1, 1
+ %cond = select i1 %xor6, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc != 2)
+define signext range(i32 0, 43) i32 @foo_012_XOR_OR(i32 noundef signext %x){
+; CHECK-LABEL: foo_012_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB4_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp4.not = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp4.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc != 3)
+define signext range(i32 0, 43) i32 @foo_013_XOR_OR(i32 noundef signext %x){
+; CHECK-LABEL: foo_013_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB5_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp4.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp4.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc == 0) ^ (cc == 2)) || (cc != 3)
+define signext range(i32 0, 43) i32 @foo_023_XOR_OR(i32 noundef signext %x){
+; CHECK-LABEL: foo_023_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB6_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp4.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp4.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc == 1) ^ (cc == 2)) || (cc != 3)
+define signext range(i32 0, 43) i32 @foo_123_XOR_OR(i32 noundef signext %x){
+; CHECK-LABEL: foo_123_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB7_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp4.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp4.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc == 0) || (cc != 1)) && (cc != 2))
+define signext range(i32 0, 43) i32 @bar_012_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB8_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %3 = icmp ult i32 %2, 2
+ %cond = select i1 %3, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc == 0) || (cc != 1)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar_013_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB9_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %.not = icmp eq i32 %2, 0
+ %cond = select i1 %.not, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) || (cc != 2)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar_023_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB10_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %.not = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %.not, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 1) || (cc != 2)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar_123_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB11_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %.not = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %.not, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc != 1)) || (cc != 2))
+define signext range(i32 0, 43) i32 @bar_012_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB12_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 2
+ %2 = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %2
+}
+
+; Test (((cc == 0) && (cc != 1)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar_013_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB13_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %2 = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %2
+}
+
+; Test (((cc == 0) && (cc != 2)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar_023_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB14_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %2 = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %2
+}
+
+; Test (((cc == 1) && (cc != 2)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar_123_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB15_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %2 = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %2
+}
+
+; Test ((cc == 0) && ((cc != 1)) || (cc != 2))
+define signext range(i32 0, 43) i32 @bar_012_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB16_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 2
+ %2 = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %2
+}
+
+; Test ((cc == 0) && ((cc != 1)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar_013_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB17_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %2 = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %2
+}
+
+; Test ((cc == 0) && ((cc != 2)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar_023_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB18_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %2 = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %2
+}
+
+; Test ((cc == 1) && ((cc != 2)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar_123_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB19_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %2 = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %2
+}
+
+; Test ((cc == 1) && ((cc != 2)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar_012_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB20_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %2, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) ^ (cc != 1)) && (cc != 2))
+define signext range(i32 0, 43) i32 @bar_013_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB21_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor8 = icmp samesign ugt i32 %asmresult1, 1
+ %cmp4 = icmp ne i32 %asmresult1, 3
+ %2 = and i1 %xor8, %cmp4
+ %cond = select i1 %2, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) ^ (cc != 2)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar_023_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB22_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %tobool = icmp ne i32 %2, 0
+ %cmp4 = icmp ne i32 %asmresult1, 3
+ %3 = and i1 %cmp4, %tobool
+ %cond = select i1 %3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 1) ^ (cc != 2)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar_123_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB23_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp eq i32 %asmresult1, 0
+ %cond = select i1 %2, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc != 1)) ^ (cc != 2))
+define signext range(i32 0, 43) i32 @bar_012_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB24_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %tobool.not = icmp eq i32 %2, 0
+ %cond = select i1 %tobool.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc != 1)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar_013_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB25_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp ne i32 %asmresult1, 0
+ %cmp3 = icmp ne i32 %asmresult1, 3
+ %xor6 = and i1 %cmp, %cmp3
+ %cond = select i1 %xor6, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc != 2)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar_023_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB26_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp ne i32 %asmresult1, 0
+ %cmp3 = icmp ne i32 %asmresult1, 3
+ %xor6 = and i1 %cmp, %cmp3
+ %cond = select i1 %xor6, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 1) && (cc != 1)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar_123_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB27_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %cond = select i1 %tobool.not.not, i32 42, i32 0
+ ret i32 %cond
+}
+
+; ((cc == 0) && ((cc != 1)) ^ (cc != 2))
+define noundef signext i32 @bar_012_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test ((cc == 0) && ((cc != 1)) ^ (cc != 3))
+define noundef signext i32 @bar_013_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test ((cc == 0) && ((cc != 2)) ^ (cc != 3))
+define noundef signext i32 @bar_023_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test ((cc == 1) && ((cc != 2)) ^ (cc != 3))
+define noundef signext i32 @bar_123_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 0
+}
+
+; Test (((cc == 0) || (cc == 1)) && (cc != 2))
+define signext range(i32 0, 43) i32 @bar1_012_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_012_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB32_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %or.cond = icmp samesign ult i32 %asmresult1, 2
+ %spec.select = select i1 %or.cond, i32 42, i32 0
+ ret i32 %spec.select
+}
+
+; Test (((cc == 0) || (cc == 1)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_013_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_013_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB33_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %or.cond = icmp samesign ult i32 %asmresult1, 2
+ %spec.select = select i1 %or.cond, i32 42, i32 0
+ ret i32 %spec.select
+}
+
+; Test (((cc == 0) || (cc == 2)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_023_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lhi %r0, 0
+; CHECK-NEXT: jno .LBB34_3
+; CHECK-NEXT: # %bb.1: # %entry
+; CHECK-NEXT: jnhe .LBB34_4
+; CHECK-NEXT: .LBB34_2: # %entry
+; CHECK-NEXT: llgfr %r2, %r0
+; CHECK-NEXT: br %r14
+; CHECK-NEXT: .LBB34_3: # %entry
+; CHECK-NEXT: lhi %r0, 42
+; CHECK-NEXT: jhe .LBB34_2
+; CHECK-NEXT: .LBB34_4: # %entry
+; CHECK-NEXT: lhi %r0, 0
+; CHECK-NEXT: llgfr %r2, %r0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %or.cond = icmp eq i32 %2, 0
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %3 = select i1 %cmp3.not, i32 0, i32 42
+ %cond = select i1 %or.cond, i32 %3, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 1) || (cc == 2)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_123_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB35_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %or.cond = icmp ult i32 %2, 2
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %3 = select i1 %cmp3.not, i32 0, i32 42
+ %cond = select i1 %or.cond, i32 %3, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc == 1)) || (cc != 2))
+define signext range(i32 0, 43) i32 @bar1_012_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_012_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB36_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc == 1)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_013_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_013_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB37_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc == 2)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_023_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_023_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB38_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc == 1) && (cc == 2)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_123_AND_OR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_123_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB39_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc == 0) && ((cc == 1)) || (cc != 2))
+define signext range(i32 0, 43) i32 @bar1_012_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_012_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB40_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc == 0) && ((cc == 1)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_013_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_013_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB41_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc == 0) && ((cc == 2)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_023_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_023_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB42_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc == 1) && ((cc == 2)) || (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_123_AND_OR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_123_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB43_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc == 1)) ^ (cc != 2))
+define signext range(i32 0, 43) i32 @bar1_012_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_012_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB44_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor8 = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %xor8, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc == 1)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_013_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_013_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB45_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor8 = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %xor8, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc == 2)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_023_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB46_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %cmp2 = icmp eq i32 %asmresult1, 2
+ %xor8 = xor i1 %cmp, %cmp2
+ %cond = select i1 %xor8, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 1) && (cc == 2)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_123_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_123_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB47_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %xor8 = icmp ult i32 %2, 2
+ %cond = select i1 %xor8, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc == 1)) ^ (cc != 2)
+define signext range(i32 0, 43) i32 @bar1_012_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB48_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc == 1)) ^ (cc != 3)
+define signext range(i32 0, 43) i32 @bar1_013_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_013_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB49_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc == 0) && (cc == 2)) ^ (cc != 3)
+define signext range(i32 0, 43) i32 @bar1_023_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB50_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc == 1) && (cc == 2)) ^ (cc != 3)
+define signext range(i32 0, 43) i32 @bar1_123_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB51_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc == 0) && ((cc == 1)) ^ (cc != 2))
+define signext range(i32 0, 43) i32 @bar1_012_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB52_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %spec.select = select i1 %cmp, i32 42, i32 0
+ ret i32 %spec.select
+}
+
+; Test ((cc == 0) && ((cc == 1)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_013_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB53_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %spec.select = select i1 %cmp, i32 42, i32 0
+ ret i32 %spec.select
+}
+
+; Test ((cc == 0) && ((cc == 2)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_023_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB54_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %spec.select = select i1 %cmp, i32 42, i32 0
+ ret i32 %spec.select
+}
+
+; Test ((cc == 1) && ((cc == 2)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar1_123_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar1_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB55_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 1
+ %spec.select = select i1 %cmp, i32 42, i32 0
+ ret i32 %spec.select
+}
+
+ at a = global i32 0, align 4
+; Test ((cc == 0) || (cc != 1)) && (cc != 2)
+define range(i64 5, 9) i64 @fua_012_OR_AND() {
+; CHECK-LABEL: fua_012_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB56_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -1
+ %narrow = icmp ult i32 %2, 2
+ %. = select i1 %narrow, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc != 1)) || (cc != 2)
+define range(i64 5, 9) i64 @fua_012_AND_OR_a() {
+; CHECK-LABEL: fua_012_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB57_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc != 1) || (cc != 2))
+define range(i64 5, 9) i64 @fua_012_AND_OR_b() {
+; CHECK-LABEL: fua_012_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB58_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc != 1)) && (cc != 3)
+define range(i64 5, 9) i64 @fua_013_OR_AND() {
+; CHECK-LABEL: fua_013_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB59_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc != 1)) || (cc != 3).
+define range(i64 5, 9) i64 @fua_013_AND_OR_a() {
+; CHECK-LABEL: fua_013_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB60_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc != 1) || (cc != 3))
+define range(i64 5, 9) i64 @fua_013_AND_OR_b() {
+; CHECK-LABEL: fua_013_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB61_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc != 2)) && (cc != 3)
+define range(i64 5, 9) i64 @fua_023_OR_AND() {
+; CHECK-LABEL: fua_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB62_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %narrow = icmp samesign ugt i32 %2, -3
+ %. = select i1 %narrow, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc != 2)) || (cc != 3)
+define range(i64 5, 9) i64 @fua_023_AND_OR_a() {
+; CHECK-LABEL: fua_023_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB63_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc != 2) || (cc != 3)).
+define range(i64 5, 9) i64 @fua_023_AND_OR_b() {
+; CHECK-LABEL: fua_023_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB64_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 1) || (cc != 2)) && (cc != 3)
+define range(i64 5, 9) i64 @fua_123_OR_AND() {
+; CHECK-LABEL: fua_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB65_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %narrow = icmp samesign ugt i32 %2, -3
+ %. = select i1 %narrow, i64 8, i64 5
+ ret i64 %.
+}
+
+; Tset ((cc == 1) && (cc != 2)) || (cc != 3).
+define range(i64 5, 9) i64 @fua_123_AND_OR_a() {
+; CHECK-LABEL: fua_123_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB66_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 1) && ((cc != 2) || (cc != 3)).
+define range(i64 5, 9) i64 @fua_123_AND_OR_b() {
+; CHECK-LABEL: fua_123_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB67_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc != 1)) && (cc != 2)
+define range(i64 5, 9) i64 @fua_012_XOR_AND() {
+; CHECK-LABEL: fua_012_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB68_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %.not = icmp eq i32 %0, 3
+ %. = select i1 %.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc != 1)) ^ (cc != 2)
+define range(i64 5, 9) i64 @fua_012_AND_XOR_a() {
+; CHECK-LABEL: fua_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB69_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc != 1)) && (cc != 3).
+define noundef i64 @fua_012_AND_XOR_b() {
+; CHECK-LABEL: fua_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) && (cc != 1)) ^ (cc != 3).
+define range(i64 5, 9) i64 @fua_013_XOR_AND() {
+; CHECK-LABEL: fua_013_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB71_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i = icmp samesign ult i32 %0, 2
+ %cmp3.i = icmp eq i32 %0, 3
+ %.not = or i1 %xor7.i, %cmp3.i
+ %. = select i1 %.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc != 1) ^ (cc != 3))
+define range(i64 5, 9) i64 @fua_013_XOR_AND_XOR_a() {
+; CHECK-LABEL: fua_013_XOR_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB72_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp eq i32 %0, 0
+ %cmp2.i = icmp eq i32 %0, 3
+ %xor5.i.not = or i1 %cmp.i, %cmp2.i
+ %. = select i1 %xor5.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc != 1) ^ (cc != 3)).
+define noundef i64 @fua_013_AND_XOR_b() {
+; CHECK-LABEL: fua_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) && (cc != 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fua_023_XOR_AND() {
+; CHECK-LABEL: fua_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB74_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp eq i32 %0, 0
+ %cmp2.i = icmp eq i32 %0, 3
+ %xor5.i.not = or i1 %cmp.i, %cmp2.i
+ %. = select i1 %xor5.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc != 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fua_023_AND_XOR_a() {
+; CHECK-LABEL: fua_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB75_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp eq i32 %0, 0
+ %cmp2.i = icmp eq i32 %0, 3
+ %xor5.i.not = or i1 %cmp.i, %cmp2.i
+ %. = select i1 %xor5.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc != 2) ^ (cc != 3)).
+define noundef i64 @fua_023_AND_XOR_b() {
+; CHECK-LABEL: fua_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 1) ^ (cc != 2)) && (cc != 3).
+define range(i64 5, 9) i64 @fua_123_XOR_AND() {
+; CHECK-LABEL: fua_123_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB77_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %.not = icmp eq i32 %0, 0
+ %. = select i1 %.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 1) && (cc != 2)) ^ (cc != 3).
+define range(i64 5, 9) i64 @fua_123_AND_XOR_a() {
+; CHECK-LABEL: fua_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB78_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 1) && ((cc != 2) ^ (cc != 3))
+define noundef i64 @fua_123_AND_XOR_b() {
+; CHECK-LABEL: fua_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 8
+}
+
+; Test ((cc == 0) || (cc != 1)) && (cc != 2)
+define i64 @bar1a_012_OR_AND() {
+; CHECK-LABEL: bar1a_012_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnlh dummy at PLT
+; CHECK-NEXT: .LBB80_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -1
+ %narrow = icmp ult i32 %2, 2
+ br i1 %narrow, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+declare void @dummy() local_unnamed_addr #1
+
+; Test ((cc == 0) && (cc != 1)) || (cc != 2)
+define i64 @bar1a_012_AND_OR_a() {
+; CHECK-LABEL: bar1a_012_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB81_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc != 1) || (cc != 2))
+define i64 @bar1a_012_AND_OR_b() {
+; CHECK-LABEL: bar1a_012_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB82_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc != 1)) && (cc != 3)
+define i64 @bar1a_013_OR_AND() {
+; CHECK-LABEL: bar1a_013_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jghe dummy at PLT
+; CHECK-NEXT: .LBB83_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc != 1)) || (cc != 3).
+define i64 @bar1a_013_XOR_AND_OR_a() {
+; CHECK-LABEL: bar1a_013_XOR_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB84_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc != 1) || (cc != 3))
+define i64 @bar1a_013_AND_OR_b() {
+; CHECK-LABEL: bar1a_013_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB85_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc != 2)) && (cc != 3)
+define i64 @bar1a_023_OR_AND() {
+; CHECK-LABEL: bar1a_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB86_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %narrow = icmp samesign ugt i32 %2, -3
+ br i1 %narrow, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc != 2)) || (cc != 3)
+define i64 @bar1a_023_AND_OR_a() {
+; CHECK-LABEL: bar1a_023_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB87_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc != 2) || (cc != 3)).
+define i64 @bar1a_023_AND_OR_b() {
+; CHECK-LABEL: bar1a_023_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB88_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) || (cc != 2)) && (cc != 3)
+define i64 @bar1a_123_OR_AND() {
+; CHECK-LABEL: bar1a_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB89_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %narrow = icmp samesign ugt i32 %2, -3
+ br i1 %narrow, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Tset ((cc == 1) && (cc != 2)) || (cc != 3).
+define i64 @bar1a_123_AND_OR_a() {
+; CHECK-LABEL: bar1a_123_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB90_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1) && ((cc != 2) || (cc != 3))
+define i64 @bar1a_123_AND_OR_b() {
+; CHECK-LABEL: bar1a_123_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB91_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc != 1)) && (cc != 2)
+define i64 @bar1a_012_XOR_AND() {
+; CHECK-LABEL: bar1a_012_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB92_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %.not = icmp eq i32 %0, 3
+ br i1 %.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc != 1)) ^ (cc != 2)
+define i64 @bar1a_012_AND_XOR_a() {
+; CHECK-LABEL: bar1a_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnhe dummy at PLT
+; CHECK-NEXT: .LBB93_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not = icmp eq i32 %2, 0
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc != 1)) && (cc != 3).
+define i64 @bar1a_012_AND_XOR_b() {
+; CHECK-LABEL: bar1a_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+define i64 @bar1a_013_XOR_AND() {
+; CHECK-LABEL: bar1a_013_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgh dummy at PLT
+; CHECK-NEXT: .LBB95_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %switch = icmp eq i32 %0, 2
+ br i1 %switch, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc != 1) ^ (cc != 3))
+define i64 @bar1a_013_XOR_AND_XOR_a() {
+; CHECK-LABEL: bar1a_013_XOR_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB96_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ switch i32 %0, label %if.then [
+ i32 3, label %if.end
+ i32 0, label %if.end
+ ]
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %entry, %if.then
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc != 1) ^ (cc != 3)).
+define i64 @bar1a_013_AND_XOR_b() {
+; CHECK-LABEL: bar1a_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc != 2)) ^ (cc != 3)
+define i64 @bar1a_023_XOR_AND() {
+; CHECK-LABEL: bar1a_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB98_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ switch i32 %0, label %if.then [
+ i32 3, label %if.end
+ i32 0, label %if.end
+ ]
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %entry, %if.then
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc != 2)) ^ (cc != 3)
+define i64 @bar1a_023_AND_XOR_a() {
+; CHECK-LABEL: bar1a_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB99_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ switch i32 %0, label %if.then [
+ i32 3, label %if.end
+ i32 0, label %if.end
+ ]
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %entry, %if.then
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc != 2) ^ (cc != 3)).
+define i64 @bar1a_023_AND_XOR_b() {
+; CHECK-LABEL: bar1a_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 1) ^ (cc != 2)) && (cc != 3).
+define i64 @bar1a_123_XOR_AND() {
+; CHECK-LABEL: bar1a_123_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB101_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %.not = icmp eq i32 %0, 0
+ br i1 %.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) && (cc != 2)) ^ (cc != 3)
+define i64 @bar1a_123_AND_XOR_a() {
+; CHECK-LABEL: bar1a_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jghe dummy at PLT
+; CHECK-NEXT: .LBB102_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1) && ((cc != 2) ^ (cc != 3))
+define i64 @bar1a_123_AND_XOR_b() {
+; CHECK-LABEL: bar1a_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 1)) && (cc != 2)
+define range(i64 5, 9) i64 @fuaa_012_OR_AND() {
+; CHECK-LABEL: fuaa_012_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB104_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %or.cond.i = icmp samesign ugt i32 %0, 1
+ %. = select i1 %or.cond.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc == 1)) || (cc != 2)
+define range(i64 5, 9) i64 @fuaa_012_AND_OR_a() {
+; CHECK-LABEL: fuaa_012_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB105_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc == 1) || (cc != 2)).
+define range(i64 5, 9) i64 @fuaa_012_AND_OR_b() {
+; CHECK-LABEL: fuaa_012_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB106_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc == 1)) && (cc != 3)
+define range(i64 5, 9) i64 @fuaa_013_OR_AND() {
+; CHECK-LABEL: fuaa_013_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB107_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %or.cond.i = icmp samesign ugt i32 %0, 1
+ %. = select i1 %or.cond.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc == 1)) || (cc != 3)
+define range(i64 5, 9) i64 @fuaa_013_AND_OR_a() {
+; CHECK-LABEL: fuaa_013_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB108_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc == 1) || (cc != 3))
+define range(i64 5, 9) i64 @fuaa_013_AND_OR_b() {
+; CHECK-LABEL: fuaa_013_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB109_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc == 2)) && (cc != 3)
+define range(i64 5, 9) i64 @fuaa_023_OR_AND() {
+; CHECK-LABEL: fuaa_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB110_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc == 2)) || (cc != 3)
+define range(i64 5, 9) i64 @fuaa_023_AND_OR_a() {
+; CHECK-LABEL: fuaa_023_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB111_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc == 2) || (cc != 3))
+define range(i64 5, 9) i64 @fuaa_023_AND_OR_b() {
+; CHECK-LABEL: fuaa_023_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB112_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 1) || (cc == 2)) && (cc != 3)
+define range(i64 5, 9) i64 @fuaa_123_OR_AND() {
+; CHECK-LABEL: fuaa_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB113_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %or.cond.i = icmp ult i32 %2, -2
+ %. = select i1 %or.cond.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 1) && (cc == 2)) || (cc != 3)
+define range(i64 5, 9) i64 @fuaa_123_AND_OR_a() {
+; CHECK-LABEL: fuaa_123_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB114_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 1) && ((cc == 2) || (cc != 3))
+define range(i64 5, 9) i64 @fuaa_123_AND_OR_b() {
+; CHECK-LABEL: fuaa_123_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB115_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc == 1)) && (cc != 2).
+define range(i64 5, 9) i64 @fuaa_012_XOR_AND() {
+; CHECK-LABEL: fuaa_012_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB116_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i = icmp samesign ugt i32 %0, 1
+ %. = select i1 %xor7.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc == 1)) ^ (cc != 2)
+define range(i64 5, 9) i64 @fuaa_012_AND_XOR_a() {
+; CHECK-LABEL: fuaa_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB117_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc == 1) ^ (cc != 2))
+define range(i64 5, 9) i64 @fuaa_012_AND_XOR_b() {
+; CHECK-LABEL: fuaa_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB118_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc == 1)) && (cc != 3)
+define range(i64 5, 9) i64 @fuaa_013_XOR_AND() {
+; CHECK-LABEL: fuaa_013_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB119_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i = icmp samesign ugt i32 %0, 1
+ %. = select i1 %xor7.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; ((cc == 0) && (cc == 1)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fuaa_013_XOR_AND_XOR_a() {
+; CHECK-LABEL: fuaa_013_XOR_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB120_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc == 1) ^ (cc != 3)
+define range(i64 5, 9) i64 @fuaa_013_AND_XOR_b() {
+; CHECK-LABEL: fuaa_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB121_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc == 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fuaa_023_XOR_AND() {
+; CHECK-LABEL: fuaa_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB122_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) && (cc == 2)) ^ (cc != 3).
+define range(i64 5, 9) i64 @fuaa_023_AND_XOR_a() {
+; CHECK-LABEL: fuaa_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB123_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) && ((cc == 2) ^ (cc != 3)).
+define range(i64 5, 9) i64 @fuaa_023_AND_XOR_b() {
+; CHECK-LABEL: fuaa_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB124_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 1) ^ (cc == 2)) && (cc != 3)
+define range(i64 5, 9) i64 @fuaa_123_XOR_AND() {
+; CHECK-LABEL: fuaa_123_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB125_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %xor7.i = icmp ult i32 %2, -2
+ %. = select i1 %xor7.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 1) && (cc == 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fuaa_123_AND_XOR_a() {
+; CHECK-LABEL: fuaa_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB126_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 1) && ((cc == 2) ^ (cc != 3))
+define range(i64 5, 9) i64 @fuaa_123_AND_XOR_b() {
+; CHECK-LABEL: fuaa_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB127_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc == 1)) && (cc != 2)
+define i64 @bar2a_012_OR_AND() {
+; CHECK-LABEL: bar2a_012_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB128_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %or.cond.i = icmp samesign ugt i32 %0, 1
+ br i1 %or.cond.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 1)) || (cc != 2)
+define i64 @bar2a_012_AND_OR_a() {
+; CHECK-LABEL: bar2a_012_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB129_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc == 1) || (cc != 2)).
+define i64 @bar2a_012_AND_OR_b() {
+; CHECK-LABEL: bar2a_012_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB130_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 1)) && (cc != 3)
+define i64 @bar2a_013_OR_AND() {
+; CHECK-LABEL: bar2a_013_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB131_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %or.cond.i = icmp samesign ugt i32 %0, 1
+ br i1 %or.cond.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 1)) || (cc != 3)
+define i64 @bar2a_013_XOR_AND_OR_a() {
+; CHECK-LABEL: bar2a_013_XOR_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB132_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc == 1) || (cc != 3))
+define i64 @bar2a_013_AND_OR_b() {
+; CHECK-LABEL: bar2a_013_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB133_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 2)) && (cc != 3)
+define i64 @bar2a_023_OR_AND() {
+; CHECK-LABEL: bar2a_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jghe dummy at PLT
+; CHECK-NEXT: .LBB134_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 2)) || (cc != 3)
+define i64 @bar2a_023_AND_OR_a() {
+; CHECK-LABEL: bar2a_023_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB135_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc == 2) || (cc != 3))
+define i64 @bar2a_023_AND_OR_b() {
+; CHECK-LABEL: bar2a_023_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB136_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) || (cc == 2)) && (cc != 3)
+define i64 @bar2a_123_OR_AND() {
+; CHECK-LABEL: bar2a_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB137_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %or.cond.i = icmp ult i32 %2, -2
+ br i1 %or.cond.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) && (cc == 2)) || (cc != 3)
+define i64 @bar2a_123_AND_OR_a() {
+; CHECK-LABEL: bar2a_123_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB138_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1) && ((cc == 2) || (cc != 3))
+define i64 @bar2a_123_AND_OR_b() {
+; CHECK-LABEL: bar2a_123_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB139_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc == 1)) && (cc != 2).
+define i64 @bar2a_012_XOR_AND() {
+; CHECK-LABEL: bar2a_012_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB140_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i = icmp samesign ugt i32 %0, 1
+ br i1 %xor7.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 1)) ^ (cc != 2)
+define i64 @bar2a_012_AND_XOR_a() {
+; CHECK-LABEL: bar2a_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB141_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc == 1) ^ (cc != 2))
+define i64 @bar2a_012_AND_XOR_b() {
+; CHECK-LABEL: bar2a_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB142_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc == 1)) && (cc != 3)
+define i64 @bar2a_013_XOR_AND() {
+; CHECK-LABEL: bar2a_013_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB143_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i = icmp samesign ugt i32 %0, 1
+ br i1 %xor7.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 1)) ^ (cc != 3)
+define i64 @bar2a_013_XOR_AND_XOR_a() {
+; CHECK-LABEL: bar2a_013_XOR_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB144_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc == 1) ^ (cc != 3)
+define i64 @bar2a_013_AND_XOR_b() {
+; CHECK-LABEL: bar2a_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB145_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (((cc == 0) ^ (cc != 2)) && (cc != 3))
+define i64 @bar2a_023_XOR_AND() {
+; CHECK-LABEL: bar2a_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB146_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc == 2)) ^ (cc != 3)
+define i64 @bar2a_023_AND_XOR_a() {
+; CHECK-LABEL: bar2a_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB147_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc == 2) ^ (cc != 3)).
+define i64 @bar2a_023_AND_XOR_b() {
+; CHECK-LABEL: bar2a_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB148_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) ^ (cc == 2)) && (cc != 3)
+define i64 @bar2a_123_XOR_AND() {
+; CHECK-LABEL: bar2a_123_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB149_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %xor7.i = icmp ult i32 %2, -2
+ br i1 %xor7.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) && (cc == 2)) ^ (cc != 3)
+define i64 @bar2a_123_AND_XOR_a() {
+; CHECK-LABEL: bar2a_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB150_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1) && ((cc == 2) ^ (cc != 3))
+define i64 @bar2a_123_AND_XOR_b() {
+; CHECK-LABEL: bar2a_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB151_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) || ((cc != 1) ^ (cc != 2))
+define range(i64 5, 9) i64 @fu1a_012_OR_XOR_a() {
+; CHECK-LABEL: fu1a_012_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB152_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 3
+ %. = select i1 %xor6.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc != 1)) ^ (cc != 2)
+define range(i64 5, 9) i64 @fu1a_012_OR_XOR_c() {
+; CHECK-LABEL: fu1a_012_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB153_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %xor5.i = icmp ult i32 %2, -2
+ %. = select i1 %xor5.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) ^ ((cc != 1) || (cc != 2))
+define range(i64 5, 9) i64 @fu1a_012_XOR_OR_a() {
+; CHECK-LABEL: fu1a_012_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB154_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc != 1)) || (cc != 2)
+define noundef range(i64 5, 9) i64 @fu1a_012_XOR_OR_c() {
+; CHECK-LABEL: fu1a_012_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test (cc == 0) || ((cc != 1) ^ (cc != 3))
+define range(i64 5, 9) i64 @fu1a_013_OR_XOR_a() {
+; CHECK-LABEL: fu1a_013_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB156_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp ne i32 %0, 0
+ %2 = and i32 %0, 1
+ %xor6.i.not = icmp eq i32 %2, 0
+ %narrow.not = and i1 %cmp.i, %xor6.i.not
+ %. = select i1 %narrow.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc != 1)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu1a_013_OR_XOR_c() {
+; CHECK-LABEL: fu1a_013_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB157_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) ^ ((cc != 1) || (cc != 3))
+define range(i64 5, 9) i64 @fu1a_013_XOR_OR_a() {
+; CHECK-LABEL: fu1a_013_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB158_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc != 1)) || (cc != 3)
+define noundef range(i64 5, 9) i64 @fu1a_013_XOR_OR_c() {
+; CHECK-LABEL: fu1a_013_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test (cc == 0) || ((cc != 2) ^ (cc != 3))
+define range(i64 5, 9) i64 @fu1a_023_OR_XOR_a() {
+; CHECK-LABEL: fu1a_023_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB160_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 1
+ %. = select i1 %xor6.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc != 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu1a_023_OR_XOR_c() {
+; CHECK-LABEL: fu1a_023_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB161_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i = icmp samesign ult i32 %0, 2
+ %. = select i1 %xor5.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) ^ ((cc != 2) || (cc != 3))
+define range(i64 5, 9) i64 @fu1a_023_XOR_OR_a() {
+; CHECK-LABEL: fu1a_023_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB162_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc != 2)) || (cc != 3)
+define noundef range(i64 5, 9) i64 @fu1a_023_XOR_OR_c() {
+; CHECK-LABEL: fu1a_023_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test (cc == 1) || ((cc != 2) ^ (cc != 3))
+define range(i64 5, 9) i64 @fu1a_123_OR_XOR_a() {
+; CHECK-LABEL: fu1a_123_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB164_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 0
+ %. = select i1 %xor6.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 1) || (cc != 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu1a_123_OR_XOR_c() {
+; CHECK-LABEL: fu1a_123_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB165_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i = icmp samesign ult i32 %0, 2
+ %. = select i1 %xor5.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 1 ) ^ ((cc != 2) || (cc != 3))
+define range(i64 5, 9) i64 @fu1a_123_XOR_OR_a() {
+; CHECK-LABEL: fu1a_123_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB166_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 1) ^ (cc != 2)) || (cc != 3)
+define noundef range(i64 5, 9) i64 @fu1a_123_XOR_OR_c() {
+; CHECK-LABEL: fu1a_123_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test (cc == 0) || ((cc != 1) ^ (cc != 2))
+define i64 @bar3a_012_OR_XOR_a() {
+; CHECK-LABEL: bar3a_012_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB168_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 3
+ br i1 %xor6.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc != 1)) ^ (cc != 2)
+define i64 @bar3a_012_OR_XOR_c() {
+; CHECK-LABEL: bar3a_012_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB169_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %xor5.i = icmp ult i32 %2, -2
+ br i1 %xor5.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) ^ ((cc != 1) || (cc != 2))
+define i64 @bar3a_012_XOR_OR_a() {
+; CHECK-LABEL: bar3a_012_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB170_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc != 1)) || (cc != 2)
+define i64 @bar3a_012_XOR_OR_c() {
+; CHECK-LABEL: bar3a_012_XOR_OR_c:
+; CHECK: # %bb.0: # %if.end
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+if.end:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret i64 undef
+}
+
+; Test (cc == 0) || ((cc != 1) ^ (cc != 3))
+define i64 @bar3a_013_OR_XOR_a() {
+; CHECK-LABEL: bar3a_013_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB172_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp ne i32 %0, 0
+ %2 = and i32 %0, 1
+ %xor6.i.not = icmp eq i32 %2, 0
+ %narrow.not = and i1 %cmp.i, %xor6.i.not
+ br i1 %narrow.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc != 1)) ^ (cc != 3)
+define i64 @bar3a_013_OR_XOR_c() {
+; CHECK-LABEL: bar3a_013_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnhe dummy at PLT
+; CHECK-NEXT: .LBB173_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) ^ ((cc != 1) || (cc != 3))
+define i64 @bar3a_013_XOR_OR_a() {
+; CHECK-LABEL: bar3a_013_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB174_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc != 1)) || (cc != 3)
+define i64 @bar3a_013_XOR_OR_c() {
+; CHECK-LABEL: bar3a_013_XOR_OR_c:
+; CHECK: # %bb.0: # %if.end
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+if.end:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret i64 undef
+}
+
+; Test (cc == 0) || ((cc != 2) ^ (cc != 3))
+define i64 @bar3a_023_OR_XOR_a() {
+; CHECK-LABEL: bar3a_023_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB176_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 1
+ br i1 %xor6.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc != 2)) ^ (cc != 3)
+define i64 @bar3a_023_OR_XOR_c() {
+; CHECK-LABEL: bar3a_023_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnle dummy at PLT
+; CHECK-NEXT: .LBB177_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i = icmp samesign ult i32 %0, 2
+ br i1 %xor5.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) ^ ((cc != 2) || (cc != 3))
+define i64 @bar3a_023_XOR_OR_a() {
+; CHECK-LABEL: bar3a_023_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB178_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc != 2)) || (cc != 3)
+define i64 @bar3a_023_XOR_OR_c() {
+; CHECK-LABEL: bar3a_023_XOR_OR_c:
+; CHECK: # %bb.0: # %if.end
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+if.end:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret i64 undef
+}
+
+; Test (cc == 1) || ((cc != 2) ^ (cc != 3))
+define i64 @bar3a_123_OR_XOR_a() {
+; CHECK-LABEL: bar3a_123_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB180_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.i.not = icmp eq i32 %0, 0
+ br i1 %xor6.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) || (cc != 2)) ^ (cc != 3)
+define i64 @bar3a_123_OR_XOR_c() {
+; CHECK-LABEL: bar3a_123_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnle dummy at PLT
+; CHECK-NEXT: .LBB181_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i = icmp samesign ult i32 %0, 2
+ br i1 %xor5.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1 ) ^ ((cc != 2) || (cc != 3))
+define i64 @bar3a_123_XOR_OR_a() {
+; CHECK-LABEL: bar3a_123_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB182_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) ^ (cc != 2)) || (cc != 3
+define i64 @bar3a_123_XOR_OR_c() {
+; CHECK-LABEL: bar3a_123_XOR_OR_c:
+; CHECK: # %bb.0: # %if.end
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+if.end:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret i64 undef
+}
+
+; Test (cc == 0) || ((cc == 1) ^ (cc != 2))
+define range(i64 5, 9) i64 @fu2a_012_OR_XOR_a() {
+; CHECK-LABEL: fu2a_012_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB184_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -1
+ %xor6.i = icmp ult i32 %2, 2
+ %. = select i1 %xor6.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc == 1)) ^ (cc != 2)
+define range(i64 5, 9) i64 @fu2a_012_OR_XOR_c() {
+; CHECK-LABEL: fu2a_012_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB185_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i.not = icmp eq i32 %0, 3
+ %. = select i1 %xor5.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 0) ^ ((cc == 1) || (cc != 2))
+define range(i64 5, 9) i64 @fu2a_012_XOR_OR_a() {
+; CHECK-LABEL: fu2a_012_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB186_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc != 2)
+define range(i64 5, 9) i64 @fu2a_012_XOR_OR_c() {
+; CHECK-LABEL: fu2a_012_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB187_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp3.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) || ((cc == 1) ^ (cc != 3))
+define range(i64 5, 9) i64 @fu2a_013_OR_XOR_a() {
+; CHECK-LABEL: fu2a_013_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB188_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc == 1)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu2a_013_OR_XOR_c() {
+; CHECK-LABEL: fu2a_013_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB189_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ult i32 %0, 2
+ %cmp2.i = icmp eq i32 %0, 3
+ %xor5.i.not = or i1 %2, %cmp2.i
+ %. = select i1 %xor5.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) ^ ((cc == 1) || (cc != 3))
+define range(i64 5, 9) i64 @fu2a_013_XOR_OR_a() {
+; CHECK-LABEL: fu2a_013_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB190_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp eq i32 %0, 0
+ %cmp3.i = icmp eq i32 %0, 3
+ %xor7.i.not = or i1 %cmp.i, %cmp3.i
+ %. = select i1 %xor7.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc != 3)
+define range(i64 5, 9) i64 @fu2a_013_XOR_OR_c() {
+; CHECK-LABEL: fu2a_013_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB191_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp3.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) || ((cc == 2) ^ (cc != 3))
+define range(i64 5, 9) i64 @fu2a_023_OR_XOR_a() {
+; CHECK-LABEL: fu2a_023_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB192_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %xor6.i = icmp samesign ugt i32 %2, -3
+ %. = select i1 %xor6.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) || (cc == 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu2a_023_OR_XOR_c() {
+; CHECK-LABEL: fu2a_023_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB193_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp eq i32 %0, 3
+ %tobool.not.not = xor i1 %3, %2
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 0) ^ ((cc == 2) || (cc != 3))
+define range(i64 5, 9) i64 @fu2a_023_XOR_OR_a() {
+; CHECK-LABEL: fu2a_023_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB194_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp eq i32 %0, 0
+ %cmp3.i = icmp eq i32 %0, 3
+ %xor7.i.not = or i1 %cmp.i, %cmp3.i
+ %. = select i1 %xor7.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 0) ^ (cc == 2)) || (cc != 3)
+define range(i64 5, 9) i64 @fu2a_023_XOR_OR_c() {
+; CHECK-LABEL: fu2a_023_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB195_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp3.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 1) || ((cc == 2) ^ (cc != 3))
+define range(i64 5, 9) i64 @fu2a_123_OR_XOR_a() {
+; CHECK-LABEL: fu2a_123_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB196_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %xor6.i = icmp samesign ugt i32 %2, -3
+ %. = select i1 %xor6.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc == 1) || (cc == 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu2a_123_OR_XOR_c() {
+; CHECK-LABEL: fu2a_123_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB197_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i.not = icmp eq i32 %0, 0
+ %. = select i1 %xor5.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc == 1 ) ^ ((cc == 2) || (cc != 3))
+define range(i64 5, 9) i64 @fu2a_123_XOR_OR_a() {
+; CHECK-LABEL: fu2a_123_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB198_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc == 1) ^ (cc == 2)) || (cc != 3)
+define range(i64 5, 9) i64 @fu2a_123_XOR_OR_c() {
+; CHECK-LABEL: fu2a_123_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB199_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp3.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc == 0) || ((cc == 1) ^ (cc != 2))
+define i64 @bar4a_012_OR_XOR_a() {
+; CHECK-LABEL: bar4a_012_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnlh dummy at PLT
+; CHECK-NEXT: .LBB200_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -1
+ %xor6.i = icmp ult i32 %2, 2
+ br i1 %xor6.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 1)) ^ (cc != 2)
+define i64 @bar4a_012_OR_XOR_c() {
+; CHECK-LABEL: bar4a_012_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB201_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i.not = icmp eq i32 %0, 3
+ br i1 %xor5.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) ^ ((cc == 1) || (cc != 2))
+define i64 @bar4a_012_XOR_OR_a() {
+; CHECK-LABEL: bar4a_012_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnhe dummy at PLT
+; CHECK-NEXT: .LBB202_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not = icmp eq i32 %2, 0
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc != 2)
+define i64 @bar4a_012_XOR_OR_c() {
+; CHECK-LABEL: bar4a_012_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB203_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 2
+ br i1 %cmp3.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) || ((cc == 1) ^ (cc != 3)
+define i64 @bar4a_013_OR_XOR_a() {
+; CHECK-LABEL: bar4a_013_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jghe dummy at PLT
+; CHECK-NEXT: .LBB204_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 1)) ^ (cc != 3)
+define i64 @bar4a_013_OR_XOR_c() {
+; CHECK-LABEL: bar4a_013_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgh dummy at PLT
+; CHECK-NEXT: .LBB205_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %switch = icmp eq i32 %0, 2
+ br i1 %switch, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret i64 undef
+}
+
+; Test (cc == 0) ^ ((cc == 1) || (cc != 3))
+define i64 @bar4a_013_XOR_OR_a() {
+; CHECK-LABEL: bar4a_013_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB206_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ switch i32 %0, label %if.then [
+ i32 3, label %if.end
+ i32 0, label %if.end
+ ]
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %entry, %if.then
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc == 1)) || (cc != 3)
+define i64 @bar4a_013_XOR_OR_c() {
+; CHECK-LABEL: bar4a_013_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB207_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ br i1 %cmp3.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) || ((cc == 2) ^ (cc != 3))
+define i64 @bar4a_023_OR_XOR_a() {
+; CHECK-LABEL: bar4a_023_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB208_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %xor6.i = icmp samesign ugt i32 %2, -3
+ br i1 %xor6.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc == 2)) ^ (cc != 3)
+define i64 @bar4a_023_OR_XOR_c() {
+; CHECK-LABEL: bar4a_023_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB209_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp eq i32 %0, 3
+ %tobool.not.not = xor i1 %3, %2
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) ^ ((cc == 2) || (cc != 3))
+define i64 @bar4a_023_XOR_OR_a() {
+; CHECK-LABEL: bar4a_023_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB210_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ switch i32 %0, label %if.then [
+ i32 3, label %if.end
+ i32 0, label %if.end
+ ]
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %entry, %if.then
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc == 2)) || (cc != 3)
+define i64 @bar4a_023_XOR_OR_c() {
+; CHECK-LABEL: bar4a_023_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB211_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ br i1 %cmp3.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1) || ((cc == 2) ^ (cc != 3))
+define i64 @bar4a_123_OR_XOR_a() {
+; CHECK-LABEL: bar4a_123_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB212_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %xor6.i = icmp samesign ugt i32 %2, -3
+ br i1 %xor6.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) || (cc == 2)) ^ (cc != 3)
+define i64 @bar4a_123_OR_XOR_c() {
+; CHECK-LABEL: bar4a_123_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB213_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i.not = icmp eq i32 %0, 0
+ br i1 %xor5.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1 ) ^ ((cc == 2) || (cc != 3))
+define i64 @bar4a_123_XOR_OR_a() {
+; CHECK-LABEL: bar4a_123_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jghe dummy at PLT
+; CHECK-NEXT: .LBB214_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) ^ (cc == 2)) || (cc != 3)
+define i64 @bar4a_123_XOR_OR_c() {
+; CHECK-LABEL: bar4a_123_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB215_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ br i1 %cmp3.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_not.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_not.ll
new file mode 100644
index 0000000000000..84b8858afc8ad
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_not.ll
@@ -0,0 +1,2543 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations.
+; This tests mixing XOR wirh OR, XOR with AND and OR with AND with
+; different ways of parenthesizing with != operator.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O3 | FileCheck %s
+
+; Test ((cc != 0) || (cc != 1)) ^ (cc != 2).
+define signext range(i32 0, 43) i32 @bar_012_OR_XOR(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB0_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+declare void @llvm.assume(i1 noundef) #1
+
+; Test ((cc != 0) || (cc != 1)) ^ (cc != 3).
+define signext range(i32 0, 43) i32 @bar_013_OR_XOR(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB1_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc != 0) || (cc != 2)) ^ (cc != 3).
+define signext range(i32 0, 43) i32 @bar_023_OR_XOR(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB2_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc != 1) || (cc != 2)) ^ (cc != 3).
+define signext range(i32 0, 43) i32 @bar_123_OR_XOR(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_OR_XOR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB3_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test ((cc != 0) ^ (cc != 1)) || (cc != 2)
+define signext range(i32 0, 43) i32 @foo_012_XOR_OR(i32 noundef signext %x) {
+; CHECK-LABEL: foo_012_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB4_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp4.not = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp4.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc != 0) ^ (cc != 1)) || (cc != 3)
+define signext range(i32 0, 43) i32 @foo_013_XOR_OR(i32 noundef signext %x) {
+; CHECK-LABEL: foo_013_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB5_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp4.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp4.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc != 0) ^ (cc != 2)) || (cc != 3)
+define signext range(i32 0, 43) i32 @foo_023_XOR_OR(i32 noundef signext %x) {
+; CHECK-LABEL: foo_023_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB6_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp4.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp4.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test ((cc != 1) ^ (cc != 2)) || (cc != 3)
+define signext range(i32 0, 43) i32 @foo_123_XOR_OR(i32 noundef signext %x) {
+; CHECK-LABEL: foo_123_XOR_OR:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB7_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp4.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp4.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc != 0) || (cc != 1)) && (cc != 2))
+define signext range(i32 0, 43) i32 @bar_012_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB8_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc != 0) || (cc != 1)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar_013_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB9_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc != 0) || (cc != 2)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar_023_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB10_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc != 1) || (cc != 2)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar_123_OR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB11_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp3.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc != 0) ^ (cc != 1)) && (cc != 2))
+define signext range(i32 0, 43) i32 @bar_012_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB12_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor8 = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %xor8, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc != 0) ^ (cc != 1)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar_013_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB13_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor8 = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %xor8, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc != 0) ^ (cc != 2)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar_023_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB14_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp ne i32 %asmresult1, 0
+ %cmp2 = icmp ne i32 %asmresult1, 2
+ %xor8 = xor i1 %cmp, %cmp2
+ %cond = select i1 %xor8, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc != 1) ^ (cc != 2)) && (cc != 3))
+define signext range(i32 0, 43) i32 @bar_123_XOR_AND(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB15_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %xor8 = icmp ult i32 %2, 2
+ %cond = select i1 %xor8, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc != 0) && (cc != 1)) ^ (cc != 2)).
+define signext range(i32 0, 43) i32 @bar_012_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB16_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor6.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %xor6.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc != 0) && (cc != 1)) ^ (cc != 3)).
+define signext range(i32 0, 43) i32 @bar_013_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB17_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ugt i32 %asmresult1, 1
+ %cmp3 = icmp ne i32 %asmresult1, 3
+ %xor6 = xor i1 %2, %cmp3
+ %cond = select i1 %xor6, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test (((cc != 0) && (cc != 2)) ^ (cc != 3)).
+define signext range(i32 0, 43) i32 @bar_023_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB18_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %asmresult1 to i1
+ %3 = icmp eq i32 %asmresult1, 3
+ %tobool.not = xor i1 %3, %2
+ %cond = select i1 %tobool.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test (((cc != 1) && (cc != 2)) ^ (cc != 3)).
+define signext range(i32 0, 43) i32 @bar_123_AND_XOR_a(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bner %r14
+; CHECK-NEXT: .LBB19_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -3
+ %3 = icmp ult i32 %2, -2
+ %cmp3 = icmp ne i32 %asmresult1, 3
+ %xor6 = xor i1 %cmp3, %3
+ %cond = select i1 %xor6, i32 42, i32 0
+ ret i32 %cond
+}
+
+; ((cc != 0) && ((cc != 1)) ^ (cc != 2))
+define signext range(i32 0, 43) i32 @bar_012_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB20_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not = icmp eq i32 %asmresult1, 0
+ %xor7.not = icmp eq i32 %asmresult1, 3
+ %2 = or i1 %cmp.not, %xor7.not
+ %cond = select i1 %2, i32 0, i32 42
+ ret i32 %cond
+}
+
+; ((cc != 0) && ((cc != 1)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar_013_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnher %r14
+; CHECK-NEXT: .LBB21_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2 = icmp ne i32 %asmresult1, 1
+ %cmp3 = icmp ne i32 %asmresult1, 3
+ %xor7 = xor i1 %cmp2, %cmp3
+ %2 = select i1 %xor7, i32 42, i32 0
+ ret i32 %2
+}
+
+; ((cc != 0) && ((cc != 2)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar_023_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB22_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %2, i32 0, i32 42
+ ret i32 %cond
+}
+
+; ((cc != 1) && ((cc != 2)) ^ (cc != 3))
+define signext range(i32 0, 43) i32 @bar_123_AND_XOR_b(i32 noundef signext %x) {
+; CHECK-LABEL: bar_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB23_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %2, i32 0, i32 42
+ ret i32 %cond
+}
+
+
+ at a = global i32 0, align 4
+
+; Test ((cc != 0) || (cc != 1)) && (cc != 2)
+define range(i64 5, 9) i64 @fu_012_OR_AND() {
+; CHECK-LABEL: fu_012_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB24_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) && (cc != 1)) || (cc != 2)
+define noundef range(i64 5, 9) i64 @fu_012_AND_OR_a() {
+; CHECK-LABEL: fu_012_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test (cc != 0) && ((cc != 1) || (cc != 2))
+define range(i64 5, 9) i64 @fu_012_AND_OR_b() {
+; CHECK-LABEL: fu_012_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB26_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.not.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) || (cc != 1)) && (cc != 3).
+define range(i64 5, 9) i64 @fu_013_OR_AND() {
+; CHECK-LABEL: fu_013_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB27_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) && (cc != 1)) || (cc != 3)
+define noundef range(i64 5, 9) i64 @fu_013_AND_OR_a() {
+; CHECK-LABEL: fu_013_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test (cc != 0) && ((cc != 1) || (cc != 3))
+define range(i64 5, 9) i64 @fu_013_AND_OR_b() {
+; CHECK-LABEL: fu_013_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB29_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.not.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) || (cc != 2)) && (cc != 3)
+define range(i64 5, 9) i64 @fu_023_OR_AND() {
+; CHECK-LABEL: fu_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB30_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; (cc != 0) && (cc != 2)) || (cc != 3
+define noundef range(i64 5, 9) i64 @fu_023_AND_OR_a() {
+; CHECK-LABEL: fu_023_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test (cc != 0) && ((cc != 2) || (cc != 3)).
+define range(i64 5, 9) i64 @fu_023_AND_OR_b() {
+; CHECK-LABEL: fu_023_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB32_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.not.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 1) || (cc != 2)) && (cc != 3)
+define range(i64 5, 9) i64 @fu_123_OR_AND() {
+; CHECK-LABEL: fu_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB33_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc != 1) && (cc != 2)) || (cc != 3)
+define noundef range(i64 5, 9) i64 @fu_123_AND_OR_a() {
+; CHECK-LABEL: fu_123_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test (cc != 1) && ((cc != 2) || (cc != 3)
+define range(i64 5, 9) i64 @fu_123_AND_OR_b() {
+; CHECK-LABEL: fu_123_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB35_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.not.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) ^ (cc != 1)) && (cc != 2)
+define range(i64 5, 9) i64 @fu_012_XOR_AND() {
+; CHECK-LABEL: fu_012_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB36_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i = icmp samesign ugt i32 %0, 1
+ %. = select i1 %xor7.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) && (cc != 1)) ^ (cc != 2)
+define range(i64 5, 9) i64 @fu_012_AND_XOR_a() {
+; CHECK-LABEL: fu_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB37_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i.not = icmp eq i32 %0, 3
+ %. = select i1 %xor5.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc != 0) && ((cc != 1) ^ (cc != 2))
+define range(i64 5, 9) i64 @fu_012_AND_XOR_b() {
+; CHECK-LABEL: fu_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB38_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i = icmp eq i32 %0, 0
+ %xor6.i = icmp eq i32 %0, 3
+ %narrow.not = or i1 %cmp.not.i, %xor6.i
+ %. = select i1 %narrow.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) ^ (cc != 1)) && (cc != 3)
+define range(i64 5, 9) i64 @fu_013_XOR_AND() {
+; CHECK-LABEL: fu_013_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB39_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i = icmp samesign ugt i32 %0, 1
+ %. = select i1 %xor7.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) && (cc != 1)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu_013_XOR_AND_XOR_a() {
+; CHECK-LABEL: fu_013_XOR_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB40_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ugt i32 %0, 1
+ %3 = icmp ne i32 %0, 3
+ %tobool.not = and i1 %2, %3
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; (cc != 0) && ((cc != 1) ^ (cc != 3))
+define range(i64 5, 9) i64 @fu_013_AND_XOR_b() {
+; CHECK-LABEL: fu_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB41_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) && (cc != 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu_023_XOR_AND() {
+; CHECK-LABEL: fu_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB42_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp eq i32 %0, 3
+ %tobool.not = xor i1 %3, %2
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) && (cc != 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu_023_AND_XOR_a() {
+; CHECK-LABEL: fu_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB43_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp eq i32 %0, 3
+ %tobool.not = xor i1 %3, %2
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc != 0) && ((cc != 2) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu_023_AND_XOR_b() {
+; CHECK-LABEL: fu_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB44_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %narrow = icmp samesign ult i32 %0, 2
+ %. = select i1 %narrow, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 1) ^ (cc != 2)) && (cc != 3)
+define range(i64 5, 9) i64 @fu_123_XOR_AND() {
+; CHECK-LABEL: fu_123_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB45_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %xor7.i = icmp ult i32 %2, -2
+ %. = select i1 %xor7.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; ((cc != 1) && (cc != 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu_123_AND_XOR_a() {
+; CHECK-LABEL: fu_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB46_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %tobool.not = icmp eq i32 %0, 0
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; (cc != 1) && ((cc != 2) ^ (cc != 3))
+define range(i64 5, 9) i64 @fu_123_AND_XOR_b() {
+; CHECK-LABEL: fu_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB47_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %narrow = icmp samesign ult i32 %0, 2
+ %. = select i1 %narrow, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (((cc != 0) || (cc != 1)) && (cc != 2))
+define i64 @bar1_012_OR_AND() {
+; CHECK-LABEL: bar1_012_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB48_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+declare void @dummy() local_unnamed_addr #1
+
+; Test (((cc == 0) && (cc != 1)) || (cc != 2))
+define i64 @bar1_012_AND_OR_a() {
+; CHECK-LABEL: bar1_012_AND_OR_a:
+; CHECK: # %bb.0: # %if.end
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+if.end:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc != 1) || (cc != 2))
+define i64 @bar1_012_AND_OR_b() {
+; CHECK-LABEL: bar1_012_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB50_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.not.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+
+; Test (((cc == 0) && (cc != 1)) || (cc != 3))
+define i64 @bar1_013_OR_AND() {
+; CHECK-LABEL: bar1_013_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB51_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (((cc == 0) && (cc != 1)) || (cc != 3)
+define i64 @bar1_013_XOR_AND_OR_a() {
+; CHECK-LABEL: bar1_013_XOR_AND_OR_a:
+; CHECK: # %bb.0: # %if.end
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+if.end:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc != 1)) || (cc != 3).
+define i64 @bar1_013_AND_OR_b() {
+; CHECK-LABEL: bar1_013_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB53_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.not.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) || (cc != 2)) && (cc != 3)
+define i64 @bar1_023_OR_AND() {
+; CHECK-LABEL: bar1_023_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB54_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc != 2)) || (cc != 3)
+define i64 @bar1_023_AND_OR_a() {
+; CHECK-LABEL: bar1_023_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc != 2) || (cc != 3))
+define i64 @bar1_023_AND_OR_b() {
+; CHECK-LABEL: bar1_023_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB56_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.not.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) || (cc != 2)) && (cc != 3)
+define i64 @bar1_123_OR_AND() {
+; CHECK-LABEL: bar1_123_OR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB57_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Tset ((cc == 1) && (cc != 2)) || (cc != 3).
+define i64 @bar1_123_AND_OR_a() {
+; CHECK-LABEL: bar1_123_AND_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret i64 undef
+}
+
+; Test (cc == 1) && ((cc != 2) || (cc != 3)).
+define i64 @bar1_123_AND_OR_b() {
+; CHECK-LABEL: bar1_123_AND_OR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB59_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.not.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc != 1)) && (cc != 2
+define i64 @bar1_012_XOR_AND() {
+; CHECK-LABEL: bar1_012_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB60_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i = icmp samesign ugt i32 %0, 1
+ br i1 %xor7.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc != 1)) ^ (cc != 2)
+define i64 @bar1_012_AND_XOR_a() {
+; CHECK-LABEL: bar1_012_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB61_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5.i.not = icmp eq i32 %0, 3
+ br i1 %xor5.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) ^ (cc != 1)) && (cc != 3).
+define i64 @bar1_012_AND_XOR_b() {
+; CHECK-LABEL: bar1_012_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB62_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ switch i32 %0, label %if.then [
+ i32 3, label %if.end
+ i32 0, label %if.end
+ ]
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %entry, %if.then
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc != 1)) ^ (cc != 3).
+define i64 @bar1_013_XOR_AND() {
+; CHECK-LABEL: bar1_013_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB63_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor7.i = icmp samesign ugt i32 %0, 1
+ br i1 %xor7.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc != 1) ^ (cc != 3))
+define i64 @bar1_013_XOR_AND_XOR_a() {
+; CHECK-LABEL: bar1_013_XOR_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB64_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %switch = icmp eq i32 %0, 2
+ br i1 %switch, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc != 1) ^ (cc != 3)).
+define i64 @bar1_013_AND_XOR_b() {
+; CHECK-LABEL: bar1_013_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnhe dummy at PLT
+; CHECK-NEXT: .LBB65_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc != 2)) ^ (cc != 3)
+define i64 @bar1_023_XOR_AND() {
+; CHECK-LABEL: bar1_023_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB66_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp eq i32 %0, 3
+ %tobool.not = xor i1 %3, %2
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 0) && (cc != 2)) ^ (cc != 3)
+define i64 @bar1_023_AND_XOR_a() {
+; CHECK-LABEL: bar1_023_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB67_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp eq i32 %0, 3
+ %tobool.not = xor i1 %3, %2
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 0) && ((cc != 2) ^ (cc != 3)).
+define i64 @bar1_023_AND_XOR_b() {
+; CHECK-LABEL: bar1_023_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnle dummy at PLT
+; CHECK-NEXT: .LBB68_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %narrow = icmp samesign ult i32 %0, 2
+ br i1 %narrow, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) ^ (cc != 2)) && (cc != 3).
+define i64 @bar1_123_XOR_AND() {
+; CHECK-LABEL: bar1_123_XOR_AND:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB69_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %xor7.i = icmp ult i32 %2, -2
+ br i1 %xor7.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc == 1) && (cc != 2)) ^ (cc != 3).
+define i64 @bar1_123_AND_XOR_a() {
+; CHECK-LABEL: bar1_123_AND_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB70_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %tobool.not = icmp eq i32 %0, 0
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc == 1) && ((cc != 2) ^ (cc != 3))
+define i64 @bar1_123_AND_XOR_b() {
+; CHECK-LABEL: bar1_123_AND_XOR_b:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnle dummy at PLT
+; CHECK-NEXT: .LBB71_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %narrow = icmp samesign ult i32 %0, 2
+ br i1 %narrow, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc != 0) || ((cc != 1) ^ (cc != 2))
+define range(i64 5, 9) i64 @fu_012_OR_XOR_a() {
+; CHECK-LABEL: fu_012_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB72_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.not.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) || (cc != 1)) ^ (cc != 2)
+define range(i64 5, 9) i64 @fu_012_OR_XOR_c() {
+; CHECK-LABEL: fu_012_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB73_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc != 0) ^ ((cc != 1) || (cc != 2));
+define range(i64 5, 9) i64 @fu_012_XOR_OR_a() {
+; CHECK-LABEL: fu_012_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB74_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc != 0) ^ (cc != 1)) || (cc != 2)
+define range(i64 5, 9) i64 @fu_012_XOR_OR_c() {
+; CHECK-LABEL: fu_012_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB75_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp3.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) ^ (cc != 1)) || (cc != 2)
+define range(i64 5, 9) i64 @fu_013_OR_XOR_a() {
+; CHECK-LABEL: fu_013_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB76_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.not.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) || (cc != 1)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu_013_OR_XOR_c() {
+; CHECK-LABEL: fu_013_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB77_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc != 0) ^ ((cc != 1) || (cc != 3))
+define range(i64 5, 9) i64 @fu_013_XOR_OR_a() {
+; CHECK-LABEL: fu_013_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB78_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc != 0) ^ (cc != 1)) || (cc != 3)
+define range(i64 5, 9) i64 @fu_013_XOR_OR_c() {
+; CHECK-LABEL: fu_013_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB79_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp3.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc != 0) || ((cc != 2) ^ (cc != 3))
+define range(i64 5, 9) i64 @fu_023_OR_XOR_a() {
+; CHECK-LABEL: fu_023_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB80_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.not.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 0) || (cc != 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu_023_OR_XOR_c() {
+; CHECK-LABEL: fu_023_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB81_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc != 0) ^ ((cc != 2) || (cc != 3))
+define range(i64 5, 9) i64 @fu_023_XOR_OR_a() {
+; CHECK-LABEL: fu_023_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB82_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc != 0) ^ (cc != 2)) || (cc != 3)
+define range(i64 5, 9) i64 @fu_023_XOR_OR_c() {
+; CHECK-LABEL: fu_023_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB83_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp3.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc != 1) || ((cc != 2) ^ (cc != 3))
+define range(i64 5, 9) i64 @fu_123_OR_XOR_a() {
+; CHECK-LABEL: fu_123_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB84_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.not.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test ((cc != 1) || (cc != 2)) ^ (cc != 3)
+define range(i64 5, 9) i64 @fu_123_OR_XOR_c() {
+; CHECK-LABEL: fu_123_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB85_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test (cc != 1 ) ^ ((cc != 2) || (cc != 3))
+define range(i64 5, 9) i64 @fu_123_XOR_OR_a() {
+; CHECK-LABEL: fu_123_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB86_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test ((cc != 1) ^ (cc != 2)) || (cc != 3)
+define range(i64 5, 9) i64 @fu_123_XOR_OR_c() {
+; CHECK-LABEL: fu_123_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB87_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp3.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test (cc != 0) || ((cc != 1) ^ (cc != 2))
+define i64 @bar_012_OR_XOR_a() {
+; CHECK-LABEL: bar_012_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB88_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.not.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc != 0) || (cc != 1)) ^ (cc != 2)
+define i64 @bar_012_OR_XOR_c() {
+; CHECK-LABEL: bar_012_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgh dummy at PLT
+; CHECK-NEXT: .LBB89_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc != 0) ^ ((cc != 1) || (cc != 2));
+define i64 @bar_012_XOR_OR_a() {
+; CHECK-LABEL: bar_012_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB90_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc != 0) ^ (cc != 1)) || (cc != 2)
+define i64 @bar_012_XOR_OR_c() {
+; CHECK-LABEL: bar_012_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB91_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 2
+ br i1 %cmp3.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc != 0) ^ (cc != 1)) || (cc != 2)
+define i64 @bar_013_OR_XOR_a() {
+; CHECK-LABEL: bar_013_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB92_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.not.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc != 0) || (cc != 1)) ^ (cc != 3)
+define i64 @bar_013_OR_XOR_c() {
+; CHECK-LABEL: bar_013_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB93_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc != 0) ^ ((cc != 1) || (cc != 3))
+define i64 @bar_013_XOR_OR_a() {
+; CHECK-LABEL: bar_013_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB94_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc != 0) ^ (cc != 1)) || (cc != 3)
+define i64 @bar_013_XOR_OR_c() {
+; CHECK-LABEL: bar_013_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB95_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ br i1 %cmp3.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc != 0) || ((cc != 2) ^ (cc != 3))
+define i64 @bar_023_OR_XOR_a() {
+; CHECK-LABEL: bar_023_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB96_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.not.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc != 0) || (cc != 2)) ^ (cc != 3)
+define i64 @bar_023_OR_XOR_c() {
+; CHECK-LABEL: bar_023_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB97_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc != 0) ^ ((cc != 2) || (cc != 3))
+define i64 @bar_023_XOR_OR_a() {
+; CHECK-LABEL: bar_023_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB98_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; ; Test ((cc != 0) ^ (cc != 2)) || (cc != 3)
+define i64 @bar_023_XOR_OR_c() {
+; CHECK-LABEL: bar_023_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB99_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ br i1 %cmp3.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc != 1) || ((cc != 2) ^ (cc != 3))
+define i64 @bar_123_OR_XOR_a() {
+; CHECK-LABEL: bar_123_OR_XOR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB100_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.not.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc != 1) || (cc != 2)) ^ (cc != 3)
+define i64 @bar_123_OR_XOR_c() {
+; CHECK-LABEL: bar_123_OR_XOR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB101_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test (cc != 1 ) ^ ((cc != 2) || (cc != 3))
+define i64 @bar_123_XOR_OR_a() {
+; CHECK-LABEL: bar_123_XOR_OR_a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB102_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
+; Test ((cc != 1) ^ (cc != 2)) || (cc != 3)
+define i64 @bar_123_XOR_OR_c() {
+; CHECK-LABEL: bar_123_XOR_OR_c:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB103_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp3.i.not = icmp eq i32 %0, 3
+ br i1 %cmp3.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret i64 undef
+}
+
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor.ll
new file mode 100644
index 0000000000000..9b51380ac4c09
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor.ll
@@ -0,0 +1,1047 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations
+; for OR for 3 three different functions, including two test cases from heiko.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
+
+; Test CC == 0.
+define signext range(i32 0, 43) i32 @foo_0(i32 noundef signext %x) {
+; CHECK-LABEL: foo_0:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB0_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %cond = select i1 %cmp, i32 42, i32 0
+ ret i32 %cond
+}
+
+;declare void @llvm.assume(i1 noundef)
+
+; Test CC == 1.
+define signext range(i32 0, 43) i32 @foo_1(i32 noundef signext %x) {
+; CHECK-LABEL: foo_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB1_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 1
+ %cond = select i1 %cmp, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 2.
+define signext range(i32 0, 43) i32 @foo_2(i32 noundef signext %x) {
+; CHECK-LABEL: foo_2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB2_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 3.
+define signext range(i32 0, 43) i32 @foo_3(i32 noundef signext %x) {
+; CHECK-LABEL: foo_3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB3_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 || CC == 1.
+define signext range(i32 0, 43) i32 @foo_01(i32 noundef signext %x) {
+; CHECK-LABEL: foo_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB4_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %2, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 || CC == 2.
+define signext range(i32 0, 43) i32 @foo_02(i32 noundef signext %x) {
+; CHECK-LABEL: foo_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB5_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %3 = icmp eq i32 %2, 0
+ %cond = select i1 %3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 || CC == 3.
+define signext range(i32 0, 43) i32 @foo_03(i32 noundef signext %x) {
+; CHECK-LABEL: foo_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB6_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %cmp2 = icmp eq i32 %asmresult1, 3
+ %2 = or i1 %cmp, %cmp2
+ %cond = select i1 %2, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 1 || CC == 2.
+define signext range(i32 0, 43) i32 @foo_12(i32 noundef signext %x) {
+; CHECK-LABEL: foo_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB7_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %3 = icmp ult i32 %2, 2
+ %cond = select i1 %3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 1 || CC == 3.
+define signext range(i32 0, 43) i32 @foo_13(i32 noundef signext %x) {
+; CHECK-LABEL: foo_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB8_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %.not = icmp eq i32 %2, 0
+ %cond = select i1 %.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 2 || CC == 3.
+define signext range(i32 0, 43) i32 @foo_23(i32 noundef signext %x) {
+; CHECK-LABEL: foo_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB9_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %.not = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 0 || CC == 1 || CC == 2.
+define signext range(i32 0, 43) i32 @foo_012(i32 noundef signext %x) {
+; CHECK-LABEL: foo_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB10_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 0 || CC == 1 || CC == 3.
+define signext range(i32 0, 43) i32 @foo_013(i32 noundef signext %x) {
+; CHECK-LABEL: foo_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB11_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %or.cond = icmp samesign ult i32 %asmresult1, 2
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %2 = or i1 %or.cond, %cmp3
+ %cond = select i1 %2, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 || CC == 2 || CC == 3.
+define signext range(i32 0, 43) i32 @foo_023(i32 noundef signext %x) {
+; CHECK-LABEL: foo_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnlr %r14
+; CHECK-NEXT: .LBB12_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %or.cond = icmp eq i32 %2, 0
+ %cmp3 = icmp eq i32 %asmresult1, 3
+ %3 = or i1 %cmp3, %or.cond
+ %cond = select i1 %3, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 1 || CC == 2 || CC == 3.
+define signext range(i32 0, 43) i32 @foo_123(i32 noundef signext %x) {
+; CHECK-LABEL: foo_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bner %r14
+; CHECK-NEXT: .LBB13_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %3 = icmp ult i32 %2, 3
+ %cond = select i1 %3, i32 42, i32 0
+ ret i32 %cond
+}
+
+
+; Test Flag Output Operands with 14 combinations of CCMask and optimizations.
+; These test cases are from heiko kernel and 14 variations of CCMask for OR.
+
+ at a = dso_local global i32 0, align 4
+
+; Test CC == 0.
+define range(i64 5, 9) i64 @fu_0() {
+; CHECK-LABEL: fu_0:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB14_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 1.
+define range(i64 5, 9) i64 @fu_1() {
+; CHECK-LABEL: fu_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB15_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 2.
+define range(i64 5, 9) i64 @fu_2() {
+; CHECK-LABEL: fu_2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB16_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 3.
+define range(i64 5, 9) i64 @fu_3() {
+; CHECK-LABEL: fu_3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB17_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 0 || CC == 1.
+define range(i64 5, 9) i64 @fu_01() {
+; CHECK-LABEL: fu_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB18_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ugt i32 %0, 1
+ %. = select i1 %2, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 || CC == 2.
+define range(i64 5, 9) i64 @fu_02() {
+; CHECK-LABEL: fu_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB19_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 0 || CC == 3.
+define range(i64 5, 9) i64 @fu_03() {
+; CHECK-LABEL: fu_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB20_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp ne i32 %0, 0
+ %cmp1.i = icmp ne i32 %0, 3
+ %.not = and i1 %cmp.i, %cmp1.i
+ %. = select i1 %.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 1 || CC == 2.
+define range(i64 5, 9) i64 @fu_12() {
+; CHECK-LABEL: fu_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB21_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %3 = icmp ult i32 %2, -2
+ %. = select i1 %3, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 1 || CC == 3.
+define range(i64 5, 9) i64 @fu_13() {
+; CHECK-LABEL: fu_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB22_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 2 || CC == 3.
+define range(i64 5, 9) i64 @fu_23() {
+; CHECK-LABEL: fu_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB23_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ult i32 %0, 2
+ %. = select i1 %2, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 || CC == 1 || CC == 2.
+define range(i64 5, 9) i64 @fu_012() {
+; CHECK-LABEL: fu_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB24_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %narrow.not = icmp eq i32 %0, 3
+ %. = select i1 %narrow.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 || CC == 1 || CC == 3.
+define range(i64 5, 9) i64 @fu_013() {
+; CHECK-LABEL: fu_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB25_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i = icmp ne i32 %0, 3
+ %or.cond.i.inv = icmp samesign ugt i32 %0, 1
+ %narrow.not = and i1 %or.cond.i.inv, %cmp2.i
+ %. = select i1 %narrow.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 || CC == 2 || CC == 3.
+define range(i64 5, 9) i64 @fu_023() {
+; CHECK-LABEL: fu_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB26_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %or.cond.i = icmp ne i32 %2, 0
+ %cmp2.i = icmp ne i32 %0, 3
+ %narrow.not = and i1 %cmp2.i, %or.cond.i
+ %. = select i1 %narrow.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test Flag Output Operands with 14 combinations of CCMask and optimizations.
+; These test cases are from heiko kernel and 14 variations of CCMask for OR.
+
+; Test CC == 0.
+define void @bar_0() {
+; CHECK-LABEL: bar_0:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB27_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+declare void @dummy()
+
+; Test CC == 1.
+define void @bar_1() {
+; CHECK-LABEL: bar_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB28_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 2.
+define void @bar_2() {
+; CHECK-LABEL: bar_2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgh dummy at PLT
+; CHECK-NEXT: .LBB29_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 2
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 3.
+define void @bar_3() {
+; CHECK-LABEL: bar_3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB30_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 3
+ br i1 %cmp.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 || CC == 1.
+define void @bar_01() {
+; CHECK-LABEL: bar_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB31_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ugt i32 %0, 1
+ br i1 %2, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 || CC == 2.
+define void @bar_02() {
+; CHECK-LABEL: bar_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jghe dummy at PLT
+; CHECK-NEXT: .LBB32_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 || CC == 3.
+define void @bar_03() {
+; CHECK-LABEL: bar_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnlh dummy at PLT
+; CHECK-NEXT: .LBB33_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ switch i32 %0, label %if.end [
+ i32 3, label %if.then
+ i32 0, label %if.then
+ ]
+
+if.then: ; preds = %entry, %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+; Test CC == 1 || CC == 2.
+define void @bar_12() {
+; CHECK-LABEL: bar_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB34_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %3 = icmp ult i32 %2, -2
+ br i1 %3, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 || CC == 3.
+define void @bar_13() {
+; CHECK-LABEL: bar_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnhe dummy at PLT
+; CHECK-NEXT: .LBB35_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not = icmp eq i32 %2, 0
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 2 || CC == 3.
+define void @bar_23() {
+; CHECK-LABEL: bar_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnle dummy at PLT
+; CHECK-NEXT: .LBB36_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = icmp samesign ult i32 %0, 2
+ br i1 %2, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 || CC == 1 || CC == 2.
+define void @bar_012() {
+; CHECK-LABEL: bar_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB37_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %narrow.not = icmp eq i32 %0, 3
+ br i1 %narrow.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 || CC == 1 || CC == 3.
+define void @bar_013() {
+; CHECK-LABEL: bar_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB38_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %switch = icmp eq i32 %0, 2
+ br i1 %switch, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+; Test CC == 0 || CC == 2 || CC == 3.
+define void @bar_023() {
+; CHECK-LABEL: bar_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB39_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %or.cond.i = icmp ne i32 %2, 0
+ %cmp2.i = icmp ne i32 %0, 3
+ %narrow.not = and i1 %cmp2.i, %or.cond.i
+ br i1 %narrow.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 || CC == 2 || CC == 3.
+define void @bar_123() {
+; CHECK-LABEL: bar_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB40_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %narrow = icmp eq i32 %0, 0
+ br i1 %narrow, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor_eq_noteq.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor_eq_noteq.ll
new file mode 100644
index 0000000000000..728f9a5bbfc3c
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor_eq_noteq.ll
@@ -0,0 +1,854 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations
+; for OR for 3 three different functions, including two test cases from heiko.
+; This test checks combinations of Equal(==) and NOT EQUAL (!=) operator
+; .e.g. CC === 0 || CC == 1 || CC != 2, or CC === 0 || CC == 1 || CC != 2.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
+
+; Test CC == 0 || CC != 1.
+define signext range(i32 0, 43) i32 @foo_01(i32 noundef signext %x) {
+; CHECK-LABEL: foo_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB0_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.not = icmp eq i32 %asmresult1, 1
+ %cond = select i1 %cmp2.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+declare void @llvm.assume(i1 noundef) #1
+
+; Test CC == 0 || CC != 2
+define signext range(i32 0, 43) i32 @foo_02(i32 noundef signext %x) {
+; CHECK-LABEL: foo_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB1_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.not = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp2.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 0 || CC != 3.
+define signext range(i32 0, 43) i32 @foo_03(i32 noundef signext %x) {
+; CHECK-LABEL: foo_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB2_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp2.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 1 || CC != 2.
+define signext range(i32 0, 43) i32 @foo_12(i32 noundef signext %x) {
+; CHECK-LABEL: foo_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB3_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.not = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp2.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 1 || CC != 3.
+define signext range(i32 0, 43) i32 @foo_13(i32 noundef signext %x) {
+; CHECK-LABEL: foo_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB4_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp2.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 2 || CC != 3.
+define signext range(i32 0, 43) i32 @foo_23(i32 noundef signext %x) {
+; CHECK-LABEL: foo_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB5_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp2.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 0 || CC != 1 || CC != 2.
+define noundef signext i32 @foo_012(i32 noundef signext %x) {
+; CHECK-LABEL: foo_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC == 0 || CC != 1 || CC != 3.
+define noundef signext i32 @foo_013(i32 noundef signext %x) {
+; CHECK-LABEL: foo_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC == 0 || CC != 2 || CC != 3.
+define noundef signext i32 @foo_023(i32 noundef signext %x) {
+; CHECK-LABEL: foo_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC == 1 || CC != 2 || CC != 3.
+define noundef signext i32 @foo_123(i32 noundef signext %x) {
+; CHECK-LABEL: foo_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+
+ at a = global i32 0, align 4
+
+; Test CC == 0 || CC != 1.
+define range(i64 5, 9) i64 @fu_01() {
+; CHECK-LABEL: fu_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB10_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp1.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 || CC != 2.
+define range(i64 5, 9) i64 @fu_02() {
+; CHECK-LABEL: fu_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB11_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp1.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 || CC != 3.
+define range(i64 5, 9) i64 @fu_03() {
+; CHECK-LABEL: fu_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB12_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp1.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 1 || CC != 2.
+define range(i64 5, 9) i64 @fu_12() {
+; CHECK-LABEL: fu_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB13_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp1.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 1 || CC != 3.
+define range(i64 5, 9) i64 @fu_13() {
+; CHECK-LABEL: fu_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB14_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp1.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 2 || CC != 3.
+define range(i64 5, 9) i64 @fu_23() {
+; CHECK-LABEL: fu_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB15_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp1.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 || CC != 1 || CC != 2.
+define noundef i64 @fu_012() {
+; CHECK-LABEL: fu_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC == 0 || CC != 1 || CC != 3.
+define noundef i64 @fu_013() {
+; CHECK-LABEL: fu_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC == 0 || CC != 2 || CC != 3.
+define noundef i64 @fu_023() {
+; CHECK-LABEL: fu_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC == 1 || CC != 2 || CC != 3.
+define noundef i64 @fu_123() {
+; CHECK-LABEL: fu_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Tset CC == 0 || CC == 1 || CC != 2.
+define range(i64 5, 9) i64 @fu1_012(){
+; CHECK-LABEL: fu1_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB20_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Tset CC == 0 || CC == 1 || CC != 3.
+define range(i64 5, 9) i64 @fu1_013(){
+; CHECK-LABEL: fu1_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB21_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Tset CC == 0 || CC == 2 || CC != 3.
+define range(i64 5, 9) i64 @fu1_023(){
+; CHECK-LABEL: fu1_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB22_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Tset CC == 1 || CC == 2 || CC != 3.
+define range(i64 5, 9) i64 @fu1_123(){
+; CHECK-LABEL: fu1_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB23_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp2.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+
+; Test CC == 0 || CC != 1.
+define void @bar_01() {
+; CHECK-LABEL: bar_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB24_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 1
+ br i1 %cmp1.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+declare void @dummy() local_unnamed_addr #1
+
+; Test CC == 0 || CC != 2.
+define void @bar_02() {
+; CHECK-LABEL: bar_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB25_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 2
+ br i1 %cmp1.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 || CC != 3.
+define void @bar_03() {
+; CHECK-LABEL: bar_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB26_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 3
+ br i1 %cmp1.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 || CC != 2.
+define void @bar_12() {
+; CHECK-LABEL: bar_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB27_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 2
+ br i1 %cmp1.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 || CC != 3
+define void @bar_13() {
+; CHECK-LABEL: bar_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB28_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 3
+ br i1 %cmp1.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 2 || CC != 3.
+define void @bar_23() {
+; CHECK-LABEL: bar_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB29_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp1.i.not = icmp eq i32 %0, 3
+ br i1 %cmp1.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 || CC != 1 || CC != 2.
+define void @bar_012() {
+; CHECK-LABEL: bar_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC == 0 || CC != 1 || CC != 3.
+define void @bar_013() {
+; CHECK-LABEL: bar_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC == 0 || CC != 2 || CC != 3.
+define void @bar_023() {
+; CHECK-LABEL: bar_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC == 1 || CC != 2 || CC != 3.
+define void @bar_123() {
+; CHECK-LABEL: bar_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Tset CC == 0 || CC == 1 || CC != 2.
+define void @bar1_012() {
+; CHECK-LABEL: bar1_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB34_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 2
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Tset CC == 0 || CC == 1 || CC != 3.
+define void @bar1_013() {
+; CHECK-LABEL: bar1_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB35_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Tset CC == 0 || CC == 2 || CC != 3
+define void @bar1_023() {
+; CHECK-LABEL: bar1_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB36_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Tset CC == 1 || CC == 2 || CC != 3.
+define void @bar1_123() {
+; CHECK-LABEL: bar1_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB37_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp2.i.not = icmp eq i32 %0, 3
+ br i1 %cmp2.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor_not.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor_not.ll
new file mode 100644
index 0000000000000..4bcd004553393
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor_not.ll
@@ -0,0 +1,806 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations
+; for OR for 3 three different functions, including two test cases from heiko.
+; This test checks NOT EQUAL (!=) operator.e.g. CC != 0 || CC != 1 || CC !=2.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
+
+; Test CC != 0.
+define signext range(i32 0, 43) i32 @foo_0(i32 noundef signext %x) {
+; CHECK-LABEL: foo_0:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB0_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not = icmp eq i32 %asmresult1, 0
+ %cond = select i1 %cmp.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+declare void @llvm.assume(i1 noundef) #1
+
+; Test CC != 1.
+define signext range(i32 0, 43) i32 @foo_1(i32 noundef signext %x) {
+; CHECK-LABEL: foo_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB1_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not = icmp eq i32 %asmresult1, 1
+ %cond = select i1 %cmp.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC != 2.
+define signext range(i32 0, 43) i32 @foo_2(i32 noundef signext %x) {
+; CHECK-LABEL: foo_2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB2_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not = icmp eq i32 %asmresult1, 2
+ %cond = select i1 %cmp.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC != 3.
+define signext range(i32 0, 43) i32 @foo_3(i32 noundef signext %x) {
+; CHECK-LABEL: foo_3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB3_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %cmp.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC != 0 || CC != 1.
+define noundef signext i32 @foo_01(i32 noundef signext %x) {
+; CHECK-LABEL: foo_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC != 0 || CC != 2.
+define noundef signext i32 @foo_02(i32 noundef signext %x) {
+; CHECK-LABEL: foo_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC != 0 || CC != 3.
+define noundef signext i32 @foo_03(i32 noundef signext %x) {
+; CHECK-LABEL: foo_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC != 1 || CC != 2.
+define noundef signext i32 @foo_12(i32 noundef signext %x) {
+; CHECK-LABEL: foo_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC != 1 || CC != 3.
+define noundef signext i32 @foo_13(i32 noundef signext %x) {
+; CHECK-LABEL: foo_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC != 2 || CC != 3.
+define noundef signext i32 @foo_23(i32 noundef signext %x) {
+; CHECK-LABEL: foo_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC != 0 || CC != 1 || CC != 2.
+define noundef signext i32 @foo_012(i32 noundef signext %x) {
+; CHECK-LABEL: foo_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC != 0 || CC != 1 || CC != 3.
+define noundef signext i32 @foo_013(i32 noundef signext %x) {
+; CHECK-LABEL: foo_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC != 0 || CC != 2 || CC != 3.
+define noundef signext i32 @foo_023(i32 noundef signext %x) {
+; CHECK-LABEL: foo_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+; Test CC != 1 || CC != 2 || CC != 3.
+define noundef signext i32 @foo_123(i32 noundef signext %x) {
+; CHECK-LABEL: foo_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i32 42
+}
+
+
+ at a = global i32 0, align 4
+
+; Test CC != 0.
+define range(i64 5, 9) i64 @fu_0(){
+; CHECK-LABEL: fu_0:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB14_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ %. = select i1 %cmp.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 1.
+define range(i64 5, 9) i64 @fu_1(){
+; CHECK-LABEL: fu_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB15_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ %. = select i1 %cmp.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 2.
+define range(i64 5, 9) i64 @fu_2(){
+; CHECK-LABEL: fu_2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB16_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 2
+ %. = select i1 %cmp.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 3.
+define range(i64 5, 9) i64 @fu_3(){
+; CHECK-LABEL: fu_3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB17_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 3
+ %. = select i1 %cmp.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 0 || CC != 1.
+define noundef i64 @fu_01(){
+; CHECK-LABEL: fu_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC != 0 || CC != 2.
+define noundef i64 @fu_02(){
+; CHECK-LABEL: fu_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC != 0 || CC != 3.
+define noundef i64 @fu_03(){
+; CHECK-LABEL: fu_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC != 1 || CC != 2.
+define noundef i64 @fu_12(){
+; CHECK-LABEL: fu_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC != 1 || CC != 3.
+define noundef i64 @fu_13(){
+; CHECK-LABEL: fu_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC != 2 || CC != 3.
+define noundef i64 @fu_23(){
+; CHECK-LABEL: fu_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC != 0 || CC != 1 || CC != 2.
+define noundef i64 @fu_012(){
+; CHECK-LABEL: fu_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC != 0 || CC != 1 || CC != 3.
+define noundef i64 @fu_013(){
+; CHECK-LABEL: fu_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC != 0 || CC != 2 || CC != 3.
+define noundef i64 @fu_023(){
+; CHECK-LABEL: fu_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC != 1 || CC != 2 || CC != 3.
+define noundef i64 @fu_123(){
+; CHECK-LABEL: fu_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ ret i64 5
+}
+
+; Test CC != 0.
+define void @bar_0() {
+; CHECK-LABEL: bar_0:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB28_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 0
+ br i1 %cmp.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+declare void @dummy() local_unnamed_addr #1
+
+; Test CC != 1.
+define void @bar_1() {
+; CHECK-LABEL: bar_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB29_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 1
+ br i1 %cmp.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 2.
+define void @bar_2() {
+; CHECK-LABEL: bar_2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB30_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 2
+ br i1 %cmp.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 3.
+define void @bar_3() {
+; CHECK-LABEL: bar_3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB31_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i.not = icmp eq i32 %0, 3
+ br i1 %cmp.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 0 || CC != 1.
+define void @bar_01() {
+; CHECK-LABEL: bar_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC != 0 || CC != 2.
+define void @bar_02() {
+; CHECK-LABEL: bar_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC != 0 || CC != 3.
+define void @bar_03() {
+; CHECK-LABEL: bar_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC != 1 || CC != 2.
+define void @bar_12() {
+; CHECK-LABEL: bar_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC != 1 || CC != 3.
+define void @bar_13() {
+; CHECK-LABEL: bar_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC != 2 || CC != 3.
+define void @bar_23() {
+; CHECK-LABEL: bar_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC != 0 || CC != 1 || CC != 2.
+define void @bar_012() {
+; CHECK-LABEL: bar_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC != 0 || CC != 1 || CC != 3.
+define void @bar_013() {
+; CHECK-LABEL: bar_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC != 0 || CC != 2 || CC != 3.
+define void @bar_023() {
+; CHECK-LABEL: bar_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
+; Test CC != 1 || CC != 2 || CC != 3.
+define void @bar_123() {
+; CHECK-LABEL: bar_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jg dummy at PLT
+entry:
+ %0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ tail call void @dummy() #3
+ ret void
+}
+
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor.ll
new file mode 100644
index 0000000000000..0a2a508000430
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor.ll
@@ -0,0 +1,784 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations
+; for XOR for 3 three different functions, including two test cases from heiko.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
+
+declare void @llvm.assume(i1 noundef)
+
+; Test CC == 0 ^ CC == 1.
+define signext range(i32 0, 43) i32 @foo_01(i32 noundef signext %x) {
+; CHECK-LABEL: foo_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB0_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5 = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC == 2.
+define signext range(i32 0, 43) i32 @foo_02(i32 noundef signext %x) {
+; CHECK-LABEL: foo_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB1_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %cmp2 = icmp eq i32 %asmresult1, 2
+ %xor5 = xor i1 %cmp, %cmp2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC == 3.
+define signext range(i32 0, 43) i32 @foo_03(i32 noundef signext %x) {
+; CHECK-LABEL: foo_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB2_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %cmp2 = icmp eq i32 %asmresult1, 3
+ %xor5 = xor i1 %cmp, %cmp2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 1 ^ CC == 2.
+define signext range(i32 0, 43) i32 @foo_12(i32 noundef signext %x) {
+; CHECK-LABEL: foo_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB3_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %xor5 = icmp ult i32 %2, 2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 2 ^ CC == 3.
+define signext range(i32 0, 43) i32 @foo_13(i32 noundef signext %x) {
+; CHECK-LABEL: foo_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnher %r14
+; CHECK-NEXT: .LBB4_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 1
+ %cmp2 = icmp eq i32 %asmresult1, 3
+ %xor5 = xor i1 %cmp, %cmp2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 2 ^ CC == 3.
+define signext range(i32 0, 43) i32 @foo_23(i32 noundef signext %x) {
+; CHECK-LABEL: foo_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB5_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5 = icmp samesign ugt i32 %asmresult1, 1
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC == 1 ^ CC == 3.
+define signext range(i32 0, 43) i32 @foo_012(i32 noundef signext %x) {
+; CHECK-LABEL: foo_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB6_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor610.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %xor610.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC == 2 ^ CC == 3.
+define signext range(i32 0, 43) i32 @foo_013(i32 noundef signext %x) {
+; CHECK-LABEL: foo_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB7_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor9 = icmp samesign ult i32 %asmresult1, 2
+ %cmp4 = icmp eq i32 %asmresult1, 3
+ %xor610 = xor i1 %xor9, %cmp4
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC == 2 ^ CC == 3.
+define signext range(i32 0, 43) i32 @foo_023(i32 noundef signext %x) {
+; CHECK-LABEL: foo_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnlr %r14
+; CHECK-NEXT: .LBB8_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %cmp2 = icmp eq i32 %asmresult1, 2
+ %xor9 = xor i1 %cmp, %cmp2
+ %cmp4 = icmp eq i32 %asmresult1, 3
+ %xor610 = xor i1 %cmp4, %xor9
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 1 ^ CC == 2 ^ CC == 3.
+define signext range(i32 0, 43) i32 @foo_123(i32 noundef signext %x) {
+; CHECK-LABEL: foo_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bner %r14
+; CHECK-NEXT: .LBB9_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %xor9 = icmp ult i32 %2, 2
+ %cmp4 = icmp eq i32 %asmresult1, 3
+ %xor610 = xor i1 %cmp4, %xor9
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations.
+; These test cases are from heiko kernel and 14 variations of CCMask for XOR.
+
+ at a = dso_local global i32 0, align 4
+
+; Test CC == 0 ^ CC == 1.
+define range(i64 5, 9) i64 @fu_01() {
+; CHECK-LABEL: fu_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB10_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor4.i = icmp samesign ugt i32 %0, 1
+ %. = select i1 %xor4.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC == 2.
+define range(i64 5, 9) i64 @fu_02() {
+; CHECK-LABEL: fu_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB11_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC == 3.
+define range(i64 5, 9) i64 @fu_03() {
+; CHECK-LABEL: fu_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB12_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp ne i32 %0, 0
+ %2 = icmp ne i32 %0, 3
+ %tobool.not = and i1 %cmp.i, %2
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 1 ^ CC == 2.
+define range(i64 5, 9) i64 @fu_12() {
+; CHECK-LABEL: fu_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB13_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %xor4.i = icmp ult i32 %2, -2
+ %. = select i1 %xor4.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 1 ^ CC == 3.
+define range(i64 5, 9) i64 @fu_13() {
+; CHECK-LABEL: fu_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB14_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 2 ^ CC == 3.
+define range(i64 5, 9) i64 @fu_23() {
+; CHECK-LABEL: fu_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB15_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor4.i = icmp samesign ult i32 %0, 2
+ %. = select i1 %xor4.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC == 1 ^ CC == 2.
+define range(i64 5, 9) i64 @fu_012() {
+; CHECK-LABEL: fu_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB16_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 3
+ %. = select i1 %xor59.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC == 1 ^ CC == 3.
+define range(i64 5, 9) i64 @fu_013() {
+; CHECK-LABEL: fu_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB17_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor8.i = icmp samesign ugt i32 %0, 1
+ %2 = icmp ne i32 %0, 3
+ %tobool.not = and i1 %xor8.i, %2
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC == 2 ^ CC == 3.
+define range(i64 5, 9) i64 @fu_023() {
+; CHECK-LABEL: fu_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB18_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp eq i32 %0, 0
+ %cmp1.i = icmp eq i32 %0, 2
+ %xor8.i = xor i1 %cmp.i, %cmp1.i
+ %2 = icmp ne i32 %0, 3
+ %tobool.not = xor i1 %2, %xor8.i
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 1 ^ CC == 2 ^ CC == 3.
+define range(i64 5, 9) i64 @fu_123() {
+; CHECK-LABEL: fu_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB19_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %tobool.not = icmp eq i32 %0, 0
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations.
+; These test cases are from heiko kernel and 14 variations of CCMask for XOR.
+
+declare void @dummy()
+
+; Test CC == 0 ^ CC == 1.
+define void @bar_01() {
+; CHECK-LABEL: bar_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB20_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor4.i = icmp samesign ugt i32 %0, 1
+ br i1 %xor4.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 ^ CC == 2.
+define void @bar_02() {
+; CHECK-LABEL: bar_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jghe dummy at PLT
+; CHECK-NEXT: .LBB21_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 ^ CC == 3.
+define void @bar_03() {
+; CHECK-LABEL: bar_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnlh dummy at PLT
+; CHECK-NEXT: .LBB22_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ switch i32 %0, label %if.end [
+ i32 3, label %if.then
+ i32 0, label %if.then
+ ]
+
+if.then: ; preds = %entry, %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+; Test CC == 1 ^ CC == 2.
+define void @bar_12() {
+; CHECK-LABEL: bar_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB23_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %xor4.i = icmp ult i32 %2, -2
+ br i1 %xor4.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 ^ CC == 3.
+define void @bar_13() {
+; CHECK-LABEL: bar_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnhe dummy at PLT
+; CHECK-NEXT: .LBB24_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 2 ^ CC == 3.
+define void @bar_23() {
+; CHECK-LABEL: bar_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnle dummy at PLT
+; CHECK-NEXT: .LBB25_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor4.i = icmp samesign ult i32 %0, 2
+ br i1 %xor4.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 ^ CC == 1 ^ CC == 2.
+define void @bar_012() {
+; CHECK-LABEL: bar_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB26_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 3
+ br i1 %xor59.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 ^ CC == 1 ^ CC == 3.
+define void @bar_013() {
+; CHECK-LABEL: bar_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB27_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %switch = icmp eq i32 %0, 2
+ br i1 %switch, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+; Test CC == 0 ^ CC == 2 ^ CC == 3.
+define void @bar_023() {
+; CHECK-LABEL: bar_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB28_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp eq i32 %0, 0
+ %cmp1.i = icmp eq i32 %0, 2
+ %xor8.i = xor i1 %cmp.i, %cmp1.i
+ %2 = icmp ne i32 %0, 3
+ %tobool.not = xor i1 %2, %xor8.i
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 ^ CC == 2 ^ CC == 3.
+define void @bar_123() {
+; CHECK-LABEL: bar_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: larl %r1, a
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB29_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %tobool.not = icmp eq i32 %0, 0
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_eq_noteq.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_eq_noteq.ll
new file mode 100644
index 0000000000000..bdbe5ff3ae924
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_eq_noteq.ll
@@ -0,0 +1,1083 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations
+; for XOR for 3 three different functions, including two test cases from heiko.
+; This test checks combinations of EQUAL(==) and NOT EQUAL (!=) operator .e.g.
+; CC == 0 ^ CC != 1 ^ CC != 2 and CC == 0 ^ CC == 2 ^ CC != 3.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
+
+; Test CC == 0 ^ CC != 1.
+define signext range(i32 0, 43) i32 @foo_01(i32 noundef signext %x) {
+; CHECK-LABEL: foo_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB0_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5 = icmp samesign ugt i32 %asmresult1, 1
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC != 2
+define signext range(i32 0, 43) i32 @foo_02(i32 noundef signext %x) {
+; CHECK-LABEL: foo_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB1_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %tobool.not = icmp eq i32 %2, 0
+ %cond = select i1 %tobool.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo_03(i32 noundef signext %x) {
+; CHECK-LABEL: foo_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB2_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp ne i32 %asmresult1, 0
+ %cmp2 = icmp ne i32 %asmresult1, 3
+ %xor5 = and i1 %cmp, %cmp2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 1 ^ CC != 2.
+define signext range(i32 0, 43) i32 @foo_12(i32 noundef signext %x) {
+; CHECK-LABEL: foo_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB3_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -3
+ %xor5 = icmp ult i32 %2, -2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 1 ^ CC != 3
+define signext range(i32 0, 43) i32 @foo_13(i32 noundef signext %x) {
+; CHECK-LABEL: foo_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB4_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %asmresult1, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %cond = select i1 %tobool.not.not, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 2 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo_23(i32 noundef signext %x) {
+; CHECK-LABEL: foo_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB5_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %asmresult1, -4
+ %xor5 = icmp samesign ult i32 %2, -2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC != 1 ^ CC != 2.
+define signext range(i32 0, 43) i32 @foo_012(i32 noundef signext %x) {
+; CHECK-LABEL: foo_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB6_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor610.not = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %xor610.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC != 1 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo_013(i32 noundef signext %x) {
+; CHECK-LABEL: foo_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB7_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor9 = icmp samesign ugt i32 %asmresult1, 1
+ %cmp4 = icmp ne i32 %asmresult1, 3
+ %xor610 = xor i1 %xor9, %cmp4
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC != 2 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo_023(i32 noundef signext %x) {
+; CHECK-LABEL: foo_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB8_1: # %entry
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %asmresult1 to i1
+ %3 = icmp eq i32 %asmresult1, 3
+ %tobool.not = xor i1 %3, %2
+ %cond = select i1 %tobool.not, i32 0, i32 42
+ ret i32 %cond
+}
+
+; Test CC == 1 ^ CC != 2 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo_123(i32 noundef signext %x) {
+; CHECK-LABEL: foo_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bner %r14
+; CHECK-NEXT: .LBB9_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -3
+ %xor9 = icmp ult i32 %2, -2
+ %cmp4 = icmp ne i32 %asmresult1, 3
+ %xor610 = xor i1 %cmp4, %xor9
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC == 1 ^ CC != 2.
+define signext range(i32 0, 43) i32 @foo1_012(i32 noundef signext %x) {
+; CHECK-LABEL: foo1_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB10_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor610 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC == 1 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo1_013(i32 noundef signext %x) {
+; CHECK-LABEL: foo1_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB11_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor9 = icmp samesign ugt i32 %asmresult1, 1
+ %cmp4 = icmp ne i32 %asmresult1, 3
+ %xor610 = and i1 %xor9, %cmp4
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 0 ^ CC == 2 ^ CC != 3
+define signext range(i32 0, 43) i32 @foo1_023(i32 noundef signext %x) {
+; CHECK-LABEL: foo1_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB12_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp eq i32 %asmresult1, 0
+ %cmp2 = icmp eq i32 %asmresult1, 2
+ %xor9 = xor i1 %cmp, %cmp2
+ %cmp4 = icmp ne i32 %asmresult1, 3
+ %xor610 = xor i1 %cmp4, %xor9
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC == 1 ^ CC == 2 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo1_123(i32 noundef signext %x) {
+; CHECK-LABEL: foo1_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB13_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor610 = icmp eq i32 %asmresult1, 0
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+
+ at a = global i32 0, align 4
+
+; Test CC == 0 ^ CC != 1.
+define range(i64 5, 9) i64 @fu_01() {
+; CHECK-LABEL: fu_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB14_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor4.i = icmp samesign ult i32 %0, 2
+ %. = select i1 %xor4.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC != 2
+define range(i64 5, 9) i64 @fu_02() {
+; CHECK-LABEL: fu_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB15_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_03() {
+; CHECK-LABEL: fu_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB16_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp eq i32 %0, 0
+ %cmp1.i = icmp eq i32 %0, 3
+ %xor4.i.not = or i1 %cmp.i, %cmp1.i
+ %. = select i1 %xor4.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 1 ^ CC != 2.
+define range(i64 5, 9) i64 @fu_12() {
+; CHECK-LABEL: fu_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB17_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -1
+ %xor4.i = icmp ult i32 %2, 2
+ %. = select i1 %xor4.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 1 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_13() {
+; CHECK-LABEL: fu_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB18_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 2 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_23() {
+; CHECK-LABEL: fu_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB19_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %xor4.i = icmp samesign ugt i32 %2, -3
+ %. = select i1 %xor4.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC != 1 ^ CC != 2.
+define range(i64 5, 9) i64 @fu_012() {
+; CHECK-LABEL: fu_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB20_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 3
+ %. = select i1 %xor59.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC != 1 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_013() {
+; CHECK-LABEL: fu_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB21_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor8.i = icmp samesign ugt i32 %0, 1
+ %2 = icmp ne i32 %0, 3
+ %tobool.not = and i1 %xor8.i, %2
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC != 2 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_023() {
+; CHECK-LABEL: fu_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB22_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp eq i32 %0, 3
+ %tobool.not = xor i1 %3, %2
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 1 ^ CC != 2 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_123() {
+; CHECK-LABEL: fu_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB23_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %tobool.not = icmp eq i32 %0, 0
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC == 1 ^ CC != 2.
+define range(i64 5, 9) i64 @fu1_012() {
+; CHECK-LABEL: fu1_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB24_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 3
+ %. = select i1 %xor59.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC == 1 ^ CC != 3.
+define range(i64 5, 9) i64 @fu1_013() {
+; CHECK-LABEL: fu1_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB25_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor8.i = icmp samesign ult i32 %0, 2
+ %cmp3.i = icmp eq i32 %0, 3
+ %xor59.i.not = or i1 %xor8.i, %cmp3.i
+ %. = select i1 %xor59.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC == 2 ^ CC != 3.
+define range(i64 5, 9) i64 @fu1_023() {
+; CHECK-LABEL: fu1_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlr %r14
+; CHECK-NEXT: .LBB26_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp eq i32 %0, 0
+ %cmp1.i = icmp eq i32 %0, 2
+ %xor8.i = xor i1 %cmp.i, %cmp1.i
+ %2 = icmp eq i32 %0, 3
+ %tobool.not = xor i1 %2, %xor8.i
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC == 1 ^ CC == 2 ^ CC != 3.
+define range(i64 5, 9) i64 @fu1_123() {
+; CHECK-LABEL: fu1_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB27_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 0
+ %. = select i1 %xor59.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC == 0 ^ CC != 1.
+define void @bar_01() {
+; CHECK-LABEL: bar_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB28_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor4.i = icmp samesign ugt i32 %0, 1
+ br i1 %xor4.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+declare void @dummy() local_unnamed_addr #1
+
+; Test CC == 0 ^ CC != 2
+define void @bar_02() {
+; CHECK-LABEL: bar_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jghe dummy at PLT
+; CHECK-NEXT: .LBB29_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 ^ CC != 3.
+define void @bar_03() {
+; CHECK-LABEL: bar_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB30_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ switch i32 %0, label %if.then [
+ i32 3, label %if.end
+ i32 0, label %if.end
+ ]
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %entry, %if.then
+ ret void
+}
+
+; Test CC == 1 ^ CC != 2.
+define void @bar_12() {
+; CHECK-LABEL: bar_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnlh dummy at PLT
+; CHECK-NEXT: .LBB31_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -1
+ %xor4.i = icmp ult i32 %2, 2
+ br i1 %xor4.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 ^ CC != 3.
+define void @bar_13() {
+; CHECK-LABEL: bar_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jghe dummy at PLT
+; CHECK-NEXT: .LBB32_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 2 ^ CC != 3.
+define void @bar_23() {
+; CHECK-LABEL: bar_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB33_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = or disjoint i32 %0, -4
+ %xor4.i = icmp samesign ugt i32 %2, -3
+ br i1 %xor4.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 ^ CC != 1 ^ CC != 2.
+define void @bar_012() {
+; CHECK-LABEL: bar_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgno dummy at PLT
+; CHECK-NEXT: .LBB34_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 3
+ br i1 %xor59.i.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 ^ CC != 1 ^ CC != 3.
+define void @bar_013() {
+; CHECK-LABEL: bar_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnh dummy at PLT
+; CHECK-NEXT: .LBB35_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %switch = icmp eq i32 %0, 2
+ br i1 %switch, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+; Test CC == 0 ^ CC != 2 ^ CC != 3.
+define void @bar_023() {
+; CHECK-LABEL: bar_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnl dummy at PLT
+; CHECK-NEXT: .LBB36_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = trunc i32 %0 to i1
+ %3 = icmp eq i32 %0, 3
+ %tobool.not = xor i1 %3, %2
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 ^ CC != 2 ^ CC != 3.
+define void @bar_123() {
+; CHECK-LABEL: bar_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgne dummy at PLT
+; CHECK-NEXT: .LBB37_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %tobool.not = icmp eq i32 %0, 0
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 ^ CC == 1 ^ CC != 2.
+define void @bar1_012() {
+; CHECK-LABEL: bar1_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB38_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 3
+ br i1 %xor59.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 0 ^ CC == 1 ^ CC != 3.
+define void @bar1_013() {
+; CHECK-LABEL: bar1_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgh dummy at PLT
+; CHECK-NEXT: .LBB39_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %switch = icmp eq i32 %0, 2
+ br i1 %switch, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+; Test CC == 0 ^ CC == 2 ^ CC != 3.
+define void @bar1_023() {
+; CHECK-LABEL: bar1_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB40_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp eq i32 %0, 0
+ %cmp1.i = icmp eq i32 %0, 2
+ %xor8.i = xor i1 %cmp.i, %cmp1.i
+ %2 = icmp eq i32 %0, 3
+ %tobool.not = xor i1 %2, %xor8.i
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC == 1 ^ CC == 2 ^ CC !=3.
+define void @bar1_123() {
+; CHECK-LABEL: bar1_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB41_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 0
+ br i1 %xor59.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_not.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_not.ll
new file mode 100644
index 0000000000000..47410d28f80e3
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_not.ll
@@ -0,0 +1,778 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test Flag Output Operands with 14 combinations of CCMASK and optimizations
+; for XOR for 3 three different functions, including two test cases from heiko.
+; This test checks NOT EQUAL (!=), e.g. CC != 0 ^ CC != 1 ^ CC != 2.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
+
+; Test CC != 0 ^ CC != 1.
+define signext range(i32 0, 43) i32 @foo_01(i32 noundef signext %x) {
+; CHECK-LABEL: foo_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB0_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5 = icmp samesign ult i32 %asmresult1, 2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+declare void @llvm.assume(i1 noundef) #1
+
+; Test CC != 0 ^ CC != 2.
+define signext range(i32 0, 43) i32 @foo_02(i32 noundef signext %x) {
+; CHECK-LABEL: foo_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB1_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp ne i32 %asmresult1, 0
+ %cmp2 = icmp ne i32 %asmresult1, 2
+ %xor5 = xor i1 %cmp, %cmp2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 0 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo_03(i32 noundef signext %x) {
+; CHECK-LABEL: foo_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB2_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp ne i32 %asmresult1, 0
+ %cmp2 = icmp ne i32 %asmresult1, 3
+ %xor5 = xor i1 %cmp, %cmp2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 1 ^ CC != 2.
+define signext range(i32 0, 43) i32 @foo_12(i32 noundef signext %x) {
+; CHECK-LABEL: foo_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB3_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %asmresult1, -1
+ %xor5 = icmp ult i32 %2, 2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 1 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo_13(i32 noundef signext %x) {
+; CHECK-LABEL: foo_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnher %r14
+; CHECK-NEXT: .LBB4_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp ne i32 %asmresult1, 1
+ %cmp2 = icmp ne i32 %asmresult1, 3
+ %xor5 = xor i1 %cmp, %cmp2
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 2 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo_23(i32 noundef signext %x) {
+; CHECK-LABEL: foo_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB5_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor5 = icmp samesign ugt i32 %asmresult1, 1
+ %cond = select i1 %xor5, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 0 ^ CC != 1 ^ CC != 2.
+define signext range(i32 0, 43) i32 @foo_012(i32 noundef signext %x) {
+; CHECK-LABEL: foo_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB6_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor610 = icmp eq i32 %asmresult1, 3
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 0 ^ CC != 1 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo_013(i32 noundef signext %x) {
+; CHECK-LABEL: foo_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: bhr %r14
+; CHECK-NEXT: .LBB7_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor9 = icmp samesign ugt i32 %asmresult1, 1
+ %cmp4 = icmp ne i32 %asmresult1, 3
+ %xor610 = and i1 %xor9, %cmp4
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 0 ^ CC != 2 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo_023(i32 noundef signext %x) {
+; CHECK-LABEL: foo_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: blr %r14
+; CHECK-NEXT: .LBB8_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp = icmp ne i32 %asmresult1, 0
+ %cmp2 = icmp ne i32 %asmresult1, 2
+ %xor9 = xor i1 %cmp, %cmp2
+ %cmp4 = icmp ne i32 %asmresult1, 3
+ %xor610 = xor i1 %cmp4, %xor9
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+; Test CC != 1 ^ CC != 2 ^ CC != 3.
+define signext range(i32 0, 43) i32 @foo_123(i32 noundef signext %x) {
+; CHECK-LABEL: foo_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: #APP
+; CHECK-NEXT: ahi %r2, 42
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 42
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB9_1: # %entry
+; CHECK-NEXT: lghi %r2, 0
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x) #2
+ %asmresult1 = extractvalue { i32, i32 } %0, 1
+ %1 = icmp ult i32 %asmresult1, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor610 = icmp eq i32 %asmresult1, 0
+ %cond = select i1 %xor610, i32 42, i32 0
+ ret i32 %cond
+}
+
+
+ at a = global i32 0, align 4
+
+; Test CC != 0 ^ CC != 1.
+define range(i64 5, 9) i64 @fu_01() {
+; CHECK-LABEL: fu_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnler %r14
+; CHECK-NEXT: .LBB10_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor4.i = icmp samesign ugt i32 %0, 1
+ %. = select i1 %xor4.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 0 ^ CC != 2.
+define range(i64 5, 9) i64 @fu_02() {
+; CHECK-LABEL: fu_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB11_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC != 0 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_03() {
+; CHECK-LABEL: fu_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: blhr %r14
+; CHECK-NEXT: .LBB12_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp ne i32 %0, 0
+ %2 = icmp ne i32 %0, 3
+ %tobool.not = and i1 %cmp.i, %2
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 1 ^ CC != 2.
+define range(i64 5, 9) i64 @fu_12() {
+; CHECK-LABEL: fu_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlhr %r14
+; CHECK-NEXT: .LBB13_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %xor4.i = icmp ult i32 %2, -2
+ %. = select i1 %xor4.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 1 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_13() {
+; CHECK-LABEL: fu_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bher %r14
+; CHECK-NEXT: .LBB14_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not.not = icmp eq i32 %2, 0
+ %. = select i1 %tobool.not.not.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 2 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_23() {
+; CHECK-LABEL: fu_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bler %r14
+; CHECK-NEXT: .LBB15_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor4.i = icmp samesign ult i32 %0, 2
+ %. = select i1 %xor4.i, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 0 ^ CC != 1 ^ CC != 2.
+define range(i64 5, 9) i64 @fu_012() {
+; CHECK-LABEL: fu_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: bor %r14
+; CHECK-NEXT: .LBB16_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 3
+ %. = select i1 %xor59.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC != 0 ^ CC != 1 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_013() {
+; CHECK-LABEL: fu_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnhr %r14
+; CHECK-NEXT: .LBB17_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor8.i = icmp samesign ult i32 %0, 2
+ %cmp3.i = icmp eq i32 %0, 3
+ %xor59.i.not = or i1 %xor8.i, %cmp3.i
+ %. = select i1 %xor59.i.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 0 ^ CC != 2 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_023() {
+; CHECK-LABEL: fu_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: bnlr %r14
+; CHECK-NEXT: .LBB18_1: # %entry
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp ne i32 %0, 0
+ %cmp1.i = icmp ne i32 %0, 2
+ %xor8.i = xor i1 %cmp.i, %cmp1.i
+ %2 = icmp eq i32 %0, 3
+ %tobool.not = xor i1 %2, %xor8.i
+ %. = select i1 %tobool.not, i64 8, i64 5
+ ret i64 %.
+}
+
+; Test CC != 1 ^ CC != 2 ^ CC != 3.
+define range(i64 5, 9) i64 @fu_123() {
+; CHECK-LABEL: fu_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lghi %r2, 5
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB19_1: # %entry
+; CHECK-NEXT: lghi %r2, 8
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #2
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 0
+ %. = select i1 %xor59.i.not, i64 5, i64 8
+ ret i64 %.
+}
+
+; Test CC != 0 ^ CC != 1.
+define void @bar_01() {
+; CHECK-LABEL: bar_01:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgle dummy at PLT
+; CHECK-NEXT: .LBB20_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor4.i = icmp samesign ugt i32 %0, 1
+ br i1 %xor4.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+declare void @dummy() local_unnamed_addr #1
+
+; Test CC != 0 ^ CC != 2.
+define void @bar_02() {
+; CHECK-LABEL: bar_02:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jghe dummy at PLT
+; CHECK-NEXT: .LBB21_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 0 ^ CC != 3.
+define void @bar_03() {
+; CHECK-LABEL: bar_03:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnlh dummy at PLT
+; CHECK-NEXT: .LBB22_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ switch i32 %0, label %if.end [
+ i32 3, label %if.then
+ i32 0, label %if.then
+ ]
+
+if.then: ; preds = %entry, %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+; Test CC != 1 ^ CC != 2.
+define void @bar_12() {
+; CHECK-LABEL: bar_12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jglh dummy at PLT
+; CHECK-NEXT: .LBB23_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = add nsw i32 %0, -3
+ %xor4.i = icmp ult i32 %2, -2
+ br i1 %xor4.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 1 ^ CC != 3.
+define void @bar_13() {
+; CHECK-LABEL: bar_13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnhe dummy at PLT
+; CHECK-NEXT: .LBB24_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %2 = and i32 %0, 1
+ %tobool.not.not.not = icmp eq i32 %2, 0
+ br i1 %tobool.not.not.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 2 ^ CC != 3.
+define void @bar_23() {
+; CHECK-LABEL: bar_23:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgnle dummy at PLT
+; CHECK-NEXT: .LBB25_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor4.i = icmp samesign ult i32 %0, 2
+ br i1 %xor4.i, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 0 ^ CC != 1 ^ CC != 2.
+define void @bar_012() {
+; CHECK-LABEL: bar_012:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB26_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 3
+ br i1 %xor59.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 0 ^ CC != 1 ^ CC != 3.
+define void @bar_013() {
+; CHECK-LABEL: bar_013:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgh dummy at PLT
+; CHECK-NEXT: .LBB27_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %switch = icmp eq i32 %0, 2
+ br i1 %switch, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %entry, %if.then
+ ret void
+}
+
+; Test CC != 0 ^ CC != 2 ^ CC != 3.
+define void @bar_023() {
+; CHECK-LABEL: bar_023:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jgl dummy at PLT
+; CHECK-NEXT: .LBB28_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %cmp.i = icmp ne i32 %0, 0
+ %cmp1.i = icmp ne i32 %0, 2
+ %xor8.i = xor i1 %cmp.i, %cmp1.i
+ %2 = icmp eq i32 %0, 3
+ %tobool.not = xor i1 %2, %xor8.i
+ br i1 %tobool.not, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+; Test CC != 1 ^ CC != 2 ^ CC != 3.
+define void @bar_123() {
+; CHECK-LABEL: bar_123:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lgrl %r1, a at GOT
+; CHECK-NEXT: #APP
+; CHECK-NEXT: alsi 0(%r1), -1
+; CHECK-EMPTY:
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: jge dummy at PLT
+; CHECK-NEXT: .LBB29_1: # %if.end
+; CHECK-NEXT: br %r14
+entry:
+ %0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
+ %1 = icmp ult i32 %0, 4
+ tail call void @llvm.assume(i1 %1)
+ %xor59.i.not = icmp eq i32 %0, 0
+ br i1 %xor59.i.not, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ tail call void @dummy() #3
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+}
+
+
>From d3f3c036d31af0e9da6cc8d1382e582d022e5087 Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Fri, 7 Feb 2025 01:29:12 +0100
Subject: [PATCH 2/8] Removed triple check in CGStmt.cpp and using StringRef in
SystemZ.h.
---
clang/include/clang/Basic/TargetInfo.h | 5 +++++
clang/lib/Basic/Targets/SystemZ.cpp | 2 +-
clang/lib/Basic/Targets/SystemZ.h | 2 ++
clang/lib/CodeGen/CGStmt.cpp | 10 +++++-----
4 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 25eda907d20a7..4d40936676268 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1212,6 +1212,11 @@ class TargetInfo : public TransferrableTargetInfo,
std::string &/*SuggestedModifier*/) const {
return true;
}
+
+ // CC is binary on most targets. SystemZ overrides it as CC interval is
+ // [0, 4).
+ virtual unsigned getFlagOutputCCUpperBound() const { return 2; }
+
virtual bool
validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const = 0;
diff --git a/clang/lib/Basic/Targets/SystemZ.cpp b/clang/lib/Basic/Targets/SystemZ.cpp
index 49f88b45220d0..e6be8b7563892 100644
--- a/clang/lib/Basic/Targets/SystemZ.cpp
+++ b/clang/lib/Basic/Targets/SystemZ.cpp
@@ -92,7 +92,7 @@ bool SystemZTargetInfo::validateAsmConstraint(
return true;
case '@':
// CC condition changes.
- if (strlen(Name) >= 3 && *(Name + 1) == 'c' && *(Name + 2) == 'c') {
+ if (!StringRef("@cc").compare(Name)) {
Name += 2;
Info.setAllowsRegister();
return true;
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index a6909ababdec0..fc23a0bcd6234 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -114,6 +114,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
return RegName == "r15";
}
+ // CC has interval [0, 4).
+ unsigned getFlagOutputCCUpperBound() const override { return 4; }
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override;
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 27f7bb6528958..de91d894872a2 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2563,11 +2563,11 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
// Target must guarantee the Value `Tmp` here is lowered to a boolean
// value.
- unsigned CCUpperBound = 2;
- if (CGF.getTarget().getTriple().getArch() == llvm::Triple::systemz) {
- // On this target CC value can be in range [0, 3].
- CCUpperBound = 4;
- }
+ // Lowering 'Tmp' as - 'icmp ult %Tmp , CCUpperBound'. On some targets
+ // CCUpperBound is not binary. CCUpperBound is 4 for SystemZ,
+ // interval [0, 4). With this range known, llvm.assume intrinsic guides
+ // optimizer to generate more optimized IR. Verified it for SystemZ.
+ unsigned CCUpperBound = CGF.getTarget().getFlagOutputCCUpperBound();
llvm::Constant *CCUpperBoundConst =
llvm::ConstantInt::get(Tmp->getType(), CCUpperBound);
llvm::Value *IsBooleanValue =
>From 062e03aa7db7611a0a6d30b735abde8de4edbc4a Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Fri, 7 Feb 2025 17:02:30 +0100
Subject: [PATCH 3/8] clang test causing pr build failure.
---
.../CodeGen/inline-asm-systemz-flag-output.c | 144 ++----------------
1 file changed, 14 insertions(+), 130 deletions(-)
diff --git a/clang/test/CodeGen/inline-asm-systemz-flag-output.c b/clang/test/CodeGen/inline-asm-systemz-flag-output.c
index ab90e031df1f2..68ba0dad26bbc 100644
--- a/clang/test/CodeGen/inline-asm-systemz-flag-output.c
+++ b/clang/test/CodeGen/inline-asm-systemz-flag-output.c
@@ -1,149 +1,33 @@
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
-// RUN: %clang_cc1 -triple s390x-linux -emit-llvm -o - %s | FileCheck %s
-// CHECK-LABEL: define dso_local signext i32 @foo_012(
-// CHECK-SAME: i32 noundef signext [[X:%.*]]) #[[ATTR0:[0-9]+]] {
-// CHECK-NEXT: [[ENTRY:.*]]:
-// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[CC:%.*]] = alloca i32, align 4
-// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP1:%.*]] = call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 [[TMP0]]) #[[ATTR2:[0-9]+]], !srcloc [[META2:![0-9]+]]
-// CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
-// CHECK-NEXT: [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
-// CHECK-NEXT: store i32 [[ASMRESULT]], ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[ASMRESULT1]], 4
-// CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
-// CHECK-NEXT: store i32 [[ASMRESULT1]], ptr [[CC]], align 4
-// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 0
-// CHECK-NEXT: br i1 [[CMP]], label %[[LOR_END:.*]], label %[[LOR_LHS_FALSE:.*]]
-// CHECK: [[LOR_LHS_FALSE]]:
-// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[TMP4]], 1
-// CHECK-NEXT: br i1 [[CMP2]], label %[[LOR_END]], label %[[LOR_RHS:.*]]
-// CHECK: [[LOR_RHS]]:
-// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[TMP5]], 2
-// CHECK-NEXT: br label %[[LOR_END]]
-// CHECK: [[LOR_END]]:
-// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ true, %[[LOR_LHS_FALSE]] ], [ true, %[[ENTRY]] ], [ [[CMP3]], %[[LOR_RHS]] ]
-// CHECK-NEXT: [[TMP7:%.*]] = zext i1 [[TMP6]] to i64
-// CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP6]], i32 42, i32 0
-// CHECK-NEXT: ret i32 [[COND]]
-//
+// RUN: %clang_cc1 -O2 -triple s390x-linux -emit-llvm -o - %s | FileCheck %s
+
int foo_012(int x) {
+// CHECK-LABEL: @foo_012
+// CHECK: = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x)
int cc;
- asm volatile ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
+ asm ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
return cc == 0 || cc == 1 || cc == 2 ? 42 : 0;
}
-// CHECK-LABEL: define dso_local signext i32 @foo_013(
-// CHECK-SAME: i32 noundef signext [[X:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*]]:
-// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[CC:%.*]] = alloca i32, align 4
-// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP1:%.*]] = call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 [[TMP0]]) #[[ATTR2]], !srcloc [[META3:![0-9]+]]
-// CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
-// CHECK-NEXT: [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
-// CHECK-NEXT: store i32 [[ASMRESULT]], ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[ASMRESULT1]], 4
-// CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
-// CHECK-NEXT: store i32 [[ASMRESULT1]], ptr [[CC]], align 4
-// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 0
-// CHECK-NEXT: br i1 [[CMP]], label %[[LOR_END:.*]], label %[[LOR_LHS_FALSE:.*]]
-// CHECK: [[LOR_LHS_FALSE]]:
-// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[TMP4]], 1
-// CHECK-NEXT: br i1 [[CMP2]], label %[[LOR_END]], label %[[LOR_RHS:.*]]
-// CHECK: [[LOR_RHS]]:
-// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[TMP5]], 3
-// CHECK-NEXT: br label %[[LOR_END]]
-// CHECK: [[LOR_END]]:
-// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ true, %[[LOR_LHS_FALSE]] ], [ true, %[[ENTRY]] ], [ [[CMP3]], %[[LOR_RHS]] ]
-// CHECK-NEXT: [[TMP7:%.*]] = zext i1 [[TMP6]] to i64
-// CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP6]], i32 42, i32 0
-// CHECK-NEXT: ret i32 [[COND]]
-//
int foo_013(int x) {
+// CHECK-LABEL: @foo_013
+// CHECK: = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x)
int cc;
- asm volatile ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
+ asm ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
return cc == 0 || cc == 1 || cc == 3 ? 42 : 0;
}
-// CHECK-LABEL: define dso_local signext i32 @foo_023(
-// CHECK-SAME: i32 noundef signext [[X:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*]]:
-// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[CC:%.*]] = alloca i32, align 4
-// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP1:%.*]] = call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 [[TMP0]]) #[[ATTR2]], !srcloc [[META4:![0-9]+]]
-// CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
-// CHECK-NEXT: [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
-// CHECK-NEXT: store i32 [[ASMRESULT]], ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[ASMRESULT1]], 4
-// CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
-// CHECK-NEXT: store i32 [[ASMRESULT1]], ptr [[CC]], align 4
-// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 0
-// CHECK-NEXT: br i1 [[CMP]], label %[[LOR_END:.*]], label %[[LOR_LHS_FALSE:.*]]
-// CHECK: [[LOR_LHS_FALSE]]:
-// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[TMP4]], 2
-// CHECK-NEXT: br i1 [[CMP2]], label %[[LOR_END]], label %[[LOR_RHS:.*]]
-// CHECK: [[LOR_RHS]]:
-// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[TMP5]], 3
-// CHECK-NEXT: br label %[[LOR_END]]
-// CHECK: [[LOR_END]]:
-// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ true, %[[LOR_LHS_FALSE]] ], [ true, %[[ENTRY]] ], [ [[CMP3]], %[[LOR_RHS]] ]
-// CHECK-NEXT: [[TMP7:%.*]] = zext i1 [[TMP6]] to i64
-// CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP6]], i32 42, i32 0
-// CHECK-NEXT: ret i32 [[COND]]
-//
int foo_023(int x) {
+// CHECK-LABEL: @foo_023
+// CHECK: = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x)
int cc;
- asm volatile ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
+ asm ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
return cc == 0 || cc == 2 || cc == 3 ? 42 : 0;
}
-// CHECK-LABEL: define dso_local signext i32 @foo_123(
-// CHECK-SAME: i32 noundef signext [[X:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT: [[ENTRY:.*]]:
-// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[CC:%.*]] = alloca i32, align 4
-// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP1:%.*]] = call { i32, i32 } asm sideeffect "ahi $0,42\0A", "=d,={@cc},0"(i32 [[TMP0]]) #[[ATTR2]], !srcloc [[META5:![0-9]+]]
-// CHECK-NEXT: [[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
-// CHECK-NEXT: [[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
-// CHECK-NEXT: store i32 [[ASMRESULT]], ptr [[X_ADDR]], align 4
-// CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[ASMRESULT1]], 4
-// CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
-// CHECK-NEXT: store i32 [[ASMRESULT1]], ptr [[CC]], align 4
-// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 1
-// CHECK-NEXT: br i1 [[CMP]], label %[[LOR_END:.*]], label %[[LOR_LHS_FALSE:.*]]
-// CHECK: [[LOR_LHS_FALSE]]:
-// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[TMP4]], 2
-// CHECK-NEXT: br i1 [[CMP2]], label %[[LOR_END]], label %[[LOR_RHS:.*]]
-// CHECK: [[LOR_RHS]]:
-// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[CC]], align 4
-// CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[TMP5]], 3
-// CHECK-NEXT: br label %[[LOR_END]]
-// CHECK: [[LOR_END]]:
-// CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ true, %[[LOR_LHS_FALSE]] ], [ true, %[[ENTRY]] ], [ [[CMP3]], %[[LOR_RHS]] ]
-// CHECK-NEXT: [[TMP7:%.*]] = zext i1 [[TMP6]] to i64
-// CHECK-NEXT: [[COND:%.*]] = select i1 [[TMP6]], i32 42, i32 0
-// CHECK-NEXT: ret i32 [[COND]]
-//
int foo_123(int x) {
+// CHECK-LABEL: @foo_123
+// CHECK: = tail call { i32, i32 } asm "ahi $0,42\0A", "=d,={@cc},0"(i32 %x)
int cc;
- asm volatile ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
+ asm ("ahi %[x],42\n" : [x] "+d"(x), "=@cc" (cc));
return cc == 1 || cc == 2 || cc == 3 ? 42 : 0;
}
>From 5aef5641cb3b509a97b558ba7b619252fed421ec Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Mon, 10 Feb 2025 19:46:58 +0100
Subject: [PATCH 4/8] Add Preprocessor test for flag output operand and some
cleanup for c string.
---
clang/lib/Basic/Targets/SystemZ.h | 5 +++--
clang/test/Preprocessor/systemz_asm_flag_outut.c | 4 ++++
2 files changed, 7 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Preprocessor/systemz_asm_flag_outut.c
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index fc23a0bcd6234..d5823381dc9c3 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -120,8 +120,9 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
TargetInfo::ConstraintInfo &info) const override;
std::string convertConstraint(const char *&Constraint) const override {
- if (strncmp(Constraint, "@cc", 3) == 0) {
- std::string Converted = "{" + std::string(Constraint, 3) + "}";
+ if (llvm::StringRef(Constraint).starts_with("@cc")) {
+ std::string Converted =
+ std::string("{") + std::string("@cc") + std::string("}");
Constraint += 3;
return Converted;
}
diff --git a/clang/test/Preprocessor/systemz_asm_flag_outut.c b/clang/test/Preprocessor/systemz_asm_flag_outut.c
new file mode 100644
index 0000000000000..b627499d5ce46
--- /dev/null
+++ b/clang/test/Preprocessor/systemz_asm_flag_outut.c
@@ -0,0 +1,4 @@
+// RUN: %clang -target systemz-unknown-unknown -x c -E -dM -o - %s | FileCheck -match-full-lines %s
+// RUN: %clang -target s390x-unknown-unknown -x c -E -dM -o - %s | FileCheck -match-full-lines %s
+
+// CHECK: #define __GCC_ASM_FLAG_OUTPUTS__ 1
>From 2ab7a75c10a366a4b693be15dc84d253569807e8 Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Tue, 11 Feb 2025 19:23:17 +0100
Subject: [PATCH 5/8] Fixed clang outputting extra byte '\7F' in clang test and
fix a warning in SystemZISelLowering.cpp.
---
clang/lib/Basic/Targets/SystemZ.h | 5 +++--
llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 4 ++++
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index d5823381dc9c3..fc2584142a78e 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -121,9 +121,10 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
std::string convertConstraint(const char *&Constraint) const override {
if (llvm::StringRef(Constraint).starts_with("@cc")) {
+ auto Len = llvm::StringRef("@cc").size();
std::string Converted =
- std::string("{") + std::string("@cc") + std::string("}");
- Constraint += 3;
+ std::string("{") + std::string(Constraint, Len) + std::string("}");
+ Constraint += Len - 1;
return Converted;
}
switch (Constraint[0]) {
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 259da48a3b223..aff2db95d494b 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -8012,6 +8012,10 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
NewCCMask = NewCCMask1;
else if (isSRL_IPM_CCSequence(AndOp2.getNode()) && IsOp2)
NewCCMask = NewCCMask2;
+ else {
+ CCValid = RestoreCCValid;
+ return false;
+ }
// Bit 29 set => CC == 2 || CC == 3.
if ((NewCCMask & 0x3) == 2)
NewCCMask = SystemZ::CCMASK_2 | SystemZ::CCMASK_3;
>From fccc70e04fa764c7adf9f00dfb624b356b12406a Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Thu, 13 Feb 2025 14:39:55 +0100
Subject: [PATCH 6/8] Incorporated suggestions in review.
---
clang/include/clang/Basic/TargetInfo.h | 16 ++--
clang/lib/Basic/Targets/SystemZ.cpp | 1 +
clang/lib/Basic/Targets/SystemZ.h | 7 +-
clang/lib/CodeGen/CGStmt.cpp | 14 +++-
.../SelectionDAG/SelectionDAGBuilder.cpp | 34 +++-----
.../Target/SystemZ/SystemZISelLowering.cpp | 80 ++++++++++---------
6 files changed, 80 insertions(+), 72 deletions(-)
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 648980f68895f..d4a18ce01f6bc 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1114,10 +1114,12 @@ class TargetInfo : public TransferrableTargetInfo,
std::string ConstraintStr; // constraint: "=rm"
std::string Name; // Operand name: [foo] with no []'s.
+ unsigned FlagOutputCCUpperBound;
+
public:
ConstraintInfo(StringRef ConstraintStr, StringRef Name)
: Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
- Name(Name.str()) {
+ Name(Name.str()), FlagOutputCCUpperBound(2) {
ImmRange.Min = ImmRange.Max = 0;
ImmRange.isConstrained = false;
}
@@ -1188,6 +1190,14 @@ class TargetInfo : public TransferrableTargetInfo,
TiedOperand = N;
// Don't copy Name or constraint string.
}
+
+ // CC range can be set by target. SystemZ sets it to 4. It is 2 by default.
+ void setFlagOutputCCUpperBound(unsigned CCBound) {
+ FlagOutputCCUpperBound = CCBound;
+ }
+ unsigned getFlagOutputCCUpperBound() const {
+ return FlagOutputCCUpperBound;
+ }
};
/// Validate register name used for global register variables.
@@ -1229,10 +1239,6 @@ class TargetInfo : public TransferrableTargetInfo,
return true;
}
- // CC is binary on most targets. SystemZ overrides it as CC interval is
- // [0, 4).
- virtual unsigned getFlagOutputCCUpperBound() const { return 2; }
-
virtual bool
validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const = 0;
diff --git a/clang/lib/Basic/Targets/SystemZ.cpp b/clang/lib/Basic/Targets/SystemZ.cpp
index e848c04530908..c7725a8bd54a0 100644
--- a/clang/lib/Basic/Targets/SystemZ.cpp
+++ b/clang/lib/Basic/Targets/SystemZ.cpp
@@ -103,6 +103,7 @@ bool SystemZTargetInfo::validateAsmConstraint(
if (!StringRef("@cc").compare(Name)) {
Name += 2;
Info.setAllowsRegister();
+ Info.setFlagOutputCCUpperBound(4);
return true;
}
return false;
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index abd7fb4566860..6db148dc45db8 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -115,16 +115,13 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
return RegName == "r15";
}
- // CC has interval [0, 4).
- unsigned getFlagOutputCCUpperBound() const override { return 4; }
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override;
std::string convertConstraint(const char *&Constraint) const override {
- if (llvm::StringRef(Constraint).starts_with("@cc")) {
+ if (llvm::StringRef(Constraint) == "@cc") {
auto Len = llvm::StringRef("@cc").size();
- std::string Converted =
- std::string("{") + std::string(Constraint, Len) + std::string("}");
+ std::string Converted = std::string("{@cc}");
Constraint += Len - 1;
return Converted;
}
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 41ee1939d6b34..2055de97a5864 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2624,8 +2624,18 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
// Lowering 'Tmp' as - 'icmp ult %Tmp , CCUpperBound'. On some targets
// CCUpperBound is not binary. CCUpperBound is 4 for SystemZ,
// interval [0, 4). With this range known, llvm.assume intrinsic guides
- // optimizer to generate more optimized IR. Verified it for SystemZ.
- unsigned CCUpperBound = CGF.getTarget().getFlagOutputCCUpperBound();
+ // optimizer to generate more optimized IR in most of the cases as
+ // observed for select_cc on SystemZ unit tests for flag output operands.
+ // For some cases for br_cc, generated IR was weird. e.g. switch table
+ // for simple simple comparison terms for br_cc.
+ StringRef Name;
+ if (const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
+ Name = GAS->getOutputName(i);
+ TargetInfo::ConstraintInfo Info(S.getOutputConstraint(i), Name);
+ bool IsValid = CGF.getTarget().validateOutputConstraint(Info);
+ (void)IsValid;
+ assert(IsValid && "Failed to parse flag output operand constraint");
+ unsigned CCUpperBound = Info.getFlagOutputCCUpperBound();
llvm::Constant *CCUpperBoundConst =
llvm::ConstantInt::get(Tmp->getType(), CCUpperBound);
llvm::Value *IsBooleanValue =
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index c7e1e89fd53fe..dbb9ac74962be 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2838,11 +2838,6 @@ void SelectionDAGBuilder::visitBr(const BranchInst &I) {
else if (match(BOp, m_LogicalOr(m_Value(BOp0), m_Value(BOp1))))
Opcode = Instruction::Or;
auto &TLI = DAG.getTargetLoweringInfo();
- bool BrSrlIPM = FuncInfo.MF->getTarget().getTargetTriple().getArch() ==
- Triple::ArchType::systemz;
- // For Flag output operands SRL/IPM sequence, we want to avoid
- // creating switch case, as it creates Basic Block and inhibits
- // optimization in DAGCombiner for flag output operands.
const auto checkSRLIPM = [&TLI](const SDValue &Op) {
if (!Op.getNumOperands())
return false;
@@ -2859,13 +2854,15 @@ void SelectionDAGBuilder::visitBr(const BranchInst &I) {
}
return false;
};
- if (BrSrlIPM) {
- if (NodeMap.count(BOp0) && NodeMap[BOp0].getNode()) {
- BrSrlIPM &= checkSRLIPM(getValue(BOp0));
- if (NodeMap.count(BOp1) && NodeMap[BOp1].getNode())
- BrSrlIPM &= checkSRLIPM(getValue(BOp1));
- } else
- BrSrlIPM = false;
+ // Incoming IR here is straight line code, FindMergedConditions splits
+ // condition code sequence across Basic Block. DAGCombiner can't combine
+ // across Basic Block. Identify SRL/IPM/CC sequence for SystemZ and avoid
+ // transformation in FindMergedConditions.
+ bool BrSrlIPM = false;
+ if (NodeMap.count(BOp0) && NodeMap[BOp0].getNode()) {
+ BrSrlIPM |= checkSRLIPM(getValue(BOp0));
+ if (NodeMap.count(BOp1) && NodeMap[BOp1].getNode())
+ BrSrlIPM &= checkSRLIPM(getValue(BOp1));
}
if (Opcode && !BrSrlIPM &&
!(match(BOp0, m_ExtractElt(m_Value(Vec), m_Value())) &&
@@ -12141,20 +12138,15 @@ void SelectionDAGBuilder::lowerWorkItem(SwitchWorkListItem W, Value *Cond,
const APInt &SmallValue = Small.Low->getValue();
const APInt &BigValue = Big.Low->getValue();
- // Creating switch cases optimizing tranformation inhibits DAGCombiner
- // for SystemZ for flag output operands. DAGCobiner compute cumulative
- // CCMask for flag output operands SRL/IPM sequence, we want to avoid
- // creating switch case, as it creates Basic Block and inhibits
- // optimization in DAGCombiner for flag output operands.
- // cases like (CC == 0) || (CC == 2) || (CC == 3), or
+ // Incoming IR is switch table.Identify SRL/IPM/CC sequence for SystemZ
+ // and we want to avoid splitting condition code sequence across basic
+ // block for cases like (CC == 0) || (CC == 2) || (CC == 3), or
// (CC == 0) || (CC == 1) ^ (CC == 3), there could potentially be
// more cases like this.
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
bool IsSrlIPM = false;
if (NodeMap.count(Cond) && NodeMap[Cond].getNode())
- IsSrlIPM = CurMF->getTarget().getTargetTriple().getArch() ==
- Triple::ArchType::systemz &&
- TLI.canLowerSRL_IPM_Switch(getValue(Cond));
+ IsSrlIPM = TLI.canLowerSRL_IPM_Switch(getValue(Cond));
// Check that there is only one bit different.
APInt CommonBit = BigValue ^ SmallValue;
if (CommonBit.isPowerOf2() || IsSrlIPM) {
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 0ae5d6a20e83f..94ae61d6d992c 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -1482,6 +1482,14 @@ SystemZTargetLowering::getConstraintType(StringRef Constraint) const {
return TargetLowering::getConstraintType(Constraint);
}
+// Convert condition code in CCReg to an i32 value.
+static SDValue getCCResult(SelectionDAG &DAG, SDValue CCReg) {
+ SDLoc DL(CCReg);
+ SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg);
+ return DAG.getNode(ISD::SRL, DL, MVT::i32, IPM,
+ DAG.getConstant(SystemZ::IPM_CC, DL, MVT::i32));
+}
+
TargetLowering::ConstraintWeight SystemZTargetLowering::
getSingleConstraintMatchWeight(AsmOperandInfo &info,
const char *constraint) const {
@@ -1717,12 +1725,7 @@ SDValue SystemZTargetLowering::LowerAsmOutputForConstraint(
Chain = Glue.getValue(1);
} else
Glue = DAG.getCopyFromReg(Chain, DL, SystemZ::CC, MVT::i32);
-
- SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, Glue);
- SDValue CC = DAG.getNode(ISD::SRL, DL, MVT::i32, IPM,
- DAG.getConstant(SystemZ::IPM_CC, DL, MVT::i32));
-
- return CC;
+ return getCCResult(DAG, Glue);
}
void SystemZTargetLowering::LowerAsmOperandForConstraint(
@@ -5227,14 +5230,6 @@ SDValue SystemZTargetLowering::lowerPREFETCH(SDValue Op,
Node->getMemoryVT(), Node->getMemOperand());
}
-// Convert condition code in CCReg to an i32 value.
-static SDValue getCCResult(SelectionDAG &DAG, SDValue CCReg) {
- SDLoc DL(CCReg);
- SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg);
- return DAG.getNode(ISD::SRL, DL, MVT::i32, IPM,
- DAG.getConstant(SystemZ::IPM_CC, DL, MVT::i32));
-}
-
SDValue
SystemZTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
SelectionDAG &DAG) const {
@@ -8082,7 +8077,7 @@ SDValue SystemZTargetLowering::combineBSWAP(
}
// Combine IPM sequence for flag output operands.
-static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
+static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
// Convert CCVal to CCMask and update it along with CCValid.
const auto convertCCValToCCMask = [&CCMask, &CCValid](int CCVal) {
bool Invert = false;
@@ -8121,6 +8116,8 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
if (!IPMOp0 || IPMOp0->getNumOperands() < 2)
return false;
auto *RN = dyn_cast<RegisterSDNode>(IPMOp0->getOperand(1));
+ // Check if operand 1 is SystemZ::CC. Also, it avoids srl/ipm/tbegin and
+ // srl/ipm/tend kind of sequences.
if (!RN || !RN->getReg().isPhysical() || RN->getReg() != SystemZ::CC)
return false;
// Return the updated CCReg link.
@@ -8177,7 +8174,7 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
return false;
int CCValidVal = CCValid1->getZExtValue();
int CCMaskVal = CCMask1->getZExtValue();
- if (combineCCIPMMask(XORReg, CCValidVal, CCMaskVal)) {
+ if (combineSRL_IPM_CCMask(XORReg, CCValidVal, CCMaskVal)) {
// CC == 0 || CC == 2 for bit 28 Test Under Mask.
CCMask = SystemZ::CCMASK_CMP_GE;
CCMask ^= CCMaskVal;
@@ -8217,7 +8214,7 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
int CCValidVal = CCValidNode->getZExtValue();
int CCMaskVal = CCMaskNode->getZExtValue();
SDValue CCRegOp = CCNode->getOperand(4);
- if (combineCCIPMMask(CCRegOp, CCValidVal, CCMaskVal) ||
+ if (combineSRL_IPM_CCMask(CCRegOp, CCValidVal, CCMaskVal) ||
isCCOperand(CCRegOp.getNode())) {
CCMask = CCMaskVal;
CCValid = SystemZ::CCMASK_ANY;
@@ -8252,8 +8249,8 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
int CCMaskVal2 = CCMask2->getZExtValue();
SDValue CCReg1 = XOROp1->getOperand(4);
SDValue CCReg2 = XOROp2->getOperand(4);
- if (!combineCCIPMMask(CCReg1, CCValidVal1, CCMaskVal1) ||
- !combineCCIPMMask(CCReg2, CCValidVal2, CCMaskVal2))
+ if (!combineSRL_IPM_CCMask(CCReg1, CCValidVal1, CCMaskVal1) ||
+ !combineSRL_IPM_CCMask(CCReg2, CCValidVal2, CCMaskVal2))
return false;
CCMask = CCMaskVal1 ^ CCMaskVal2;
CCReg = CCReg1;
@@ -8280,8 +8277,8 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
SDValue CmpOp2 = CCNode->getOperand(1);
int CCValid1 = CCValid, CCValid2 = CCValid;
int CCMask1 = CCMask, CCMask2 = CCMask;
- bool IsOp1 = combineCCIPMMask(CmpOp1, CCValid1, CCMask1);
- bool IsOp2 = combineCCIPMMask(CmpOp2, CCValid2, CCMask2);
+ bool IsOp1 = combineSRL_IPM_CCMask(CmpOp1, CCValid1, CCMask1);
+ bool IsOp2 = combineSRL_IPM_CCMask(CmpOp2, CCValid2, CCMask2);
if (IsOp1 && IsOp2) {
CCMask = CCMask1 ^ CCMask2;
CCReg = CmpOp1;
@@ -8300,7 +8297,7 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
if (CCMask == SystemZ::CCMASK_CMP_NE)
Invert = !Invert;
SDValue NewCCReg = CCNode->getOperand(0);
- if (combineCCIPMMask(NewCCReg, CCValid, CCMask)) {
+ if (combineSRL_IPM_CCMask(NewCCReg, CCValid, CCMask)) {
CCMask |= Mask;
if (Invert)
CCMask ^= SystemZ::CCMASK_ANY;
@@ -8320,8 +8317,8 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
SDValue OrOp2 = LHS->getOperand(1);
int NewCCMask1 = CCMask, NewCCMask2 = CCMask, NewCCMask = CCMask;
if (!isa<ConstantSDNode>(OrOp1) && !isa<ConstantSDNode>(OrOp2)) {
- bool IsOp1 = combineCCIPMMask(OrOp1, CCValid, NewCCMask1);
- bool IsOp2 = combineCCIPMMask(OrOp2, CCValid, NewCCMask2);
+ bool IsOp1 = combineSRL_IPM_CCMask(OrOp1, CCValid, NewCCMask1);
+ bool IsOp2 = combineSRL_IPM_CCMask(OrOp2, CCValid, NewCCMask2);
if (!IsOp1 && !IsOp2) {
CCValid = RestoreCCValid;
return false;
@@ -8364,8 +8361,8 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
int NewCCMask2 = CCMask;
int NewCCMask;
if (!isa<ConstantSDNode>(AndOp1) && !isa<ConstantSDNode>(AndOp2)) {
- bool IsOp1 = combineCCIPMMask(AndOp1, CCValid, NewCCMask1);
- bool IsOp2 = combineCCIPMMask(AndOp2, CCValid, NewCCMask2);
+ bool IsOp1 = combineSRL_IPM_CCMask(AndOp1, CCValid, NewCCMask1);
+ bool IsOp2 = combineSRL_IPM_CCMask(AndOp2, CCValid, NewCCMask2);
if (!IsOp1 && !IsOp2) {
CCValid = RestoreCCValid;
return false;
@@ -8455,7 +8452,7 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
if (CCMask == SystemZ::CCMASK_CMP_NE)
Invert = !Invert;
// If both the operands are select_cc.
- if (combineCCIPMMask(XORReg, CCValid, CCMask)) {
+ if (combineSRL_IPM_CCMask(XORReg, CCValid, CCMask)) {
CCReg = XORReg;
CCValid = SystemZ::CCMASK_ANY;
return true;
@@ -8479,8 +8476,8 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
SDValue XORReg1 = XOROp->getOperand(4);
SDValue XORReg2 = LHS->getOperand(1);
int CCMaskVal1 = CCMaskVal, CCMaskVal2 = CCMaskVal;
- if (combineCCIPMMask(XORReg1, CCValidVal, CCMaskVal1) &&
- combineCCIPMMask(XORReg2, CCValidVal, CCMaskVal2)) {
+ if (combineSRL_IPM_CCMask(XORReg1, CCValidVal, CCMaskVal1) &&
+ combineSRL_IPM_CCMask(XORReg2, CCValidVal, CCMaskVal2)) {
CCMask = CCMaskVal1 ^ CCMaskVal2;
CCReg = XORReg1;
CCValid = SystemZ::CCMASK_ANY;
@@ -8493,6 +8490,17 @@ static bool combineCCIPMMask(SDValue &CCReg, int &CCValid, int &CCMask) {
}
static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
+ // combineSRL_IPM_CCMask tries to combine srl/ipm/cc sequence.
+ // This sequence here seems to be only for flag output operand.
+ // IPM operand has physical operand SystemZ::CC and CCValid is 15.
+ if (combineSRL_IPM_CCMask(CCReg, CCValid, CCMask))
+ return true;
+
+ // Code for SELECT_CCMASK does not seem to have ipm sequence.
+ // There is one case with sra/ipm that does not have SystemZ::CC as an
+ // operand. Test cases for sra/ipm are bcmp.ll, memcmp-01.ll and
+ // strcmp-01.ll. These tests have sra/sll/ipm/clc sequence.
+
// We have a SELECT_CCMASK or BR_CCMASK comparing the condition code
// set by the CCReg instruction using the CCValid / CCMask masks,
// If the CCReg instruction is itself a ICMP testing the condition
@@ -8545,7 +8553,6 @@ static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
CCReg = CompareLHS->getOperand(4);
return true;
}
-
// Optimize the case where CompareRHS is (SRA (SHL (IPM))).
if (CompareLHS->getOpcode() == ISD::SRA) {
auto *SRACount = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(1));
@@ -8575,7 +8582,6 @@ static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
CCReg = IPM->getOperand(0);
return true;
}
-
return false;
}
@@ -8642,7 +8648,7 @@ SystemZTargetLowering::combineSELECT_CC_CCIPMMask(SDNode *N,
SDValue CCReg = N->getOperand(4);
SDValue CCRegOp = CCOpNode->getOperand(4);
// Combine current select_cc.
- if (combineCCIPMMask(CCReg, CCValid, CCMask)) {
+ if (combineSRL_IPM_CCMask(CCReg, CCValid, CCMask)) {
if (InvertOp1)
CCMask ^= SystemZ::CCMASK_ANY;
// There are two scenarios here.
@@ -8652,7 +8658,7 @@ SystemZTargetLowering::combineSELECT_CC_CCIPMMask(SDNode *N,
// SELECT_CCMASK. Check for isCCOperand. In this case we will not know
// original CCMask, but if only one bit is set in CCMaskValOp, that means
// original CCMask was SystemZ::CCMASK_CMP_EQ.
- if (!combineCCIPMMask(CCRegOp, CCValidValOp, CCMaskValOp) &&
+ if (!combineSRL_IPM_CCMask(CCRegOp, CCValidValOp, CCMaskValOp) &&
!isCCOperand(CCRegOp.getNode()))
return std::nullopt;
// If outer SELECT_CCMASK is CCMASK_CMP_EQ or single bit is set in
@@ -8722,9 +8728,7 @@ SDValue SystemZTargetLowering::combineBR_CCMASK(
SDValue Chain = N->getOperand(0);
SDValue CCReg = N->getOperand(4);
- // combineCCIPMMask tries to combine srl/ipm sequence for flag output operand.
- if (combineCCIPMMask(CCReg, CCValidVal, CCMaskVal) ||
- combineCCMask(CCReg, CCValidVal, CCMaskVal))
+ if (combineCCMask(CCReg, CCValidVal, CCMaskVal))
return DAG.getNode(SystemZISD::BR_CCMASK, SDLoc(N), N->getValueType(0),
Chain,
DAG.getTargetConstant(CCValidVal, SDLoc(N), MVT::i32),
@@ -8753,9 +8757,7 @@ SDValue SystemZTargetLowering::combineSELECT_CCMASK(
int CCMaskVal = CCMask->getZExtValue();
SDValue CCReg = N->getOperand(4);
- // combineCCIPMMask tries to combine srl/ipm sequence for flag output operand.
- if (combineCCIPMMask(CCReg, CCValidVal, CCMaskVal) ||
- combineCCMask(CCReg, CCValidVal, CCMaskVal))
+ if (combineCCMask(CCReg, CCValidVal, CCMaskVal))
return DAG.getNode(SystemZISD::SELECT_CCMASK, SDLoc(N), N->getValueType(0),
N->getOperand(0), N->getOperand(1),
DAG.getTargetConstant(CCValidVal, SDLoc(N), MVT::i32),
>From 7ea0c5f7f62f5873f48108ae60097c95f23f33ac Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Tue, 25 Feb 2025 03:20:01 +0100
Subject: [PATCH 7/8] - Changes relating to ConstraintInfo for setting flag
output CC upper bound for all backend suuporting flag output operand (X86,
AARCH64 and SystemZ). - Remove all changes target specific changes from
SelectionDAGBuiler.cpp. - Added getJumpConditionMergingParams for SystemZ for
setting cost for merging srl/ipm/cc. - TODO: Handle the cases where
simplifyBranchOnICmpChain creates switch table while folding branch on
And'd or Or'd chain of icmp instructions.
---
clang/include/clang/Basic/TargetInfo.h | 2 +-
clang/lib/Basic/Targets/AArch64.cpp | 1 +
clang/lib/Basic/Targets/SystemZ.cpp | 2 +-
clang/lib/Basic/Targets/SystemZ.h | 6 +-
clang/lib/Basic/Targets/X86.cpp | 1 +
clang/lib/CodeGen/CGStmt.cpp | 16 ++---
llvm/include/llvm/CodeGen/TargetLowering.h | 3 -
.../SelectionDAG/SelectionDAGBuilder.cpp | 58 +++----------------
.../CodeGen/SelectionDAG/TargetLowering.cpp | 4 --
.../Target/SystemZ/SystemZISelLowering.cpp | 47 ++++++++++-----
llvm/lib/Target/SystemZ/SystemZISelLowering.h | 6 +-
.../SystemZ/flag_output_operand_ccand_not.ll | 11 +++-
.../flag_output_operand_ccmixed_eq_noteq.ll | 45 ++++++++++++--
.../flag_output_operand_ccmixed_not.ll | 9 ++-
.../SystemZ/flag_output_operand_ccor.ll | 12 +++-
.../SystemZ/flag_output_operand_ccxor.ll | 14 +++--
.../flag_output_operand_ccxor_eq_noteq.ll | 9 ++-
.../SystemZ/flag_output_operand_ccxor_not.ll | 15 +++--
18 files changed, 146 insertions(+), 115 deletions(-)
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index d4a18ce01f6bc..15d7bd50aca25 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1119,7 +1119,7 @@ class TargetInfo : public TransferrableTargetInfo,
public:
ConstraintInfo(StringRef ConstraintStr, StringRef Name)
: Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
- Name(Name.str()), FlagOutputCCUpperBound(2) {
+ Name(Name.str()), FlagOutputCCUpperBound(0) {
ImmRange.Min = ImmRange.Max = 0;
ImmRange.isConstrained = false;
}
diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index fad8d773bfc52..7e33cba217884 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -1552,6 +1552,7 @@ bool AArch64TargetInfo::validateAsmConstraint(
if (const unsigned Len = matchAsmCCConstraint(Name)) {
Name += Len - 1;
Info.setAllowsRegister();
+ Info.setFlagOutputCCUpperBound(2);
return true;
}
}
diff --git a/clang/lib/Basic/Targets/SystemZ.cpp b/clang/lib/Basic/Targets/SystemZ.cpp
index c7725a8bd54a0..8f5bb70925d60 100644
--- a/clang/lib/Basic/Targets/SystemZ.cpp
+++ b/clang/lib/Basic/Targets/SystemZ.cpp
@@ -100,7 +100,7 @@ bool SystemZTargetInfo::validateAsmConstraint(
return true;
case '@':
// CC condition changes.
- if (!StringRef("@cc").compare(Name)) {
+ if (StringRef(Name) == "@cc") {
Name += 2;
Info.setAllowsRegister();
Info.setFlagOutputCCUpperBound(4);
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index 6db148dc45db8..26bdf65ebc2d5 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -120,10 +120,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
std::string convertConstraint(const char *&Constraint) const override {
if (llvm::StringRef(Constraint) == "@cc") {
- auto Len = llvm::StringRef("@cc").size();
- std::string Converted = std::string("{@cc}");
- Constraint += Len - 1;
- return Converted;
+ Constraint += 2;
+ return std::string("{@cc}");
}
switch (Constraint[0]) {
case 'p': // Keep 'p' constraint.
diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp
index 84a05cec04e7f..e822b1ce8d089 100644
--- a/clang/lib/Basic/Targets/X86.cpp
+++ b/clang/lib/Basic/Targets/X86.cpp
@@ -1580,6 +1580,7 @@ bool X86TargetInfo::validateAsmConstraint(
if (auto Len = matchAsmCCConstraint(Name)) {
Name += Len - 1;
Info.setAllowsRegister();
+ Info.setFlagOutputCCUpperBound(2);
return true;
}
return false;
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 2055de97a5864..f7f322c163646 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2601,7 +2601,7 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
const llvm::ArrayRef<LValue> ResultRegDests,
const llvm::ArrayRef<QualType> ResultRegQualTys,
const llvm::BitVector &ResultTypeRequiresCast,
- const llvm::BitVector &ResultRegIsFlagReg) {
+ const std::vector<unsigned> &ResultRegIsFlagReg) {
CGBuilderTy &Builder = CGF.Builder;
CodeGenModule &CGM = CGF.CGM;
llvm::LLVMContext &CTX = CGF.getLLVMContext();
@@ -2628,14 +2628,7 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
// observed for select_cc on SystemZ unit tests for flag output operands.
// For some cases for br_cc, generated IR was weird. e.g. switch table
// for simple simple comparison terms for br_cc.
- StringRef Name;
- if (const GCCAsmStmt *GAS = dyn_cast<GCCAsmStmt>(&S))
- Name = GAS->getOutputName(i);
- TargetInfo::ConstraintInfo Info(S.getOutputConstraint(i), Name);
- bool IsValid = CGF.getTarget().validateOutputConstraint(Info);
- (void)IsValid;
- assert(IsValid && "Failed to parse flag output operand constraint");
- unsigned CCUpperBound = Info.getFlagOutputCCUpperBound();
+ unsigned CCUpperBound = ResultRegIsFlagReg[i];
llvm::Constant *CCUpperBoundConst =
llvm::ConstantInt::get(Tmp->getType(), CCUpperBound);
llvm::Value *IsBooleanValue =
@@ -2766,7 +2759,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
std::vector<llvm::Type *> ArgElemTypes;
std::vector<llvm::Value*> Args;
llvm::BitVector ResultTypeRequiresCast;
- llvm::BitVector ResultRegIsFlagReg;
+ std::vector<unsigned> ResultRegIsFlagReg;
// Keep track of inout constraints.
std::string InOutConstraints;
@@ -2824,8 +2817,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
ResultRegQualTys.push_back(QTy);
ResultRegDests.push_back(Dest);
- bool IsFlagReg = llvm::StringRef(OutputConstraint).starts_with("{@cc");
- ResultRegIsFlagReg.push_back(IsFlagReg);
+ ResultRegIsFlagReg.push_back(Info.getFlagOutputCCUpperBound());
llvm::Type *Ty = ConvertTypeForMem(QTy);
const bool RequiresCast = Info.allowsRegister() &&
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 305ef4c7bea4c..bbecc7a6ddaee 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -5107,9 +5107,6 @@ class TargetLowering : public TargetLoweringBase {
std::vector<SDValue> &Ops,
SelectionDAG &DAG) const;
- // Lower switch statement for flag output operand with SRL/IPM Sequence.
- virtual bool canLowerSRL_IPM_Switch(SDValue Cond) const;
-
// Lower custom output constraints. If invalid, return SDValue().
virtual SDValue LowerAsmOutputForConstraint(SDValue &Chain, SDValue &Glue,
const SDLoc &DL,
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index dbb9ac74962be..8bfe49020ee7b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -2837,34 +2837,7 @@ void SelectionDAGBuilder::visitBr(const BranchInst &I) {
Opcode = Instruction::And;
else if (match(BOp, m_LogicalOr(m_Value(BOp0), m_Value(BOp1))))
Opcode = Instruction::Or;
- auto &TLI = DAG.getTargetLoweringInfo();
- const auto checkSRLIPM = [&TLI](const SDValue &Op) {
- if (!Op.getNumOperands())
- return false;
- SDValue OpVal = Op.getOperand(0);
- SDNode *N = OpVal.getNode();
- if (N && N->getOpcode() == ISD::SRL)
- return TLI.canLowerSRL_IPM_Switch(OpVal);
- else if (N && OpVal.getNumOperands() &&
- (N->getOpcode() == ISD::AND || N->getOpcode() == ISD::OR)) {
- SDValue OpVal1 = OpVal.getOperand(0);
- SDNode *N1 = OpVal1.getNode();
- if (N1 && N1->getOpcode() == ISD::SRL)
- return TLI.canLowerSRL_IPM_Switch(OpVal1);
- }
- return false;
- };
- // Incoming IR here is straight line code, FindMergedConditions splits
- // condition code sequence across Basic Block. DAGCombiner can't combine
- // across Basic Block. Identify SRL/IPM/CC sequence for SystemZ and avoid
- // transformation in FindMergedConditions.
- bool BrSrlIPM = false;
- if (NodeMap.count(BOp0) && NodeMap[BOp0].getNode()) {
- BrSrlIPM |= checkSRLIPM(getValue(BOp0));
- if (NodeMap.count(BOp1) && NodeMap[BOp1].getNode())
- BrSrlIPM &= checkSRLIPM(getValue(BOp1));
- }
- if (Opcode && !BrSrlIPM &&
+ if (Opcode &&
!(match(BOp0, m_ExtractElt(m_Value(Vec), m_Value())) &&
match(BOp1, m_ExtractElt(m_Specific(Vec), m_Value()))) &&
!shouldKeepJumpConditionsTogether(
@@ -12138,36 +12111,19 @@ void SelectionDAGBuilder::lowerWorkItem(SwitchWorkListItem W, Value *Cond,
const APInt &SmallValue = Small.Low->getValue();
const APInt &BigValue = Big.Low->getValue();
- // Incoming IR is switch table.Identify SRL/IPM/CC sequence for SystemZ
- // and we want to avoid splitting condition code sequence across basic
- // block for cases like (CC == 0) || (CC == 2) || (CC == 3), or
- // (CC == 0) || (CC == 1) ^ (CC == 3), there could potentially be
- // more cases like this.
- const TargetLowering &TLI = DAG.getTargetLoweringInfo();
- bool IsSrlIPM = false;
- if (NodeMap.count(Cond) && NodeMap[Cond].getNode())
- IsSrlIPM = TLI.canLowerSRL_IPM_Switch(getValue(Cond));
// Check that there is only one bit different.
APInt CommonBit = BigValue ^ SmallValue;
- if (CommonBit.isPowerOf2() || IsSrlIPM) {
+ if (CommonBit.isPowerOf2()) {
SDValue CondLHS = getValue(Cond);
EVT VT = CondLHS.getValueType();
SDLoc DL = getCurSDLoc();
SDValue Cond;
- if (CommonBit.isPowerOf2()) {
- SDValue Or = DAG.getNode(ISD::OR, DL, VT, CondLHS,
- DAG.getConstant(CommonBit, DL, VT));
- Cond = DAG.getSetCC(DL, MVT::i1, Or,
- DAG.getConstant(BigValue | SmallValue, DL, VT),
- ISD::SETEQ);
- } else if (IsSrlIPM && BigValue == 3 && SmallValue == 0) {
- SDValue SetCC =
- DAG.getSetCC(DL, MVT::i32, CondLHS,
- DAG.getConstant(SmallValue, DL, VT), ISD::SETEQ);
- Cond = DAG.getSetCC(DL, MVT::i32, SetCC,
- DAG.getConstant(BigValue, DL, VT), ISD::SETEQ);
- }
+ SDValue Or = DAG.getNode(ISD::OR, DL, VT, CondLHS,
+ DAG.getConstant(CommonBit, DL, VT));
+ Cond = DAG.getSetCC(DL, MVT::i1, Or,
+ DAG.getConstant(BigValue | SmallValue, DL, VT),
+ ISD::SETEQ);
// Update successor info.
// Both Small and Big will jump to Small.BB, so we sum up the
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 288639beacba7..adfb96041c5c0 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -5576,10 +5576,6 @@ const char *TargetLowering::LowerXConstraint(EVT ConstraintVT) const {
return nullptr;
}
-bool TargetLowering::canLowerSRL_IPM_Switch(SDValue Cond) const {
- return false;
-}
-
SDValue TargetLowering::LowerAsmOutputForConstraint(
SDValue &Chain, SDValue &Glue, const SDLoc &DL,
const AsmOperandInfo &OpInfo, SelectionDAG &DAG) const {
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 94ae61d6d992c..f656401f45876 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -24,6 +24,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsS390.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
@@ -8694,23 +8695,37 @@ SystemZTargetLowering::combineSELECT_CC_CCIPMMask(SDNode *N,
return std::nullopt;
}
-bool SystemZTargetLowering::canLowerSRL_IPM_Switch(SDValue Cond) const {
- auto *SRL = Cond.getNode();
- if (!SRL || SRL->getOpcode() != ISD::SRL)
- return false;
- auto *SRLCount = dyn_cast<ConstantSDNode>(SRL->getOperand(1));
- if (!SRLCount || SRLCount->getZExtValue() != SystemZ::IPM_CC)
- return false;
- auto *IPM = SRL->getOperand(0).getNode();
- if (!IPM || IPM->getOpcode() != SystemZISD::IPM)
- return false;
- auto IPMOp0 = IPM->getOperand(0).getNode();
- if (!IPMOp0 || IPMOp0->getNumOperands() < 2)
- return false;
- auto RN = dyn_cast<RegisterSDNode>(IPMOp0->getOperand(1));
- if (!RN || !RN->getReg().isPhysical() || RN->getReg() != SystemZ::CC)
+// Merging versus split in multiple branches cost.
+TargetLoweringBase::CondMergingParams
+SystemZTargetLowering::getJumpConditionMergingParams(Instruction::BinaryOps Opc,
+ const Value *Lhs,
+ const Value *Rhs) const {
+ const auto isFlagOutOpCC = [](const Value *V) {
+ using namespace llvm::PatternMatch;
+ const Value *RHSVal;
+ const APInt *RHSC;
+ if (const auto *I = dyn_cast<Instruction>(V)) {
+ if (match(I->getOperand(0), m_And(m_Value(RHSVal), m_APInt(RHSC))) ||
+ match(I, m_Cmp(m_Value(RHSVal), m_APInt(RHSC)))) {
+ if (const auto *CB = dyn_cast<CallBase>(RHSVal)) {
+ if (CB->isInlineAsm()) {
+ const InlineAsm *IA = cast<InlineAsm>(CB->getCalledOperand());
+ return IA &&
+ IA->getConstraintString().find("{@cc}") != std::string::npos;
+ }
+ }
+ }
+ }
return false;
- return true;
+ };
+ // Pattern (ICmp %asm) or (ICmp (And %asm)).
+ // Cost of longest dependency chain (ICmp, And) is 2. CostThreshold or
+ // BaseCost can be set >=2. If cost of instruction <= CostThreshold
+ // conditionals will be merged or else conditionals will be split.
+ if (isFlagOutOpCC(Lhs) && isFlagOutOpCC(Rhs))
+ return {3, 0, -1};
+ // Default.
+ return {-1, -1, -1};
}
SDValue SystemZTargetLowering::combineBR_CCMASK(
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 7275c972ef6e8..70c742839b3bd 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -521,8 +521,10 @@ class SystemZTargetLowering : public TargetLowering {
const char *getTargetNodeName(unsigned Opcode) const override;
- // Check for if flag output operands has SRL/IPM Sequence.
- bool canLowerSRL_IPM_Switch(SDValue Cond) const override;
+ // This function currently returns cost for srl/ipm/cc sequence for merging.
+ CondMergingParams
+ getJumpConditionMergingParams(Instruction::BinaryOps Opc, const Value *Lhs,
+ const Value *Rhs) const override;
// Handle Lowering flag assembly outputs.
SDValue LowerAsmOutputForConstraint(SDValue &Chain, SDValue &Flag,
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_not.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_not.ll
index 766bb07eef209..29afcdbca4849 100644
--- a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_not.ll
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccand_not.ll
@@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; Test Flag Output Operands with 14 combinations of CCMASK and optimizations.
; This test negate of flag_output_operand_ccand, e.g
-; CC != 0 && cc !- 1 && cc != 2 for AND for 3 three different functions,
+; CC != 0 && cc != 1 && cc != 2 for AND for three different functions,
; including two test cases from heiko.
; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
@@ -555,6 +555,8 @@ if.end: ; preds = %if.then, %entry
}
; Test CC != 0 && CC != 3.
+; TODO: DAGCombiner is not able to optimize srl/ipm/cc sequence because of
+; switch table created by simplifyBranchOnICmpChain.
define void @bar_03(){
; CHECK-LABEL: bar_03:
; CHECK: # %bb.0: # %entry
@@ -563,8 +565,13 @@ define void @bar_03(){
; CHECK-NEXT: alsi 0(%r1), -1
; CHECK-EMPTY:
; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ipm %r0
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB22_1: # %entry
+; CHECK-NEXT: srl %r0, 28
+; CHECK-NEXT: chi %r0, 3
; CHECK-NEXT: jglh dummy at PLT
-; CHECK-NEXT: .LBB22_1: # %if.end
+; CHECK-NEXT: .LBB22_2: # %if.end
; CHECK-NEXT: br %r14
entry:
%0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_eq_noteq.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_eq_noteq.ll
index 3c071709b2e2a..cce7e1150aa95 100644
--- a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_eq_noteq.ll
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_eq_noteq.ll
@@ -2269,6 +2269,8 @@ if.end: ; preds = %entry, %if.then
}
; Test (cc == 0) && ((cc != 1) ^ (cc != 3))
+; TODO: DAGCombiner is not able to optimize srl/ipm/cc sequence because of
+; switch table created by simplifyBranchOnICmpChain.
define i64 @bar1a_013_XOR_AND_XOR_a() {
; CHECK-LABEL: bar1a_013_XOR_AND_XOR_a:
; CHECK: # %bb.0: # %entry
@@ -2277,8 +2279,13 @@ define i64 @bar1a_013_XOR_AND_XOR_a() {
; CHECK-NEXT: alsi 0(%r1), -1
; CHECK-EMPTY:
; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ipm %r0
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB96_1: # %entry
+; CHECK-NEXT: srl %r0, 28
+; CHECK-NEXT: chi %r0, 3
; CHECK-NEXT: jglh dummy at PLT
-; CHECK-NEXT: .LBB96_1: # %if.end
+; CHECK-NEXT: .LBB96_2: # %if.end
; CHECK-NEXT: br %r14
entry:
%0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
@@ -2315,6 +2322,8 @@ entry:
}
; Test ((cc == 0) && (cc != 2)) ^ (cc != 3)
+; TODO: DAGCombiner is not able to optimize srl/ipm/cc sequence because of
+; switch table created by simplifyBranchOnICmpChain.
define i64 @bar1a_023_XOR_AND() {
; CHECK-LABEL: bar1a_023_XOR_AND:
; CHECK: # %bb.0: # %entry
@@ -2323,8 +2332,13 @@ define i64 @bar1a_023_XOR_AND() {
; CHECK-NEXT: alsi 0(%r1), -1
; CHECK-EMPTY:
; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ipm %r0
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB98_1: # %entry
+; CHECK-NEXT: srl %r0, 28
+; CHECK-NEXT: chi %r0, 3
; CHECK-NEXT: jglh dummy at PLT
-; CHECK-NEXT: .LBB98_1: # %if.end
+; CHECK-NEXT: .LBB98_2: # %if.end
; CHECK-NEXT: br %r14
entry:
%0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
@@ -2344,6 +2358,8 @@ if.end: ; preds = %entry, %entry, %if.
}
; Test ((cc == 0) && (cc != 2)) ^ (cc != 3)
+; TODO: DAGCombiner is not able to optimize srl/ipm/cc sequence because of
+; switch table created by simplifyBranchOnICmpChain.
define i64 @bar1a_023_AND_XOR_a() {
; CHECK-LABEL: bar1a_023_AND_XOR_a:
; CHECK: # %bb.0: # %entry
@@ -2352,8 +2368,13 @@ define i64 @bar1a_023_AND_XOR_a() {
; CHECK-NEXT: alsi 0(%r1), -1
; CHECK-EMPTY:
; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ipm %r0
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB99_1: # %entry
+; CHECK-NEXT: srl %r0, 28
+; CHECK-NEXT: chi %r0, 3
; CHECK-NEXT: jglh dummy at PLT
-; CHECK-NEXT: .LBB99_1: # %if.end
+; CHECK-NEXT: .LBB99_2: # %if.end
; CHECK-NEXT: br %r14
entry:
%0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
@@ -4969,6 +4990,8 @@ if.end: ; preds = %entry, %if.then
}
; Test (cc == 0) ^ ((cc == 1) || (cc != 3))
+; TODO: DAGCombiner is not able to optimize srl/ipm/cc sequence because of
+; switch table created by simplifyBranchOnICmpChain.
define i64 @bar4a_013_XOR_OR_a() {
; CHECK-LABEL: bar4a_013_XOR_OR_a:
; CHECK: # %bb.0: # %entry
@@ -4977,8 +5000,13 @@ define i64 @bar4a_013_XOR_OR_a() {
; CHECK-NEXT: alsi 0(%r1), -1
; CHECK-EMPTY:
; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ipm %r0
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB206_1: # %entry
+; CHECK-NEXT: srl %r0, 28
+; CHECK-NEXT: chi %r0, 3
; CHECK-NEXT: jglh dummy at PLT
-; CHECK-NEXT: .LBB206_1: # %if.end
+; CHECK-NEXT: .LBB206_2: # %if.end
; CHECK-NEXT: br %r14
entry:
%0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
@@ -5082,6 +5110,8 @@ if.end: ; preds = %if.then, %entry
}
; Test (cc == 0) ^ ((cc == 2) || (cc != 3))
+; TODO: DAGCombiner is not able to optimize srl/ipm/cc sequence because of
+; switch table created by simplifyBranchOnICmpChain.
define i64 @bar4a_023_XOR_OR_a() {
; CHECK-LABEL: bar4a_023_XOR_OR_a:
; CHECK: # %bb.0: # %entry
@@ -5090,8 +5120,13 @@ define i64 @bar4a_023_XOR_OR_a() {
; CHECK-NEXT: alsi 0(%r1), -1
; CHECK-EMPTY:
; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ipm %r0
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB210_1: # %entry
+; CHECK-NEXT: srl %r0, 28
+; CHECK-NEXT: chi %r0, 3
; CHECK-NEXT: jglh dummy at PLT
-; CHECK-NEXT: .LBB210_1: # %if.end
+; CHECK-NEXT: .LBB210_2: # %if.end
; CHECK-NEXT: br %r14
entry:
%0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_not.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_not.ll
index 84b8858afc8ad..629497ca6ceaf 100644
--- a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_not.ll
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccmixed_not.ll
@@ -1464,6 +1464,8 @@ if.end: ; preds = %if.then, %entry
}
; Test ((cc == 0) ^ (cc != 1)) && (cc != 3).
+; TODO: DAGCombiner is not able to optimize srl/ipm/cc sequence because of
+; switch table created by simplifyBranchOnICmpChain.
define i64 @bar1_012_AND_XOR_b() {
; CHECK-LABEL: bar1_012_AND_XOR_b:
; CHECK: # %bb.0: # %entry
@@ -1472,8 +1474,13 @@ define i64 @bar1_012_AND_XOR_b() {
; CHECK-NEXT: alsi 0(%r1), -1
; CHECK-EMPTY:
; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ipm %r0
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB62_1: # %entry
+; CHECK-NEXT: srl %r0, 28
+; CHECK-NEXT: chi %r0, 3
; CHECK-NEXT: jglh dummy at PLT
-; CHECK-NEXT: .LBB62_1: # %if.end
+; CHECK-NEXT: .LBB62_2: # %if.end
; CHECK-NEXT: br %r14
entry:
%0 = tail call i32 asm " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor.ll
index 9b51380ac4c09..d793949847820 100644
--- a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor.ll
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccor.ll
@@ -823,6 +823,8 @@ if.end: ; preds = %if.then, %entry
}
; Test CC == 0 || CC == 3.
+; TODO: DAGCombiner is not able to optimize srl/ipm/cc sequence because of
+; switch table created by simplifyBranchOnICmpChain.
define void @bar_03() {
; CHECK-LABEL: bar_03:
; CHECK: # %bb.0: # %entry
@@ -831,9 +833,13 @@ define void @bar_03() {
; CHECK-NEXT: alsi 0(%r1), -1
; CHECK-EMPTY:
; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: jgnlh dummy at PLT
-; CHECK-NEXT: .LBB33_1: # %if.end
-; CHECK-NEXT: br %r14
+; CHECK-NEXT: ipm %r0
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB33_1: # %entry
+; CHECK-NEXT: srl %r0, 28
+; CHECK-NEXT: ciblh %r0, 0, 0(%r14)
+; CHECK-NEXT: .LBB33_2: # %if.then
+; CHECK-NEXT: jg dummy at PLT
entry:
%0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
%1 = icmp ult i32 %0, 4
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor.ll
index 0a2a508000430..63c4b506458ea 100644
--- a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor.ll
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; Test Flag Output Operands with 14 combinations of CCMASK and optimizations
-; for XOR for 3 three different functions, including two test cases from heiko.
+; for XOR for three different functions, including two test cases from heiko.
; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
@@ -559,6 +559,8 @@ if.end: ; preds = %if.then, %entry
}
; Test CC == 0 ^ CC == 3.
+; TODO: DAGCombiner is not able to optimize srl/ipm/cc sequence because of
+; switch table created by simplifyBranchOnICmpChain.
define void @bar_03() {
; CHECK-LABEL: bar_03:
; CHECK: # %bb.0: # %entry
@@ -567,9 +569,13 @@ define void @bar_03() {
; CHECK-NEXT: alsi 0(%r1), -1
; CHECK-EMPTY:
; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: jgnlh dummy at PLT
-; CHECK-NEXT: .LBB22_1: # %if.end
-; CHECK-NEXT: br %r14
+; CHECK-NEXT: ipm %r0
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB22_1: # %entry
+; CHECK-NEXT: srl %r0, 28
+; CHECK-NEXT: ciblh %r0, 0, 0(%r14)
+; CHECK-NEXT: .LBB22_2: # %if.then
+; CHECK-NEXT: jg dummy at PLT
entry:
%0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
%1 = icmp ult i32 %0, 4
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_eq_noteq.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_eq_noteq.ll
index bdbe5ff3ae924..de953265d82ee 100644
--- a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_eq_noteq.ll
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_eq_noteq.ll
@@ -746,6 +746,8 @@ if.end: ; preds = %if.then, %entry
}
; Test CC == 0 ^ CC != 3.
+; TODO: DAGCombiner is not able to optimize srl/ipm/cc sequence because of
+; switch table created by simplifyBranchOnICmpChain.
define void @bar_03() {
; CHECK-LABEL: bar_03:
; CHECK: # %bb.0: # %entry
@@ -754,8 +756,13 @@ define void @bar_03() {
; CHECK-NEXT: alsi 0(%r1), -1
; CHECK-EMPTY:
; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: ipm %r0
+; CHECK-NEXT: ber %r14
+; CHECK-NEXT: .LBB30_1: # %entry
+; CHECK-NEXT: srl %r0, 28
+; CHECK-NEXT: chi %r0, 3
; CHECK-NEXT: jglh dummy at PLT
-; CHECK-NEXT: .LBB30_1: # %if.end
+; CHECK-NEXT: .LBB30_2: # %if.end
; CHECK-NEXT: br %r14
entry:
%0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
diff --git a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_not.ll b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_not.ll
index 47410d28f80e3..d0bea528cbf37 100644
--- a/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_not.ll
+++ b/llvm/test/CodeGen/SystemZ/flag_output_operand_ccxor_not.ll
@@ -1,10 +1,9 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; Test Flag Output Operands with 14 combinations of CCMASK and optimizations
-; for XOR for 3 three different functions, including two test cases from heiko.
+; for XOR for three different functions, including two test cases from heiko.
; This test checks NOT EQUAL (!=), e.g. CC != 0 ^ CC != 1 ^ CC != 2.
; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -O2 | FileCheck %s
-
; Test CC != 0 ^ CC != 1.
define signext range(i32 0, 43) i32 @foo_01(i32 noundef signext %x) {
; CHECK-LABEL: foo_01:
@@ -552,6 +551,8 @@ if.end: ; preds = %if.then, %entry
}
; Test CC != 0 ^ CC != 3.
+; TODO: DAGCombiner is not able to optimize srl/ipm/cc sequence because of
+; switch table created by simplifyBranchOnICmpChain.
define void @bar_03() {
; CHECK-LABEL: bar_03:
; CHECK: # %bb.0: # %entry
@@ -560,9 +561,13 @@ define void @bar_03() {
; CHECK-NEXT: alsi 0(%r1), -1
; CHECK-EMPTY:
; CHECK-NEXT: #NO_APP
-; CHECK-NEXT: jgnlh dummy at PLT
-; CHECK-NEXT: .LBB22_1: # %if.end
-; CHECK-NEXT: br %r14
+; CHECK-NEXT: ipm %r0
+; CHECK-NEXT: jgo dummy at PLT
+; CHECK-NEXT: .LBB22_1: # %entry
+; CHECK-NEXT: srl %r0, 28
+; CHECK-NEXT: ciblh %r0, 0, 0(%r14)
+; CHECK-NEXT: .LBB22_2: # %if.then
+; CHECK-NEXT: jg dummy at PLT
entry:
%0 = tail call i32 asm sideeffect " alsi $1,-1\0A", "={@cc},=*QS,*QS,~{memory}"(ptr nonnull elementtype(i32) @a, ptr nonnull elementtype(i32) @a) #3
%1 = icmp ult i32 %0, 4
>From d787c8bb3530ca522c60c50db4e37915b801797e Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Tue, 22 Apr 2025 00:03:16 +0200
Subject: [PATCH 8/8] Incorporated changes for code review feedback.
---
clang/include/clang/Basic/TargetInfo.h | 14 +-
clang/lib/Basic/Targets/SystemZ.cpp | 1 +
clang/lib/Basic/Targets/SystemZ.h | 10 +-
clang/lib/CodeGen/CGStmt.cpp | 26 +-
.../SelectionDAG/SelectionDAGBuilder.cpp | 7 +-
.../Target/SystemZ/SystemZISelLowering.cpp | 345 ++++++++----------
llvm/lib/Target/SystemZ/SystemZISelLowering.h | 5 +-
llvm/test/CodeGen/SystemZ/htm-intrinsics.ll | 4 +-
8 files changed, 190 insertions(+), 222 deletions(-)
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 15d7bd50aca25..60497e273d31c 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1114,12 +1114,11 @@ class TargetInfo : public TransferrableTargetInfo,
std::string ConstraintStr; // constraint: "=rm"
std::string Name; // Operand name: [foo] with no []'s.
- unsigned FlagOutputCCUpperBound;
public:
ConstraintInfo(StringRef ConstraintStr, StringRef Name)
: Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
- Name(Name.str()), FlagOutputCCUpperBound(0) {
+ Name(Name.str()) {
ImmRange.Min = ImmRange.Max = 0;
ImmRange.isConstrained = false;
}
@@ -1191,13 +1190,13 @@ class TargetInfo : public TransferrableTargetInfo,
// Don't copy Name or constraint string.
}
- // CC range can be set by target. SystemZ sets it to 4. It is 2 by default.
+ // CC range can be set by targets supporting flag output operand.
void setFlagOutputCCUpperBound(unsigned CCBound) {
- FlagOutputCCUpperBound = CCBound;
- }
- unsigned getFlagOutputCCUpperBound() const {
- return FlagOutputCCUpperBound;
+ // Using ImmRange.Max to store CC upper bound. Interval [0, CCBound).
+ ImmRange.Max = CCBound;
+ ImmRange.isConstrained = true;
}
+ unsigned getFlagOutputCCUpperBound() const { return ImmRange.Max; }
};
/// Validate register name used for global register variables.
@@ -1238,7 +1237,6 @@ class TargetInfo : public TransferrableTargetInfo,
std::string &/*SuggestedModifier*/) const {
return true;
}
-
virtual bool
validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const = 0;
diff --git a/clang/lib/Basic/Targets/SystemZ.cpp b/clang/lib/Basic/Targets/SystemZ.cpp
index 8f5bb70925d60..18cb5ea0444a2 100644
--- a/clang/lib/Basic/Targets/SystemZ.cpp
+++ b/clang/lib/Basic/Targets/SystemZ.cpp
@@ -103,6 +103,7 @@ bool SystemZTargetInfo::validateAsmConstraint(
if (StringRef(Name) == "@cc") {
Name += 2;
Info.setAllowsRegister();
+ // SystemZ has 2-bits CC, and hence Interval [0, 4).
Info.setFlagOutputCCUpperBound(4);
return true;
}
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index 26bdf65ebc2d5..fc9ee2cd4b693 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -119,11 +119,13 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
TargetInfo::ConstraintInfo &info) const override;
std::string convertConstraint(const char *&Constraint) const override {
- if (llvm::StringRef(Constraint) == "@cc") {
- Constraint += 2;
- return std::string("{@cc}");
- }
switch (Constraint[0]) {
+ case '@': // Flag output operand.
+ if (llvm::StringRef(Constraint) == "@cc") {
+ Constraint += 2;
+ return std::string("{@cc}");
+ }
+ break;
case 'p': // Keep 'p' constraint.
return std::string("p");
case 'Z':
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index f7f322c163646..5f56297ae5746 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2601,7 +2601,7 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
const llvm::ArrayRef<LValue> ResultRegDests,
const llvm::ArrayRef<QualType> ResultRegQualTys,
const llvm::BitVector &ResultTypeRequiresCast,
- const std::vector<unsigned> &ResultRegIsFlagReg) {
+ const std::vector<unsigned> &ResultFlagRegCCBound) {
CGBuilderTy &Builder = CGF.Builder;
CodeGenModule &CGM = CGF.CGM;
llvm::LLVMContext &CTX = CGF.getLLVMContext();
@@ -2612,23 +2612,19 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
// ResultRegDests can be also populated by addReturnRegisterOutputs() above,
// in which case its size may grow.
assert(ResultTypeRequiresCast.size() <= ResultRegDests.size());
- assert(ResultRegIsFlagReg.size() <= ResultRegDests.size());
+ assert(ResultFlagRegCCBound.size() <= ResultRegDests.size());
for (unsigned i = 0, e = RegResults.size(); i != e; ++i) {
llvm::Value *Tmp = RegResults[i];
llvm::Type *TruncTy = ResultTruncRegTypes[i];
- if ((i < ResultRegIsFlagReg.size()) && ResultRegIsFlagReg[i]) {
+ if ((i < ResultFlagRegCCBound.size()) && ResultFlagRegCCBound[i]) {
// Target must guarantee the Value `Tmp` here is lowered to a boolean
// value.
- // Lowering 'Tmp' as - 'icmp ult %Tmp , CCUpperBound'. On some targets
- // CCUpperBound is not binary. CCUpperBound is 4 for SystemZ,
- // interval [0, 4). With this range known, llvm.assume intrinsic guides
- // optimizer to generate more optimized IR in most of the cases as
- // observed for select_cc on SystemZ unit tests for flag output operands.
- // For some cases for br_cc, generated IR was weird. e.g. switch table
- // for simple simple comparison terms for br_cc.
- unsigned CCUpperBound = ResultRegIsFlagReg[i];
+ // Lowering 'Tmp' as - 'icmp ult %Tmp , CCUpperBound'.
+ unsigned CCUpperBound = ResultFlagRegCCBound[i];
+ assert((CCUpperBound == 2 || CCUpperBound == 4) &&
+ "CC upper bound out of range!");
llvm::Constant *CCUpperBoundConst =
llvm::ConstantInt::get(Tmp->getType(), CCUpperBound);
llvm::Value *IsBooleanValue =
@@ -2759,7 +2755,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
std::vector<llvm::Type *> ArgElemTypes;
std::vector<llvm::Value*> Args;
llvm::BitVector ResultTypeRequiresCast;
- std::vector<unsigned> ResultRegIsFlagReg;
+ std::vector<unsigned> ResultFlagRegCCBound;
// Keep track of inout constraints.
std::string InOutConstraints;
@@ -2817,7 +2813,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
ResultRegQualTys.push_back(QTy);
ResultRegDests.push_back(Dest);
- ResultRegIsFlagReg.push_back(Info.getFlagOutputCCUpperBound());
+ ResultFlagRegCCBound.push_back(Info.getFlagOutputCCUpperBound());
llvm::Type *Ty = ConvertTypeForMem(QTy);
const bool RequiresCast = Info.allowsRegister() &&
@@ -3164,7 +3160,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
EmitAsmStores(*this, S, RegResults, ResultRegTypes, ResultTruncRegTypes,
ResultRegDests, ResultRegQualTys, ResultTypeRequiresCast,
- ResultRegIsFlagReg);
+ ResultFlagRegCCBound);
// If this is an asm goto with outputs, repeat EmitAsmStores, but with a
// different insertion point; one for each indirect destination and with
@@ -3175,7 +3171,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
Builder.SetInsertPoint(Succ, --(Succ->end()));
EmitAsmStores(*this, S, CBRRegResults[Succ], ResultRegTypes,
ResultTruncRegTypes, ResultRegDests, ResultRegQualTys,
- ResultTypeRequiresCast, ResultRegIsFlagReg);
+ ResultTypeRequiresCast, ResultFlagRegCCBound);
}
}
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 8bfe49020ee7b..b734b5babfbd1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -12117,13 +12117,12 @@ void SelectionDAGBuilder::lowerWorkItem(SwitchWorkListItem W, Value *Cond,
SDValue CondLHS = getValue(Cond);
EVT VT = CondLHS.getValueType();
SDLoc DL = getCurSDLoc();
- SDValue Cond;
SDValue Or = DAG.getNode(ISD::OR, DL, VT, CondLHS,
DAG.getConstant(CommonBit, DL, VT));
- Cond = DAG.getSetCC(DL, MVT::i1, Or,
- DAG.getConstant(BigValue | SmallValue, DL, VT),
- ISD::SETEQ);
+ SDValue Cond = DAG.getSetCC(
+ DL, MVT::i1, Or, DAG.getConstant(BigValue | SmallValue, DL, VT),
+ ISD::SETEQ);
// Update successor info.
// Both Small and Big will jump to Small.BB, so we sum up the
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index f656401f45876..749cd4cb4ef2c 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -2797,21 +2797,6 @@ static unsigned CCMaskForCondCode(ISD::CondCode CC) {
#undef CONV
}
-static unsigned CCMaskForSystemZCCVal(unsigned CC) {
- switch (CC) {
- default:
- llvm_unreachable("invalid integer condition!");
- case 0:
- return SystemZ::CCMASK_CMP_EQ;
- case 1:
- return SystemZ::CCMASK_CMP_LT;
- case 2:
- return SystemZ::CCMASK_CMP_GT;
- case 3:
- return SystemZ::CCMASK_CMP_UO;
- }
-}
-
// If C can be converted to a comparison against zero, adjust the operands
// as necessary.
static void adjustZeroCmp(SelectionDAG &DAG, const SDLoc &DL, Comparison &C) {
@@ -8078,27 +8063,29 @@ SDValue SystemZTargetLowering::combineBSWAP(
}
// Combine IPM sequence for flag output operands.
-static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
- // Convert CCVal to CCMask and update it along with CCValid.
- const auto convertCCValToCCMask = [&CCMask, &CCValid](int CCVal) {
+static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
+ // CCMask for ICmp is equal to 0, 1, 2 or 3.
+ const auto CCMaskForICmpEQCCVal = [](unsigned CC) {
+ assert(CC < 4 && "CC out of range");
+ return 1 << (3 - CC);
+ };
+ // Convert CCVal to CCMask and update it.
+ const auto convertCCValToCCMask = [&](int CCVal) {
bool Invert = false;
if (CCMask == SystemZ::CCMASK_CMP_NE)
Invert = !Invert;
if (CCMask == SystemZ::CCMASK_CMP_EQ || CCMask == SystemZ::CCMASK_CMP_NE) {
- CCMask = CCMaskForSystemZCCVal(CCVal);
+ CCMask = CCMaskForICmpEQCCVal(CCVal);
if (Invert)
CCMask ^= SystemZ::CCMASK_ANY;
- CCValid = SystemZ::CCMASK_ANY;
return true;
} else if (CCMask == SystemZ::CCMASK_CMP_LT) {
// CC in range [0, CCVal).
CCMask = ((~0U << (4 - CCVal)) & SystemZ::CCMASK_ANY);
- CCValid = SystemZ::CCMASK_ANY;
return true;
} else if (CCMask == SystemZ::CCMASK_CMP_GT) {
// CC in range (CCVal, 3].
CCMask = (~(~0U << (3 - CCVal))) & SystemZ::CCMASK_ANY;
- CCValid = SystemZ::CCMASK_ANY;
return true;
}
return false;
@@ -8113,33 +8100,34 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
auto *IPM = N->getOperand(0).getNode();
if (!IPM || IPM->getOpcode() != SystemZISD::IPM)
return false;
- auto *IPMOp0 = IPM->getOperand(0).getNode();
- if (!IPMOp0 || IPMOp0->getNumOperands() < 2)
- return false;
- auto *RN = dyn_cast<RegisterSDNode>(IPMOp0->getOperand(1));
- // Check if operand 1 is SystemZ::CC. Also, it avoids srl/ipm/tbegin and
- // srl/ipm/tend kind of sequences.
- if (!RN || !RN->getReg().isPhysical() || RN->getReg() != SystemZ::CC)
- return false;
- // Return the updated CCReg link.
CCReg = IPM->getOperand(0);
return true;
};
- // Check if N has SystemZ::CC operand.
- const auto isCCOperand = [](SDNode *N) {
- if (!N || N->getNumOperands() < 2)
+ // Check if select_cc has already been combined and uses the same ipm/cc
+ // as CCOp and return evaluated mask CCMaskVal. (SELECT_CCMASK (CC)).
+ const auto isSameCCIPMOp = [](SDValue &CCOp, SDNode *N, int &CCValidVal,
+ int &CCMaskVal) {
+ if (!N || N->getOpcode() != SystemZISD::SELECT_CCMASK)
return false;
- auto *RN = dyn_cast<RegisterSDNode>(N->getOperand(1));
- if (!RN || !RN->getReg().isPhysical() || RN->getReg() != SystemZ::CC)
+ auto *CCValidNode = dyn_cast<ConstantSDNode>(N->getOperand(2));
+ auto *CCMaskNode = dyn_cast<ConstantSDNode>(N->getOperand(3));
+ if (!CCValidNode || !CCMaskNode)
return false;
- return true;
- };
+ CCValidVal = CCValidNode->getZExtValue();
+ // Already been combined.
+ if (CCValidVal != SystemZ::CCMASK_ANY)
+ return false;
+ CCMaskVal = CCMaskNode->getZExtValue();
+ SDValue CCRegOp = N->getOperand(4);
+ auto *CCOpNode = CCOp.getNode(), *CCRegOpNode = CCRegOp.getNode();
+ // Uses the same ipm/cc.
+ return CCOpNode && CCRegOpNode && CCOpNode == CCRegOpNode;
+ };
auto *CCNode = CCReg.getNode();
if (!CCNode)
return false;
- int RestoreCCValid = CCValid;
// Optimize (TM (IPM (CC)))
if (CCNode->getOpcode() == SystemZISD::TM) {
bool Invert = false;
@@ -8166,8 +8154,8 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
return false;
// OP1. (SELECT_CCMASK (ICMP (SRL (IPM (CC))))).
// OP2. (SRL (IPM (CC))).
- if (XOROp1->getOpcode() == SystemZISD::SELECT_CCMASK &&
- isSRL_IPM_CCSequence(XOROp2)) {
+ if (XOROp1->getOpcode() == SystemZISD::SELECT_CCMASK /*&&
+ isSRL_IPM_CCSequence(XOROp2)*/) {
auto *CCValid1 = dyn_cast<ConstantSDNode>(XOROp1->getOperand(2));
auto *CCMask1 = dyn_cast<ConstantSDNode>(XOROp1->getOperand(3));
SDValue XORReg = XOROp1->getOperand(4);
@@ -8175,7 +8163,7 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
return false;
int CCValidVal = CCValid1->getZExtValue();
int CCMaskVal = CCMask1->getZExtValue();
- if (combineSRL_IPM_CCMask(XORReg, CCValidVal, CCMaskVal)) {
+ if (combineCCMask(XORReg, CCValidVal, CCMaskVal)) {
// CC == 0 || CC == 2 for bit 28 Test Under Mask.
CCMask = SystemZ::CCMASK_CMP_GE;
CCMask ^= CCMaskVal;
@@ -8202,10 +8190,9 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
CCValid = SystemZ::CCMASK_ANY;
return true;
}
- CCValid = RestoreCCValid;
return false;
}
- // (SELECT_CCMASK (CC)) or (SELECT_CCMASK (ICMP (SRL (IPM (CC)))))
+ // (SELECT_CCMASK (ICMP (SRL (IPM (CC)))))
if (CCNode->getOpcode() == SystemZISD::SELECT_CCMASK) {
auto *CCValidNode = dyn_cast<ConstantSDNode>(CCNode->getOperand(2));
auto *CCMaskNode = dyn_cast<ConstantSDNode>(CCNode->getOperand(3));
@@ -8215,14 +8202,12 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
int CCValidVal = CCValidNode->getZExtValue();
int CCMaskVal = CCMaskNode->getZExtValue();
SDValue CCRegOp = CCNode->getOperand(4);
- if (combineSRL_IPM_CCMask(CCRegOp, CCValidVal, CCMaskVal) ||
- isCCOperand(CCRegOp.getNode())) {
+ if (combineCCMask(CCRegOp, CCValidVal, CCMaskVal)) {
CCMask = CCMaskVal;
CCValid = SystemZ::CCMASK_ANY;
CCReg = CCRegOp;
return true;
}
- CCValid = RestoreCCValid;
return false;
}
@@ -8250,15 +8235,14 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
int CCMaskVal2 = CCMask2->getZExtValue();
SDValue CCReg1 = XOROp1->getOperand(4);
SDValue CCReg2 = XOROp2->getOperand(4);
- if (!combineSRL_IPM_CCMask(CCReg1, CCValidVal1, CCMaskVal1) ||
- !combineSRL_IPM_CCMask(CCReg2, CCValidVal2, CCMaskVal2))
+ if (!combineCCMask(CCReg1, CCValidVal1, CCMaskVal1) ||
+ !combineCCMask(CCReg2, CCValidVal2, CCMaskVal2))
return false;
CCMask = CCMaskVal1 ^ CCMaskVal2;
CCReg = CCReg1;
CCValid = SystemZ::CCMASK_ANY;
return true;
}
- CCValid = RestoreCCValid;
return false;
}
@@ -8276,37 +8260,74 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
if (!RHS) {
SDValue CmpOp1 = CCNode->getOperand(0);
SDValue CmpOp2 = CCNode->getOperand(1);
- int CCValid1 = CCValid, CCValid2 = CCValid;
- int CCMask1 = CCMask, CCMask2 = CCMask;
- bool IsOp1 = combineSRL_IPM_CCMask(CmpOp1, CCValid1, CCMask1);
- bool IsOp2 = combineSRL_IPM_CCMask(CmpOp2, CCValid2, CCMask2);
- if (IsOp1 && IsOp2) {
- CCMask = CCMask1 ^ CCMask2;
- CCReg = CmpOp1;
- CCValid = SystemZ::CCMASK_ANY;
- return true;
+ auto *CmpNode1 = CmpOp1.getNode(), *CmpNode2 = CmpOp2.getNode();
+ if (!CmpNode1 || !CmpNode2)
+ return false;
+ if (CmpNode1->getOpcode() == SystemZISD::SELECT_CCMASK ||
+ CmpNode2->getOpcode() == SystemZISD::SELECT_CCMASK) {
+ SDValue CmpOp =
+ CmpNode1->getOpcode() == SystemZISD::SELECT_CCMASK ? CmpOp2 : CmpOp1;
+ SDNode *SelectCC = CmpNode1->getOpcode() == SystemZISD::SELECT_CCMASK
+ ? CmpNode1
+ : CmpNode2;
+ int CmpCCValid = CCValid, SelectCCValid = CCValid;
+ int CmpCCMask = CCMask, SelectCCMask = CCMask;
+ bool IsOp1 = combineCCMask(CmpOp, CmpCCValid, CmpCCMask);
+ bool IsOp2 = isSameCCIPMOp(CmpOp, SelectCC, SelectCCValid, SelectCCMask);
+ if (IsOp1 && IsOp2) {
+ CCMask = CmpCCMask ^ SelectCCMask;
+ CCReg = CmpOp;
+ CCValid = SystemZ::CCMASK_ANY;
+ return true;
+ }
}
- CCValid = RestoreCCValid;
return false;
}
int CmpVal = RHS->getZExtValue();
// (BR_CC (ICMP (SELECT_CCMASK (CC))))
if (LHS->getOpcode() == SystemZISD::SELECT_CCMASK) {
int CCVal = RHS->getZExtValue();
- int Mask = CCMaskForSystemZCCVal(CCVal);
+ int Mask = CCMaskForICmpEQCCVal(CCVal);
bool Invert = false;
if (CCMask == SystemZ::CCMASK_CMP_NE)
Invert = !Invert;
SDValue NewCCReg = CCNode->getOperand(0);
- if (combineSRL_IPM_CCMask(NewCCReg, CCValid, CCMask)) {
+ if (combineCCMask(NewCCReg, CCValid, CCMask)) {
CCMask |= Mask;
if (Invert)
CCMask ^= SystemZ::CCMASK_ANY;
CCReg = NewCCReg;
CCValid = SystemZ::CCMASK_ANY;
return true;
+ } else if (CCMask == SystemZ::CCMASK_CMP_NE ||
+ CCMask != SystemZ::CCMASK_CMP_EQ) {
+ // Original combineCCMask.
+ // Verify that the ICMP compares against one of select values.
+ auto *TrueVal = dyn_cast<ConstantSDNode>(LHS->getOperand(0));
+ if (!TrueVal)
+ return false;
+ auto *FalseVal = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
+ if (!FalseVal)
+ return false;
+ if (RHS->getAPIntValue() == FalseVal->getAPIntValue())
+ Invert = !Invert;
+ else if (RHS->getAPIntValue() != TrueVal->getAPIntValue())
+ return false;
+
+ // Compute the effective CC mask for the new branch or select.
+ auto *NewCCValid = dyn_cast<ConstantSDNode>(LHS->getOperand(2));
+ auto *NewCCMask = dyn_cast<ConstantSDNode>(LHS->getOperand(3));
+ if (!NewCCValid || !NewCCMask)
+ return false;
+ CCValid = NewCCValid->getZExtValue();
+ CCMask = NewCCMask->getZExtValue();
+ if (Invert)
+ CCMask ^= CCValid;
+
+ // Return the updated CCReg link.
+ CCReg = LHS->getOperand(4);
+ return true;
}
- CCValid = RestoreCCValid;
return false;
}
// (BR_CC (ICMP OR ((SRL (IPM (CC))) (SELECT_CCMASK (CC)))))
@@ -8316,12 +8337,12 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
Invert = !Invert;
SDValue OrOp1 = LHS->getOperand(0);
SDValue OrOp2 = LHS->getOperand(1);
+ int CCValid1 = CCValid, CCValid2 = CCValid;
int NewCCMask1 = CCMask, NewCCMask2 = CCMask, NewCCMask = CCMask;
if (!isa<ConstantSDNode>(OrOp1) && !isa<ConstantSDNode>(OrOp2)) {
- bool IsOp1 = combineSRL_IPM_CCMask(OrOp1, CCValid, NewCCMask1);
- bool IsOp2 = combineSRL_IPM_CCMask(OrOp2, CCValid, NewCCMask2);
+ bool IsOp1 = combineCCMask(OrOp1, CCValid1, NewCCMask1);
+ bool IsOp2 = combineCCMask(OrOp2, CCValid2, NewCCMask2);
if (!IsOp1 && !IsOp2) {
- CCValid = RestoreCCValid;
return false;
}
if (IsOp1 && IsOp2) {
@@ -8344,11 +8365,12 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
// setullt unsigned(-2), mask = 0x1100
// setugt unsigned(-4), mask = 0x0011
CmpVal &= 0x3;
- if (convertCCValToCCMask(CmpVal))
+ if (convertCCValToCCMask(CmpVal)) {
+ CCValid = SystemZ::CCMASK_ANY;
return true;
+ }
}
}
- CCValid = RestoreCCValid;
return false;
}
// (BR_CC (ICMP AND ((SRL (IPM (CC))) (SELECT_CCMASK (CC)))))
@@ -8358,16 +8380,13 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
Invert = !Invert;
SDValue AndOp1 = LHS->getOperand(0);
SDValue AndOp2 = LHS->getOperand(1);
- int NewCCMask1 = CCMask;
- int NewCCMask2 = CCMask;
- int NewCCMask;
+ int NewCCMask1 = CCMask, NewCCMask2 = CCMask, NewCCMask;
+ int CCValid1 = CCValid, CCValid2 = CCValid;
if (!isa<ConstantSDNode>(AndOp1) && !isa<ConstantSDNode>(AndOp2)) {
- bool IsOp1 = combineSRL_IPM_CCMask(AndOp1, CCValid, NewCCMask1);
- bool IsOp2 = combineSRL_IPM_CCMask(AndOp2, CCValid, NewCCMask2);
- if (!IsOp1 && !IsOp2) {
- CCValid = RestoreCCValid;
+ bool IsOp1 = combineCCMask(AndOp1, CCValid1, NewCCMask1);
+ bool IsOp2 = combineCCMask(AndOp2, CCValid2, NewCCMask2);
+ if (!IsOp1 && !IsOp2)
return false;
- }
if (IsOp1 && IsOp2) {
NewCCMask = NewCCMask1 & NewCCMask2;
bool IsEqualCmpVal = NewCCMask == CmpVal;
@@ -8383,10 +8402,8 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
NewCCMask = NewCCMask1;
else if (isSRL_IPM_CCSequence(AndOp2.getNode()) && IsOp2)
NewCCMask = NewCCMask2;
- else {
- CCValid = RestoreCCValid;
+ else
return false;
- }
// Bit 29 set => CC == 2 || CC == 3.
if ((NewCCMask & 0x3) == 2)
NewCCMask = SystemZ::CCMASK_2 | SystemZ::CCMASK_3;
@@ -8394,7 +8411,7 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
else if ((NewCCMask & 0x3) == 1)
NewCCMask = SystemZ::CCMASK_1 | SystemZ::CCMASK_3;
int CCVal = RHS->getZExtValue();
- int Mask = CCMaskForSystemZCCVal(CCVal);
+ int Mask = CCMaskForICmpEQCCVal(CCVal);
CCMask = Mask | NewCCMask;
if (Invert ^ CmpVal)
CCMask ^= SystemZ::CCMASK_ANY;
@@ -8402,15 +8419,15 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
return true;
}
}
- CCValid = RestoreCCValid;
return false;
}
// Optimize the case where LHS is (ICMP (SRL (IPM))).
if (isSRL_IPM_CCSequence(LHS)) {
unsigned CCVal = RHS->getZExtValue();
- if (convertCCValToCCMask(CCVal))
+ if (convertCCValToCCMask(CCVal)) {
+ CCValid = SystemZ::CCMASK_ANY;
return true;
- CCValid = RestoreCCValid;
+ }
return false;
}
if (LHS->getOpcode() == ISD::ADD) {
@@ -8438,10 +8455,10 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
CCMask ^= SystemZ::CCMASK_CMP_EQ;
if (Invert)
CCMask ^= SystemZ::CCMASK_ANY;
+ CCValid = SystemZ::CCMASK_ANY;
return true;
}
}
- CCValid = RestoreCCValid;
return false;
}
@@ -8453,7 +8470,7 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
if (CCMask == SystemZ::CCMASK_CMP_NE)
Invert = !Invert;
// If both the operands are select_cc.
- if (combineSRL_IPM_CCMask(XORReg, CCValid, CCMask)) {
+ if (combineCCMask(XORReg, CCValid, CCMask)) {
CCReg = XORReg;
CCValid = SystemZ::CCMASK_ANY;
return true;
@@ -8477,8 +8494,8 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
SDValue XORReg1 = XOROp->getOperand(4);
SDValue XORReg2 = LHS->getOperand(1);
int CCMaskVal1 = CCMaskVal, CCMaskVal2 = CCMaskVal;
- if (combineSRL_IPM_CCMask(XORReg1, CCValidVal, CCMaskVal1) &&
- combineSRL_IPM_CCMask(XORReg2, CCValidVal, CCMaskVal2)) {
+ if (combineCCMask(XORReg1, CCValidVal, CCMaskVal1) &&
+ combineCCMask(XORReg2, CCValidVal, CCMaskVal2)) {
CCMask = CCMaskVal1 ^ CCMaskVal2;
CCReg = XORReg1;
CCValid = SystemZ::CCMASK_ANY;
@@ -8486,80 +8503,14 @@ static bool combineSRL_IPM_CCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
}
}
}
- CCValid = RestoreCCValid;
- return false;
-}
-
-static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
- // combineSRL_IPM_CCMask tries to combine srl/ipm/cc sequence.
- // This sequence here seems to be only for flag output operand.
- // IPM operand has physical operand SystemZ::CC and CCValid is 15.
- if (combineSRL_IPM_CCMask(CCReg, CCValid, CCMask))
- return true;
-
- // Code for SELECT_CCMASK does not seem to have ipm sequence.
- // There is one case with sra/ipm that does not have SystemZ::CC as an
- // operand. Test cases for sra/ipm are bcmp.ll, memcmp-01.ll and
- // strcmp-01.ll. These tests have sra/sll/ipm/clc sequence.
-
- // We have a SELECT_CCMASK or BR_CCMASK comparing the condition code
- // set by the CCReg instruction using the CCValid / CCMask masks,
- // If the CCReg instruction is itself a ICMP testing the condition
- // code set by some other instruction, see whether we can directly
- // use that condition code.
-
- // Verify that we have an ICMP against some constant.
- if (CCValid != SystemZ::CCMASK_ICMP)
- return false;
- auto *ICmp = CCReg.getNode();
- if (ICmp->getOpcode() != SystemZISD::ICMP)
- return false;
- auto *CompareLHS = ICmp->getOperand(0).getNode();
- auto *CompareRHS = dyn_cast<ConstantSDNode>(ICmp->getOperand(1));
- if (!CompareRHS)
- return false;
-
- // Optimize the case where CompareLHS is a SELECT_CCMASK.
- if (CompareLHS->getOpcode() == SystemZISD::SELECT_CCMASK) {
- // Verify that we have an appropriate mask for a EQ or NE comparison.
- bool Invert = false;
- if (CCMask == SystemZ::CCMASK_CMP_NE)
- Invert = !Invert;
- else if (CCMask != SystemZ::CCMASK_CMP_EQ)
- return false;
-
- // Verify that the ICMP compares against one of select values.
- auto *TrueVal = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(0));
- if (!TrueVal)
- return false;
- auto *FalseVal = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(1));
- if (!FalseVal)
- return false;
- if (CompareRHS->getAPIntValue() == FalseVal->getAPIntValue())
- Invert = !Invert;
- else if (CompareRHS->getAPIntValue() != TrueVal->getAPIntValue())
- return false;
- // Compute the effective CC mask for the new branch or select.
- auto *NewCCValid = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(2));
- auto *NewCCMask = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(3));
- if (!NewCCValid || !NewCCMask)
- return false;
- CCValid = NewCCValid->getZExtValue();
- CCMask = NewCCMask->getZExtValue();
- if (Invert)
- CCMask ^= CCValid;
-
- // Return the updated CCReg link.
- CCReg = CompareLHS->getOperand(4);
- return true;
- }
- // Optimize the case where CompareRHS is (SRA (SHL (IPM))).
- if (CompareLHS->getOpcode() == ISD::SRA) {
- auto *SRACount = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(1));
+ // Original combineCCMask.
+ // Optimize the case where RHS is (SRA (SHL (IPM))).
+ if (LHS->getOpcode() == ISD::SRA) {
+ auto *SRACount = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
if (!SRACount || SRACount->getZExtValue() != 30)
return false;
- auto *SHL = CompareLHS->getOperand(0).getNode();
+ auto *SHL = LHS->getOperand(0).getNode();
if (SHL->getOpcode() != ISD::SHL)
return false;
auto *SHLCount = dyn_cast<ConstantSDNode>(SHL->getOperand(1));
@@ -8570,10 +8521,10 @@ static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
return false;
// Avoid introducing CC spills (because SRA would clobber CC).
- if (!CompareLHS->hasOneUse())
+ if (!LHS->hasOneUse())
return false;
// Verify that the ICMP compares against zero.
- if (CompareRHS->getZExtValue() != 0)
+ if (RHS->getZExtValue() != 0)
return false;
// Compute the effective CC mask for the new branch or select.
@@ -8586,18 +8537,33 @@ static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) {
return false;
}
-std::optional<SDValue>
+// Combine and compute CCMask two select_cc for flag output operand where
+// one of operands TrueVal/FalseVal is not constant and subtree select_cc has
+// already been combined/evaluated.
+// This functions can be integerated in combineCCMask with following changes to
+// the design.
+// 1. combineCCMask function should have argument N and DCI as arguments, as
+// operand 0 and 1(TrueVal/FalseVal) required to check Inverted select_cc with
+// respect to subtree select_cc. which is needed if CCMask needs to be inverted
+// or swapping of Op0 and Op1 is required while creatiing new SDValue.
+// 2. This code has to be integrated in the beginning of combineCCMask so that
+// there is early exit from combineCCMask in case this tranformation is applied
+// without interfereing with combineCCMask combining single select_cc sequence.
+// 3. This function calls combineCCMask to combine outer select_cc. It may be
+// an issue if combineCCMask is converetd into iterative.
+// 4. Function combineCCMask is already a long function.
+SDValue
SystemZTargetLowering::combineSELECT_CC_CCIPMMask(SDNode *N,
DAGCombinerInfo &DCI) const {
SelectionDAG &DAG = DCI.DAG;
- // Check if N has SystemZ::CC operand.
- const auto isCCOperand = [](SDNode *N) {
- if (!N || N->getNumOperands() < 2)
+ // Check if CCOp1 and CCOp2 refers to the same CC condition node.
+ const auto isSameCCIPMOp = [](SDValue &CCOp1, SDValue &CCOp2,
+ int &CCValidVal) {
+ // Already combined/evaluated sequence.
+ if (CCValidVal != SystemZ::CCMASK_ANY)
return false;
- auto *RN = dyn_cast<RegisterSDNode>(N->getOperand(1));
- if (!RN || !RN->getReg().isPhysical() || RN->getReg() != SystemZ::CC)
- return false;
- return true;
+ SDNode *N1 = CCOp1.getNode(), *N2 = CCOp2.getNode();
+ return N1 && N2 && N1 == N2;
};
auto *TrueVal = dyn_cast<ConstantSDNode>(N->getOperand(0));
@@ -8606,12 +8572,12 @@ SystemZTargetLowering::combineSELECT_CC_CCIPMMask(SDNode *N,
// Not yet encountered the case where both operands not constants,
// that case can be handled by removing this condition.
if (!((TrueVal != nullptr) ^ (FalseVal != nullptr)))
- return std::nullopt;
+ return SDValue();
SDValue CCOp = TrueVal ? N->getOperand(1) : N->getOperand(0);
auto *CCOpNode = CCOp.getNode();
if (!CCOpNode || CCOpNode->getOpcode() != SystemZISD::SELECT_CCMASK)
- return std::nullopt;
+ return SDValue();
auto *TrueValOp = dyn_cast<ConstantSDNode>(CCOpNode->getOperand(0));
auto *FalseValOp = dyn_cast<ConstantSDNode>(CCOpNode->getOperand(1));
@@ -8622,13 +8588,13 @@ SystemZTargetLowering::combineSELECT_CC_CCIPMMask(SDNode *N,
if (FalseValOp && TrueVal->getZExtValue() == FalseValOp->getZExtValue())
InvertOp2 = !InvertOp2;
else if (!TrueValOp || TrueVal->getZExtValue() != TrueValOp->getZExtValue())
- return std::nullopt;
+ return SDValue();
} else if (FalseVal) {
if (TrueValOp && FalseVal->getZExtValue() == TrueValOp->getZExtValue())
InvertOp1 = !InvertOp1;
else if (!FalseValOp ||
FalseVal->getZExtValue() != FalseValOp->getZExtValue())
- return std::nullopt;
+ return SDValue();
}
auto *CCValidNode = dyn_cast<ConstantSDNode>(N->getOperand(2));
@@ -8636,7 +8602,7 @@ SystemZTargetLowering::combineSELECT_CC_CCIPMMask(SDNode *N,
auto *CCValidOp = dyn_cast<ConstantSDNode>(CCOpNode->getOperand(2));
auto *CCMaskOp = dyn_cast<ConstantSDNode>(CCOpNode->getOperand(3));
if (!CCValidNode || !CCMaskNode || !CCMaskOp || !CCValidOp)
- return std::nullopt;
+ return SDValue();
int CCValid = CCValidNode->getZExtValue();
int CCMaskValOp = CCMaskOp->getZExtValue();
@@ -8644,24 +8610,24 @@ SystemZTargetLowering::combineSELECT_CC_CCIPMMask(SDNode *N,
int CCMask = CCMaskNode->getZExtValue();
bool IsUnionMask = CCMask == SystemZ::CCMASK_CMP_EQ;
if (CCValid != SystemZ::CCMASK_ICMP)
- return std::nullopt;
+ return SDValue();
SDValue CCReg = N->getOperand(4);
SDValue CCRegOp = CCOpNode->getOperand(4);
// Combine current select_cc.
- if (combineSRL_IPM_CCMask(CCReg, CCValid, CCMask)) {
+ if (combineCCMask(CCReg, CCValid, CCMask)) {
if (InvertOp1)
CCMask ^= SystemZ::CCMASK_ANY;
// There are two scenarios here.
// Case 1. Inner (ICMP (SELECT_CCMASK)) has not already been combined into
// SELECT_CCMASK. Compute CCMask after optimization.
// Case 2. Inner (ICMP (SELECT_CCMASK)) already been combined into
- // SELECT_CCMASK. Check for isCCOperand. In this case we will not know
+ // SELECT_CCMASK. Check for isSameCCIPMOp. In this case we will not know
// original CCMask, but if only one bit is set in CCMaskValOp, that means
// original CCMask was SystemZ::CCMASK_CMP_EQ.
- if (!combineSRL_IPM_CCMask(CCRegOp, CCValidValOp, CCMaskValOp) &&
- !isCCOperand(CCRegOp.getNode()))
- return std::nullopt;
+ if (/*!combineCCMask(CCRegOp, CCValidValOp, CCMaskValOp) &&*/
+ !isSameCCIPMOp(CCReg, CCRegOp, CCValidValOp))
+ return SDValue();
// If outer SELECT_CCMASK is CCMASK_CMP_EQ or single bit is set in
// CCMaskValOp(inner SELECT_CCMASK is CCMASK_CMP_EQ).
bool OnlyOneBitSet = CCMaskValOp && !(CCMaskValOp & (CCMaskValOp - 1));
@@ -8692,7 +8658,7 @@ SystemZTargetLowering::combineSELECT_CC_CCIPMMask(SDNode *N,
DAG.getTargetConstant(CCValid, SDLoc(N), MVT::i32),
DAG.getTargetConstant(CCMask, SDLoc(N), MVT::i32), CCRegOp);
}
- return std::nullopt;
+ return SDValue();
}
// Merging versus split in multiple branches cost.
@@ -8705,6 +8671,7 @@ SystemZTargetLowering::getJumpConditionMergingParams(Instruction::BinaryOps Opc,
const Value *RHSVal;
const APInt *RHSC;
if (const auto *I = dyn_cast<Instruction>(V)) {
+ // PatternMatch.h provides concise tree-based pattern match of llvm IR.
if (match(I->getOperand(0), m_And(m_Value(RHSVal), m_APInt(RHSC))) ||
match(I, m_Cmp(m_Value(RHSVal), m_APInt(RHSC)))) {
if (const auto *CB = dyn_cast<CallBase>(RHSVal)) {
@@ -8754,11 +8721,19 @@ SDValue SystemZTargetLowering::combineBR_CCMASK(
SDValue SystemZTargetLowering::combineSELECT_CCMASK(
SDNode *N, DAGCombinerInfo &DCI) const {
- // Try to combine select_cc with select_cc for flag output operand.
- // select_cc may have one of True/Flase Operand SDValue.
- std::optional<SDValue> Res = combineSELECT_CC_CCIPMMask(N, DCI);
- if (Res.has_value())
- return Res.value();
+ // Try to combine two select_cc if following two conditions are met.
+ // 1. Subtree select_cc has aleady been combined/evaluated for flag output
+ // operand srl/ipm sequence.
+ // 2. One of True/False operand of select_cc is not constant.
+ // In case it is true, we take early exit returning combined select_cc with
+ // computed CCMask.
+ // Why haven't we apply the same logic in combineBR_CCMASK above? We can add
+ // following code combineSELECT_CC_CCIPMMask in combineBR_CCMASK as well, but
+ // it would not be used as it would call combineSELECT_CCMASK to combine two
+ // select_cc.
+ SDValue Res = combineSELECT_CC_CCIPMMask(N, DCI);
+ if (Res != SDValue())
+ return Res;
SelectionDAG &DAG = DCI.DAG;
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 70c742839b3bd..22bd015dc2d81 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -768,11 +768,8 @@ class SystemZTargetLowering : public TargetLowering {
SDValue combineINT_TO_FP(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue combineBSWAP(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue combineBR_CCMASK(SDNode *N, DAGCombinerInfo &DCI) const;
- std::optional<SDValue> combineBR_CCJoinIPMMask(SDNode *N,
- DAGCombinerInfo &DCI) const;
SDValue combineSELECT_CCMASK(SDNode *N, DAGCombinerInfo &DCI) const;
- std::optional<SDValue> combineSELECT_CC_CCIPMMask(SDNode *N,
- DAGCombinerInfo &DCI) const;
+ SDValue combineSELECT_CC_CCIPMMask(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue combineGET_CCMASK(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue combineIntDIVREM(SDNode *N, DAGCombinerInfo &DCI) const;
SDValue combineINTRINSIC(SDNode *N, DAGCombinerInfo &DCI) const;
diff --git a/llvm/test/CodeGen/SystemZ/htm-intrinsics.ll b/llvm/test/CodeGen/SystemZ/htm-intrinsics.ll
index c6ee8042a5f2a..07fbed9bd0dd7 100644
--- a/llvm/test/CodeGen/SystemZ/htm-intrinsics.ll
+++ b/llvm/test/CodeGen/SystemZ/htm-intrinsics.ll
@@ -90,7 +90,7 @@ define i32 @test_tbegin_nofloat4(i32 %pad, ptr %ptr) {
; CHECK: tbegin 0, 65292
; CHECK: ipm %r2
; CHECK: srl %r2, 28
-; CHECK: ciblh %r2, 2, 0(%r14)
+; CHECK: bnhr %r14
; CHECK: mvhi 0(%r3), 0
; CHECK: br %r14
%res = call i32 @llvm.s390.tbegin.nofloat(ptr null, i32 65292)
@@ -219,7 +219,7 @@ define i32 @test_tend2(i32 %pad, ptr %ptr) {
; CHECK: tend
; CHECK: ipm %r2
; CHECK: srl %r2, 28
-; CHECK: ciblh %r2, 2, 0(%r14)
+; CHECK: bnhr %r14
; CHECK: mvhi 0(%r3), 0
; CHECK: br %r14
%res = call i32 @llvm.s390.tend()
More information about the llvm-commits
mailing list