AsmPrinter: Compute absolute label difference directly

Create a low-overhead path for `EmitLabelDifference()` that emits a
emits an absolute number when (1) the output is an object stream and (2)
the two symbols are in the same data fragment.

This drops memory usage on Mach-O from 975 MB down to 919 MB (5.8%).
The only call is when `!doesDwarfUseRelocationsAcrossSections()` --
i.e., on Mach-O -- since otherwise an absolute offset from the start of
the section needs a relocation.  (`EmitLabelDifference()` is cheaper on
ELF anyway, since it creates 1 fewer temp symbol, and it gets called far
less often.  It's not clear to me if this is even a bottleneck there.)

(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237876 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan P. N. Exon Smith 2015-05-21 02:41:23 +00:00
parent 1d4f2ba509
commit 583dac827c
4 changed files with 47 additions and 0 deletions

View File

@ -136,6 +136,17 @@ public:
void EmitZeros(uint64_t NumBytes) override;
void FinishImpl() override;
/// Emit the absolute difference between two symbols if possible.
///
/// Emit the absolute difference between \c Hi and \c Lo, as long as we can
/// compute it. Currently, that requires that both symbols are in the same
/// data fragment. Otherwise, do nothing and return \c false.
///
/// \pre Offset of \c Hi is greater than the offset \c Lo.
/// \return true on success.
bool emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
unsigned Size) override;
bool mayHaveInstructions() const override {
return getCurrentSectionData()->hasInstructions();
}

View File

@ -652,6 +652,15 @@ public:
unsigned Isa, unsigned Discriminator,
StringRef FileName);
/// Emit the absolute difference between two symbols if possible.
///
/// \pre Offset of \c Hi is greater than the offset \c Lo.
/// \return true on success.
virtual bool emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
unsigned Size) {
return false;
}
virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID);
virtual void EmitCFISections(bool EH, bool Debug);
void EmitCFIStartProc(bool IsSimple);

View File

@ -1591,6 +1591,10 @@ void AsmPrinter::EmitInt32(int Value) const {
/// .set if it avoids relocations.
void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
unsigned Size) const {
if (!MAI->doesDwarfUseRelocationsAcrossSections())
if (OutStreamer->emitAbsoluteSymbolDiff(Hi, Lo, Size))
return;
// Get the Hi-Lo expression.
const MCExpr *Diff =
MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(Hi, OutContext),

View File

@ -53,6 +53,29 @@ void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
}
}
bool MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
const MCSymbol *Lo,
unsigned Size) {
// Must have symbol data.
if (!Assembler->hasSymbolData(*Hi) || !Assembler->hasSymbolData(*Lo))
return false;
auto &HiD = Assembler->getSymbolData(*Hi);
auto &LoD = Assembler->getSymbolData(*Lo);
// Must both be assigned to the same (valid) fragment.
if (!HiD.getFragment() || HiD.getFragment() != LoD.getFragment())
return false;
// Must be a data fragment.
if (!isa<MCDataFragment>(HiD.getFragment()))
return false;
assert(HiD.getOffset() >= LoD.getOffset() &&
"Expected Hi to be greater than Lo");
EmitIntValue(HiD.getOffset() - LoD.getOffset(), Size);
return true;
}
void MCObjectStreamer::reset() {
if (Assembler)
Assembler->reset();