diff options
Diffstat (limited to 'llvm/lib/Target/AArch64/AArch64CollectLOH.cpp')
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64CollectLOH.cpp | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64CollectLOH.cpp b/llvm/lib/Target/AArch64/AArch64CollectLOH.cpp index efdb1131abc9..ac243347b24d 100644 --- a/llvm/lib/Target/AArch64/AArch64CollectLOH.cpp +++ b/llvm/lib/Target/AArch64/AArch64CollectLOH.cpp @@ -419,13 +419,37 @@ static void handleADRP(const MachineInstr &MI, AArch64FunctionInfo &AFI, ++NumADRPToLDR; } break; - case MCLOH_AdrpAddLdr: + case MCLOH_AdrpAddLdr: { + // There is a possibility that the linker may try to rewrite: + // adrp x0, @sym@PAGE + // add x1, x0, @sym@PAGEOFF + // [x0 = some other def] + // ldr x2, [x1] + // ...into... + // adrp x0, @sym + // nop + // [x0 = some other def] + // ldr x2, [x0] + // ...if the offset to the symbol won't fit within a literal load. + // This causes the load to use the result of the adrp, which in this + // case has already been clobbered. + // FIXME: Implement proper liveness tracking for all registers. For now, + // don't emit the LOH if there are any instructions between the add and + // the ldr. + MachineInstr *AddMI = const_cast<MachineInstr *>(Info.MI1); + const MachineInstr *LdrMI = Info.MI0; + auto AddIt = MachineBasicBlock::iterator(AddMI); + auto EndIt = AddMI->getParent()->end(); + if (AddMI->getIterator() == EndIt || LdrMI != &*next_nodbg(AddIt, EndIt)) + break; + LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAddLdr:\n" << '\t' << MI << '\t' << *Info.MI1 << '\t' << *Info.MI0); AFI.addLOHDirective(MCLOH_AdrpAddLdr, {&MI, Info.MI1, Info.MI0}); ++NumADDToLDR; break; + } case MCLOH_AdrpAddStr: if (Info.MI1 != nullptr) { LLVM_DEBUG(dbgs() << "Adding MCLOH_AdrpAddStr:\n" |