[BOLT][AArch64] Add support for LDR relaxation on LDRSWl (#196051)
BOLT currently supports LDR relaxation for LDRXl and LDRWl. Add support for LDR relaxation on LDRSWl.
This commit is contained in:
parent
27c5421df2
commit
51e82b849c
4 changed files with 58 additions and 24 deletions
|
|
@ -861,12 +861,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual bool isLDRWl(const MCInst &Inst) const {
|
||||
llvm_unreachable("not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool isLDRXl(const MCInst &Inst) const {
|
||||
virtual bool isLoadLiteralGPR(const MCInst &Inst) const {
|
||||
llvm_unreachable("not implemented");
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ void AArch64RelaxationPass::runOnFunction(BinaryFunction &BF) {
|
|||
bool IsADR = BC.MIB->isADR(Inst);
|
||||
|
||||
// TODO: Handle other types of LDR (literal, PC-relative) instructions.
|
||||
if (!IsADR && !BC.MIB->isLDRXl(Inst) && !BC.MIB->isLDRWl(Inst))
|
||||
if (!IsADR && !BC.MIB->isLoadLiteralGPR(Inst))
|
||||
continue;
|
||||
|
||||
const MCSymbol *Symbol = BC.MIB->getTargetSymbol(Inst, IsADR ? 0 : 1);
|
||||
|
|
|
|||
|
|
@ -715,12 +715,10 @@ public:
|
|||
return Inst.getOpcode() == AArch64::ADDXri;
|
||||
}
|
||||
|
||||
bool isLDRWl(const MCInst &Inst) const override {
|
||||
return Inst.getOpcode() == AArch64::LDRWl;
|
||||
}
|
||||
|
||||
bool isLDRXl(const MCInst &Inst) const override {
|
||||
return Inst.getOpcode() == AArch64::LDRXl;
|
||||
bool isLoadLiteralGPR(const MCInst &Inst) const override {
|
||||
unsigned OpCode = Inst.getOpcode();
|
||||
return OpCode == AArch64::LDRWl || OpCode == AArch64::LDRXl ||
|
||||
OpCode == AArch64::LDRSWl;
|
||||
}
|
||||
|
||||
MCPhysReg getADRReg(const MCInst &Inst) const {
|
||||
|
|
@ -744,16 +742,36 @@ public:
|
|||
|
||||
InstructionListType createAdrpLdr(const MCInst &LDRInst,
|
||||
MCContext *Ctx) const override {
|
||||
assert((isLDRXl(LDRInst) || isLDRWl(LDRInst)) &&
|
||||
"LDR (literal, 32 or 64-bit integer load) instruction expected");
|
||||
assert(isLoadLiteralGPR(LDRInst) &&
|
||||
"LDR (literal) or LDRSW (literal) expected");
|
||||
assert(LDRInst.getOperand(0).isReg() &&
|
||||
"unexpected operand in LDR instruction");
|
||||
const MCPhysReg DataReg = LDRInst.getOperand(0).getReg();
|
||||
const MCPhysReg AddrReg =
|
||||
isLDRXl(LDRInst) ? DataReg
|
||||
: (MCPhysReg)RegInfo->getMatchingSuperReg(
|
||||
DataReg, AArch64::sub_32,
|
||||
&RegInfo->getRegClass(AArch64::GPR64RegClassID));
|
||||
MCPhysReg AddrReg;
|
||||
unsigned OpCode;
|
||||
uint32_t RelType;
|
||||
switch (LDRInst.getOpcode()) {
|
||||
case AArch64::LDRWl:
|
||||
AddrReg = (MCPhysReg)RegInfo->getMatchingSuperReg(
|
||||
DataReg, AArch64::sub_32,
|
||||
&RegInfo->getRegClass(AArch64::GPR64RegClassID));
|
||||
OpCode = AArch64::LDRWui;
|
||||
RelType = ELF::R_AARCH64_LDST32_ABS_LO12_NC;
|
||||
break;
|
||||
case AArch64::LDRXl:
|
||||
AddrReg = DataReg;
|
||||
OpCode = AArch64::LDRXui;
|
||||
RelType = ELF::R_AARCH64_LDST64_ABS_LO12_NC;
|
||||
break;
|
||||
case AArch64::LDRSWl:
|
||||
AddrReg = DataReg;
|
||||
OpCode = AArch64::LDRSWui;
|
||||
RelType = ELF::R_AARCH64_LDST64_ABS_LO12_NC;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("LDR (literal) or LDRSW (literal) expected");
|
||||
}
|
||||
|
||||
const MCSymbol *Target = getTargetSymbol(LDRInst, 1);
|
||||
assert(Target && "missing target symbol in LDR instruction");
|
||||
|
||||
|
|
@ -764,15 +782,13 @@ public:
|
|||
Insts[0].addOperand(MCOperand::createImm(0));
|
||||
setOperandToSymbolRef(Insts[0], /* OpNum */ 1, Target, 0, Ctx,
|
||||
ELF::R_AARCH64_NONE);
|
||||
Insts[1].setOpcode(isLDRXl(LDRInst) ? AArch64::LDRXui : AArch64::LDRWui);
|
||||
Insts[1].setOpcode(OpCode);
|
||||
Insts[1].clear();
|
||||
Insts[1].addOperand(MCOperand::createReg(DataReg));
|
||||
Insts[1].addOperand(MCOperand::createReg(AddrReg));
|
||||
Insts[1].addOperand(MCOperand::createImm(0));
|
||||
Insts[1].addOperand(MCOperand::createImm(0));
|
||||
setOperandToSymbolRef(Insts[1], /* OpNum */ 2, Target, 0, Ctx,
|
||||
isLDRXl(LDRInst) ? ELF::R_AARCH64_LDST64_ABS_LO12_NC
|
||||
: ELF::R_AARCH64_LDST32_ABS_LO12_NC);
|
||||
setOperandToSymbolRef(Insts[1], /* OpNum */ 2, Target, 0, Ctx, RelType);
|
||||
return Insts;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,29 @@ _start:
|
|||
ret
|
||||
.cfi_endproc
|
||||
.size _start, .-_start
|
||||
.endif
|
||||
|
||||
## Check LDR relaxation works on LDRSW (literal)
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \
|
||||
# RUN: --defsym RELAX_SIMPLE_LDRSW=1 %s -o %t.o
|
||||
# RUN: %clang %cflags %t.o -o %t.so -Wl,-q
|
||||
# RUN: llvm-bolt %t.so -o %t.bolt
|
||||
# RUN: llvm-objdump -d %t.bolt | FileCheck %s --check-prefix=RELAX_LDRSW
|
||||
|
||||
# RELAX_LDRSW: adrp
|
||||
# RELAX_LDRSW-NEXT: ldrsw
|
||||
|
||||
.ifdef RELAX_SIMPLE_LDRSW
|
||||
.text
|
||||
.global _start
|
||||
.type _start, %function
|
||||
_start:
|
||||
.cfi_startproc
|
||||
ldrsw x0, _foo
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size _start, .-_start
|
||||
.endif
|
||||
|
||||
.section .text_cold
|
||||
|
|
|
|||
Loading…
Reference in a new issue