From 0b73d71abb5f08e435a6731bc65f4cb9d755f00c Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Thu, 21 May 2015 02:41:23 +0000 Subject: [PATCH] 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.) llvm-svn: 237876 --- llvm/include/llvm/MC/MCObjectStreamer.h | 11 +++++++++++ llvm/include/llvm/MC/MCStreamer.h | 9 +++++++++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 4 ++++ llvm/lib/MC/MCObjectStreamer.cpp | 23 ++++++++++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 8499560d2d78..1a1222562f15 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -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(); } diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 9107df629337..3dec9491a265 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -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); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 5af083536d79..17bbf01c43fb 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -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), diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index d82dd15df2bc..836b1ced5c53 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -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(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();