[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