Skip to content

[RISCV] Add isel patterns for generating Xqcibi branch instructions #139872

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 16, 2025

Conversation

svs-quic
Copy link
Contributor

Add ISEL patterns for generating the Xqcibi branch immediate instructions. Similar to #135771 adds new CondCodes for the various branch instructions and uses them to return the appropriate instruction.

@llvmbot
Copy link
Member

llvmbot commented May 14, 2025

@llvm/pr-subscribers-backend-risc-v

Author: Sudharsan Veeravalli (svs-quic)

Changes

Add ISEL patterns for generating the Xqcibi branch immediate instructions. Similar to #135771 adds new CondCodes for the various branch instructions and uses them to return the appropriate instruction.


Patch is 22.94 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/139872.diff

5 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+22)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+96)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.h (+12)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+92)
  • (added) llvm/test/CodeGen/RISCV/xqcibi.ll (+359)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index c01496c9a7f3a..282b848c9a330 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -2389,6 +2389,8 @@ static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS,
 
   if (auto *RHSC = dyn_cast<ConstantSDNode>(RHS)) {
     int64_t C = RHSC->getSExtValue();
+    const RISCVSubtarget &Subtarget =
+        DAG.getMachineFunction().getSubtarget<RISCVSubtarget>();
     switch (CC) {
     default: break;
     case ISD::SETGT:
@@ -2398,6 +2400,13 @@ static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS,
         CC = ISD::SETGE;
         return;
       }
+      if (Subtarget.hasVendorXqcibi() && isInt<16>(C + 1)) {
+        // We have a branch immediate instruction for SETGE but not SETGT.
+        // Convert X > C to X >= C + 1, if (C + 1) is a 16-bit signed immediate.
+        RHS = DAG.getSignedConstant(C + 1, DL, RHS.getValueType());
+        CC = ISD::SETGE;
+        return;
+      }
       break;
     case ISD::SETLT:
       // Convert X < 1 to 0 >= X.
@@ -2408,6 +2417,15 @@ static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS,
         return;
       }
       break;
+    case ISD::SETUGT:
+      if (Subtarget.hasVendorXqcibi() && isInt<16>(C + 1) && C != -1) {
+        // We have a branch immediate instruction for SETUGE but not SETUGT.
+        // Convert X > C to X >= C + 1, if (C + 1) is a 16-bit signed immediate.
+        RHS = DAG.getSignedConstant(C + 1, DL, RHS.getValueType());
+        CC = ISD::SETUGE;
+        return;
+      }
+      break;
     }
   }
 
@@ -21203,6 +21221,10 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
     return emitReadCounterWidePseudo(MI, BB);
   case RISCV::Select_GPR_Using_CC_GPR:
   case RISCV::Select_GPR_Using_CC_Imm:
+  case RISCV::Select_GPR_Using_CC_Simm5NonZero:
+  case RISCV::Select_GPR_Using_CC_Uimm5NonZero:
+  case RISCV::Select_GPR_Using_CC_Simm16NonZero:
+  case RISCV::Select_GPR_Using_CC_Uimm16NonZero:
   case RISCV::Select_FPR16_Using_CC_GPR:
   case RISCV::Select_FPR16INX_Using_CC_GPR:
   case RISCV::Select_FPR32_Using_CC_GPR:
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index f181c1e137545..a4f33546b01ac 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -993,6 +993,30 @@ static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc) {
     return RISCVCC::COND_CV_BEQIMM;
   case RISCV::CV_BNEIMM:
     return RISCVCC::COND_CV_BNEIMM;
+  case RISCV::QC_BEQI:
+    return RISCVCC::COND_QC_BEQI;
+  case RISCV::QC_E_BEQI:
+    return RISCVCC::COND_QC_E_BEQI;
+  case RISCV::QC_BNEI:
+    return RISCVCC::COND_QC_BNEI;
+  case RISCV::QC_E_BNEI:
+    return RISCVCC::COND_QC_E_BNEI;
+  case RISCV::QC_BLTI:
+    return RISCVCC::COND_QC_BLTI;
+  case RISCV::QC_E_BLTI:
+    return RISCVCC::COND_QC_E_BLTI;
+  case RISCV::QC_BGEI:
+    return RISCVCC::COND_QC_BGEI;
+  case RISCV::QC_E_BGEI:
+    return RISCVCC::COND_QC_E_BGEI;
+  case RISCV::QC_BLTUI:
+    return RISCVCC::COND_QC_BLTUI;
+  case RISCV::QC_E_BLTUI:
+    return RISCVCC::COND_QC_E_BLTUI;
+  case RISCV::QC_BGEUI:
+    return RISCVCC::COND_QC_BGEUI;
+  case RISCV::QC_E_BGEUI:
+    return RISCVCC::COND_QC_E_BGEUI;
   }
 }
 
@@ -1050,6 +1074,30 @@ unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC) {
     return RISCV::CV_BEQIMM;
   case RISCVCC::COND_CV_BNEIMM:
     return RISCV::CV_BNEIMM;
+  case RISCVCC::COND_QC_BEQI:
+    return RISCV::QC_BEQI;
+  case RISCVCC::COND_QC_E_BEQI:
+    return RISCV::QC_E_BEQI;
+  case RISCVCC::COND_QC_BNEI:
+    return RISCV::QC_BNEI;
+  case RISCVCC::COND_QC_E_BNEI:
+    return RISCV::QC_E_BNEI;
+  case RISCVCC::COND_QC_BLTI:
+    return RISCV::QC_BLTI;
+  case RISCVCC::COND_QC_E_BLTI:
+    return RISCV::QC_E_BLTI;
+  case RISCVCC::COND_QC_BGEI:
+    return RISCV::QC_BGEI;
+  case RISCVCC::COND_QC_E_BGEI:
+    return RISCV::QC_E_BGEI;
+  case RISCVCC::COND_QC_BLTUI:
+    return RISCV::QC_BLTUI;
+  case RISCVCC::COND_QC_E_BLTUI:
+    return RISCV::QC_E_BLTUI;
+  case RISCVCC::COND_QC_BGEUI:
+    return RISCV::QC_BGEUI;
+  case RISCVCC::COND_QC_E_BGEUI:
+    return RISCV::QC_E_BGEUI;
   }
 }
 
@@ -1077,6 +1125,30 @@ RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
     return RISCVCC::COND_CV_BNEIMM;
   case RISCVCC::COND_CV_BNEIMM:
     return RISCVCC::COND_CV_BEQIMM;
+  case RISCVCC::COND_QC_BEQI:
+    return RISCVCC::COND_QC_BNEI;
+  case RISCVCC::COND_QC_E_BEQI:
+    return RISCVCC::COND_QC_E_BNEI;
+  case RISCVCC::COND_QC_BNEI:
+    return RISCVCC::COND_QC_BEQI;
+  case RISCVCC::COND_QC_E_BNEI:
+    return RISCVCC::COND_QC_E_BEQI;
+  case RISCVCC::COND_QC_BLTI:
+    return RISCVCC::COND_QC_BGEI;
+  case RISCVCC::COND_QC_E_BLTI:
+    return RISCVCC::COND_QC_E_BGEI;
+  case RISCVCC::COND_QC_BGEI:
+    return RISCVCC::COND_QC_BLTI;
+  case RISCVCC::COND_QC_E_BGEI:
+    return RISCVCC::COND_QC_E_BLTI;
+  case RISCVCC::COND_QC_BLTUI:
+    return RISCVCC::COND_QC_BGEUI;
+  case RISCVCC::COND_QC_E_BLTUI:
+    return RISCVCC::COND_QC_E_BGEUI;
+  case RISCVCC::COND_QC_BGEUI:
+    return RISCVCC::COND_QC_BLTUI;
+  case RISCVCC::COND_QC_E_BGEUI:
+    return RISCVCC::COND_QC_E_BLTUI;
   }
 }
 
@@ -1452,6 +1524,18 @@ bool RISCVInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
   case RISCV::BGEU:
   case RISCV::CV_BEQIMM:
   case RISCV::CV_BNEIMM:
+  case RISCV::QC_BEQI:
+  case RISCV::QC_BNEI:
+  case RISCV::QC_BGEI:
+  case RISCV::QC_BLTI:
+  case RISCV::QC_BLTUI:
+  case RISCV::QC_BGEUI:
+  case RISCV::QC_E_BEQI:
+  case RISCV::QC_E_BNEI:
+  case RISCV::QC_E_BGEI:
+  case RISCV::QC_E_BLTI:
+  case RISCV::QC_E_BLTUI:
+  case RISCV::QC_E_BGEUI:
     return isIntN(13, BrOffset);
   case RISCV::JAL:
   case RISCV::PseudoBR:
@@ -2633,6 +2717,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
         case RISCVOp::OPERAND_UIMM5_LSB0:
           Ok = isShiftedUInt<4, 1>(Imm);
           break;
+        case RISCVOp::OPERAND_UIMM5_NONZERO:
+          Ok = isUInt<5>(Imm) && (Imm != 0);
+          break;
         case RISCVOp::OPERAND_UIMM6_LSB0:
           Ok = isShiftedUInt<5, 1>(Imm);
           break;
@@ -2660,6 +2747,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
         case RISCVOp::OPERAND_UIMM10_LSB00_NONZERO:
           Ok = isShiftedUInt<8, 2>(Imm) && (Imm != 0);
           break;
+        case RISCVOp::OPERAND_UIMM16_NONZERO:
+          Ok = isUInt<16>(Imm) && (Imm != 0);
+          break;
         case RISCVOp::OPERAND_ZERO:
           Ok = Imm == 0;
           break;
@@ -2679,6 +2769,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
         case RISCVOp::OPERAND_SIMM5_PLUS1:
           Ok = (isInt<5>(Imm) && Imm != -16) || Imm == 16;
           break;
+        case RISCVOp::OPERAND_SIMM5_NONZERO:
+          Ok = isInt<5>(Imm) && (Imm != 0);
+          break;
         case RISCVOp::OPERAND_SIMM6_NONZERO:
           Ok = Imm != 0 && isInt<6>(Imm);
           break;
@@ -2691,6 +2784,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
         case RISCVOp::OPERAND_SIMM12_LSB00000:
           Ok = isShiftedInt<7, 5>(Imm);
           break;
+        case RISCVOp::OPERAND_SIMM16_NONZERO:
+          Ok = isInt<16>(Imm) && (Imm != 0);
+          break;
         case RISCVOp::OPERAND_SIMM20_LI:
           Ok = isInt<20>(Imm);
           break;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index 1ec6eed82469e..b099acd81e995 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -43,6 +43,18 @@ enum CondCode {
   COND_GEU,
   COND_CV_BEQIMM,
   COND_CV_BNEIMM,
+  COND_QC_BEQI,
+  COND_QC_BNEI,
+  COND_QC_BLTI,
+  COND_QC_BGEI,
+  COND_QC_BLTUI,
+  COND_QC_BGEUI,
+  COND_QC_E_BEQI,
+  COND_QC_E_BNEI,
+  COND_QC_E_BLTI,
+  COND_QC_E_BGEI,
+  COND_QC_E_BLTUI,
+  COND_QC_E_BGEUI,
   COND_INVALID
 };
 
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 57c1e999ac366..5e8f8f2956dc0 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -188,6 +188,36 @@ def AddLike: PatFrags<(ops node:$A, node:$B),
 def AddShl : PatFrag<(ops node:$Ra, node:$Rb, node:$SH3),
                      (add node:$Ra, (shl node:$Rb, node:$SH3))>;
 
+def IntCCtoQCRISCVCC : SDNodeXForm<riscv_selectcc, [{
+  ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+  int64_t Imm = dyn_cast<ConstantSDNode>(N->getOperand(1))->getSExtValue();
+  RISCVCC::CondCode BrCC;
+  switch (CC) {
+  default:
+   report_fatal_error("Unexpected CondCode for Xqcibi branch instructions");
+  case ISD::SETEQ:
+    BrCC = isInt<5>(Imm) ? RISCVCC::COND_QC_BEQI :  RISCVCC::COND_QC_E_BEQI;
+    break;
+  case ISD::SETNE:
+    BrCC = isInt<5>(Imm) ? RISCVCC::COND_QC_BNEI :  RISCVCC::COND_QC_E_BNEI;
+    break;
+  case ISD::SETLT:
+    BrCC = isInt<5>(Imm) ? RISCVCC::COND_QC_BLTI :  RISCVCC::COND_QC_E_BLTI;
+    break;
+  case ISD::SETGE:
+    BrCC = isInt<5>(Imm) ? RISCVCC::COND_QC_BGEI :  RISCVCC::COND_QC_E_BGEI;
+    break;
+  case ISD::SETULT:
+    BrCC = isUInt<5>(Imm) ? RISCVCC::COND_QC_BLTUI :  RISCVCC::COND_QC_E_BLTUI;
+    break;
+  case ISD::SETUGE:
+    BrCC = isUInt<5>(Imm) ? RISCVCC::COND_QC_BGEUI :  RISCVCC::COND_QC_E_BGEUI;
+    break;
+  }
+  return CurDAG->getTargetConstant(BrCC, SDLoc(N), Subtarget->getXLenVT());
+}]>;
+
+
 //===----------------------------------------------------------------------===//
 // Instruction Formats
 //===----------------------------------------------------------------------===//
@@ -1288,6 +1318,36 @@ class QCScaledStPat<PatFrag StoreOp, RVInst Inst>
     : Pat<(StoreOp (i32 GPR:$rd), (AddShl (i32 GPRMem:$rs1), (i32 GPRNoX0:$rs2), uimm3:$shamt)),
           (Inst GPR:$rd, GPRMem:$rs1, GPRNoX0:$rs2, uimm3:$shamt)>;
 
+// Match `riscv_brcc` and lower to the appropriate XQCIBI branch instruction.
+class BcciPat<CondCode Cond, QCIBranchInst_rii Inst, DAGOperand InTyImm>
+    : Pat<(riscv_brcc (XLenVT GPRNoX0:$rs1), InTyImm:$rs2, Cond, bb:$imm12),
+          (Inst GPRNoX0:$rs1, InTyImm:$rs2, bare_simm13_lsb0:$imm12)>;
+
+class Bcci48Pat<CondCode Cond, QCIBranchInst48_rii Inst, DAGOperand InTyImm>
+    : Pat<(riscv_brcc (XLenVT GPRNoX0:$rs1), InTyImm:$rs2, Cond, bb:$imm12),
+          (Inst GPRNoX0:$rs1, InTyImm:$rs2, bare_simm13_lsb0:$imm12)>;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, usesCustomInserter = 1 in {
+  def Select_GPR_Using_CC_Simm5NonZero : Pseudo<(outs GPR:$dst),
+                                                (ins GPR:$lhs, simm5nonzero:$imm5,
+                                                 cond_code:$cc, GPR:$truev, GPR:$falsev), []>;
+  def Select_GPR_Using_CC_Uimm5NonZero : Pseudo<(outs GPR:$dst),
+                                                (ins GPR:$lhs, uimm5nonzero:$imm5,
+                                                 cond_code:$cc, GPR:$truev, GPR:$falsev), []>;
+  def Select_GPR_Using_CC_Simm16NonZero : Pseudo<(outs GPR:$dst),
+                                                 (ins GPR:$lhs, simm16nonzero:$imm16,
+                                                  cond_code:$cc, GPR:$truev, GPR:$falsev), []>;
+  def Select_GPR_Using_CC_Uimm16NonZero : Pseudo<(outs GPR:$dst),
+                                                 (ins GPR:$lhs, uimm16nonzero:$imm16,
+                                                  cond_code:$cc, GPR:$truev, GPR:$falsev), []>;
+}
+
+class SelectQCbi<CondCode Cond, DAGOperand InTyImm, Pseudo OpNode >
+    : Pat<(riscv_selectcc_frag:$cc (i32 GPR:$lhs), InTyImm:$Constant, Cond,
+                                   (i32 GPR:$truev), GPR:$falsev),
+          (OpNode GPR:$lhs, InTyImm:$Constant,
+           (IntCCtoQCRISCVCC $cc), GPR:$truev, GPR:$falsev)>;
+
 /// Simple arithmetic operations
 
 let Predicates = [HasVendorXqcilia, IsRV32] in {
@@ -1342,6 +1402,38 @@ def : PatGprNoX0GprNoX0<ushlsat, QC_SHLUSAT>;
 def : PatGprNoX0GprNoX0<sshlsat, QC_SHLSAT>;
 } // Predicates = [HasVendorXqcia, IsRV32]
 
+/// Branches
+
+let Predicates = [HasVendorXqcibi, IsRV32], AddedComplexity = 2 in {
+def : BcciPat<SETEQ, QC_BEQI, simm5nonzero>;
+def : BcciPat<SETNE, QC_BNEI, simm5nonzero>;
+def : BcciPat<SETLT, QC_BLTI, simm5nonzero>;
+def : BcciPat<SETGE, QC_BGEI, simm5nonzero>;
+def : BcciPat<SETULT, QC_BLTUI, uimm5nonzero>;
+def : BcciPat<SETUGE, QC_BGEUI, uimm5nonzero>;
+
+def : Bcci48Pat<SETEQ, QC_E_BEQI, simm16nonzero>;
+def : Bcci48Pat<SETNE, QC_E_BNEI, simm16nonzero>;
+def : Bcci48Pat<SETLT, QC_E_BLTI, simm16nonzero>;
+def : Bcci48Pat<SETGE, QC_E_BGEI, simm16nonzero>;
+def : Bcci48Pat<SETULT, QC_E_BLTUI, uimm16nonzero>;
+def : Bcci48Pat<SETUGE, QC_E_BGEUI, uimm16nonzero>;
+
+def : SelectQCbi<SETEQ, simm5nonzero, Select_GPR_Using_CC_Simm5NonZero>;
+def : SelectQCbi<SETNE, simm5nonzero, Select_GPR_Using_CC_Simm5NonZero>;
+def : SelectQCbi<SETLT, simm5nonzero, Select_GPR_Using_CC_Simm5NonZero>;
+def : SelectQCbi<SETGE, simm5nonzero, Select_GPR_Using_CC_Simm5NonZero>;
+def : SelectQCbi<SETULT, uimm5nonzero, Select_GPR_Using_CC_Uimm5NonZero>;
+def : SelectQCbi<SETUGE, uimm5nonzero, Select_GPR_Using_CC_Uimm5NonZero>;
+
+def : SelectQCbi<SETEQ, simm16nonzero, Select_GPR_Using_CC_Simm16NonZero>;
+def : SelectQCbi<SETNE, simm16nonzero, Select_GPR_Using_CC_Simm16NonZero>;
+def : SelectQCbi<SETLT, simm16nonzero, Select_GPR_Using_CC_Simm16NonZero>;
+def : SelectQCbi<SETGE, simm16nonzero, Select_GPR_Using_CC_Simm16NonZero>;
+def : SelectQCbi<SETULT, uimm16nonzero, Select_GPR_Using_CC_Uimm16NonZero>;
+def : SelectQCbi<SETUGE, uimm16nonzero, Select_GPR_Using_CC_Uimm16NonZero>;
+} // let Predicates = [HasVendorXqcibi, IsRV32], AddedComplexity = 2
+
 let Predicates = [HasVendorXqciint, IsRV32] in
 def : Pat<(riscv_mileaveret_glue), (QC_C_MILEAVERET)>;
 
diff --git a/llvm/test/CodeGen/RISCV/xqcibi.ll b/llvm/test/CodeGen/RISCV/xqcibi.ll
new file mode 100644
index 0000000000000..242012b5ad462
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xqcibi.ll
@@ -0,0 +1,359 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test that we are able to generate the Xqcibi instructions
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefixes=RV32I
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcibi -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefixes=RV32IXQCIBI
+
+define i32 @beqimm(i32 %a) {
+; RV32I-LABEL: beqimm:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    li a1, -16
+; RV32I-NEXT:    beq a0, a1, .LBB0_2
+; RV32I-NEXT:  # %bb.1: # %f
+; RV32I-NEXT:    li a0, 0
+; RV32I-NEXT:    ret
+; RV32I-NEXT:  .LBB0_2: # %t
+; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIBI-LABEL: beqimm:
+; RV32IXQCIBI:       # %bb.0:
+; RV32IXQCIBI-NEXT:    qc.beqi a0, -16, .LBB0_2
+; RV32IXQCIBI-NEXT:  # %bb.1: # %f
+; RV32IXQCIBI-NEXT:    li a0, 0
+; RV32IXQCIBI-NEXT:    ret
+; RV32IXQCIBI-NEXT:  .LBB0_2: # %t
+; RV32IXQCIBI-NEXT:    li a0, 1
+; RV32IXQCIBI-NEXT:    ret
+  %1 = icmp eq i32 %a, -16
+  br i1 %1, label %t, label %f, !prof !0
+f:
+  ret i32 0
+t:
+  ret i32 1
+}
+
+define i32 @bneimm(i32 %a) {
+; RV32I-LABEL: bneimm:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    li a1, 15
+; RV32I-NEXT:    bne a0, a1, .LBB1_2
+; RV32I-NEXT:  # %bb.1: # %f
+; RV32I-NEXT:    li a0, 0
+; RV32I-NEXT:    ret
+; RV32I-NEXT:  .LBB1_2: # %t
+; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIBI-LABEL: bneimm:
+; RV32IXQCIBI:       # %bb.0:
+; RV32IXQCIBI-NEXT:    qc.bnei a0, 15, .LBB1_2
+; RV32IXQCIBI-NEXT:  # %bb.1: # %f
+; RV32IXQCIBI-NEXT:    li a0, 0
+; RV32IXQCIBI-NEXT:    ret
+; RV32IXQCIBI-NEXT:  .LBB1_2: # %t
+; RV32IXQCIBI-NEXT:    li a0, 1
+; RV32IXQCIBI-NEXT:    ret
+  %1 = icmp ne i32 %a, 15
+  br i1 %1, label %t, label %f, !prof !0
+f:
+  ret i32 0
+t:
+  ret i32 1
+}
+
+define i32 @bltimm(i32 %a) {
+; RV32I-LABEL: bltimm:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    li a1, 5
+; RV32I-NEXT:    blt a0, a1, .LBB2_2
+; RV32I-NEXT:  # %bb.1: # %f
+; RV32I-NEXT:    li a0, 0
+; RV32I-NEXT:    ret
+; RV32I-NEXT:  .LBB2_2: # %t
+; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIBI-LABEL: bltimm:
+; RV32IXQCIBI:       # %bb.0:
+; RV32IXQCIBI-NEXT:    qc.blti a0, 5, .LBB2_2
+; RV32IXQCIBI-NEXT:  # %bb.1: # %f
+; RV32IXQCIBI-NEXT:    li a0, 0
+; RV32IXQCIBI-NEXT:    ret
+; RV32IXQCIBI-NEXT:  .LBB2_2: # %t
+; RV32IXQCIBI-NEXT:    li a0, 1
+; RV32IXQCIBI-NEXT:    ret
+  %1 = icmp slt i32 %a, 5
+  br i1 %1, label %t, label %f, !prof !0
+f:
+  ret i32 0
+t:
+  ret i32 1
+}
+
+define i32 @bgeimm(i32 %a) {
+; RV32I-LABEL: bgeimm:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    li a1, -6
+; RV32I-NEXT:    blt a1, a0, .LBB3_2
+; RV32I-NEXT:  # %bb.1: # %f
+; RV32I-NEXT:    li a0, 0
+; RV32I-NEXT:    ret
+; RV32I-NEXT:  .LBB3_2: # %t
+; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIBI-LABEL: bgeimm:
+; RV32IXQCIBI:       # %bb.0:
+; RV32IXQCIBI-NEXT:    qc.bgei a0, -5, .LBB3_2
+; RV32IXQCIBI-NEXT:  # %bb.1: # %f
+; RV32IXQCIBI-NEXT:    li a0, 0
+; RV32IXQCIBI-NEXT:    ret
+; RV32IXQCIBI-NEXT:  .LBB3_2: # %t
+; RV32IXQCIBI-NEXT:    li a0, 1
+; RV32IXQCIBI-NEXT:    ret
+  %1 = icmp sge i32 %a, -5
+  br i1 %1, label %t, label %f, !prof !0
+f:
+  ret i32 0
+t:
+  ret i32 1
+}
+
+define i32 @bltuimm(i32 %a) {
+; RV32I-LABEL: bltuimm:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    li a1, 31
+; RV32I-NEXT:    bltu a0, a1, .LBB4_2
+; RV32I-NEXT:  # %bb.1: # %f
+; RV32I-NEXT:    li a0, 0
+; RV32I-NEXT:    ret
+; RV32I-NEXT:  .LBB4_2: # %t
+; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIBI-LABEL: bltuimm:
+; RV32IXQCIBI:       # %bb.0:
+; RV32IXQCIBI-NEXT:    qc.bltui a0, 31, .LBB4_2
+; RV32IXQCIBI-NEXT:  # %bb.1: # %f
+; RV32IXQCIBI-NEXT:    li a0, 0
+; RV32IXQCIBI-NEXT:    ret
+; RV32IXQCIBI-NEXT:  .LBB4_2: # %t
+; RV32IXQCIBI-NEXT:    li a0, 1
+; RV32IXQCIBI-NEXT:    ret
+  %1 = icmp ult i32 %a, 31
+  br i1 %1, label %t, label %f, !prof !0
+f:
+  ret i32 0
+t:
+  ret i32 1
+}
+
+define i32 @bgeuimm(i32 %a) {
+; RV32I-LABEL: bgeuimm:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    li a1, 9
+; RV32I-NEXT:    bltu a1, a0, .LBB5_2
+; RV32I-NEXT:  # %bb.1: # %f
+; RV32I-NEXT:    li a0, 0
+; RV32I-NEXT:    ret
+; RV32I-NEXT:  .LBB5_2: # %t
+; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIBI-LABEL: bgeuimm:
+; RV32IXQCIBI:       # %bb.0:
+; RV32IXQCIBI-NEXT:    qc.bgeui a0, 10, .LBB5_2
+; RV32IXQCIBI-NEXT:  # %bb.1: # %f
+; RV32IXQCIBI-NEXT:    li a0, 0
+; RV32IXQCIBI-NEXT:    ret
+; RV32IXQCIBI-NEXT:  .LBB5_2: # %t
+; RV32IXQCIBI-NEXT:    li a0, 1
+; RV32IXQCIBI-NEXT:    ret
+  %1 = icmp uge i32 %a, 10
+  br i1 %1, label %t, label %f, !prof !0
+f:
+  ret i32 0
+t:
+  ret i32 1
+}
+
+define i32 @beqimm16(i32 %a) {
+; RV32I-LABEL: beqimm16:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a1, 1048568
+; RV32I-NEXT:    beq a0, a1, .LBB6_2
+; RV32I-NEXT:  # %bb.1: # %f
+; RV32I-NEXT:    li a0, 0
+; RV32I-NEXT:    ret
+; RV32I-NEXT:  .LBB6_2: # %t
+; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIBI-LABEL: beqimm16:
+; RV32IXQCIBI:       # %bb.0:
+; RV32IXQCIBI-NEXT:    qc.e.beqi a0, -32768, .LBB6_2
+; RV32IXQCIBI-NEXT:  # %bb.1: # %f
+; RV32IXQCIBI-NEXT:    li a0, 0
+; RV32IXQCIBI-NEXT:    ret
+; RV32IXQCIBI-NEXT:  .LBB6_2: # %t
+; RV32IXQCIBI-NEXT:    li a0, 1
+; RV32IXQCIBI-NEXT:    ret
+  %1 = icmp eq i32 %a, -32768
+  br i1 %1, label %t, label %f, !prof !0
+f:
+  ret i32 0
+t:
+  ret i32 1
+}
+
+define i32 @bneimm16(i32 %a) {
+; RV32I-LABEL: bneimm16:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a1, 8
+; RV32I-NEXT:    addi a1, a1, -1
+; RV32I-NEXT:    bne a0, a1, .LBB7_2
+; RV32I-NEXT:  # %bb.1: # %f
+; RV32I-NEXT:    li a0, 0
+; RV32I-NEXT:    ret
+; RV32I-NEXT:  .LBB7_2: # %t
+; RV32I-NEXT:    li a0, 1
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIBI-LABEL: bneimm16:
+; RV32IXQCIBI:       # %bb.0:
+; RV32IXQCIBI-NEXT:    qc.e.bnei a0, 32767, .LBB7_2
+; RV32IXQCIBI-NEXT:  # %bb.1: # %f
+; RV32IXQCIBI-NEXT:    li a0, 0
+; RV32IXQCIBI-NEXT:    ret
+; RV32IXQCIBI-NEXT:  .LBB7_2: # %t
+; RV32IXQCIBI-NEXT:    li a0, 1
+; RV32IXQCIBI-NEXT:    ret
+  %1 = icmp ne i32 %a, 32767
+  br i1 %1, label %t, label %f, !prof !0
+f:
+  ret i32 0
+t:
+  ret i32 1
+}
+
+define...
[truncated]

@svs-quic
Copy link
Contributor Author

@topperc do the changes look good to you?

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@tclin914 tclin914 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@svs-quic svs-quic merged commit dc9171a into llvm:main May 16, 2025
11 checks passed
@svs-quic svs-quic deleted the xqcibi_patterns branch May 16, 2025 03:15
tclin914 added a commit to tclin914/llvm-project that referenced this pull request Jun 21, 2025
…instructions

Similar to llvm#139872. This patch adds isel patterns to match
`riscv_brcc` and `riscv_selectcc_frag` to XAndesPerf branch instructions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants