[llvm] [RISCV] Relax out of range Xqcibi conditional branches (PR #134336)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 3 19:16:22 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mc
@llvm/pr-subscribers-backend-risc-v
Author: Sudharsan Veeravalli (svs-quic)
<details>
<summary>Changes</summary>
If .L1 is not within +-4KiB range,
convert
qc.(e.)bge a0, 10, .L1
to
qc.(e.)blt a0, 10, 8(10)
j .L1
This is similar to what is done for the RISCV conditional branches.
---
Full diff: https://github.com/llvm/llvm-project/pull/134336.diff
5 Files Affected:
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp (+36)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (+97)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+33)
- (added) llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s (+134)
- (modified) llvm/test/MC/RISCV/xqcibi-relocations.s (+6-7)
``````````diff
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index 10a26554ed672..ac0f7421664c5 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -198,6 +198,30 @@ static unsigned getRelaxedOpcode(unsigned Op) {
return RISCV::PseudoLongBLTU;
case RISCV::BGEU:
return RISCV::PseudoLongBGEU;
+ case RISCV::QC_BEQI:
+ return RISCV::PseudoLongQC_BEQI;
+ case RISCV::QC_BNEI:
+ return RISCV::PseudoLongQC_BNEI;
+ case RISCV::QC_BLTI:
+ return RISCV::PseudoLongQC_BLTI;
+ case RISCV::QC_BGEI:
+ return RISCV::PseudoLongQC_BGEI;
+ case RISCV::QC_BLTUI:
+ return RISCV::PseudoLongQC_BLTUI;
+ case RISCV::QC_BGEUI:
+ return RISCV::PseudoLongQC_BGEUI;
+ case RISCV::QC_E_BEQI:
+ return RISCV::PseudoLongQC_E_BEQI;
+ case RISCV::QC_E_BNEI:
+ return RISCV::PseudoLongQC_E_BNEI;
+ case RISCV::QC_E_BLTI:
+ return RISCV::PseudoLongQC_E_BLTI;
+ case RISCV::QC_E_BGEI:
+ return RISCV::PseudoLongQC_E_BGEI;
+ case RISCV::QC_E_BLTUI:
+ return RISCV::PseudoLongQC_E_BLTUI;
+ case RISCV::QC_E_BGEUI:
+ return RISCV::PseudoLongQC_E_BGEUI;
}
}
@@ -224,6 +248,18 @@ void RISCVAsmBackend::relaxInstruction(MCInst &Inst,
case RISCV::BGE:
case RISCV::BLTU:
case RISCV::BGEU:
+ case RISCV::QC_BEQI:
+ case RISCV::QC_BNEI:
+ case RISCV::QC_BLTI:
+ case RISCV::QC_BGEI:
+ case RISCV::QC_BLTUI:
+ case RISCV::QC_BGEUI:
+ case RISCV::QC_E_BEQI:
+ case RISCV::QC_E_BNEI:
+ case RISCV::QC_E_BLTI:
+ case RISCV::QC_E_BGEI:
+ case RISCV::QC_E_BLTUI:
+ case RISCV::QC_E_BGEUI:
Res.setOpcode(getRelaxedOpcode(Inst.getOpcode()));
Res.addOperand(Inst.getOperand(0));
Res.addOperand(Inst.getOperand(1));
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index fc98859314680..37a2ac336d20c 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -68,6 +68,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ void expandQCLongCondBrImm(const MCInst &MI, SmallVectorImpl<char> &CB,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI, unsigned Size) const;
+
/// TableGen'erated function for getting the binary encoding for an
/// instruction.
uint64_t getBinaryCodeForInstr(const MCInst &MI,
@@ -240,6 +244,30 @@ static unsigned getInvertedBranchOp(unsigned BrOp) {
return RISCV::BGEU;
case RISCV::PseudoLongBGEU:
return RISCV::BLTU;
+ case RISCV::PseudoLongQC_BEQI:
+ return RISCV::QC_BNEI;
+ case RISCV::PseudoLongQC_BNEI:
+ return RISCV::QC_BEQI;
+ case RISCV::PseudoLongQC_BLTI:
+ return RISCV::QC_BGEI;
+ case RISCV::PseudoLongQC_BGEI:
+ return RISCV::QC_BLTI;
+ case RISCV::PseudoLongQC_BLTUI:
+ return RISCV::QC_BGEUI;
+ case RISCV::PseudoLongQC_BGEUI:
+ return RISCV::QC_BLTUI;
+ case RISCV::PseudoLongQC_E_BEQI:
+ return RISCV::QC_E_BNEI;
+ case RISCV::PseudoLongQC_E_BNEI:
+ return RISCV::QC_E_BEQI;
+ case RISCV::PseudoLongQC_E_BLTI:
+ return RISCV::QC_E_BGEI;
+ case RISCV::PseudoLongQC_E_BGEI:
+ return RISCV::QC_E_BLTI;
+ case RISCV::PseudoLongQC_E_BLTUI:
+ return RISCV::QC_E_BGEUI;
+ case RISCV::PseudoLongQC_E_BGEUI:
+ return RISCV::QC_E_BLTUI;
}
}
@@ -305,6 +333,57 @@ void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI,
}
}
+// Expand PseudoLongQC_(E_)Bxxx to an inverted conditional branch and an
+// unconditional jump.
+void RISCVMCCodeEmitter::expandQCLongCondBrImm(const MCInst &MI,
+ SmallVectorImpl<char> &CB,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI,
+ unsigned Size) const {
+ MCRegister SrcReg1 = MI.getOperand(0).getReg();
+ auto BrImm = MI.getOperand(1).getImm();
+ MCOperand SrcSymbol = MI.getOperand(2);
+ unsigned Opcode = MI.getOpcode();
+ uint32_t Offset;
+ unsigned InvOpc = getInvertedBranchOp(Opcode);
+ // Emit inverted conditional branch with offset:
+ // 8 (QC.BXXX(4) + JAL(4))
+ // or
+ // 10 (QC.E.BXXX(6) + JAL(4)).
+ if (Size == 4) {
+ MCInst TmpBr =
+ MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(BrImm).addImm(8);
+ uint32_t BrBinary = getBinaryCodeForInstr(TmpBr, Fixups, STI);
+ support::endian::write(CB, BrBinary, llvm::endianness::little);
+ } else {
+ MCInst TmpBr =
+ MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(BrImm).addImm(10);
+ uint64_t BrBinary =
+ getBinaryCodeForInstr(TmpBr, Fixups, STI) & 0xffff'ffff'ffffu;
+ SmallVector<char, 8> Encoding;
+ support::endian::write(Encoding, BrBinary, llvm::endianness::little);
+ assert(Encoding[6] == 0 && Encoding[7] == 0 &&
+ "Unexpected encoding for 48-bit instruction");
+ Encoding.truncate(6);
+ CB.append(Encoding);
+ }
+ Offset = Size;
+ // Save the number fixups.
+ size_t FixupStartIndex = Fixups.size();
+ // Emit an unconditional jump to the destination.
+ MCInst TmpJ =
+ MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addOperand(SrcSymbol);
+ uint32_t JBinary = getBinaryCodeForInstr(TmpJ, Fixups, STI);
+ support::endian::write(CB, JBinary, llvm::endianness::little);
+ // Drop any fixup added so we can add the correct one.
+ Fixups.resize(FixupStartIndex);
+ if (SrcSymbol.isExpr()) {
+ Fixups.push_back(MCFixup::create(Offset, SrcSymbol.getExpr(),
+ MCFixupKind(RISCV::fixup_riscv_jal),
+ MI.getLoc()));
+ }
+}
+
void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,
SmallVectorImpl<char> &CB,
SmallVectorImpl<MCFixup> &Fixups,
@@ -339,6 +418,24 @@ void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,
expandLongCondBr(MI, CB, Fixups, STI);
MCNumEmitted += 2;
return;
+ case RISCV::PseudoLongQC_BEQI:
+ case RISCV::PseudoLongQC_BNEI:
+ case RISCV::PseudoLongQC_BLTI:
+ case RISCV::PseudoLongQC_BGEI:
+ case RISCV::PseudoLongQC_BLTUI:
+ case RISCV::PseudoLongQC_BGEUI:
+ expandQCLongCondBrImm(MI, CB, Fixups, STI, 4);
+ MCNumEmitted += 2;
+ return;
+ case RISCV::PseudoLongQC_E_BEQI:
+ case RISCV::PseudoLongQC_E_BNEI:
+ case RISCV::PseudoLongQC_E_BLTI:
+ case RISCV::PseudoLongQC_E_BGEI:
+ case RISCV::PseudoLongQC_E_BLTUI:
+ case RISCV::PseudoLongQC_E_BGEUI:
+ expandQCLongCondBrImm(MI, CB, Fixups, STI, 6);
+ MCNumEmitted += 2;
+ return;
case RISCV::PseudoTLSDESCCall:
expandTLSDESCCall(MI, CB, Fixups, STI);
MCNumEmitted += 1;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 64d6f6d8f8bbf..f762c4943f630 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1152,6 +1152,39 @@ let EmitPriority = 0 in {
} // EmitPriority = 0
} // Predicates = [HasVendorXqcilo, IsRV32]
+//===----------------------------------------------------------------------===//
+// 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
+// QC.E.BXXX(6 bytes) + JAL(4 bytes)
+def PseudoLongQC_BEQI : LongBcciPseudo<simm5nonzero, 8>;
+def PseudoLongQC_BNEI : LongBcciPseudo<simm5nonzero, 8>;
+def PseudoLongQC_BLTI : LongBcciPseudo<simm5nonzero, 8>;
+def PseudoLongQC_BGEI : LongBcciPseudo<simm5nonzero, 8>;
+def PseudoLongQC_BLTUI : LongBcciPseudo<uimm5nonzero, 8>;
+def PseudoLongQC_BGEUI : LongBcciPseudo<uimm5nonzero, 8>;
+def PseudoLongQC_E_BEQI : LongBcciPseudo<simm16nonzero, 10>;
+def PseudoLongQC_E_BNEI : LongBcciPseudo<simm16nonzero, 10>;
+def PseudoLongQC_E_BLTI : LongBcciPseudo<simm16nonzero, 10>;
+def PseudoLongQC_E_BGEI : LongBcciPseudo<simm16nonzero, 10>;
+def PseudoLongQC_E_BLTUI : LongBcciPseudo<uimm16nonzero, 10>;
+def PseudoLongQC_E_BGEUI : LongBcciPseudo<uimm16nonzero, 10>;
//===----------------------------------------------------------------------===//
// Code Gen Patterns
diff --git a/llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s b/llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
new file mode 100644
index 0000000000000..788fddaa94463
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
@@ -0,0 +1,134 @@
+# RUN: llvm-mc -filetype=obj --mattr=+experimental-xqcibi -triple=riscv32 %s \
+# RUN: | llvm-objdump --mattr=+experimental-xqcibi -d -M no-aliases - \
+# RUN: | FileCheck --check-prefix=CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax,+experimental-xqcibi %s \
+# RUN: | llvm-objdump --mattr=+experimental-xqcibi -dr -M no-aliases - \
+# RUN: | FileCheck --check-prefix=CHECK-INST-RELAX %s
+
+ .text
+ .type test, at function
+
+test:
+
+# CHECK-INST: qc.beqi a0, 0xa, 0x8
+# CHECK-INST-NEXT: jal zero, 0x1458
+# CHECK-INST-RELAX: qc.beqi a0, 0xa, 0x8
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L1
+ qc.bnei a0, 10, .L1
+.fill 1300, 4, 0
+.L1:
+ ret
+
+# CHECK-INST: qc.bnei a0, 0x6, 0x1462
+# CHECK-INST-NEXT: jal zero, 0x28b2
+# CHECK-INST-RELAX: qc.bnei a0, 0x6, 0x1462
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L2
+ qc.beqi a0, 6, .L2
+.fill 1300, 4, 0
+.L2:
+ ret
+
+# CHECK-INST: qc.bgei a0, 0xd, 0x28bc
+# CHECK-INST-NEXT: jal zero, 0x3d0c
+# CHECK-INST-RELAX: qc.bgei a0, 0xd, 0x28bc
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L3
+ qc.blti a0, 13, .L3
+.fill 1300, 4, 0
+.L3:
+ ret
+
+# CHECK-INST: qc.blti a0, 0x1, 0x3d16
+# CHECK-INST-NEXT: jal zero, 0x5166
+# CHECK-INST-RELAX: qc.blti a0, 0x1, 0x3d16
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L4
+ qc.bgei a0, 1, .L4
+.fill 1300, 4, 0
+.L4:
+ ret
+
+# CHECK-INST: qc.bgeui a0, 0x5, 0x5170
+# CHECK-INST-NEXT: jal zero, 0x65c0
+# CHECK-INST-RELAX: qc.bgeui a0, 0x5, 0x5170
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L5
+ qc.bltui a0, 5, .L5
+.fill 1300, 4, 0
+.L5:
+ ret
+
+# CHECK-INST: qc.bltui a0, 0xc, 0x65ca
+# CHECK-INST-NEXT: jal zero, 0x7a1a
+# CHECK-INST-RELAX: qc.bltui a0, 0xc, 0x65ca
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L6
+ qc.bgeui a0, 12, .L6
+.fill 1300, 4, 0
+.L6:
+ ret
+
+# CHECK-INST: qc.e.beqi a0, 0x1, 0x7a26
+# CHECK-INST-NEXT: jal zero, 0x8e76
+# CHECK-INST-RELAX: qc.e.beqi a0, 0x1, 0x7a26
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L7
+ qc.e.bnei a0, 1, .L7
+.fill 1300, 4, 0
+.L7:
+ ret
+
+# CHECK-INST: qc.e.bnei a0, 0x2, 0x8e82
+# CHECK-INST-NEXT: jal zero, 0xa2d2
+# CHECK-INST-RELAX: qc.e.bnei a0, 0x2, 0x8e82
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L8
+ qc.e.beqi a0, 2, .L8
+.fill 1300, 4, 0
+.L8:
+ ret
+
+# CHECK-INST: qc.e.bgei a0, 0x3, 0xa2de
+# CHECK-INST-NEXT: jal zero, 0xb72e
+# CHECK-INST-RELAX: qc.e.bgei a0, 0x3, 0xa2de
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L9
+ qc.e.blti a0, 3, .L9
+.fill 1300, 4, 0
+.L9:
+ ret
+
+# CHECK-INST: qc.e.blti a0, 0x4, 0xb73a
+# CHECK-INST-NEXT: jal zero, 0xcb8a
+# CHECK-INST-RELAX: qc.e.blti a0, 0x4, 0xb73a
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L10
+ qc.e.bgei a0, 4, .L10
+.fill 1300, 4, 0
+.L10:
+ ret
+
+# CHECK-INST: qc.e.bgeui a0, 0x5, 0xcb96
+# CHECK-INST-NEXT: jal zero, 0xdfe6
+# CHECK-INST-RELAX: qc.e.bgeui a0, 0x5, 0xcb96
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L11
+ qc.e.bltui a0, 5, .L11
+.fill 1300, 4, 0
+.L11:
+ ret
+
+# CHECK-INST: qc.e.bltui a0, 0x6, 0xdff2
+# CHECK-INST-NEXT: jal zero, 0xf442
+# CHECK-INST-RELAX: qc.e.bltui a0, 0x6, 0xdff2
+# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
+# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L12
+ qc.e.bgeui a0, 6, .L12
+.fill 1300, 4, 0
+.L12:
+ ret
+
+.Lfunc_end0:
+ .size test, .Lfunc_end0-test
diff --git a/llvm/test/MC/RISCV/xqcibi-relocations.s b/llvm/test/MC/RISCV/xqcibi-relocations.s
index 4899e5f1eac46..e8c04fdf40aa9 100644
--- a/llvm/test/MC/RISCV/xqcibi-relocations.s
+++ b/llvm/test/MC/RISCV/xqcibi-relocations.s
@@ -10,23 +10,22 @@
.text
-# Check that branch to an undefined symbol is handled
-# FIXME: This should be relaxed to an inverse branch and jump
+# Since foo is undefined, this will be relaxed to (qc.beqi + jal)
qc.bnei x6, 10, foo
-# RELOC: R_RISCV_BRANCH foo 0x0
+# RELOC: R_RISCV_JAL foo 0x0
# INSTR: qc.bnei t1, 10, foo
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_branch
-# FIXME: This should be relaxed to an inverse branch and jump
+# Since foo is undefined, this will be relaxed to (qc.e.bltui + jal)
qc.e.bgeui x8, 12, foo
-# RELOC: R_RISCV_CUSTOM193 foo 0x0
+# RELOC: R_RISCV_JAL foo 0x0
# INSTR: qc.e.bgeui s0, 12, foo
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_qc_e_branch
# Check that a label in a different section is handled similar to an undefined symbol
-# FIXME: This should be relaxed to an inverse branch and jump
+# Since foo is undefined, this will be relaxed to (qc.e.bgeui + jal)
qc.e.bltui x4, 9, .bar
-# RELOC: R_RISCV_CUSTOM193 .bar 0x0
+# RELOC: R_RISCV_JAL .bar 0x0
# INSTR: qc.e.bltui tp, 9, .bar
# FIXUP: fixup A - offset: 0, value: .bar, kind: fixup_riscv_qc_e_branch
``````````
</details>
https://github.com/llvm/llvm-project/pull/134336
More information about the llvm-commits
mailing list