mirror of
https://github.com/intel/llvm.git
synced 2026-01-27 06:06:34 +08:00
[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.
This commit is contained in:
committed by
GitHub
parent
1f72fa29ec
commit
d59594d697
@@ -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));
|
||||
|
||||
@@ -68,6 +68,10 @@ public:
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
|
||||
134
llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
Normal file
134
llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
Normal file
@@ -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
|
||||
@@ -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
|
||||
# Check that a label in a different section is handled similar to an undefined
|
||||
# symbol and gets 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user