[llvm] 0fe0968 - [AArch64][FEAT_CMPBR] Codegen for Armv9.6-a compare-and-branch (#116465)

via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 19 13:58:25 PST 2025


Author: David Tellenbach
Date: 2025-02-19T13:58:20-08:00
New Revision: 0fe0968c936b5e3ea83ed75ad8f8bb56e517eebe

URL: https://github.com/llvm/llvm-project/commit/0fe0968c936b5e3ea83ed75ad8f8bb56e517eebe
DIFF: https://github.com/llvm/llvm-project/commit/0fe0968c936b5e3ea83ed75ad8f8bb56e517eebe.diff

LOG: [AArch64][FEAT_CMPBR] Codegen for Armv9.6-a compare-and-branch (#116465)

This patch adds codegen for all Arm9.6-a compare-and-branch
instructions, that operate on full w or x registers. The instruction
variants operating on half-words (cbh) and bytes (cbb) are added in a
subsequent patch.

Since CB doesn't use standard 4-bit Arm condition codes but a reduced
set of conditions, encoded in 3 bits, some conditions are expressed by
modifying operands, namely incrementing or decrementing immediate
operands and swapping register operands. To invert a CB instruction it's
therefore not enough to just modify the condition code which doesn't
play particularly well with how the backend is currently organized. We
therefore introduce a number of pseudos which operate on the standard
4-bit condition codes and lower them late during codegen.

Added: 
    llvm/test/CodeGen/AArch64/cmpbr-branch-relaxation.mir
    llvm/test/CodeGen/AArch64/cmpbr-early-ifcvt.mir
    llvm/test/CodeGen/AArch64/cmpbr-reg-imm-at-bounds.ll
    llvm/test/CodeGen/AArch64/cmpbr-reg-imm.ll
    llvm/test/CodeGen/AArch64/cmpbr-reg-reg.ll

Modified: 
    llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
    llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
    llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
    llvm/lib/Target/AArch64/AArch64ISelLowering.h
    llvm/lib/Target/AArch64/AArch64InstrFormats.td
    llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
    llvm/lib/Target/AArch64/AArch64InstrInfo.h
    llvm/lib/Target/AArch64/AArch64InstrInfo.td
    llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index f1f25b65fc53f..eaca75b80dd12 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -208,6 +208,9 @@ class AArch64AsmPrinter : public AsmPrinter {
   void emitAttributes(unsigned Flags, uint64_t PAuthABIPlatform,
                       uint64_t PAuthABIVersion, AArch64TargetStreamer *TS);
 
+  // Emit expansion of Compare-and-branch pseudo instructions
+  void emitCBPseudoExpansion(const MachineInstr *MI);
+
   void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
   void EmitToStreamer(const MCInst &Inst) {
     EmitToStreamer(*OutStreamer, Inst);
@@ -2589,6 +2592,124 @@ AArch64AsmPrinter::lowerBlockAddressConstant(const BlockAddress &BA) {
   return BAE;
 }
 
+void AArch64AsmPrinter::emitCBPseudoExpansion(const MachineInstr *MI) {
+  bool IsImm = false;
+  bool Is32Bit = false;
+
+  switch (MI->getOpcode()) {
+  default:
+    llvm_unreachable("This is not a CB pseudo instruction");
+  case AArch64::CBWPrr:
+    Is32Bit = true;
+    break;
+  case AArch64::CBXPrr:
+    Is32Bit = false;
+    break;
+  case AArch64::CBWPri:
+    IsImm = true;
+    Is32Bit = true;
+    break;
+  case AArch64::CBXPri:
+    IsImm = true;
+    break;
+  }
+
+  AArch64CC::CondCode CC =
+      static_cast<AArch64CC::CondCode>(MI->getOperand(0).getImm());
+  bool NeedsRegSwap = false;
+  bool NeedsImmDec = false;
+  bool NeedsImmInc = false;
+
+  // Decide if we need to either swap register operands or increment/decrement
+  // immediate operands
+  unsigned MCOpC;
+  switch (CC) {
+  default:
+    llvm_unreachable("Invalid CB condition code");
+  case AArch64CC::EQ:
+    MCOpC = IsImm ? (Is32Bit ? AArch64::CBEQWri : AArch64::CBEQXri)
+                  : (Is32Bit ? AArch64::CBEQWrr : AArch64::CBEQXrr);
+    break;
+  case AArch64CC::NE:
+    MCOpC = IsImm ? (Is32Bit ? AArch64::CBNEWri : AArch64::CBNEXri)
+                  : (Is32Bit ? AArch64::CBNEWrr : AArch64::CBNEXrr);
+    break;
+  case AArch64CC::HS:
+    MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
+                  : (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
+    NeedsImmDec = IsImm;
+    break;
+  case AArch64CC::LO:
+    MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
+                  : (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
+    NeedsRegSwap = !IsImm;
+    break;
+  case AArch64CC::HI:
+    MCOpC = IsImm ? (Is32Bit ? AArch64::CBHIWri : AArch64::CBHIXri)
+                  : (Is32Bit ? AArch64::CBHIWrr : AArch64::CBHIXrr);
+    break;
+  case AArch64CC::LS:
+    MCOpC = IsImm ? (Is32Bit ? AArch64::CBLOWri : AArch64::CBLOXri)
+                  : (Is32Bit ? AArch64::CBHSWrr : AArch64::CBHSXrr);
+    NeedsRegSwap = !IsImm;
+    NeedsImmInc = IsImm;
+    break;
+  case AArch64CC::GE:
+    MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
+                  : (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
+    NeedsImmDec = IsImm;
+    break;
+  case AArch64CC::LT:
+    MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
+                  : (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
+    NeedsRegSwap = !IsImm;
+    break;
+  case AArch64CC::GT:
+    MCOpC = IsImm ? (Is32Bit ? AArch64::CBGTWri : AArch64::CBGTXri)
+                  : (Is32Bit ? AArch64::CBGTWrr : AArch64::CBGTXrr);
+    break;
+  case AArch64CC::LE:
+    MCOpC = IsImm ? (Is32Bit ? AArch64::CBLTWri : AArch64::CBLTXri)
+                  : (Is32Bit ? AArch64::CBGEWrr : AArch64::CBGEXrr);
+    NeedsRegSwap = !IsImm;
+    NeedsImmInc = IsImm;
+    break;
+  }
+
+  MCInst Inst;
+  Inst.setOpcode(MCOpC);
+
+  MCOperand Lhs, Rhs, Trgt;
+  lowerOperand(MI->getOperand(1), Lhs);
+  lowerOperand(MI->getOperand(2), Rhs);
+  lowerOperand(MI->getOperand(3), Trgt);
+
+  // Now swap, increment or decrement
+  if (NeedsRegSwap) {
+    assert(Lhs.isReg() && "Expected register operand for CB");
+    assert(Rhs.isReg() && "Expected register operand for CB");
+    Inst.addOperand(Rhs);
+    Inst.addOperand(Lhs);
+  } else if (NeedsImmDec) {
+    Rhs.setImm(Rhs.getImm() - 1);
+    Inst.addOperand(Lhs);
+    Inst.addOperand(Rhs);
+  } else if (NeedsImmInc) {
+    Rhs.setImm(Rhs.getImm() + 1);
+    Inst.addOperand(Lhs);
+    Inst.addOperand(Rhs);
+  } else {
+    Inst.addOperand(Lhs);
+    Inst.addOperand(Rhs);
+  }
+
+  assert((!IsImm || (Rhs.getImm() >= 0 && Rhs.getImm() < 64)) &&
+         "CB immediate operand out-of-bounds");
+
+  Inst.addOperand(Trgt);
+  EmitToStreamer(*OutStreamer, Inst);
+}
+
 // Simple pseudo-instructions have their lowering (with expansion to real
 // instructions) auto-generated.
 #include "AArch64GenMCPseudoLowering.inc"
@@ -3155,13 +3276,20 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
     return;
 
   case AArch64::BLR:
-  case AArch64::BR:
+  case AArch64::BR: {
     recordIfImportCall(MI);
     MCInst TmpInst;
     MCInstLowering.Lower(MI, TmpInst);
     EmitToStreamer(*OutStreamer, TmpInst);
     return;
   }
+  case AArch64::CBWPri:
+  case AArch64::CBXPri:
+  case AArch64::CBWPrr:
+  case AArch64::CBXPrr:
+    emitCBPseudoExpansion(MI);
+    return;
+  }
 
   // Finally, do the automated lowerings for everything else.
   MCInst TmpInst;

diff  --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 1387a224fa660..3ca9107cb2ce5 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -507,6 +507,8 @@ class AArch64DAGToDAGISel : public SelectionDAGISel {
 
   bool SelectAllActivePredicate(SDValue N);
   bool SelectAnyPredicate(SDValue N);
+
+  bool SelectCmpBranchUImm6Operand(SDNode *P, SDValue N, SDValue &Imm);
 };
 
 class AArch64DAGToDAGISelLegacy : public SelectionDAGISelLegacy {
@@ -7489,3 +7491,52 @@ bool AArch64DAGToDAGISel::SelectSMETileSlice(SDValue N, unsigned MaxSize,
   Offset = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i64);
   return true;
 }
+
+bool AArch64DAGToDAGISel::SelectCmpBranchUImm6Operand(SDNode *P, SDValue N,
+                                                      SDValue &Imm) {
+  AArch64CC::CondCode CC =
+      static_cast<AArch64CC::CondCode>(P->getConstantOperandVal(1));
+  if (auto *CN = dyn_cast<ConstantSDNode>(N)) {
+    // Check conservatively if the immediate fits the valid range [0, 64).
+    // Immediate variants for GE and HS definitely need to be decremented
+    // when lowering the pseudos later, so an immediate of 1 would become 0.
+    // For the inverse conditions LT and LO we don't know for sure if they
+    // will need a decrement but should the decision be made to reverse the
+    // branch condition, we again end up with the need to decrement.
+    // The same argument holds for LE, LS, GT and HI and possibly
+    // incremented immediates. This can lead to slightly less optimal
+    // codegen, e.g. we never codegen the legal case
+    //    cblt w0, #63, A
+    // because we could end up with the illegal case
+    //    cbge w0, #64, B
+    // should the decision to reverse the branch direction be made. For the
+    // lower bound cases this is no problem since we can express comparisons
+    // against 0 with either tbz/tnbz or using wzr/xzr.
+    uint64_t LowerBound = 0, UpperBound = 64;
+    switch (CC) {
+    case AArch64CC::GE:
+    case AArch64CC::HS:
+    case AArch64CC::LT:
+    case AArch64CC::LO:
+      LowerBound = 1;
+      break;
+    case AArch64CC::LE:
+    case AArch64CC::LS:
+    case AArch64CC::GT:
+    case AArch64CC::HI:
+      UpperBound = 63;
+      break;
+    default:
+      break;
+    }
+
+    if (CN->getAPIntValue().uge(LowerBound) &&
+        CN->getAPIntValue().ult(UpperBound)) {
+      SDLoc DL(N);
+      Imm = CurDAG->getTargetConstant(CN->getZExtValue(), DL, N.getValueType());
+      return true;
+    }
+  }
+
+  return false;
+}

diff  --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 50be082777835..d519bfc06af05 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -2993,6 +2993,7 @@ const char *AArch64TargetLowering::getTargetNodeName(unsigned Opcode) const {
     MAKE_CASE(AArch64ISD::CTTZ_ELTS)
     MAKE_CASE(AArch64ISD::CALL_ARM64EC_TO_X64)
     MAKE_CASE(AArch64ISD::URSHR_I_PRED)
+    MAKE_CASE(AArch64ISD::CB)
   }
 #undef MAKE_CASE
   return nullptr;
@@ -10603,6 +10604,17 @@ SDValue AArch64TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
                          DAG.getConstant(SignBitPos, dl, MVT::i64), Dest);
     }
 
+    // Try to emit Armv9.6 CB instructions. We prefer tb{n}z/cb{n}z due to their
+    // larger branch displacement but do prefer CB over cmp + br.
+    if (Subtarget->hasCMPBR() &&
+        AArch64CC::isValidCBCond(changeIntCCToAArch64CC(CC)) &&
+        ProduceNonFlagSettingCondBr) {
+      SDValue Cond =
+          DAG.getTargetConstant(changeIntCCToAArch64CC(CC), dl, MVT::i32);
+      return DAG.getNode(AArch64ISD::CB, dl, MVT::Other, Chain, Cond, LHS, RHS,
+                         Dest);
+    }
+
     SDValue CCVal;
     SDValue Cmp = getAArch64Cmp(LHS, RHS, CC, CCVal, DAG, dl);
     return DAG.getNode(AArch64ISD::BRCOND, dl, MVT::Other, Chain, Dest, CCVal,

diff  --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index b26f28dc79f88..1987c892ac080 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -529,6 +529,9 @@ enum NodeType : unsigned {
   // SME ZA loads and stores
   SME_ZA_LDR,
   SME_ZA_STR,
+
+  // Compare-and-branch
+  CB,
 };
 
 } // end namespace AArch64ISD

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 03ae42493a035..7a8b743faf4a3 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -400,6 +400,16 @@ def uimm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 64; }]> {
    let ParserMatchClass = UImm6Operand;
 }
 
+def CmpBranchUImm6Operand_32b
+    : ComplexPattern<i32, 1, "SelectCmpBranchUImm6Operand", [imm]> {
+  let WantsParent = true;
+}
+
+def CmpBranchUImm6Operand_64b
+    : ComplexPattern<i64, 1, "SelectCmpBranchUImm6Operand", [imm]> {
+  let WantsParent = true;
+}
+
 def UImm6Plus1Operand : AsmOperandClass {
   let Name = "UImm6P1";
   let DiagnosticType = "InvalidImm1_64";
@@ -13225,6 +13235,21 @@ multiclass CmpBranchRegisterAlias<string mnemonic, string insn> {
   def : InstAlias<mnemonic # "\t$Rt, $Rm, $target",
                  (!cast<Instruction>(insn # "Xrr") GPR64:$Rm, GPR64:$Rt, am_brcmpcond:$target), 0>;
 }
+
+class CmpBranchRegisterPseudo<RegisterClass regtype>
+  : Pseudo<(outs), (ins ccode:$Cond, regtype:$Rt, regtype:$Rm, am_brcmpcond:$Target), []>,
+    Sched<[WriteBr]> {
+  let isBranch = 1;
+  let isTerminator = 1;
+}
+
+class CmpBranchImmediatePseudo<RegisterClass regtype, ImmLeaf imtype>
+  : Pseudo<(outs), (ins ccode:$Cond, regtype:$Rt, imtype:$Imm, am_brcmpcond:$Target), []>,
+    Sched<[WriteBr]> {
+  let isBranch = 1;
+  let isTerminator = 1;
+}
+
 //----------------------------------------------------------------------------
 // Allow the size specifier tokens to be upper case, not just lower.
 def : TokenAlias<".4B", ".4b">;  // Add dot product

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 0f2b969fba35c..efa03d4a1035b 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -62,6 +62,10 @@ using namespace llvm;
 #define GET_INSTRINFO_CTOR_DTOR
 #include "AArch64GenInstrInfo.inc"
 
+static cl::opt<unsigned>
+    CBDisplacementBits("aarch64-cb-offset-bits", cl::Hidden, cl::init(9),
+                       cl::desc("Restrict range of CB instructions (DEBUG)"));
+
 static cl::opt<unsigned> TBZDisplacementBits(
     "aarch64-tbz-offset-bits", cl::Hidden, cl::init(14),
     cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"));
@@ -216,6 +220,18 @@ static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,
     Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
     Cond.push_back(LastInst->getOperand(0));
     Cond.push_back(LastInst->getOperand(1));
+    break;
+  case AArch64::CBWPri:
+  case AArch64::CBXPri:
+  case AArch64::CBWPrr:
+  case AArch64::CBXPrr:
+    Target = LastInst->getOperand(3).getMBB();
+    Cond.push_back(MachineOperand::CreateImm(-1));
+    Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
+    Cond.push_back(LastInst->getOperand(0));
+    Cond.push_back(LastInst->getOperand(1));
+    Cond.push_back(LastInst->getOperand(2));
+    break;
   }
 }
 
@@ -237,6 +253,11 @@ static unsigned getBranchDisplacementBits(unsigned Opc) {
     return CBZDisplacementBits;
   case AArch64::Bcc:
     return BCCDisplacementBits;
+  case AArch64::CBWPri:
+  case AArch64::CBXPri:
+  case AArch64::CBWPrr:
+  case AArch64::CBXPrr:
+    return CBDisplacementBits;
   }
 }
 
@@ -266,6 +287,11 @@ AArch64InstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
   case AArch64::CBNZX:
   case AArch64::Bcc:
     return MI.getOperand(1).getMBB();
+  case AArch64::CBWPri:
+  case AArch64::CBXPri:
+  case AArch64::CBWPrr:
+  case AArch64::CBXPrr:
+    return MI.getOperand(3).getMBB();
   }
 }
 
@@ -543,6 +569,17 @@ bool AArch64InstrInfo::reverseBranchCondition(
     case AArch64::TBNZX:
       Cond[1].setImm(AArch64::TBZX);
       break;
+
+    // Cond is { -1, Opcode, CC, Op0, Op1 }
+    case AArch64::CBWPri:
+    case AArch64::CBXPri:
+    case AArch64::CBWPrr:
+    case AArch64::CBXPrr: {
+      // Pseudos using standard 4bit Arm condition codes
+      AArch64CC::CondCode CC =
+          static_cast<AArch64CC::CondCode>(Cond[2].getImm());
+      Cond[2].setImm(AArch64CC::getInvertedCondCode(CC));
+    }
     }
   }
 
@@ -593,10 +630,19 @@ void AArch64InstrInfo::instantiateCondBranch(
   } else {
     // Folded compare-and-branch
     // Note that we use addOperand instead of addReg to keep the flags.
+
+    // cbz, cbnz
     const MachineInstrBuilder MIB =
         BuildMI(&MBB, DL, get(Cond[1].getImm())).add(Cond[2]);
+
+    // tbz/tbnz
     if (Cond.size() > 3)
-      MIB.addImm(Cond[3].getImm());
+      MIB.add(Cond[3]);
+
+    // cb
+    if (Cond.size() > 4)
+      MIB.add(Cond[4]);
+
     MIB.addMBB(TBB);
   }
 }
@@ -842,6 +888,48 @@ void AArch64InstrInfo::insertSelect(MachineBasicBlock &MBB,
               AArch64_AM::encodeLogicalImmediate(1ull << Cond[3].getImm(), 64));
     break;
   }
+  case 5: { // cb
+    // We must insert a cmp, that is a subs
+    //            0       1   2    3    4
+    // Cond is { -1, Opcode, CC, Op0, Op1 }
+    unsigned SUBSOpC, SUBSDestReg;
+    bool IsImm = false;
+    CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
+    switch (Cond[1].getImm()) {
+    default:
+      llvm_unreachable("Unknown branch opcode in Cond");
+    case AArch64::CBWPri:
+      SUBSOpC = AArch64::SUBSWri;
+      SUBSDestReg = AArch64::WZR;
+      IsImm = true;
+      break;
+    case AArch64::CBXPri:
+      SUBSOpC = AArch64::SUBSXri;
+      SUBSDestReg = AArch64::XZR;
+      IsImm = true;
+      break;
+    case AArch64::CBWPrr:
+      SUBSOpC = AArch64::SUBSWrr;
+      SUBSDestReg = AArch64::WZR;
+      IsImm = false;
+      break;
+    case AArch64::CBXPrr:
+      SUBSOpC = AArch64::SUBSXrr;
+      SUBSDestReg = AArch64::XZR;
+      IsImm = false;
+      break;
+    }
+
+    if (IsImm)
+      BuildMI(MBB, I, DL, get(SUBSOpC), SUBSDestReg)
+          .addReg(Cond[3].getReg())
+          .addImm(Cond[4].getImm())
+          .addImm(0);
+    else
+      BuildMI(MBB, I, DL, get(SUBSOpC), SUBSDestReg)
+          .addReg(Cond[3].getReg())
+          .addReg(Cond[4].getReg());
+  }
   }
 
   unsigned Opc = 0;
@@ -8426,6 +8514,10 @@ bool AArch64InstrInfo::optimizeCondBranch(MachineInstr &MI) const {
   default:
     llvm_unreachable("Unknown branch instruction?");
   case AArch64::Bcc:
+  case AArch64::CBWPri:
+  case AArch64::CBXPri:
+  case AArch64::CBWPrr:
+  case AArch64::CBXPrr:
     return false;
   case AArch64::CBZW:
   case AArch64::CBZX:

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index 9a0034223ab9b..f7a1485cdd26a 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -692,6 +692,10 @@ static inline bool isCondBranchOpcode(int Opc) {
   case AArch64::TBZX:
   case AArch64::TBNZW:
   case AArch64::TBNZX:
+  case AArch64::CBWPri:
+  case AArch64::CBXPri:
+  case AArch64::CBWPrr:
+  case AArch64::CBXPrr:
     return true;
   default:
     return false;

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 93a6100ce54e9..fc86dd4742bc4 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -516,6 +516,10 @@ def SDT_AArch64TBL : SDTypeProfile<1, 2, [
   SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisInt<2>
 ]>;
 
+def SDT_AArch64cb : SDTypeProfile<0, 4,
+                                  [SDTCisVT<0, i32>, SDTCisInt<1>, SDTCisInt<2>,
+                                   SDTCisVT<3, OtherVT>]>;
+
 // non-extending masked load fragment.
 def nonext_masked_load :
   PatFrag<(ops node:$ptr, node:$pred, node:$def),
@@ -692,6 +696,7 @@ def topbitsallzero64: PatLeaf<(i64 GPR64:$src), [{
   }]>;
 
 // Node definitions.
+def AArch64CB : SDNode<"AArch64ISD::CB", SDT_AArch64cb, [SDNPHasChain]>;
 def AArch64adrp          : SDNode<"AArch64ISD::ADRP", SDTIntUnaryOp, []>;
 def AArch64adr           : SDNode<"AArch64ISD::ADR", SDTIntUnaryOp, []>;
 def AArch64addlow        : SDNode<"AArch64ISD::ADDlow", SDTIntBinOp, []>;
@@ -10459,6 +10464,10 @@ defm : PromoteBinaryv8f16Tov4f32<any_fdiv, FDIVv4f32>;
 defm : PromoteBinaryv8f16Tov4f32<any_fmul, FMULv4f32>;
 defm : PromoteBinaryv8f16Tov4f32<any_fsub, FSUBv4f32>;
 
+//===----------------------------------------------------------------------===//
+// Compare and Branch (FEAT_CMPBR)
+//===----------------------------------------------------------------------===//
+
 let Predicates = [HasCMPBR] in {
  defm CBGT : CmpBranchRegister<0b000, "cbgt">;
  defm CBGE : CmpBranchRegister<0b001, "cbge">;
@@ -10507,6 +10516,25 @@ let Predicates = [HasCMPBR] in {
  defm : CmpBranchWRegisterAlias<"cbhlo", "CBHHI">;
  defm : CmpBranchWRegisterAlias<"cbhls", "CBHHS">;
  defm : CmpBranchWRegisterAlias<"cbhlt", "CBHGT">;
+
+  // Pseudos for codegen
+  def CBWPrr : CmpBranchRegisterPseudo<GPR32>;
+  def CBXPrr : CmpBranchRegisterPseudo<GPR64>;
+  def CBWPri : CmpBranchImmediatePseudo<GPR32, uimm6_32b>;
+  def CBXPri : CmpBranchImmediatePseudo<GPR64, uimm6_64b>;
+
+  def : Pat<(AArch64CB i32:$Cond, GPR32:$Rn, CmpBranchUImm6Operand_32b:$Imm,
+                bb:$Target),
+            (CBWPri i32:$Cond, GPR32:$Rn, uimm6_32b:$Imm,
+                am_brcmpcond:$Target)>;
+  def : Pat<(AArch64CB i32:$Cond, GPR64:$Rn, CmpBranchUImm6Operand_64b:$Imm,
+                bb:$Target),
+            (CBXPri i32:$Cond, GPR64:$Rn, uimm6_64b:$Imm,
+                am_brcmpcond:$Target)>;
+  def : Pat<(AArch64CB i32:$Cond, GPR32:$Rn, GPR32:$Rt, bb:$Target),
+            (CBWPrr ccode:$Cond, GPR32:$Rn, GPR32:$Rt, am_brcmpcond:$Target)>;
+  def : Pat<(AArch64CB i32:$Cond, GPR64:$Rn, GPR64:$Rt, bb:$Target),
+            (CBXPrr ccode:$Cond, GPR64:$Rn, GPR64:$Rt, am_brcmpcond:$Target)>;
 } // HasCMPBR
 
 

diff  --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
index 9671fa3b3d92f..a4ee963e2cce0 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
+++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
@@ -362,6 +362,26 @@ inline static unsigned getNZCVToSatisfyCondCode(CondCode Code) {
   }
 }
 
+/// True, if a given condition code can be used in a fused compare-and-branch
+/// instructions, false otherwise.
+inline static bool isValidCBCond(AArch64CC::CondCode Code) {
+  switch (Code) {
+  default:
+    return false;
+  case AArch64CC::EQ:
+  case AArch64CC::NE:
+  case AArch64CC::HS:
+  case AArch64CC::LO:
+  case AArch64CC::HI:
+  case AArch64CC::LS:
+  case AArch64CC::GE:
+  case AArch64CC::LT:
+  case AArch64CC::GT:
+  case AArch64CC::LE:
+    return true;
+  }
+}
+
 } // end namespace AArch64CC
 
 struct SysAlias {

diff  --git a/llvm/test/CodeGen/AArch64/cmpbr-branch-relaxation.mir b/llvm/test/CodeGen/AArch64/cmpbr-branch-relaxation.mir
new file mode 100644
index 0000000000000..5fccb452e9642
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/cmpbr-branch-relaxation.mir
@@ -0,0 +1,156 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple arm64-apple-ios -mattr +cmpbr -o - -aarch64-cb-offset-bits=3 \
+# RUN:    -run-pass=branch-relaxation -verify-machineinstrs -simplify-mir %s | \
+# RUN:    FileCheck -check-prefix=RELAX %s
+# RUN: llc -mtriple arm64-apple-ios -mattr +cmpbr -o - -aarch64-cb-offset-bits=9 \
+# RUN:    -run-pass=branch-relaxation -verify-machineinstrs -simplify-mir %s | \
+# RUN:    FileCheck -check-prefix=NO-RELAX %s
+---
+name:            relax_cb
+registers:
+  - { id: 0, class: gpr32 }
+  - { id: 1, class: gpr32 }
+liveins:
+  - { reg: '$w0', virtual-reg: '%0' }
+  - { reg: '$w1', virtual-reg: '%1' }
+body:             |
+  ; RELAX-LABEL: name: relax_cb
+  ; RELAX: bb.0:
+  ; RELAX-NEXT:   [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+  ; RELAX-NEXT:   [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+  ; RELAX-NEXT:   CBWPrr 1, [[COPY]], [[COPY1]], %bb.1
+  ; RELAX-NEXT:   B %bb.2
+  ; RELAX-NEXT: {{  $}}
+  ; RELAX-NEXT: bb.1:
+  ; RELAX-NEXT:   [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[COPY]], [[COPY1]]
+  ; RELAX-NEXT:   [[ADDWrr1:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr]], [[COPY1]]
+  ; RELAX-NEXT:   [[ADDWrr2:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr1]], [[ADDWrr]]
+  ; RELAX-NEXT:   [[ADDWrr3:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr2]], [[ADDWrr1]]
+  ; RELAX-NEXT:   [[ADDWrr4:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr3]], [[ADDWrr2]]
+  ; RELAX-NEXT:   $w0 = ADDWrr [[ADDWrr4]], [[ADDWrr3]]
+  ; RELAX-NEXT: {{  $}}
+  ; RELAX-NEXT: bb.2:
+  ; RELAX-NEXT:   RET_ReallyLR implicit $w0
+  ;
+  ; NO-RELAX-LABEL: name: relax_cb
+  ; NO-RELAX: bb.0:
+  ; NO-RELAX-NEXT:   successors: %bb.1, %bb.2
+  ; NO-RELAX-NEXT: {{  $}}
+  ; NO-RELAX-NEXT:   [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+  ; NO-RELAX-NEXT:   [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+  ; NO-RELAX-NEXT:   CBWPrr 0, [[COPY]], [[COPY1]], %bb.2
+  ; NO-RELAX-NEXT: {{  $}}
+  ; NO-RELAX-NEXT: bb.1:
+  ; NO-RELAX-NEXT:   [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[COPY]], [[COPY1]]
+  ; NO-RELAX-NEXT:   [[ADDWrr1:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr]], [[COPY1]]
+  ; NO-RELAX-NEXT:   [[ADDWrr2:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr1]], [[ADDWrr]]
+  ; NO-RELAX-NEXT:   [[ADDWrr3:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr2]], [[ADDWrr1]]
+  ; NO-RELAX-NEXT:   [[ADDWrr4:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr3]], [[ADDWrr2]]
+  ; NO-RELAX-NEXT:   $w0 = ADDWrr [[ADDWrr4]], [[ADDWrr3]]
+  ; NO-RELAX-NEXT: {{  $}}
+  ; NO-RELAX-NEXT: bb.2:
+  ; NO-RELAX-NEXT:   RET_ReallyLR implicit $w0
+  bb.0:
+    successors: %bb.1, %bb.2
+    %0:gpr32 = COPY $w0
+    %1:gpr32 = COPY $w1
+    CBWPrr 0, %0, %1, %bb.2
+
+  bb.1:
+    successors: %bb.2
+    %2:gpr32 = ADDWrr %0, %1
+    %3:gpr32 = ADDWrr %2, %1
+    %4:gpr32 = ADDWrr %3, %2
+    %5:gpr32 = ADDWrr %4, %3
+    %6:gpr32 = ADDWrr %5, %4
+    $w0 = ADDWrr %6, %5
+
+  bb.2:
+    RET_ReallyLR implicit $w0
+...
+---
+name:              relax_and_split_block
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gpr32 }
+  - { id: 1, class: gpr32 }
+liveins:
+  - { reg: '$w0', virtual-reg: '%0' }
+  - { reg: '$w1', virtual-reg: '%1' }
+body:             |
+  ; RELAX-LABEL: name: relax_and_split_block
+  ; RELAX: bb.0:
+  ; RELAX-NEXT:   liveins: $w0, $w1
+  ; RELAX-NEXT: {{  $}}
+  ; RELAX-NEXT:   [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+  ; RELAX-NEXT:   [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+  ; RELAX-NEXT:   CBWPrr 1, [[COPY]], [[COPY1]], %bb.3
+  ; RELAX-NEXT:   B %bb.2
+  ; RELAX-NEXT: {{  $}}
+  ; RELAX-NEXT: bb.3:
+  ; RELAX-NEXT:   liveins: $w0, $w1
+  ; RELAX-NEXT: {{  $}}
+  ; RELAX-NEXT:   CBWPrr 0, [[COPY]], [[COPY1]], %bb.1
+  ; RELAX-NEXT:   B %bb.2
+  ; RELAX-NEXT: {{  $}}
+  ; RELAX-NEXT: bb.1:
+  ; RELAX-NEXT:   liveins: $w0, $w1
+  ; RELAX-NEXT: {{  $}}
+  ; RELAX-NEXT:   [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[COPY]], [[COPY1]]
+  ; RELAX-NEXT:   [[ADDWrr1:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr]], [[COPY1]]
+  ; RELAX-NEXT:   [[ADDWrr2:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr1]], [[ADDWrr]]
+  ; RELAX-NEXT:   [[ADDWrr3:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr2]], [[ADDWrr1]]
+  ; RELAX-NEXT:   [[ADDWrr4:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr3]], [[ADDWrr2]]
+  ; RELAX-NEXT:   $w0 = ADDWrr [[ADDWrr4]], [[ADDWrr3]]
+  ; RELAX-NEXT: {{  $}}
+  ; RELAX-NEXT: bb.2:
+  ; RELAX-NEXT:   liveins: $w0, $w1
+  ; RELAX-NEXT: {{  $}}
+  ; RELAX-NEXT:   RET_ReallyLR implicit $w0
+  ;
+  ; NO-RELAX-LABEL: name: relax_and_split_block
+  ; NO-RELAX: bb.0:
+  ; NO-RELAX-NEXT:   successors: %bb.1, %bb.2
+  ; NO-RELAX-NEXT:   liveins: $w0, $w1
+  ; NO-RELAX-NEXT: {{  $}}
+  ; NO-RELAX-NEXT:   [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+  ; NO-RELAX-NEXT:   [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+  ; NO-RELAX-NEXT:   CBWPrr 0, [[COPY]], [[COPY1]], %bb.2
+  ; NO-RELAX-NEXT:   CBWPrr 1, [[COPY]], [[COPY1]], %bb.2
+  ; NO-RELAX-NEXT: {{  $}}
+  ; NO-RELAX-NEXT: bb.1:
+  ; NO-RELAX-NEXT:   liveins: $w0, $w1
+  ; NO-RELAX-NEXT: {{  $}}
+  ; NO-RELAX-NEXT:   [[ADDWrr:%[0-9]+]]:gpr32 = ADDWrr [[COPY]], [[COPY1]]
+  ; NO-RELAX-NEXT:   [[ADDWrr1:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr]], [[COPY1]]
+  ; NO-RELAX-NEXT:   [[ADDWrr2:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr1]], [[ADDWrr]]
+  ; NO-RELAX-NEXT:   [[ADDWrr3:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr2]], [[ADDWrr1]]
+  ; NO-RELAX-NEXT:   [[ADDWrr4:%[0-9]+]]:gpr32 = ADDWrr [[ADDWrr3]], [[ADDWrr2]]
+  ; NO-RELAX-NEXT:   $w0 = ADDWrr [[ADDWrr4]], [[ADDWrr3]]
+  ; NO-RELAX-NEXT: {{  $}}
+  ; NO-RELAX-NEXT: bb.2:
+  ; NO-RELAX-NEXT:   liveins: $w0, $w1
+  ; NO-RELAX-NEXT: {{  $}}
+  ; NO-RELAX-NEXT:   RET_ReallyLR implicit $w0
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $w0, $w1
+    %0:gpr32 = COPY $w0
+    %1:gpr32 = COPY $w1
+    CBWPrr 0, %0, %1, %bb.2
+    CBWPrr 1, %0, %1, %bb.2
+
+  bb.1:
+    successors: %bb.2
+    liveins: $w0, $w1
+    %2:gpr32 = ADDWrr %0, %1
+    %3:gpr32 = ADDWrr %2, %1
+    %4:gpr32 = ADDWrr %3, %2
+    %5:gpr32 = ADDWrr %4, %3
+    %6:gpr32 = ADDWrr %5, %4
+    $w0 = ADDWrr %6, %5
+
+  bb.2:
+    liveins: $w0, $w1
+    RET_ReallyLR implicit $w0
+...

diff  --git a/llvm/test/CodeGen/AArch64/cmpbr-early-ifcvt.mir b/llvm/test/CodeGen/AArch64/cmpbr-early-ifcvt.mir
new file mode 100644
index 0000000000000..c3377164f357e
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/cmpbr-early-ifcvt.mir
@@ -0,0 +1,116 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple=arm64-apple-ios -mattr +cmpbr -run-pass=early-ifcvt -simplify-mir -o - %s | FileCheck %s
+# CHECK: cb_diamond
+---
+name:            cb_diamond
+alignment:       4
+tracksRegLiveness: true
+noPhis:          false
+isSSA:           true
+noVRegs:         false
+hasFakeUses:     false
+registers:
+  - { id: 0, class: gpr64 }
+  - { id: 1, class: gpr64 }
+  - { id: 2, class: gpr64 }
+  - { id: 3, class: gpr64 }
+  - { id: 4, class: gpr64 }
+  - { id: 5, class: gpr64 }
+liveins:
+  - { reg: '$x0', virtual-reg: '%0' }
+  - { reg: '$x1', virtual-reg: '%1' }
+frameInfo:
+  maxAlignment:    1
+  maxCallFrameSize: 0
+machineFunctionInfo: {}
+body:             |
+  ; CHECK-LABEL: name: cb_diamond
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   liveins: $x0, $x1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:gpr64 = COPY $x0
+  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:gpr64 = COPY $x1
+  ; CHECK-NEXT:   [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[COPY]], [[COPY1]]
+  ; CHECK-NEXT:   [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[COPY]], [[COPY1]], $xzr
+  ; CHECK-NEXT:   $xzr = SUBSXrr [[COPY]], [[COPY1]], implicit-def $nzcv
+  ; CHECK-NEXT:   [[CSELXr:%[0-9]+]]:gpr64 = CSELXr [[ADDXrr]], [[MADDXrrr]], 11, implicit $nzcv
+  ; CHECK-NEXT:   [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr killed [[CSELXr]], [[COPY]]
+  ; CHECK-NEXT:   $x0 = COPY [[ADDXrr1]]
+  ; CHECK-NEXT:   RET_ReallyLR implicit $x0
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $x0, $x1
+
+    %0:gpr64 = COPY $x0
+    %1:gpr64 = COPY $x1
+    CBXPrr 11, %0, %1, %bb.1
+    B %bb.2
+
+  bb.1:
+    successors: %bb.3
+    %2:gpr64 = ADDXrr %0, %1
+    B %bb.3
+
+  bb.2:
+    successors: %bb.3
+    %3:gpr64 = MADDXrrr %0, %1, $xzr
+    B %bb.3
+
+  bb.3:
+    %4:gpr64 = PHI %2, %bb.1, %3, %bb.2
+    %5:gpr64 = ADDXrr killed %4, %0
+    $x0 = COPY %5
+    RET_ReallyLR implicit $x0
+...
+---
+name:            cb_triangle
+alignment:       4
+tracksRegLiveness: true
+noPhis:          false
+isSSA:           true
+noVRegs:         false
+hasFakeUses:     false
+registers:
+  - { id: 0, class: gpr64 }
+  - { id: 1, class: gpr64 }
+  - { id: 2, class: gpr64 }
+  - { id: 3, class: gpr64 }
+  - { id: 4, class: gpr64 }
+liveins:
+  - { reg: '$x0', virtual-reg: '%0' }
+  - { reg: '$x1', virtual-reg: '%1' }
+frameInfo:
+  maxAlignment:    1
+  maxCallFrameSize: 0
+machineFunctionInfo: {}
+body:             |
+  ; CHECK-LABEL: name: cb_triangle
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   liveins: $x0, $x1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:gpr64 = COPY $x0
+  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:gpr64 = COPY $x1
+  ; CHECK-NEXT:   [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[COPY]], [[COPY1]]
+  ; CHECK-NEXT:   $xzr = SUBSXrr [[COPY]], [[COPY1]], implicit-def $nzcv
+  ; CHECK-NEXT:   [[CSELXr:%[0-9]+]]:gpr64 = CSELXr [[COPY1]], [[ADDXrr]], 10, implicit $nzcv
+  ; CHECK-NEXT:   [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr killed [[CSELXr]], [[COPY]]
+  ; CHECK-NEXT:   $x0 = COPY [[ADDXrr1]]
+  ; CHECK-NEXT:   RET_ReallyLR implicit $x0
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $x0, $x1
+
+    %0:gpr64 = COPY $x0
+    %1:gpr64 = COPY $x1
+    CBXPrr 10, %0, %1, %bb.2
+
+  bb.1:
+    successors: %bb.2
+    %2:gpr64 = ADDXrr %0, %1
+
+  bb.2:
+    %3:gpr64 = PHI %1, %bb.0, %2, %bb.1
+    %4:gpr64 = ADDXrr killed %3, %0
+    $x0 = COPY %4
+    RET_ReallyLR implicit $x0
+...

diff  --git a/llvm/test/CodeGen/AArch64/cmpbr-reg-imm-at-bounds.ll b/llvm/test/CodeGen/AArch64/cmpbr-reg-imm-at-bounds.ll
new file mode 100644
index 0000000000000..d264cf2126099
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/cmpbr-reg-imm-at-bounds.ll
@@ -0,0 +1,1328 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple arm64-apple-ios -mattr +cmpbr -verify-machineinstrs -o - < %s | FileCheck %s --check-prefix=CHECK-CMPBR
+; RUN: llc -mtriple arm64-apple-ios -mattr -cmpbr -verify-machineinstrs -o - < %s | FileCheck %s --check-prefix=CHECK-NO-CMPBR
+
+; slt, sle, sgt, sge, ult, ule, ugt, uge, eq, ne
+
+define void @slt_0_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: slt_0_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    tbnz w0, #31, LBB0_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB0_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: slt_0_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    tbnz w0, #31, LBB0_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB0_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp slt i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @slt_m1_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: slt_m1_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #-2 ; =0xfffffffe
+; CHECK-CMPBR-NEXT:    cbge w8, w0, LBB1_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB1_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: slt_m1_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmn w0, #2
+; CHECK-NO-CMPBR-NEXT:    b.le LBB1_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB1_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp slt i32 %a, -1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @slt_63_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: slt_63_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblt w0, #63, LBB2_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB2_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: slt_63_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #62
+; CHECK-NO-CMPBR-NEXT:    b.le LBB2_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB2_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp slt i32 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @slt_64_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: slt_64_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #63 ; =0x3f
+; CHECK-CMPBR-NEXT:    cbge w8, w0, LBB3_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB3_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: slt_64_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #63
+; CHECK-NO-CMPBR-NEXT:    b.le LBB3_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB3_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp slt i32 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sle_0_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sle_0_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblt w0, #1, LBB4_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB4_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sle_0_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #0
+; CHECK-NO-CMPBR-NEXT:    b.le LBB4_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB4_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sle i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sle_m1_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sle_m1_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    tbnz w0, #31, LBB5_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB5_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sle_m1_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    tbnz w0, #31, LBB5_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB5_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sle i32 %a, -1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sle_63_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sle_63_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #63 ; =0x3f
+; CHECK-CMPBR-NEXT:    cbge w8, w0, LBB6_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB6_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sle_63_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #63
+; CHECK-NO-CMPBR-NEXT:    b.le LBB6_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB6_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sle i32 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sle_64_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sle_64_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #64 ; =0x40
+; CHECK-CMPBR-NEXT:    cbge w8, w0, LBB7_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB7_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sle_64_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #64
+; CHECK-NO-CMPBR-NEXT:    b.le LBB7_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB7_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sle i32 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sgt_0_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sgt_0_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbgt w0, #0, LBB8_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB8_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sgt_0_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #1
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB8_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB8_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sgt i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sgt_m1_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sgt_m1_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    tbz w0, #31, LBB9_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB9_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sgt_m1_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    tbz w0, #31, LBB9_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB9_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sgt i32 %a, -1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sgt_63_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sgt_63_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #64 ; =0x40
+; CHECK-CMPBR-NEXT:    cbge w0, w8, LBB10_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB10_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sgt_63_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #64
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB10_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB10_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sgt i32 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sgt_64_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sgt_64_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #65 ; =0x41
+; CHECK-CMPBR-NEXT:    cbge w0, w8, LBB11_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB11_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sgt_64_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #65
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB11_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB11_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sgt i32 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sge_0_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sge_0_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    tbz w0, #31, LBB12_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB12_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sge_0_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    tbz w0, #31, LBB12_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB12_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sge i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sge_m1_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sge_m1_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #-1 ; =0xffffffff
+; CHECK-CMPBR-NEXT:    cbge w0, w8, LBB13_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB13_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sge_m1_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmn w0, #1
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB13_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB13_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sge i32 %a, -1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sge_63_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sge_63_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbgt w0, #62, LBB14_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB14_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sge_63_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #63
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB14_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB14_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sge i32 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sge_64_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: sge_64_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #64 ; =0x40
+; CHECK-CMPBR-NEXT:    cbge w0, w8, LBB15_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB15_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sge_64_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #64
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB15_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB15_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sge i32 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ult_0_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ult_0_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhi wzr, w0, LBB16_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB16_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ult_0_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #0
+; CHECK-NO-CMPBR-NEXT:    b.lo LBB16_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB16_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ult i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ult_63_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ult_63_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblo w0, #63, LBB17_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB17_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ult_63_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #62
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB17_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB17_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ult i32 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ult_64_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ult_64_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #63 ; =0x3f
+; CHECK-CMPBR-NEXT:    cbhs w8, w0, LBB18_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB18_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ult_64_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #63
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB18_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB18_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ult i32 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ule_0_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ule_0_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbz w0, LBB19_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB19_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ule_0_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cbz w0, LBB19_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB19_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ule i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ule_63_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ule_63_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #63 ; =0x3f
+; CHECK-CMPBR-NEXT:    cbhs w8, w0, LBB20_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB20_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ule_63_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #63
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB20_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB20_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ule i32 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ule_64_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ule_64_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #64 ; =0x40
+; CHECK-CMPBR-NEXT:    cbhs w8, w0, LBB21_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB21_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ule_64_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #64
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB21_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB21_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ule i32 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ugt_0_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ugt_0_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbnz w0, LBB22_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB22_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ugt_0_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cbnz w0, LBB22_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB22_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ugt i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ugt_63_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ugt_63_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #64 ; =0x40
+; CHECK-CMPBR-NEXT:    cbhs w0, w8, LBB23_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB23_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ugt_63_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #64
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB23_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB23_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ugt i32 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ugt_64_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ugt_64_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #65 ; =0x41
+; CHECK-CMPBR-NEXT:    cbhs w0, w8, LBB24_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB24_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ugt_64_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #65
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB24_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB24_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ugt i32 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @uge_0_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: uge_0_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhs w0, wzr, LBB25_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB25_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: uge_0_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #0
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB25_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB25_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp uge i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @uge_63_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: uge_63_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhi w0, #62, LBB26_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB26_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: uge_63_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #63
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB26_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB26_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp uge i32 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @uge_64_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: uge_64_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #64 ; =0x40
+; CHECK-CMPBR-NEXT:    cbhs w0, w8, LBB27_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB27_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: uge_64_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #64
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB27_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB27_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp uge i32 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @eq_0_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: eq_0_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbz w0, LBB28_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB28_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: eq_0_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cbz w0, LBB28_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB28_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp eq i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @eq_m1_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: eq_m1_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #-1 ; =0xffffffff
+; CHECK-CMPBR-NEXT:    cbeq w0, w8, LBB29_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB29_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: eq_m1_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmn w0, #1
+; CHECK-NO-CMPBR-NEXT:    b.eq LBB29_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB29_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp eq i32 %a, -1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @eq_63_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: eq_63_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbeq w0, #63, LBB30_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB30_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: eq_63_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #63
+; CHECK-NO-CMPBR-NEXT:    b.eq LBB30_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB30_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp eq i32 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @eq_64_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: eq_64_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #64 ; =0x40
+; CHECK-CMPBR-NEXT:    cbeq w0, w8, LBB31_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB31_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: eq_64_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #64
+; CHECK-NO-CMPBR-NEXT:    b.eq LBB31_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB31_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp eq i32 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ne_0_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ne_0_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbnz w0, LBB32_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB32_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ne_0_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cbnz w0, LBB32_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB32_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ne i32 %a, 0
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ne_m1_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ne_m1_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #-1 ; =0xffffffff
+; CHECK-CMPBR-NEXT:    cbne w0, w8, LBB33_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB33_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ne_m1_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmn w0, #1
+; CHECK-NO-CMPBR-NEXT:    b.ne LBB33_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB33_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ne i32 %a, -1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ne_63_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ne_63_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbne w0, #63, LBB34_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB34_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ne_63_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #63
+; CHECK-NO-CMPBR-NEXT:    b.ne LBB34_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB34_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ne i32 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ne_64_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: ne_64_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #64 ; =0x40
+; CHECK-CMPBR-NEXT:    cbne w0, w8, LBB35_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB35_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ne_64_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #64
+; CHECK-NO-CMPBR-NEXT:    b.ne LBB35_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB35_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ne i32 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbge_out_of_upper_bound_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cbge_out_of_upper_bound_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #71 ; =0x47
+; CHECK-CMPBR-NEXT:    cbge w0, w8, LBB36_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB36_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbge_out_of_upper_bound_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #71
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB36_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB36_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sgt i32 %a, 70
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbge_out_of_lower_bound_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cbge_out_of_lower_bound_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #-10 ; =0xfffffff6
+; CHECK-CMPBR-NEXT:    cbge w0, w8, LBB37_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB37_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbge_out_of_lower_bound_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmn w0, #10
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB37_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB37_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sge i32 %a, -10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+; This should trigger a register swap.
+define void @cble_out_of_lower_bound_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cble_out_of_lower_bound_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #-10 ; =0xfffffff6
+; CHECK-CMPBR-NEXT:    cbhs w8, w0, LBB38_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB38_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cble_out_of_lower_bound_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmn w0, #10
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB38_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB38_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ule i32 %a, -10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @slt_m1_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: slt_m1_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov x8, #-2 ; =0xfffffffffffffffe
+; CHECK-CMPBR-NEXT:    cbge x8, x0, LBB39_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB39_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: slt_m1_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmn x0, #2
+; CHECK-NO-CMPBR-NEXT:    b.le LBB39_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB39_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp slt i64 %a, -1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @sle_64_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: sle_64_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #64 ; =0x40
+; CHECK-CMPBR-NEXT:    cbge x8, x0, LBB40_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB40_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: sle_64_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #64
+; CHECK-NO-CMPBR-NEXT:    b.le LBB40_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB40_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sle i64 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ult_63_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: ult_63_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblo x0, #63, LBB41_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB41_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ult_63_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #62
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB41_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB41_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ult i64 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @uge_64_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: uge_64_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov w8, #64 ; =0x40
+; CHECK-CMPBR-NEXT:    cbhs x0, x8, LBB42_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB42_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: uge_64_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #64
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB42_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB42_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp uge i64 %a, 64
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @eq_m1_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: eq_m1_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    mov x8, #-1 ; =0xffffffffffffffff
+; CHECK-CMPBR-NEXT:    cbeq x0, x8, LBB43_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB43_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: eq_m1_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmn x0, #1
+; CHECK-NO-CMPBR-NEXT:    b.eq LBB43_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB43_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp eq i64 %a, -1
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @ne_63_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: ne_63_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbne x0, #63, LBB44_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB44_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: ne_63_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #63
+; CHECK-NO-CMPBR-NEXT:    b.ne LBB44_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB44_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ne i64 %a, 63
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}

diff  --git a/llvm/test/CodeGen/AArch64/cmpbr-reg-imm.ll b/llvm/test/CodeGen/AArch64/cmpbr-reg-imm.ll
new file mode 100644
index 0000000000000..ad778181bcf9b
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/cmpbr-reg-imm.ll
@@ -0,0 +1,583 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple arm64-apple-ios -mattr +cmpbr -verify-machineinstrs -o - < %s | FileCheck %s --check-prefix=CHECK-CMPBR
+; RUN: llc -mtriple arm64-apple-ios -mattr -cmpbr -verify-machineinstrs -o - < %s | FileCheck %s --check-prefix=CHECK-NO-CMPBR
+
+define void @cbgt_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cbgt_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbgt w0, #10, LBB0_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB0_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbgt_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #11
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB0_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB0_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sgt i32 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cblt_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cblt_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblt w0, #10, LBB1_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB1_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cblt_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #9
+; CHECK-NO-CMPBR-NEXT:    b.le LBB1_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB1_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp slt i32 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbhi_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cbhi_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhi w0, #10, LBB2_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB2_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbhi_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #11
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB2_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB2_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ugt i32 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cblo_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cblo_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblo w0, #10, LBB3_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB3_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cblo_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #9
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB3_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB3_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ult i32 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbeq_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cbeq_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbeq w0, #10, LBB4_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB4_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbeq_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #10
+; CHECK-NO-CMPBR-NEXT:    b.eq LBB4_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB4_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp eq i32 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbne_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cbne_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbne w0, #10, LBB5_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB5_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbne_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #10
+; CHECK-NO-CMPBR-NEXT:    b.ne LBB5_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB5_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ne i32 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbge_gt_dec_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cbge_gt_dec_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbgt w0, #9, LBB6_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB6_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbge_gt_dec_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #10
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB6_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB6_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sge i32 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbhs_hi_dec_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cbhs_hi_dec_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhi w0, #9, LBB7_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB7_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbhs_hi_dec_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #10
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB7_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB7_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp uge i32 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cble_lt_inc_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cble_lt_inc_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblt w0, #11, LBB8_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB8_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cble_lt_inc_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #10
+; CHECK-NO-CMPBR-NEXT:    b.le LBB8_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB8_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sle i32 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbls_lo_inc_i32(i32 %a)  {
+; CHECK-CMPBR-LABEL: cbls_lo_inc_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblo w0, #11, LBB9_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB9_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbls_lo_inc_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, #10
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB9_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB9_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ule i32 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbgt_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: cbgt_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbgt x0, #10, LBB10_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB10_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbgt_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #11
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB10_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB10_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sgt i64 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cblt_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: cblt_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblt x0, #10, LBB11_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB11_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cblt_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #9
+; CHECK-NO-CMPBR-NEXT:    b.le LBB11_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB11_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp slt i64 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbhi_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: cbhi_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhi x0, #10, LBB12_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB12_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbhi_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #11
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB12_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB12_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ugt i64 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cblo_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: cblo_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblo x0, #10, LBB13_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB13_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cblo_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #9
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB13_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB13_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ult i64 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbeq_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: cbeq_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbeq x0, #10, LBB14_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB14_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbeq_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #10
+; CHECK-NO-CMPBR-NEXT:    b.eq LBB14_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB14_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp eq i64 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbne_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: cbne_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbne x0, #10, LBB15_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB15_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbne_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #10
+; CHECK-NO-CMPBR-NEXT:    b.ne LBB15_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB15_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ne i64 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbge_gt_dec_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: cbge_gt_dec_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbgt x0, #9, LBB16_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB16_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbge_gt_dec_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #10
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB16_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB16_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sge i64 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbhs_hi_dec_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: cbhs_hi_dec_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhi x0, #9, LBB17_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB17_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbhs_hi_dec_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #10
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB17_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB17_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp uge i64 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cble_lt_inc_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: cble_lt_inc_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblt x0, #11, LBB18_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB18_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cble_lt_inc_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #10
+; CHECK-NO-CMPBR-NEXT:    b.le LBB18_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB18_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sle i64 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbls_lo_inc_i64(i64 %a)  {
+; CHECK-CMPBR-LABEL: cbls_lo_inc_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cblo x0, #11, LBB19_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB19_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbls_lo_inc_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, #10
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB19_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB19_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ule i64 %a, 10
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}

diff  --git a/llvm/test/CodeGen/AArch64/cmpbr-reg-reg.ll b/llvm/test/CodeGen/AArch64/cmpbr-reg-reg.ll
new file mode 100644
index 0000000000000..9e95434564f02
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/cmpbr-reg-reg.ll
@@ -0,0 +1,586 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple arm64-apple-ios -mattr +cmpbr -verify-machineinstrs -o - < %s | FileCheck %s --check-prefix=CHECK-CMPBR
+; RUN: llc -mtriple arm64-apple-ios -mattr -cmpbr -verify-machineinstrs -o - < %s | FileCheck %s --check-prefix=CHECK-NO-CMPBR
+
+
+define void @cbgt_i32(i32 %a, i32 %b)  {
+; CHECK-CMPBR-LABEL: cbgt_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbgt w0, w1, LBB0_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB0_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbgt_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, w1
+; CHECK-NO-CMPBR-NEXT:    b.gt LBB0_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB0_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sgt i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbge_i32(i32 %a, i32 %b)  {
+; CHECK-CMPBR-LABEL: cbge_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbge w0, w1, LBB1_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB1_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbge_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, w1
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB1_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB1_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sge i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+
+define void @cbhi_i32(i32 %a, i32 %b)  {
+; CHECK-CMPBR-LABEL: cbhi_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhi w0, w1, LBB2_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB2_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbhi_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, w1
+; CHECK-NO-CMPBR-NEXT:    b.hi LBB2_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB2_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ugt i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbhs_i32(i32 %a, i32 %b)  {
+; CHECK-CMPBR-LABEL: cbhs_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhs w0, w1, LBB3_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB3_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbhs_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, w1
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB3_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB3_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp uge i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbeq_i32(i32 %a, i32 %b)  {
+; CHECK-CMPBR-LABEL: cbeq_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbeq w0, w1, LBB4_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB4_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbeq_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, w1
+; CHECK-NO-CMPBR-NEXT:    b.eq LBB4_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB4_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp eq i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbne_i32(i32 %a, i32 %b)  {
+; CHECK-CMPBR-LABEL: cbne_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbne w0, w1, LBB5_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB5_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbne_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, w1
+; CHECK-NO-CMPBR-NEXT:    b.ne LBB5_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB5_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ne i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cble_ge_swap_i32(i32 %a, i32 %b)  {
+; CHECK-CMPBR-LABEL: cble_ge_swap_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbge w1, w0, LBB6_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB6_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cble_ge_swap_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, w1
+; CHECK-NO-CMPBR-NEXT:    b.le LBB6_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB6_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sle i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cblo_hi_swap_i32(i32 %a, i32 %b)  {
+; CHECK-CMPBR-LABEL: cblo_hi_swap_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhi w1, w0, LBB7_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB7_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cblo_hi_swap_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, w1
+; CHECK-NO-CMPBR-NEXT:    b.lo LBB7_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB7_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ult i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbls_hs_swap_i32(i32 %a, i32 %b)  {
+; CHECK-CMPBR-LABEL: cbls_hs_swap_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhs w1, w0, LBB8_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB8_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbls_hs_swap_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, w1
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB8_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB8_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ule i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cblt_gt_swap_i32(i32 %a, i32 %b)  {
+; CHECK-CMPBR-LABEL: cblt_gt_swap_i32:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbgt w1, w0, LBB9_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB9_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cblt_gt_swap_i32:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp w0, w1
+; CHECK-NO-CMPBR-NEXT:    b.lt LBB9_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB9_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp slt i32 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbgt_i64(i64 %a, i64 %b)  {
+; CHECK-CMPBR-LABEL: cbgt_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbgt x0, x1, LBB10_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB10_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbgt_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, x1
+; CHECK-NO-CMPBR-NEXT:    b.gt LBB10_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB10_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sgt i64 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbge_i64(i64 %a, i64 %b)  {
+; CHECK-CMPBR-LABEL: cbge_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbge x0, x1, LBB11_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB11_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbge_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, x1
+; CHECK-NO-CMPBR-NEXT:    b.ge LBB11_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB11_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sge i64 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+
+define void @cbhi_i64(i64 %a, i64 %b)  {
+; CHECK-CMPBR-LABEL: cbhi_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhi x0, x1, LBB12_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB12_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbhi_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, x1
+; CHECK-NO-CMPBR-NEXT:    b.hi LBB12_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB12_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ugt i64 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbhs_i64(i64 %a, i64 %b)  {
+; CHECK-CMPBR-LABEL: cbhs_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhs x0, x1, LBB13_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB13_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbhs_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, x1
+; CHECK-NO-CMPBR-NEXT:    b.hs LBB13_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB13_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp uge i64 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbeq_i64(i64 %a, i64 %b)  {
+; CHECK-CMPBR-LABEL: cbeq_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbeq x0, x1, LBB14_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB14_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbeq_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, x1
+; CHECK-NO-CMPBR-NEXT:    b.eq LBB14_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB14_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp eq i64 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbne_i64(i64 %a, i64 %b)  {
+; CHECK-CMPBR-LABEL: cbne_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbne x0, x1, LBB15_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB15_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbne_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, x1
+; CHECK-NO-CMPBR-NEXT:    b.ne LBB15_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB15_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ne i64 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cble_ge_swap_i64(i64 %a, i64 %b)  {
+; CHECK-CMPBR-LABEL: cble_ge_swap_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbge x1, x0, LBB16_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB16_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cble_ge_swap_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, x1
+; CHECK-NO-CMPBR-NEXT:    b.le LBB16_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB16_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp sle i64 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cblo_hi_swap_i64(i64 %a, i64 %b)  {
+; CHECK-CMPBR-LABEL: cblo_hi_swap_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhi x1, x0, LBB17_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB17_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cblo_hi_swap_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, x1
+; CHECK-NO-CMPBR-NEXT:    b.lo LBB17_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB17_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ult i64 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cbls_hs_swap_i64(i64 %a, i64 %b)  {
+; CHECK-CMPBR-LABEL: cbls_hs_swap_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbhs x1, x0, LBB18_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB18_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cbls_hs_swap_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, x1
+; CHECK-NO-CMPBR-NEXT:    b.ls LBB18_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB18_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp ule i64 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}
+
+define void @cblt_gt_swap_i64(i64 %a, i64 %b)  {
+; CHECK-CMPBR-LABEL: cblt_gt_swap_i64:
+; CHECK-CMPBR:       ; %bb.0: ; %entry
+; CHECK-CMPBR-NEXT:    cbgt x1, x0, LBB19_2
+; CHECK-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-CMPBR-NEXT:    ret
+; CHECK-CMPBR-NEXT:  LBB19_2: ; %if.then
+; CHECK-CMPBR-NEXT:    brk #0x1
+;
+; CHECK-NO-CMPBR-LABEL: cblt_gt_swap_i64:
+; CHECK-NO-CMPBR:       ; %bb.0: ; %entry
+; CHECK-NO-CMPBR-NEXT:    cmp x0, x1
+; CHECK-NO-CMPBR-NEXT:    b.lt LBB19_2
+; CHECK-NO-CMPBR-NEXT:  ; %bb.1: ; %if.end
+; CHECK-NO-CMPBR-NEXT:    ret
+; CHECK-NO-CMPBR-NEXT:  LBB19_2: ; %if.then
+; CHECK-NO-CMPBR-NEXT:    brk #0x1
+entry:
+  %cmp = icmp slt i64 %a, %b
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  tail call void @llvm.trap()
+  unreachable
+
+if.end:
+  ret void
+}


        


More information about the llvm-commits mailing list