-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[RISCV] Relax out of range Xqcibi conditional branches #134336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
|
@llvm/pr-subscribers-mc @llvm/pr-subscribers-backend-risc-v Author: Sudharsan Veeravalli (svs-quic) ChangesIf .L1 is not within +-4KiB range, convert qc.(e.)bge a0, 10, .L1 to qc.(e.)blt a0, 10, 8(10) 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:
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,@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
|
hchandel
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
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.