[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