Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand All @@ -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));
Expand Down
97 changes: 97 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
33 changes: 33 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
134 changes: 134 additions & 0 deletions llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
Original file line number Diff line number Diff line change
@@ -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
15 changes: 7 additions & 8 deletions llvm/test/MC/RISCV/xqcibi-relocations.s
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down