Skip to content

Commit d59594d

Browse files
authored
[RISCV] Relax out of range Xqcibi conditional branches (#134336)
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.
1 parent 1f72fa2 commit d59594d

File tree

5 files changed

+307
-8
lines changed

5 files changed

+307
-8
lines changed

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,30 @@ static unsigned getRelaxedOpcode(unsigned Op) {
198198
return RISCV::PseudoLongBLTU;
199199
case RISCV::BGEU:
200200
return RISCV::PseudoLongBGEU;
201+
case RISCV::QC_BEQI:
202+
return RISCV::PseudoLongQC_BEQI;
203+
case RISCV::QC_BNEI:
204+
return RISCV::PseudoLongQC_BNEI;
205+
case RISCV::QC_BLTI:
206+
return RISCV::PseudoLongQC_BLTI;
207+
case RISCV::QC_BGEI:
208+
return RISCV::PseudoLongQC_BGEI;
209+
case RISCV::QC_BLTUI:
210+
return RISCV::PseudoLongQC_BLTUI;
211+
case RISCV::QC_BGEUI:
212+
return RISCV::PseudoLongQC_BGEUI;
213+
case RISCV::QC_E_BEQI:
214+
return RISCV::PseudoLongQC_E_BEQI;
215+
case RISCV::QC_E_BNEI:
216+
return RISCV::PseudoLongQC_E_BNEI;
217+
case RISCV::QC_E_BLTI:
218+
return RISCV::PseudoLongQC_E_BLTI;
219+
case RISCV::QC_E_BGEI:
220+
return RISCV::PseudoLongQC_E_BGEI;
221+
case RISCV::QC_E_BLTUI:
222+
return RISCV::PseudoLongQC_E_BLTUI;
223+
case RISCV::QC_E_BGEUI:
224+
return RISCV::PseudoLongQC_E_BGEUI;
201225
}
202226
}
203227

@@ -224,6 +248,18 @@ void RISCVAsmBackend::relaxInstruction(MCInst &Inst,
224248
case RISCV::BGE:
225249
case RISCV::BLTU:
226250
case RISCV::BGEU:
251+
case RISCV::QC_BEQI:
252+
case RISCV::QC_BNEI:
253+
case RISCV::QC_BLTI:
254+
case RISCV::QC_BGEI:
255+
case RISCV::QC_BLTUI:
256+
case RISCV::QC_BGEUI:
257+
case RISCV::QC_E_BEQI:
258+
case RISCV::QC_E_BNEI:
259+
case RISCV::QC_E_BLTI:
260+
case RISCV::QC_E_BGEI:
261+
case RISCV::QC_E_BLTUI:
262+
case RISCV::QC_E_BGEUI:
227263
Res.setOpcode(getRelaxedOpcode(Inst.getOpcode()));
228264
Res.addOperand(Inst.getOperand(0));
229265
Res.addOperand(Inst.getOperand(1));

llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
6868
SmallVectorImpl<MCFixup> &Fixups,
6969
const MCSubtargetInfo &STI) const;
7070

71+
void expandQCLongCondBrImm(const MCInst &MI, SmallVectorImpl<char> &CB,
72+
SmallVectorImpl<MCFixup> &Fixups,
73+
const MCSubtargetInfo &STI, unsigned Size) const;
74+
7175
/// TableGen'erated function for getting the binary encoding for an
7276
/// instruction.
7377
uint64_t getBinaryCodeForInstr(const MCInst &MI,
@@ -240,6 +244,30 @@ static unsigned getInvertedBranchOp(unsigned BrOp) {
240244
return RISCV::BGEU;
241245
case RISCV::PseudoLongBGEU:
242246
return RISCV::BLTU;
247+
case RISCV::PseudoLongQC_BEQI:
248+
return RISCV::QC_BNEI;
249+
case RISCV::PseudoLongQC_BNEI:
250+
return RISCV::QC_BEQI;
251+
case RISCV::PseudoLongQC_BLTI:
252+
return RISCV::QC_BGEI;
253+
case RISCV::PseudoLongQC_BGEI:
254+
return RISCV::QC_BLTI;
255+
case RISCV::PseudoLongQC_BLTUI:
256+
return RISCV::QC_BGEUI;
257+
case RISCV::PseudoLongQC_BGEUI:
258+
return RISCV::QC_BLTUI;
259+
case RISCV::PseudoLongQC_E_BEQI:
260+
return RISCV::QC_E_BNEI;
261+
case RISCV::PseudoLongQC_E_BNEI:
262+
return RISCV::QC_E_BEQI;
263+
case RISCV::PseudoLongQC_E_BLTI:
264+
return RISCV::QC_E_BGEI;
265+
case RISCV::PseudoLongQC_E_BGEI:
266+
return RISCV::QC_E_BLTI;
267+
case RISCV::PseudoLongQC_E_BLTUI:
268+
return RISCV::QC_E_BGEUI;
269+
case RISCV::PseudoLongQC_E_BGEUI:
270+
return RISCV::QC_E_BLTUI;
243271
}
244272
}
245273

@@ -305,6 +333,57 @@ void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI,
305333
}
306334
}
307335

336+
// Expand PseudoLongQC_(E_)Bxxx to an inverted conditional branch and an
337+
// unconditional jump.
338+
void RISCVMCCodeEmitter::expandQCLongCondBrImm(const MCInst &MI,
339+
SmallVectorImpl<char> &CB,
340+
SmallVectorImpl<MCFixup> &Fixups,
341+
const MCSubtargetInfo &STI,
342+
unsigned Size) const {
343+
MCRegister SrcReg1 = MI.getOperand(0).getReg();
344+
auto BrImm = MI.getOperand(1).getImm();
345+
MCOperand SrcSymbol = MI.getOperand(2);
346+
unsigned Opcode = MI.getOpcode();
347+
uint32_t Offset;
348+
unsigned InvOpc = getInvertedBranchOp(Opcode);
349+
// Emit inverted conditional branch with offset:
350+
// 8 (QC.BXXX(4) + JAL(4))
351+
// or
352+
// 10 (QC.E.BXXX(6) + JAL(4)).
353+
if (Size == 4) {
354+
MCInst TmpBr =
355+
MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(BrImm).addImm(8);
356+
uint32_t BrBinary = getBinaryCodeForInstr(TmpBr, Fixups, STI);
357+
support::endian::write(CB, BrBinary, llvm::endianness::little);
358+
} else {
359+
MCInst TmpBr =
360+
MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(BrImm).addImm(10);
361+
uint64_t BrBinary =
362+
getBinaryCodeForInstr(TmpBr, Fixups, STI) & 0xffff'ffff'ffffu;
363+
SmallVector<char, 8> Encoding;
364+
support::endian::write(Encoding, BrBinary, llvm::endianness::little);
365+
assert(Encoding[6] == 0 && Encoding[7] == 0 &&
366+
"Unexpected encoding for 48-bit instruction");
367+
Encoding.truncate(6);
368+
CB.append(Encoding);
369+
}
370+
Offset = Size;
371+
// Save the number fixups.
372+
size_t FixupStartIndex = Fixups.size();
373+
// Emit an unconditional jump to the destination.
374+
MCInst TmpJ =
375+
MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addOperand(SrcSymbol);
376+
uint32_t JBinary = getBinaryCodeForInstr(TmpJ, Fixups, STI);
377+
support::endian::write(CB, JBinary, llvm::endianness::little);
378+
// Drop any fixup added so we can add the correct one.
379+
Fixups.resize(FixupStartIndex);
380+
if (SrcSymbol.isExpr()) {
381+
Fixups.push_back(MCFixup::create(Offset, SrcSymbol.getExpr(),
382+
MCFixupKind(RISCV::fixup_riscv_jal),
383+
MI.getLoc()));
384+
}
385+
}
386+
308387
void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,
309388
SmallVectorImpl<char> &CB,
310389
SmallVectorImpl<MCFixup> &Fixups,
@@ -339,6 +418,24 @@ void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,
339418
expandLongCondBr(MI, CB, Fixups, STI);
340419
MCNumEmitted += 2;
341420
return;
421+
case RISCV::PseudoLongQC_BEQI:
422+
case RISCV::PseudoLongQC_BNEI:
423+
case RISCV::PseudoLongQC_BLTI:
424+
case RISCV::PseudoLongQC_BGEI:
425+
case RISCV::PseudoLongQC_BLTUI:
426+
case RISCV::PseudoLongQC_BGEUI:
427+
expandQCLongCondBrImm(MI, CB, Fixups, STI, 4);
428+
MCNumEmitted += 2;
429+
return;
430+
case RISCV::PseudoLongQC_E_BEQI:
431+
case RISCV::PseudoLongQC_E_BNEI:
432+
case RISCV::PseudoLongQC_E_BLTI:
433+
case RISCV::PseudoLongQC_E_BGEI:
434+
case RISCV::PseudoLongQC_E_BLTUI:
435+
case RISCV::PseudoLongQC_E_BGEUI:
436+
expandQCLongCondBrImm(MI, CB, Fixups, STI, 6);
437+
MCNumEmitted += 2;
438+
return;
342439
case RISCV::PseudoTLSDESCCall:
343440
expandTLSDESCCall(MI, CB, Fixups, STI);
344441
MCNumEmitted += 1;

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,39 @@ let EmitPriority = 0 in {
11521152
} // EmitPriority = 0
11531153
} // Predicates = [HasVendorXqcilo, IsRV32]
11541154

1155+
//===----------------------------------------------------------------------===//
1156+
// Pseudo-instructions
1157+
//===----------------------------------------------------------------------===//
1158+
1159+
class LongBcciPseudo<DAGOperand InTyImm, int size>
1160+
: Pseudo<(outs), (ins GPR:$rs1, InTyImm:$imm, simm21_lsb0_jal:$imm20), []>
1161+
{
1162+
let Size = size;
1163+
let isBarrier = 1;
1164+
let isBranch = 1;
1165+
let hasSideEffects = 0;
1166+
let mayStore = 0;
1167+
let mayLoad = 0;
1168+
let isAsmParserOnly = 1;
1169+
let hasNoSchedulingInfo = 1;
1170+
}
1171+
1172+
// This will be expanded into either:
1173+
// QC.BXXX(4 bytes) + JAL(4 bytes)
1174+
// or
1175+
// QC.E.BXXX(6 bytes) + JAL(4 bytes)
1176+
def PseudoLongQC_BEQI : LongBcciPseudo<simm5nonzero, 8>;
1177+
def PseudoLongQC_BNEI : LongBcciPseudo<simm5nonzero, 8>;
1178+
def PseudoLongQC_BLTI : LongBcciPseudo<simm5nonzero, 8>;
1179+
def PseudoLongQC_BGEI : LongBcciPseudo<simm5nonzero, 8>;
1180+
def PseudoLongQC_BLTUI : LongBcciPseudo<uimm5nonzero, 8>;
1181+
def PseudoLongQC_BGEUI : LongBcciPseudo<uimm5nonzero, 8>;
1182+
def PseudoLongQC_E_BEQI : LongBcciPseudo<simm16nonzero, 10>;
1183+
def PseudoLongQC_E_BNEI : LongBcciPseudo<simm16nonzero, 10>;
1184+
def PseudoLongQC_E_BLTI : LongBcciPseudo<simm16nonzero, 10>;
1185+
def PseudoLongQC_E_BGEI : LongBcciPseudo<simm16nonzero, 10>;
1186+
def PseudoLongQC_E_BLTUI : LongBcciPseudo<uimm16nonzero, 10>;
1187+
def PseudoLongQC_E_BGEUI : LongBcciPseudo<uimm16nonzero, 10>;
11551188

11561189
//===----------------------------------------------------------------------===//
11571190
// Code Gen Patterns
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# RUN: llvm-mc -filetype=obj --mattr=+experimental-xqcibi -triple=riscv32 %s \
2+
# RUN: | llvm-objdump --mattr=+experimental-xqcibi -d -M no-aliases - \
3+
# RUN: | FileCheck --check-prefix=CHECK-INST %s
4+
# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax,+experimental-xqcibi %s \
5+
# RUN: | llvm-objdump --mattr=+experimental-xqcibi -dr -M no-aliases - \
6+
# RUN: | FileCheck --check-prefix=CHECK-INST-RELAX %s
7+
8+
.text
9+
.type test,@function
10+
11+
test:
12+
13+
# CHECK-INST: qc.beqi a0, 0xa, 0x8
14+
# CHECK-INST-NEXT: jal zero, 0x1458
15+
# CHECK-INST-RELAX: qc.beqi a0, 0xa, 0x8
16+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
17+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L1
18+
qc.bnei a0, 10, .L1
19+
.fill 1300, 4, 0
20+
.L1:
21+
ret
22+
23+
# CHECK-INST: qc.bnei a0, 0x6, 0x1462
24+
# CHECK-INST-NEXT: jal zero, 0x28b2
25+
# CHECK-INST-RELAX: qc.bnei a0, 0x6, 0x1462
26+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
27+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L2
28+
qc.beqi a0, 6, .L2
29+
.fill 1300, 4, 0
30+
.L2:
31+
ret
32+
33+
# CHECK-INST: qc.bgei a0, 0xd, 0x28bc
34+
# CHECK-INST-NEXT: jal zero, 0x3d0c
35+
# CHECK-INST-RELAX: qc.bgei a0, 0xd, 0x28bc
36+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
37+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L3
38+
qc.blti a0, 13, .L3
39+
.fill 1300, 4, 0
40+
.L3:
41+
ret
42+
43+
# CHECK-INST: qc.blti a0, 0x1, 0x3d16
44+
# CHECK-INST-NEXT: jal zero, 0x5166
45+
# CHECK-INST-RELAX: qc.blti a0, 0x1, 0x3d16
46+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
47+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L4
48+
qc.bgei a0, 1, .L4
49+
.fill 1300, 4, 0
50+
.L4:
51+
ret
52+
53+
# CHECK-INST: qc.bgeui a0, 0x5, 0x5170
54+
# CHECK-INST-NEXT: jal zero, 0x65c0
55+
# CHECK-INST-RELAX: qc.bgeui a0, 0x5, 0x5170
56+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
57+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L5
58+
qc.bltui a0, 5, .L5
59+
.fill 1300, 4, 0
60+
.L5:
61+
ret
62+
63+
# CHECK-INST: qc.bltui a0, 0xc, 0x65ca
64+
# CHECK-INST-NEXT: jal zero, 0x7a1a
65+
# CHECK-INST-RELAX: qc.bltui a0, 0xc, 0x65ca
66+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
67+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L6
68+
qc.bgeui a0, 12, .L6
69+
.fill 1300, 4, 0
70+
.L6:
71+
ret
72+
73+
# CHECK-INST: qc.e.beqi a0, 0x1, 0x7a26
74+
# CHECK-INST-NEXT: jal zero, 0x8e76
75+
# CHECK-INST-RELAX: qc.e.beqi a0, 0x1, 0x7a26
76+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
77+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L7
78+
qc.e.bnei a0, 1, .L7
79+
.fill 1300, 4, 0
80+
.L7:
81+
ret
82+
83+
# CHECK-INST: qc.e.bnei a0, 0x2, 0x8e82
84+
# CHECK-INST-NEXT: jal zero, 0xa2d2
85+
# CHECK-INST-RELAX: qc.e.bnei a0, 0x2, 0x8e82
86+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
87+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L8
88+
qc.e.beqi a0, 2, .L8
89+
.fill 1300, 4, 0
90+
.L8:
91+
ret
92+
93+
# CHECK-INST: qc.e.bgei a0, 0x3, 0xa2de
94+
# CHECK-INST-NEXT: jal zero, 0xb72e
95+
# CHECK-INST-RELAX: qc.e.bgei a0, 0x3, 0xa2de
96+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
97+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L9
98+
qc.e.blti a0, 3, .L9
99+
.fill 1300, 4, 0
100+
.L9:
101+
ret
102+
103+
# CHECK-INST: qc.e.blti a0, 0x4, 0xb73a
104+
# CHECK-INST-NEXT: jal zero, 0xcb8a
105+
# CHECK-INST-RELAX: qc.e.blti a0, 0x4, 0xb73a
106+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
107+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L10
108+
qc.e.bgei a0, 4, .L10
109+
.fill 1300, 4, 0
110+
.L10:
111+
ret
112+
113+
# CHECK-INST: qc.e.bgeui a0, 0x5, 0xcb96
114+
# CHECK-INST-NEXT: jal zero, 0xdfe6
115+
# CHECK-INST-RELAX: qc.e.bgeui a0, 0x5, 0xcb96
116+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
117+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L11
118+
qc.e.bltui a0, 5, .L11
119+
.fill 1300, 4, 0
120+
.L11:
121+
ret
122+
123+
# CHECK-INST: qc.e.bltui a0, 0x6, 0xdff2
124+
# CHECK-INST-NEXT: jal zero, 0xf442
125+
# CHECK-INST-RELAX: qc.e.bltui a0, 0x6, 0xdff2
126+
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
127+
# CHECK-INST-RELAX-NEXT: R_RISCV_JAL .L12
128+
qc.e.bgeui a0, 6, .L12
129+
.fill 1300, 4, 0
130+
.L12:
131+
ret
132+
133+
.Lfunc_end0:
134+
.size test, .Lfunc_end0-test

llvm/test/MC/RISCV/xqcibi-relocations.s

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,22 @@
1010

1111
.text
1212

13-
# Check that branch to an undefined symbol is handled
14-
# FIXME: This should be relaxed to an inverse branch and jump
13+
# Since foo is undefined, this will be relaxed to (qc.beqi + jal)
1514
qc.bnei x6, 10, foo
16-
# RELOC: R_RISCV_BRANCH foo 0x0
15+
# RELOC: R_RISCV_JAL foo 0x0
1716
# INSTR: qc.bnei t1, 10, foo
1817
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_branch
1918

20-
# FIXME: This should be relaxed to an inverse branch and jump
19+
# Since foo is undefined, this will be relaxed to (qc.e.bltui + jal)
2120
qc.e.bgeui x8, 12, foo
22-
# RELOC: R_RISCV_CUSTOM193 foo 0x0
21+
# RELOC: R_RISCV_JAL foo 0x0
2322
# INSTR: qc.e.bgeui s0, 12, foo
2423
# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_riscv_qc_e_branch
2524

26-
# Check that a label in a different section is handled similar to an undefined symbol
27-
# FIXME: This should be relaxed to an inverse branch and jump
25+
# Check that a label in a different section is handled similar to an undefined
26+
# symbol and gets relaxed to (qc.e.bgeui + jal)
2827
qc.e.bltui x4, 9, .bar
29-
# RELOC: R_RISCV_CUSTOM193 .bar 0x0
28+
# RELOC: R_RISCV_JAL .bar 0x0
3029
# INSTR: qc.e.bltui tp, 9, .bar
3130
# FIXUP: fixup A - offset: 0, value: .bar, kind: fixup_riscv_qc_e_branch
3231

0 commit comments

Comments
 (0)