[llvm-branch-commits] [llvm] backport: [RISCV] Relax out of range Zibi conditional branches (#186965) (PR #187507)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Mar 19 07:12:59 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Pengcheng Wang (wangpc-pp)
<details>
<summary>Changes</summary>
If `.Label` is not within +-4KiB range, we convert
```
beqi/bnei reg, imm, .Label
```
to
```
bnei/beqi reg, imm, 8
j .Label
```
This is similar to what is done for the RISCV conditional branches and `Xqcibi` conditional branches.
---
Full diff: https://github.com/llvm/llvm-project/pull/187507.diff
6 Files Affected:
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp (+6)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (+10-3)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+14)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (-13)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td (+5)
- (added) llvm/test/MC/RISCV/zibi-long-conditional-jump.s (+110)
``````````diff
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index 584c000519b20..03ee683fd3ef3 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -196,6 +196,10 @@ static unsigned getRelaxedOpcode(unsigned Opcode, ArrayRef<MCOperand> Operands,
return RISCV::PseudoLongBEQ;
case RISCV::BNE:
return RISCV::PseudoLongBNE;
+ case RISCV::BEQI:
+ return RISCV::PseudoLongBEQI;
+ case RISCV::BNEI:
+ return RISCV::PseudoLongBNEI;
case RISCV::BLT:
return RISCV::PseudoLongBLT;
case RISCV::BGE:
@@ -285,6 +289,8 @@ void RISCVAsmBackend::relaxInstruction(MCInst &Inst,
}
case RISCV::BEQ:
case RISCV::BNE:
+ case RISCV::BEQI:
+ case RISCV::BNEI:
case RISCV::BLT:
case RISCV::BGE:
case RISCV::BLTU:
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index 5cf1f296d4f72..da63bb47c6311 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -255,6 +255,10 @@ static unsigned getInvertedBranchOp(unsigned BrOp) {
return RISCV::BNE;
case RISCV::PseudoLongBNE:
return RISCV::BEQ;
+ case RISCV::PseudoLongBEQI:
+ return RISCV::BNEI;
+ case RISCV::PseudoLongBNEI:
+ return RISCV::BEQI;
case RISCV::PseudoLongBLT:
return RISCV::BGE;
case RISCV::PseudoLongBGE:
@@ -297,14 +301,15 @@ void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
MCRegister SrcReg1 = MI.getOperand(0).getReg();
- MCRegister SrcReg2 = MI.getOperand(1).getReg();
- MCOperand SrcSymbol = MI.getOperand(2);
+ const MCOperand &Src2 = MI.getOperand(1);
+ const MCOperand &SrcSymbol = MI.getOperand(2);
unsigned Opcode = MI.getOpcode();
bool IsEqTest =
Opcode == RISCV::PseudoLongBNE || Opcode == RISCV::PseudoLongBEQ;
bool UseCompressedBr = false;
if (IsEqTest && STI.hasFeature(RISCV::FeatureStdExtZca)) {
+ MCRegister SrcReg2 = Src2.getReg();
if (RISCV::X8 <= SrcReg1.id() && SrcReg1.id() <= RISCV::X15 &&
SrcReg2.id() == RISCV::X0) {
UseCompressedBr = true;
@@ -326,7 +331,7 @@ void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI,
} else {
unsigned InvOpc = getInvertedBranchOp(Opcode);
MCInst TmpInst =
- MCInstBuilder(InvOpc).addReg(SrcReg1).addReg(SrcReg2).addImm(8);
+ MCInstBuilder(InvOpc).addReg(SrcReg1).addOperand(Src2).addImm(8);
uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
support::endian::write(CB, Binary, llvm::endianness::little);
Offset = 4;
@@ -429,6 +434,8 @@ void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,
return;
case RISCV::PseudoLongBEQ:
case RISCV::PseudoLongBNE:
+ case RISCV::PseudoLongBEQI:
+ case RISCV::PseudoLongBNEI:
case RISCV::PseudoLongBLT:
case RISCV::PseudoLongBGE:
case RISCV::PseudoLongBLTU:
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 708414496f4b6..ff582b8e741cd 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1744,6 +1744,20 @@ class LongBccPseudo : Pseudo<(outs),
let hasNoSchedulingInfo = 1;
}
+class LongBcciPseudo<DAGOperand InTyImm, int size>
+ : Pseudo<(outs),
+ (ins GPR:$rs1, InTyImm:$imm, simm21_lsb0_jal:$imm20),
+ []> {
+ let Size = size;
+ let isBarrier = 1;
+ let isBranch = 1;
+ let hasSideEffects = 0;
+ let mayStore = 0;
+ let mayLoad = 0;
+ let isAsmParserOnly = 1;
+ let hasNoSchedulingInfo = 1;
+}
+
def PseudoLongBEQ : LongBccPseudo;
def PseudoLongBNE : LongBccPseudo;
def PseudoLongBLT : LongBccPseudo;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index eae92c43aae39..74e987d88f19d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1335,19 +1335,6 @@ let EmitPriority = 1 in {
// Pseudo-instructions
//===----------------------------------------------------------------------===//
-class LongBcciPseudo<DAGOperand InTyImm, int size>
- : Pseudo<(outs), (ins GPR:$rs1, InTyImm:$imm, simm21_lsb0_jal:$imm20), []>
-{
- let Size = size;
- let isBarrier = 1;
- let isBranch = 1;
- let hasSideEffects = 0;
- let mayStore = 0;
- let mayLoad = 0;
- let isAsmParserOnly = 1;
- let hasNoSchedulingInfo = 1;
-}
-
// This will be expanded into either:
// QC.BXXX(4 bytes) + JAL(4 bytes)
// or
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td
index 412bb08b00929..0ffb6b963790b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZibi.td
@@ -41,6 +41,11 @@ class Branch_imm<bits<3> funct3, string opcodestr>
let Predicates = [HasStdExtZibi] in {
def BEQI : Branch_imm<0b010, "beqi">;
def BNEI : Branch_imm<0b011, "bnei">;
+
+ // For long branch relaxation.
+ // This will be expanded into BEQI/BNEI(4 bytes) + JAL(4 bytes).
+ def PseudoLongBEQI : LongBcciPseudo<imm5_zibi, 8>;
+ def PseudoLongBNEI : LongBcciPseudo<imm5_zibi, 8>;
} // Predicates = [HasStdExtZibi]
multiclass BccImmPat<CondCode Cond, Branch_imm Inst> {
diff --git a/llvm/test/MC/RISCV/zibi-long-conditional-jump.s b/llvm/test/MC/RISCV/zibi-long-conditional-jump.s
new file mode 100644
index 0000000000000..dc90a5d0b9055
--- /dev/null
+++ b/llvm/test/MC/RISCV/zibi-long-conditional-jump.s
@@ -0,0 +1,110 @@
+# RUN: llvm-mc -filetype=obj --mattr=+experimental-zibi -triple=riscv32 %s \
+# RUN: | llvm-objdump --mattr=+experimental-zibi -d -M no-aliases - \
+# RUN: | FileCheck --check-prefix=CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax,+experimental-zibi %s \
+# RUN: | llvm-objdump --mattr=+experimental-zibi -dr -M no-aliases - \
+# RUN: | FileCheck --check-prefix=CHECK-INST-RELAX %s
+
+# Tests that are forward in range.
+
+# CHECK-INST-LABEL: beqi_in_range_forward
+# CHECK-INST: beqi a0, 0xa, {{.*}}
+
+# CHECK-INST-RELAX-LABEL: beqi_in_range_forward
+# CHECK-INST-RELAX: beqi a0, 0xa, {{.*}}
+beqi_in_range_forward:
+ beqi a0, 10, .L1
+ .fill 1000, 4, 0
+.L1:
+ ret
+
+# CHECK-INST-LABEL: bnei_in_range_forward
+# CHECK-INST: bnei a0, 0xa, {{.*}}
+
+# CHECK-INST-RELAX-LABEL: bnei_in_range_forward
+# CHECK-INST-RELAX: bnei a0, 0xa, {{.*}}
+bnei_in_range_forward:
+ bnei a0, 10, .L2
+ .fill 1000, 4, 0
+.L2:
+ ret
+
+# Tests that are backward in range.
+
+# CHECK-INST-LABEL: beqi_in_range_backward
+# CHECK-INST: beqi a0, 0xa, {{.*}}
+
+# CHECK-INST-RELAX-LABEL: beqi_in_range_backward
+# CHECK-INST-RELAX: beqi a0, 0xa, {{.*}}
+beqi_in_range_backward:
+.L3:
+ .fill 1000, 4, 0
+ beqi a0, 10, .L3
+ ret
+
+# CHECK-INST-LABEL: bnei_in_range_backward
+# CHECK-INST: bnei a0, 0xa, {{.*}}
+
+# CHECK-INST-RELAX-LABEL: bnei_in_range_backward
+# CHECK-INST-RELAX: bnei a0, 0xa, {{.*}}
+bnei_in_range_backward:
+.L4:
+ .fill 1000, 4, 0
+ bnei a0, 10, .L4
+ ret
+
+# Tests that are forward out of range.
+
+# CHECK-INST-LABEL: beqi_out_of_range_forward
+# CHECK-INST: bnei a0, 0xa, {{.*}}+0x8
+# CHECK-INST-NEXT: jal zero, {{.*}}
+
+# CHECK-INST-RELAX-LABEL: beqi_out_of_range_forward
+# CHECK-INST-RELAX: bnei a0, 0xa, {{.*}}+0x8
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+beqi_out_of_range_forward:
+ beqi a0, 10, .L5
+ .fill 1300, 4, 0
+.L5:
+ ret
+
+# CHECK-INST-LABEL: bnei_out_of_range_forward
+# CHECK-INST: beqi a0, 0xa, {{.*}}+0x8
+# CHECK-INST-NEXT: jal zero, {{.*}}
+
+# CHECK-INST-RELAX-LABEL: bnei_out_of_range_forward
+# CHECK-INST-RELAX: beqi a0, 0xa, {{.*}}+0x8
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+bnei_out_of_range_forward:
+ bnei a0, 10, .L6
+ .fill 1300, 4, 0
+.L6:
+ ret
+
+# Tests that are backward out of range.
+
+# CHECK-INST-LABEL: beqi_out_of_range_backward
+# CHECK-INST: bnei a0, 0xa, {{.*}}+0x1458
+# CHECK-INST-NEXT: jal zero, {{.*}}
+
+# CHECK-INST-RELAX-LABEL: beqi_out_of_range_backward
+# CHECK-INST-RELAX: bnei a0, 0xa, {{.*}}+0x1458
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+beqi_out_of_range_backward:
+.L7:
+ .fill 1300, 4, 0
+ beqi a0, 10, .L7
+ ret
+
+# CHECK-INST-LABEL: bnei_out_of_range_backward
+# CHECK-INST: beqi a0, 0xa, {{.*}}+0x1458
+# CHECK-INST-NEXT: jal zero, {{.*}}
+
+# CHECK-INST-RELAX-LABEL: bnei_out_of_range_backward
+# CHECK-INST-RELAX: beqi a0, 0xa, {{.*}}+0x1458
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+bnei_out_of_range_backward:
+.L8:
+ .fill 1300, 4, 0
+ bnei a0, 10, .L8
+ ret
``````````
</details>
https://github.com/llvm/llvm-project/pull/187507
More information about the llvm-branch-commits
mailing list