[llvm] [RISCV][NFC] Prepare for Short Forward Branch of branches with immediates (PR #182456)

via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 20 01:25:27 PST 2026


https://github.com/hchandel updated https://github.com/llvm/llvm-project/pull/182456

>From 131ce22aee8e026397bc589e833aca1dcd5757b4 Mon Sep 17 00:00:00 2001
From: Harsh Chandel <hchandel at qti.qualcomm.com>
Date: Tue, 17 Feb 2026 18:04:58 +0530
Subject: [PATCH 1/2] [RISCV][NFC] Prepare for Short Forward Branch of branches
 with immediates

Change-Id: I36abc2bb682302ca66cc8c3eef3677f741b7255b
---
 .../Target/RISCV/MCTargetDesc/RISCVBaseInfo.h |   3 +-
 .../Target/RISCV/RISCVExpandPseudoInsts.cpp   |  41 +++++-
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp      | 119 ++++++++++++++++--
 llvm/lib/Target/RISCV/RISCVInstrInfo.h        |   1 +
 llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td    |  80 +++++++-----
 llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td   |   9 +-
 6 files changed, 203 insertions(+), 50 deletions(-)

diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index cda2f95bbef78..eae00fc9595ea 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -462,7 +462,8 @@ enum OperandType : unsigned {
   // instructions to represent a value that be passed as AVL to either vsetvli
   // or vsetivli.
   OPERAND_AVL,
-
+  OPERAND_SFBRHS,
+  OPERAND_BCC_OPCODE,
   OPERAND_VMASK,
 };
 } // namespace RISCVOp
diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
index 8376a9c2e2236..3efa07e6a206e 100644
--- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
@@ -217,13 +217,13 @@ bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,
   // We want to copy the "true" value when the condition is true which means
   // we need to invert the branch condition to jump over TrueBB when the
   // condition is false.
-  auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
-  CC = RISCVCC::getInverseBranchCondition(CC);
+
+  unsigned BranchOpCode = MI.getOperand(3).getImm();
 
   // Insert branch instruction.
-  BuildMI(MBB, MBBI, DL, TII->get(RISCVCC::getBrCond(CC)))
-      .addReg(MI.getOperand(1).getReg())
-      .addReg(MI.getOperand(2).getReg())
+  BuildMI(MBB, MBBI, DL, TII->get(BranchOpCode))
+      .add(MI.getOperand(1))
+      .add(MI.getOperand(2))
       .addMBB(MergeBB);
 
   Register DestReg = MI.getOperand(0).getReg();
@@ -345,7 +345,36 @@ bool RISCVExpandPseudo::expandCCOpToCMov(MachineBasicBlock &MBB,
       MI.getOperand(5).getReg() == RISCV::X0)
     return false;
 
-  auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
+  auto BCC = MI.getOperand(3).getImm();
+  auto CC = RISCVCC::COND_EQ;
+  switch (BCC) {
+  default:
+    llvm_unreachable("Unexpected branch opcode!");
+  case RISCV::BEQ: {
+    CC = RISCVCC::COND_NE;
+    break;
+  }
+  case RISCV::BNE: {
+    CC = RISCVCC::COND_EQ;
+    break;
+  }
+  case RISCV::BLT: {
+    CC = RISCVCC::COND_GE;
+    break;
+  }
+  case RISCV::BGE: {
+    CC = RISCVCC::COND_LT;
+    break;
+  }
+  case RISCV::BLTU: {
+    CC = RISCVCC::COND_GEU;
+    break;
+  }
+  case RISCV::BGEU: {
+    CC = RISCVCC::COND_LTU;
+    break;
+  }
+  }
 
   unsigned CMovOpcode, CMovIOpcode;
   switch (CC) {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index cf679d786ab61..6126b00fead6c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -970,10 +970,10 @@ MachineInstr *RISCVInstrInfo::foldMemoryOperandImpl(
                                   .add({MI.getOperand(1), MI.getOperand(2)});
 
   // Add condition code, inverting if necessary.
-  auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
+  auto BCC = MI.getOperand(3).getImm();
   if (!Invert)
-    CC = RISCVCC::getInverseBranchCondition(CC);
-  NewMI.addImm(CC);
+    BCC = RISCVCC::getInverseBranchOpcode(BCC);
+  NewMI.addImm(BCC);
 
   // Copy the false register.
   NewMI.add(FalseReg);
@@ -1286,6 +1286,49 @@ RISCVCC::CondCode RISCVCC::getInverseBranchCondition(RISCVCC::CondCode CC) {
   }
 }
 
+unsigned RISCVCC::getInverseBranchOpcode(unsigned CC) {
+  switch (CC) {
+  default:
+    llvm_unreachable("Unexpected condition code!");
+  case RISCV::BEQ:
+    return RISCV::BNE;
+  case RISCV::BNE:
+    return RISCV::BEQ;
+  case RISCV::BLT:
+    return RISCV::BGE;
+  case RISCV::BGE:
+    return RISCV::BLT;
+  case RISCV::BLTU:
+    return RISCV::BGEU;
+  case RISCV::BGEU:
+    return RISCV::BLTU;
+  case RISCV::QC_BEQI:
+    return RISCV::QC_BNEI;
+  case RISCV::QC_BNEI:
+    return RISCV::QC_BEQI;
+  case RISCV::QC_BLTI:
+    return RISCV::QC_BGEI;
+  case RISCV::QC_BGEI:
+    return RISCV::QC_BLTI;
+  case RISCV::QC_BLTUI:
+    return RISCV::QC_BGEUI;
+  case RISCV::QC_BGEUI:
+    return RISCV::QC_BLTUI;
+  case RISCV::QC_E_BEQI:
+    return RISCV::QC_E_BNEI;
+  case RISCV::QC_E_BNEI:
+    return RISCV::QC_E_BEQI;
+  case RISCV::QC_E_BLTI:
+    return RISCV::QC_E_BGEI;
+  case RISCV::QC_E_BGEI:
+    return RISCV::QC_E_BLTI;
+  case RISCV::QC_E_BLTUI:
+    return RISCV::QC_E_BGEUI;
+  case RISCV::QC_E_BGEUI:
+    return RISCV::QC_E_BLTUI;
+  }
+}
+
 bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
                                    MachineBasicBlock *&TBB,
                                    MachineBasicBlock *&FBB,
@@ -1958,10 +2001,10 @@ RISCVInstrInfo::optimizeSelect(MachineInstr &MI,
   NewMI.add(MI.getOperand(2));
 
   // Add condition code, inverting if necessary.
-  auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
+  unsigned BCCOpcode = MI.getOperand(3).getImm();
   if (Invert)
-    CC = RISCVCC::getInverseBranchCondition(CC);
-  NewMI.addImm(CC);
+    BCCOpcode = RISCVCC::getInverseBranchOpcode(BCCOpcode);
+  NewMI.addImm(BCCOpcode);
 
   // Copy the false register.
   NewMI.add(FalseReg);
@@ -2025,6 +2068,58 @@ unsigned RISCVInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
   case RISCV::PseudoMV_FPR32INX:
     // MV is always compressible to either c.mv or c.li rd, 0.
     return STI.hasStdExtZca() ? 2 : 4;
+  case RISCV::PseudoCCMOVGPRNoX0:
+    return get(MI.getOperand(3).getImm()).getSize() + 2;
+  case RISCV::PseudoCCMOVGPR:
+  case RISCV::PseudoCCADD:
+  case RISCV::PseudoCCSUB:
+  case RISCV::PseudoCCSLL:
+  case RISCV::PseudoCCSRL:
+  case RISCV::PseudoCCSRA:
+  case RISCV::PseudoCCAND:
+  case RISCV::PseudoCCOR:
+  case RISCV::PseudoCCXOR:
+  case RISCV::PseudoCCADDI:
+  case RISCV::PseudoCCANDI:
+  case RISCV::PseudoCCORI:
+  case RISCV::PseudoCCXORI:
+  case RISCV::PseudoCCLUI:
+  case RISCV::PseudoCCSLLI:
+  case RISCV::PseudoCCSRLI:
+  case RISCV::PseudoCCSRAI:
+  case RISCV::PseudoCCADDW:
+  case RISCV::PseudoCCSUBW:
+  case RISCV::PseudoCCSLLW:
+  case RISCV::PseudoCCSRLW:
+  case RISCV::PseudoCCSRAW:
+  case RISCV::PseudoCCADDIW:
+  case RISCV::PseudoCCSLLIW:
+  case RISCV::PseudoCCSRLIW:
+  case RISCV::PseudoCCSRAIW:
+  case RISCV::PseudoCCANDN:
+  case RISCV::PseudoCCORN:
+  case RISCV::PseudoCCXNOR:
+  case RISCV::PseudoCCMAX:
+  case RISCV::PseudoCCMIN:
+  case RISCV::PseudoCCMAXU:
+  case RISCV::PseudoCCMINU:
+  case RISCV::PseudoCCMUL:
+  case RISCV::PseudoCCLB:
+  case RISCV::PseudoCCLH:
+  case RISCV::PseudoCCLW:
+  case RISCV::PseudoCCLHU:
+  case RISCV::PseudoCCLBU:
+  case RISCV::PseudoCCLWU:
+  case RISCV::PseudoCCLD:
+  case RISCV::PseudoCCQC_LI:
+    return get(MI.getOperand(3).getImm()).getSize() + 4;
+  case RISCV::PseudoCCQC_E_LI:
+  case RISCV::PseudoCCQC_E_LB:
+  case RISCV::PseudoCCQC_E_LH:
+  case RISCV::PseudoCCQC_E_LW:
+  case RISCV::PseudoCCQC_E_LHU:
+  case RISCV::PseudoCCQC_E_LBU:
+    return get(MI.getOperand(3).getImm()).getSize() + 6;
   case TargetOpcode::STACKMAP:
     // The upper bound for a stackmap intrinsic is the full length of its shadow
     return StackMapOpers(&MI).getNumPatchBytes();
@@ -3198,6 +3293,12 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
         return false;
       }
       break;
+    case RISCVOp::OPERAND_SFBRHS:
+      if (!MO.isReg() && !MO.isImm()) {
+        ErrInfo = "Expected a register or immediate operand.";
+        return false;
+      }
+      break;
     }
   }
 
@@ -4258,10 +4359,10 @@ MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI,
   case RISCV::PseudoCCMOVGPRNoX0:
   case RISCV::PseudoCCMOVGPR: {
     // CCMOV can be commuted by inverting the condition.
-    auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
-    CC = RISCVCC::getInverseBranchCondition(CC);
+    auto bcc = MI.getOperand(3).getImm();
+    bcc = RISCVCC::getInverseBranchOpcode(bcc);
     auto &WorkingMI = cloneIfNew(MI);
-    WorkingMI.getOperand(3).setImm(CC);
+    WorkingMI.getOperand(3).setImm(bcc);
     return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI*/ false,
                                                    OpIdx1, OpIdx2);
   }
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index 05f97332a600f..fc42ac093a22c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -64,6 +64,7 @@ enum CondCode {
 };
 
 CondCode getInverseBranchCondition(CondCode);
+unsigned getInverseBranchOpcode(unsigned CC);
 unsigned getBrCond(CondCode CC, unsigned SelectOpc = 0);
 
 } // end of namespace RISCVCC
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
index b06b9c2847168..92ff89516ed26 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
@@ -10,108 +10,132 @@
 //
 //===----------------------------------------------------------------------===//
 
+// Represents the Opcode for a branch instruction, used by SFB pseudos
+def bcc_opcode : RISCVOp<i32> {
+  let OperandType = "OPERAND_BCC_OPCODE";
+}
+
+def SFBRHS : RegisterOperand<GPR> {
+  let OperandNamespace = "RISCVOp";
+  let OperandType = "OPERAND_SFBRHS";
+}
+
+// cond -> bcc_opcode
+def CCtoRISCVBCC : SDNodeXForm<cond, [{
+  ISD::CondCode CC = N->get();
+  RISCVCC::CondCode RvCC = getRISCVCCForIntCC(CC);
+  RvCC = RISCVCC::getInverseBranchCondition(RvCC);
+  unsigned BccOpcode = RISCVCC::getBrCond(RvCC);
+  return CurDAG->getTargetConstant(BccOpcode, SDLoc(N), MVT::i32);
+}]>;
+
+// cond_code -> bcc_opcode
+def RISCVCCtoRISCVBCC : SDNodeXForm<imm, [{
+  auto CCImm = cast<ConstantSDNode>(N)->getZExtValue();
+  auto RvCC = static_cast<RISCVCC::CondCode>(CCImm);
+  RvCC = RISCVCC::getInverseBranchCondition(RvCC);
+  unsigned BccOpcode = RISCVCC::getBrCond(RvCC);
+  return CurDAG->getTargetConstant(BccOpcode, SDLoc(N), MVT::i32);
+}]>;
+
+def cond_as_bcc_opcode : PatLeaf<(cond), [{}], CCtoRISCVBCC>;
+
 let Predicates = [HasShortForwardBranchIALU], isSelect = 1,
-    Constraints = "$dst = $falsev", isCommutable = 1, Size = 8 in {
+    Constraints = "$dst = $falsev", isCommutable = 1 in {
 // This instruction moves $truev to $dst when the condition is true. It will
 // be expanded to control flow in RISCVExpandPseudoInsts.
 def PseudoCCMOVGPR : Pseudo<(outs GPR:$dst),
-                            (ins GPR:$lhs, GPR:$rhs, cond_code:$cc,
+                            (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$bcc,
                              GPR:$falsev, GPR:$truev),
-                            [(set GPR:$dst,
-                              (riscv_selectcc (XLenVT GPR:$lhs), GPR:$rhs,
-                                              riscv_cond:$cc,
-                                              (XLenVT GPR:$truev),
-                                              GPR:$falsev))]>,
+                            []>,
                      Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp,
                             ReadSFBALU, ReadSFBALU]>;
 }
 
+let Predicates = [HasShortForwardBranchIALU] in
+def : Pat<(riscv_selectcc (XLenVT GPR:$lhs), GPR:$rhs, cond:$cc, (XLenVT GPR:$truev), GPR:$falsev),
+           (PseudoCCMOVGPR GPR:$lhs, GPR:$rhs, (CCtoRISCVBCC $cc), GPR:$falsev, GPR:$truev)>;
+
 // This should always expand to a branch+c.mv so the size is 6 or 4 if the
 // branch is compressible.
 let Predicates = [HasConditionalMoveFusion, NoShortForwardBranch],
-    Constraints = "$dst = $falsev", isCommutable = 1, Size = 6 in {
+    Constraints = "$dst = $falsev", isCommutable = 1 in {
 // This instruction moves $truev to $dst when the condition is true. It will
 // be expanded to control flow in RISCVExpandPseudoInsts.
 // We use GPRNoX0 because c.mv cannot encode X0.
 def PseudoCCMOVGPRNoX0 : Pseudo<(outs GPRNoX0:$dst),
-                                (ins GPR:$lhs, GPR:$rhs, cond_code:$cc,
+                                (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$bcc,
                                  GPRNoX0:$falsev, GPRNoX0:$truev),
-                                [(set GPRNoX0:$dst,
-                                  (riscv_selectcc (XLenVT GPR:$lhs), GPR:$rhs,
-                                                  riscv_cond:$cc,
-                                                  (XLenVT GPRNoX0:$truev),
-                                                  GPRNoX0:$falsev))]>,
+                                []>,
                          Sched<[]>;
 }
 
+let Predicates = [HasConditionalMoveFusion, NoShortForwardBranch] in
+def :Pat<(riscv_selectcc (XLenVT GPR:$lhs), GPR:$rhs, cond:$cc, (XLenVT GPRNoX0:$truev), GPRNoX0:$falsev),
+         (PseudoCCMOVGPRNoX0 GPR:$lhs, GPR:$rhs, (CCtoRISCVBCC $cc), GPRNoX0:$falsev, GPRNoX0:$truev)>;
+
 class SFBALU_rr
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, GPR:$rhs, cond_code:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   GPR:$rs2), []>,
       Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, ReadSFBALU,
              ReadSFBALU]> {
   let hasSideEffects = 0;
   let mayLoad = 0;
   let mayStore = 0;
-  let Size = 8;
   let Constraints = "$dst = $falsev";
 }
 
 class SFBALU_ri
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, GPR:$rhs, cond_code:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   simm12_lo:$imm), []>,
       Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, ReadSFBALU]> {
   let hasSideEffects = 0;
   let mayLoad = 0;
   let mayStore = 0;
-  let Size = 8;
   let Constraints = "$dst = $falsev";
 }
 
 class SFBLUI
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, GPR:$rhs, cond_code:$cc, GPR:$falsev,
+             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev,
                   uimm20_lui:$imm), []> {
   let hasSideEffects = 0;
   let mayLoad = 0;
   let mayStore = 0;
-  let Size = 8;
   let Constraints = "$dst = $falsev";
 }
 
 class SFBLoad
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, GPR:$rhs, cond_code:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   simm12_lo:$imm), []> {
   let hasSideEffects = 0;
   let mayLoad = 1;
   let mayStore = 0;
-  let Size = 8;
   let Constraints = "$dst = $falsev";
 }
 
 class SFBShift_ri
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, GPR:$rhs, cond_code:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   uimmlog2xlen:$imm), []>,
       Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, ReadSFBALU]> {
   let hasSideEffects = 0;
   let mayLoad = 0;
   let mayStore = 0;
-  let Size = 8;
   let Constraints = "$dst = $falsev";
 }
 
 class SFBShiftW_ri
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, GPR:$rhs, cond_code:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   uimm5:$imm), []>,
       Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, ReadSFBALU]> {
   let hasSideEffects = 0;
   let mayLoad = 0;
   let mayStore = 0;
-  let Size = 8;
   let Constraints = "$dst = $falsev";
 }
 
@@ -161,11 +185,11 @@ def PseudoCCXNOR : SFBALU_rr;
 
 let Predicates = [HasShortForwardBranchIALU] in
 def : Pat<(XLenVT (abs GPR:$rs1)),
-          (PseudoCCSUB (XLenVT GPR:$rs1), (XLenVT X0), /* COND_LT */ 2,
+          (PseudoCCSUB (XLenVT GPR:$rs1), (XLenVT X0), (RISCVCCtoRISCVBCC (i32 /* COND_LT */ 2)),
            (XLenVT GPR:$rs1), (XLenVT X0), (XLenVT GPR:$rs1))>;
 let Predicates = [HasShortForwardBranchIALU, IsRV64] in
 def : Pat<(sext_inreg (abs 33signbits_node:$rs1), i32),
-          (PseudoCCSUBW (i64 GPR:$rs1), (i64 X0), /* COND_LT */ 2,
+          (PseudoCCSUBW (i64 GPR:$rs1), (i64 X0), (RISCVCCtoRISCVBCC (i32 /* COND_LT */ 2)),
            (i64 GPR:$rs1), (i64 X0), (i64 GPR:$rs1))>;
 
 let Predicates = [HasShortForwardBranchIMinMax] in {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 6359d94de409e..44449d46e8545 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -838,34 +838,31 @@ class QCIRVInst48EJ<bits<2> func2, string opcodestr>
 
 class SFBQC_LI
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, GPR:$rhs, cond_code:$cc, GPR:$falsev,
+             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev,
                   simm20_li:$imm), []> {
   let hasSideEffects = 0;
   let mayLoad = 0;
   let mayStore = 0;
-  let Size = 8;
   let Constraints = "$dst = $falsev";
 }
 
 class SFBQC_E_LI
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, GPR:$rhs, cond_code:$cc, GPR:$falsev,
+             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev,
                   bare_simm32:$imm), []> {
   let hasSideEffects = 0;
   let mayLoad = 0;
   let mayStore = 0;
-  let Size = 10;
   let Constraints = "$dst = $falsev";
 }
 
 class SFBQCLoad
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, GPR:$rhs, cond_code:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   simm26:$imm), []> {
   let hasSideEffects = 0;
   let mayLoad = 1;
   let mayStore = 0;
-  let Size = 10;
   let Constraints = "$dst = $falsev";
 }
 

>From 12bc297ddfe68567f513641622b4ddcc75b537e7 Mon Sep 17 00:00:00 2001
From: Harsh Chandel <hchandel at qti.qualcomm.com>
Date: Fri, 20 Feb 2026 14:10:01 +0530
Subject: [PATCH 2/2] fixup! Add comments and do some changes

Change-Id: I0013c12f847468e91693affb50726415b9a1f3a6
---
 .../Target/RISCV/MCTargetDesc/RISCVBaseInfo.h |  7 ++-
 .../Target/RISCV/RISCVExpandPseudoInsts.cpp   | 50 ++++---------------
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp      | 12 +++--
 llvm/lib/Target/RISCV/RISCVInstrInfo.h        |  2 +-
 llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td    | 42 ++++++++--------
 llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td   |  6 +--
 6 files changed, 49 insertions(+), 70 deletions(-)

diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index eae00fc9595ea..464006f80647c 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -462,7 +462,12 @@ enum OperandType : unsigned {
   // instructions to represent a value that be passed as AVL to either vsetvli
   // or vsetivli.
   OPERAND_AVL,
-  OPERAND_SFBRHS,
+
+  // Operand is either a register or imm, this is used by short forward branch
+  // (SFB) pseudos to enable SFB with branches on reg-reg and reg-imm compares.
+  OPERAND_SFB_RHS,
+
+  // Operand is a branch opcode, this too is used by SFB pseudos.
   OPERAND_BCC_OPCODE,
   OPERAND_VMASK,
 };
diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
index 3efa07e6a206e..f706130d22e52 100644
--- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
@@ -216,7 +216,8 @@ bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,
 
   // We want to copy the "true" value when the condition is true which means
   // we need to invert the branch condition to jump over TrueBB when the
-  // condition is false.
+  // condition is false. We can directly use the branch opcode which has been
+  // inverted when SDNodeXform transforms were applied on it.
 
   unsigned BranchOpCode = MI.getOperand(3).getImm();
 
@@ -345,62 +346,33 @@ bool RISCVExpandPseudo::expandCCOpToCMov(MachineBasicBlock &MBB,
       MI.getOperand(5).getReg() == RISCV::X0)
     return false;
 
+  // Use branch opcode to select appropriate Xqcicm instruction
   auto BCC = MI.getOperand(3).getImm();
-  auto CC = RISCVCC::COND_EQ;
-  switch (BCC) {
-  default:
-    llvm_unreachable("Unexpected branch opcode!");
-  case RISCV::BEQ: {
-    CC = RISCVCC::COND_NE;
-    break;
-  }
-  case RISCV::BNE: {
-    CC = RISCVCC::COND_EQ;
-    break;
-  }
-  case RISCV::BLT: {
-    CC = RISCVCC::COND_GE;
-    break;
-  }
-  case RISCV::BGE: {
-    CC = RISCVCC::COND_LT;
-    break;
-  }
-  case RISCV::BLTU: {
-    CC = RISCVCC::COND_GEU;
-    break;
-  }
-  case RISCV::BGEU: {
-    CC = RISCVCC::COND_LTU;
-    break;
-  }
-  }
-
   unsigned CMovOpcode, CMovIOpcode;
-  switch (CC) {
+  switch (BCC) {
   default:
-    llvm_unreachable("Unhandled CC");
-  case RISCVCC::COND_EQ:
+    return false; // Unhandled branch opcodes
+  case RISCV::BNE:
     CMovOpcode = RISCV::QC_MVEQ;
     CMovIOpcode = RISCV::QC_MVEQI;
     break;
-  case RISCVCC::COND_NE:
+  case RISCV::BEQ:
     CMovOpcode = RISCV::QC_MVNE;
     CMovIOpcode = RISCV::QC_MVNEI;
     break;
-  case RISCVCC::COND_LT:
+  case RISCV::BGE:
     CMovOpcode = RISCV::QC_MVLT;
     CMovIOpcode = RISCV::QC_MVLTI;
     break;
-  case RISCVCC::COND_GE:
+  case RISCV::BLT:
     CMovOpcode = RISCV::QC_MVGE;
     CMovIOpcode = RISCV::QC_MVGEI;
     break;
-  case RISCVCC::COND_LTU:
+  case RISCV::BGEU:
     CMovOpcode = RISCV::QC_MVLTU;
     CMovIOpcode = RISCV::QC_MVLTUI;
     break;
-  case RISCVCC::COND_GEU:
+  case RISCV::BLTU:
     CMovOpcode = RISCV::QC_MVGEU;
     CMovIOpcode = RISCV::QC_MVGEUI;
     break;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 6126b00fead6c..7a1fcce7296d7 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -969,7 +969,7 @@ MachineInstr *RISCVInstrInfo::foldMemoryOperandImpl(
                                       MI.getDebugLoc(), get(PredOpc), DestReg)
                                   .add({MI.getOperand(1), MI.getOperand(2)});
 
-  // Add condition code, inverting if necessary.
+  // Add branch opcode, inverting if necessary.
   auto BCC = MI.getOperand(3).getImm();
   if (!Invert)
     BCC = RISCVCC::getInverseBranchOpcode(BCC);
@@ -1286,8 +1286,9 @@ RISCVCC::CondCode RISCVCC::getInverseBranchCondition(RISCVCC::CondCode CC) {
   }
 }
 
-unsigned RISCVCC::getInverseBranchOpcode(unsigned CC) {
-  switch (CC) {
+// Return inverse branch
+unsigned RISCVCC::getInverseBranchOpcode(unsigned BCC) {
+  switch (BCC) {
   default:
     llvm_unreachable("Unexpected condition code!");
   case RISCV::BEQ:
@@ -2000,7 +2001,7 @@ RISCVInstrInfo::optimizeSelect(MachineInstr &MI,
   NewMI.add(MI.getOperand(1));
   NewMI.add(MI.getOperand(2));
 
-  // Add condition code, inverting if necessary.
+  // Add branch opcode, inverting if necessary.
   unsigned BCCOpcode = MI.getOperand(3).getImm();
   if (Invert)
     BCCOpcode = RISCVCC::getInverseBranchOpcode(BCCOpcode);
@@ -2068,6 +2069,7 @@ unsigned RISCVInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
   case RISCV::PseudoMV_FPR32INX:
     // MV is always compressible to either c.mv or c.li rd, 0.
     return STI.hasStdExtZca() ? 2 : 4;
+  // Below cases are for short forward branch pseudos
   case RISCV::PseudoCCMOVGPRNoX0:
     return get(MI.getOperand(3).getImm()).getSize() + 2;
   case RISCV::PseudoCCMOVGPR:
@@ -3293,7 +3295,7 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
         return false;
       }
       break;
-    case RISCVOp::OPERAND_SFBRHS:
+    case RISCVOp::OPERAND_SFB_RHS:
       if (!MO.isReg() && !MO.isImm()) {
         ErrInfo = "Expected a register or immediate operand.";
         return false;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index fc42ac093a22c..4a8a8d8fa5c08 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -64,7 +64,7 @@ enum CondCode {
 };
 
 CondCode getInverseBranchCondition(CondCode);
-unsigned getInverseBranchOpcode(unsigned CC);
+unsigned getInverseBranchOpcode(unsigned BCC);
 unsigned getBrCond(CondCode CC, unsigned SelectOpc = 0);
 
 } // end of namespace RISCVCC
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
index 92ff89516ed26..abb8740414452 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
@@ -15,9 +15,9 @@ def bcc_opcode : RISCVOp<i32> {
   let OperandType = "OPERAND_BCC_OPCODE";
 }
 
-def SFBRHS : RegisterOperand<GPR> {
+def sfb_rhs : RegisterOperand<GPR> {
   let OperandNamespace = "RISCVOp";
-  let OperandType = "OPERAND_SFBRHS";
+  let OperandType = "OPERAND_SFB_RHS";
 }
 
 // cond -> bcc_opcode
@@ -29,23 +29,14 @@ def CCtoRISCVBCC : SDNodeXForm<cond, [{
   return CurDAG->getTargetConstant(BccOpcode, SDLoc(N), MVT::i32);
 }]>;
 
-// cond_code -> bcc_opcode
-def RISCVCCtoRISCVBCC : SDNodeXForm<imm, [{
-  auto CCImm = cast<ConstantSDNode>(N)->getZExtValue();
-  auto RvCC = static_cast<RISCVCC::CondCode>(CCImm);
-  RvCC = RISCVCC::getInverseBranchCondition(RvCC);
-  unsigned BccOpcode = RISCVCC::getBrCond(RvCC);
-  return CurDAG->getTargetConstant(BccOpcode, SDLoc(N), MVT::i32);
-}]>;
-
-def cond_as_bcc_opcode : PatLeaf<(cond), [{}], CCtoRISCVBCC>;
-
+// For each of the short forward branch pseudos, corresponding code for
+// getting correct size of the pseduo is needed in getInstSizeInBytes.
 let Predicates = [HasShortForwardBranchIALU], isSelect = 1,
     Constraints = "$dst = $falsev", isCommutable = 1 in {
 // This instruction moves $truev to $dst when the condition is true. It will
 // be expanded to control flow in RISCVExpandPseudoInsts.
 def PseudoCCMOVGPR : Pseudo<(outs GPR:$dst),
-                            (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$bcc,
+                            (ins GPR:$lhs, sfb_rhs:$rhs, bcc_opcode:$bcc,
                              GPR:$falsev, GPR:$truev),
                             []>,
                      Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp,
@@ -64,7 +55,7 @@ let Predicates = [HasConditionalMoveFusion, NoShortForwardBranch],
 // be expanded to control flow in RISCVExpandPseudoInsts.
 // We use GPRNoX0 because c.mv cannot encode X0.
 def PseudoCCMOVGPRNoX0 : Pseudo<(outs GPRNoX0:$dst),
-                                (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$bcc,
+                                (ins GPR:$lhs, sfb_rhs:$rhs, bcc_opcode:$bcc,
                                  GPRNoX0:$falsev, GPRNoX0:$truev),
                                 []>,
                          Sched<[]>;
@@ -76,7 +67,7 @@ def :Pat<(riscv_selectcc (XLenVT GPR:$lhs), GPR:$rhs, cond:$cc, (XLenVT GPRNoX0:
 
 class SFBALU_rr
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, sfb_rhs:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   GPR:$rs2), []>,
       Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, ReadSFBALU,
              ReadSFBALU]> {
@@ -88,7 +79,7 @@ class SFBALU_rr
 
 class SFBALU_ri
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, sfb_rhs:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   simm12_lo:$imm), []>,
       Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, ReadSFBALU]> {
   let hasSideEffects = 0;
@@ -99,7 +90,7 @@ class SFBALU_ri
 
 class SFBLUI
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev,
+             (ins GPR:$lhs, sfb_rhs:$rhs, bcc_opcode:$cc, GPR:$falsev,
                   uimm20_lui:$imm), []> {
   let hasSideEffects = 0;
   let mayLoad = 0;
@@ -109,7 +100,7 @@ class SFBLUI
 
 class SFBLoad
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, sfb_rhs:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   simm12_lo:$imm), []> {
   let hasSideEffects = 0;
   let mayLoad = 1;
@@ -119,7 +110,7 @@ class SFBLoad
 
 class SFBShift_ri
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, sfb_rhs:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   uimmlog2xlen:$imm), []>,
       Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, ReadSFBALU]> {
   let hasSideEffects = 0;
@@ -130,7 +121,7 @@ class SFBShift_ri
 
 class SFBShiftW_ri
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, sfb_rhs:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   uimm5:$imm), []>,
       Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU, ReadSFBALU]> {
   let hasSideEffects = 0;
@@ -183,6 +174,15 @@ def PseudoCCORN  : SFBALU_rr;
 def PseudoCCXNOR : SFBALU_rr;
 }
 
+// imm -> bcc_opcode
+def RISCVCCtoRISCVBCC : SDNodeXForm<imm, [{
+  auto CCImm = cast<ConstantSDNode>(N)->getZExtValue();
+  auto RvCC = static_cast<RISCVCC::CondCode>(CCImm);
+  RvCC = RISCVCC::getInverseBranchCondition(RvCC);
+  unsigned BccOpcode = RISCVCC::getBrCond(RvCC);
+  return CurDAG->getTargetConstant(BccOpcode, SDLoc(N), MVT::i32);
+}]>;
+
 let Predicates = [HasShortForwardBranchIALU] in
 def : Pat<(XLenVT (abs GPR:$rs1)),
           (PseudoCCSUB (XLenVT GPR:$rs1), (XLenVT X0), (RISCVCCtoRISCVBCC (i32 /* COND_LT */ 2)),
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 44449d46e8545..9e42111b2c773 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -838,7 +838,7 @@ class QCIRVInst48EJ<bits<2> func2, string opcodestr>
 
 class SFBQC_LI
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev,
+             (ins GPR:$lhs, sfb_rhs:$rhs, bcc_opcode:$cc, GPR:$falsev,
                   simm20_li:$imm), []> {
   let hasSideEffects = 0;
   let mayLoad = 0;
@@ -848,7 +848,7 @@ class SFBQC_LI
 
 class SFBQC_E_LI
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev,
+             (ins GPR:$lhs, sfb_rhs:$rhs, bcc_opcode:$cc, GPR:$falsev,
                   bare_simm32:$imm), []> {
   let hasSideEffects = 0;
   let mayLoad = 0;
@@ -858,7 +858,7 @@ class SFBQC_E_LI
 
 class SFBQCLoad
     : Pseudo<(outs GPR:$dst),
-             (ins GPR:$lhs, SFBRHS:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
+             (ins GPR:$lhs, sfb_rhs:$rhs, bcc_opcode:$cc, GPR:$falsev, GPR:$rs1,
                   simm26:$imm), []> {
   let hasSideEffects = 0;
   let mayLoad = 1;



More information about the llvm-commits mailing list