[RISCV] Relax out of range Zibi conditional branches (#186965)
If `.Label` is not within +-4KiB range, we convert ``` beqi/bnei reg, imm, .Label ``` to ``` bnei/beqi reg, imm, 8 j .Label ``` This is similar to what is done for the RISCV conditional branches and `Xqcibi` conditional branches. --------- Co-authored-by: Sudharsan Veeravalli <svs@qti.qualcomm.com>
This commit is contained in:
parent
94411c9d56
commit
8efb87ae5a
6 changed files with 145 additions and 16 deletions
|
|
@ -196,6 +196,10 @@ static unsigned getRelaxedOpcode(unsigned Opcode, ArrayRef<MCOperand> Operands,
|
|||
return RISCV::PseudoLongBEQ;
|
||||
case RISCV::BNE:
|
||||
return RISCV::PseudoLongBNE;
|
||||
case RISCV::BEQI:
|
||||
return RISCV::PseudoLongBEQI;
|
||||
case RISCV::BNEI:
|
||||
return RISCV::PseudoLongBNEI;
|
||||
case RISCV::BLT:
|
||||
return RISCV::PseudoLongBLT;
|
||||
case RISCV::BGE:
|
||||
|
|
@ -285,6 +289,8 @@ void RISCVAsmBackend::relaxInstruction(MCInst &Inst,
|
|||
}
|
||||
case RISCV::BEQ:
|
||||
case RISCV::BNE:
|
||||
case RISCV::BEQI:
|
||||
case RISCV::BNEI:
|
||||
case RISCV::BLT:
|
||||
case RISCV::BGE:
|
||||
case RISCV::BLTU:
|
||||
|
|
|
|||
|
|
@ -255,6 +255,10 @@ static unsigned getInvertedBranchOp(unsigned BrOp) {
|
|||
return RISCV::BNE;
|
||||
case RISCV::PseudoLongBNE:
|
||||
return RISCV::BEQ;
|
||||
case RISCV::PseudoLongBEQI:
|
||||
return RISCV::BNEI;
|
||||
case RISCV::PseudoLongBNEI:
|
||||
return RISCV::BEQI;
|
||||
case RISCV::PseudoLongBLT:
|
||||
return RISCV::BGE;
|
||||
case RISCV::PseudoLongBGE:
|
||||
|
|
@ -297,14 +301,15 @@ void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI,
|
|||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
MCRegister SrcReg1 = MI.getOperand(0).getReg();
|
||||
MCRegister SrcReg2 = MI.getOperand(1).getReg();
|
||||
MCOperand SrcSymbol = MI.getOperand(2);
|
||||
const MCOperand &Src2 = MI.getOperand(1);
|
||||
const MCOperand &SrcSymbol = MI.getOperand(2);
|
||||
unsigned Opcode = MI.getOpcode();
|
||||
bool IsEqTest =
|
||||
Opcode == RISCV::PseudoLongBNE || Opcode == RISCV::PseudoLongBEQ;
|
||||
|
||||
bool UseCompressedBr = false;
|
||||
if (IsEqTest && STI.hasFeature(RISCV::FeatureStdExtZca)) {
|
||||
MCRegister SrcReg2 = Src2.getReg();
|
||||
if (RISCV::X8 <= SrcReg1.id() && SrcReg1.id() <= RISCV::X15 &&
|
||||
SrcReg2.id() == RISCV::X0) {
|
||||
UseCompressedBr = true;
|
||||
|
|
@ -326,7 +331,7 @@ void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI,
|
|||
} else {
|
||||
unsigned InvOpc = getInvertedBranchOp(Opcode);
|
||||
MCInst TmpInst =
|
||||
MCInstBuilder(InvOpc).addReg(SrcReg1).addReg(SrcReg2).addImm(8);
|
||||
MCInstBuilder(InvOpc).addReg(SrcReg1).addOperand(Src2).addImm(8);
|
||||
uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
|
||||
support::endian::write(CB, Binary, llvm::endianness::little);
|
||||
Offset = 4;
|
||||
|
|
@ -429,6 +434,8 @@ void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,
|
|||
return;
|
||||
case RISCV::PseudoLongBEQ:
|
||||
case RISCV::PseudoLongBNE:
|
||||
case RISCV::PseudoLongBEQI:
|
||||
case RISCV::PseudoLongBNEI:
|
||||
case RISCV::PseudoLongBLT:
|
||||
case RISCV::PseudoLongBGE:
|
||||
case RISCV::PseudoLongBLTU:
|
||||
|
|
|
|||
|
|
@ -1744,6 +1744,20 @@ class LongBccPseudo : Pseudo<(outs),
|
|||
let hasNoSchedulingInfo = 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
def PseudoLongBEQ : LongBccPseudo;
|
||||
def PseudoLongBNE : LongBccPseudo;
|
||||
def PseudoLongBLT : LongBccPseudo;
|
||||
|
|
|
|||
|
|
@ -1335,19 +1335,6 @@ let EmitPriority = 1 in {
|
|||
// 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
|
||||
|
|
|
|||
|
|
@ -41,6 +41,11 @@ class Branch_imm<bits<3> funct3, string opcodestr>
|
|||
let Predicates = [HasStdExtZibi] in {
|
||||
def BEQI : Branch_imm<0b010, "beqi">;
|
||||
def BNEI : Branch_imm<0b011, "bnei">;
|
||||
|
||||
// For long branch relaxation.
|
||||
// This will be expanded into BEQI/BNEI(4 bytes) + JAL(4 bytes).
|
||||
def PseudoLongBEQI : LongBcciPseudo<imm5_zibi, 8>;
|
||||
def PseudoLongBNEI : LongBcciPseudo<imm5_zibi, 8>;
|
||||
} // Predicates = [HasStdExtZibi]
|
||||
|
||||
multiclass BccImmPat<CondCode Cond, Branch_imm Inst> {
|
||||
|
|
|
|||
110
llvm/test/MC/RISCV/zibi-long-conditional-jump.s
Normal file
110
llvm/test/MC/RISCV/zibi-long-conditional-jump.s
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
# RUN: llvm-mc -filetype=obj --mattr=+experimental-zibi -triple=riscv32 %s \
|
||||
# RUN: | llvm-objdump --mattr=+experimental-zibi -d -M no-aliases - \
|
||||
# RUN: | FileCheck --check-prefix=CHECK-INST %s
|
||||
# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax,+experimental-zibi %s \
|
||||
# RUN: | llvm-objdump --mattr=+experimental-zibi -dr -M no-aliases - \
|
||||
# RUN: | FileCheck --check-prefix=CHECK-INST-RELAX %s
|
||||
|
||||
# Tests that are forward in range.
|
||||
|
||||
# CHECK-INST-LABEL: beqi_in_range_forward
|
||||
# CHECK-INST: beqi a0, 0xa, {{.*}}
|
||||
|
||||
# CHECK-INST-RELAX-LABEL: beqi_in_range_forward
|
||||
# CHECK-INST-RELAX: beqi a0, 0xa, {{.*}}
|
||||
beqi_in_range_forward:
|
||||
beqi a0, 10, .L1
|
||||
.fill 1000, 4, 0
|
||||
.L1:
|
||||
ret
|
||||
|
||||
# CHECK-INST-LABEL: bnei_in_range_forward
|
||||
# CHECK-INST: bnei a0, 0xa, {{.*}}
|
||||
|
||||
# CHECK-INST-RELAX-LABEL: bnei_in_range_forward
|
||||
# CHECK-INST-RELAX: bnei a0, 0xa, {{.*}}
|
||||
bnei_in_range_forward:
|
||||
bnei a0, 10, .L2
|
||||
.fill 1000, 4, 0
|
||||
.L2:
|
||||
ret
|
||||
|
||||
# Tests that are backward in range.
|
||||
|
||||
# CHECK-INST-LABEL: beqi_in_range_backward
|
||||
# CHECK-INST: beqi a0, 0xa, {{.*}}
|
||||
|
||||
# CHECK-INST-RELAX-LABEL: beqi_in_range_backward
|
||||
# CHECK-INST-RELAX: beqi a0, 0xa, {{.*}}
|
||||
beqi_in_range_backward:
|
||||
.L3:
|
||||
.fill 1000, 4, 0
|
||||
beqi a0, 10, .L3
|
||||
ret
|
||||
|
||||
# CHECK-INST-LABEL: bnei_in_range_backward
|
||||
# CHECK-INST: bnei a0, 0xa, {{.*}}
|
||||
|
||||
# CHECK-INST-RELAX-LABEL: bnei_in_range_backward
|
||||
# CHECK-INST-RELAX: bnei a0, 0xa, {{.*}}
|
||||
bnei_in_range_backward:
|
||||
.L4:
|
||||
.fill 1000, 4, 0
|
||||
bnei a0, 10, .L4
|
||||
ret
|
||||
|
||||
# Tests that are forward out of range.
|
||||
|
||||
# CHECK-INST-LABEL: beqi_out_of_range_forward
|
||||
# CHECK-INST: bnei a0, 0xa, {{.*}}+0x8
|
||||
# CHECK-INST-NEXT: jal zero, {{.*}}
|
||||
|
||||
# CHECK-INST-RELAX-LABEL: beqi_out_of_range_forward
|
||||
# CHECK-INST-RELAX: bnei a0, 0xa, {{.*}}+0x8
|
||||
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
|
||||
beqi_out_of_range_forward:
|
||||
beqi a0, 10, .L5
|
||||
.fill 1300, 4, 0
|
||||
.L5:
|
||||
ret
|
||||
|
||||
# CHECK-INST-LABEL: bnei_out_of_range_forward
|
||||
# CHECK-INST: beqi a0, 0xa, {{.*}}+0x8
|
||||
# CHECK-INST-NEXT: jal zero, {{.*}}
|
||||
|
||||
# CHECK-INST-RELAX-LABEL: bnei_out_of_range_forward
|
||||
# CHECK-INST-RELAX: beqi a0, 0xa, {{.*}}+0x8
|
||||
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
|
||||
bnei_out_of_range_forward:
|
||||
bnei a0, 10, .L6
|
||||
.fill 1300, 4, 0
|
||||
.L6:
|
||||
ret
|
||||
|
||||
# Tests that are backward out of range.
|
||||
|
||||
# CHECK-INST-LABEL: beqi_out_of_range_backward
|
||||
# CHECK-INST: bnei a0, 0xa, {{.*}}+0x1458
|
||||
# CHECK-INST-NEXT: jal zero, {{.*}}
|
||||
|
||||
# CHECK-INST-RELAX-LABEL: beqi_out_of_range_backward
|
||||
# CHECK-INST-RELAX: bnei a0, 0xa, {{.*}}+0x1458
|
||||
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
|
||||
beqi_out_of_range_backward:
|
||||
.L7:
|
||||
.fill 1300, 4, 0
|
||||
beqi a0, 10, .L7
|
||||
ret
|
||||
|
||||
# CHECK-INST-LABEL: bnei_out_of_range_backward
|
||||
# CHECK-INST: beqi a0, 0xa, {{.*}}+0x1458
|
||||
# CHECK-INST-NEXT: jal zero, {{.*}}
|
||||
|
||||
# CHECK-INST-RELAX-LABEL: bnei_out_of_range_backward
|
||||
# CHECK-INST-RELAX: beqi a0, 0xa, {{.*}}+0x1458
|
||||
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
|
||||
bnei_out_of_range_backward:
|
||||
.L8:
|
||||
.fill 1300, 4, 0
|
||||
bnei a0, 10, .L8
|
||||
ret
|
||||
Loading…
Reference in a new issue