[llvm] [MC][DebugInfo] Emit linetable entries with known offsets immediately (PR #134677)
Jeremy Morse via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 7 09:00:27 PDT 2025
https://github.com/jmorse created https://github.com/llvm/llvm-project/pull/134677
DWARF linetable entries are usually emitted as a sequence of MCDwarfLineAddrFragment fragments containing the line-number difference and an MCExpr describing the instruction-range the linetable entry covers. These then get relaxed during assembly emission.
However, a large number of these instruction-range expressions are ranges within a fixed MCDataFragment, i.e. a range over fixed-size instructions that are not subject to relaxation at a later stage. Thus, we can compute the address-delta immediately, and not spend time and memory describing that computation so it can be deferred.
~
A slightly earlier+dirtier version of this patch scored a cool 5% reduction in max-rss on most compile-time tracker samples -- see [0], scroll down to stage1-releaselto-g and observe the improvement in ".link" jobs. The intermediate jobs are LTO bitcode compilations so don't codegen, thus only the .link jobs are representative. The three compiles that don't improve (tramp3d, mafft, SPASS) are due to the domination of variable-location storage for tramp3d, and LiveDebugValues hitting max-rss for the last two.
I'm not intensely familiar with the MCFragment layer so I'm not sure what the best test strategy is. A stage2reldeb build of clang produced an identical binary, but as a performance improvement it's not clear if this needs a functional test. If so, I imagine using `-debug-only=mc-dump` and examining what fragments are produced would be the way forwards?
Note that the RISCV opt-out comes from precedent set in `MCObjectStreamer::emitAbsoluteSymbolDiff` and friends, RISCV appears to want to opt out of these space optimisations.
[0] https://llvm-compile-time-tracker.com/compare.php?from=e2c43ba981620cf71ce3ccf004db7c0db4caf8a7&to=ca512762f92108bea21b2e2517f9e17f9d680a33&stat=max-rss&details=on
>From ccf51251975c10ab78ea23e19d20cd1635d2c0a5 Mon Sep 17 00:00:00 2001
From: Jeremy Morse <jeremy.morse at sony.com>
Date: Mon, 7 Apr 2025 15:46:30 +0100
Subject: [PATCH 1/2] [MC][DebugInfo] Emit linetable entries with known offsets
immediately
DWARF linetable entries are usually emitted as a sequence of
MCDwarfLineAddrFragment fragments containing the line-number difference and
an MCExpr describing the instruction-range the linetable entry covers.
These then get relaxed during assembly emission.
However, a large number of these instruction-range expressions are ranges
within a fixed MCDataFragment, i.e. a range over fixed-size instructions
that are not subject to relaxation at a later stage. Thus, we can compute
the address-delta immediately, and not spend time and memory describing
that computation so it can be deferred.
---
llvm/lib/MC/MCObjectStreamer.cpp | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index e228418fea987..4aee1cedaf346 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -462,6 +462,22 @@ void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
Label, PointerSize);
return;
}
+
+ // If the two labels are within the same fragment and it's a plain data
+ // fragment, then the address-offset is already a fixed constant and is not
+ // relaxable. Emit the advance-line-addr data immediately to save time and
+ // memory.
+ MCFragment *LastFrag = LastLabel->getFragment();
+ if (LastFrag->getKind() == MCFragment::FT_Data &&
+ Label->getFragment() == LastFrag) {
+ uint64_t AddrDelta = Label->getOffset() - LastLabel->getOffset();
+ SmallString<16> Tmp;
+ MCDwarfLineAddr::encode(getContext(), Assembler->getDWARFLinetableParams(),
+ LineDelta, AddrDelta, Tmp);
+ emitBytes(Tmp);
+ return;
+ }
+
const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, SMLoc());
insert(getContext().allocFragment<MCDwarfLineAddrFragment>(LineDelta,
*AddrDelta));
>From e5bcdbf4063e4356242526b963f1031d2b33e5a0 Mon Sep 17 00:00:00 2001
From: Jeremy Morse <jeremy.morse at sony.com>
Date: Mon, 7 Apr 2025 16:50:19 +0100
Subject: [PATCH 2/2] Disable this performance opt on RISCV
See the comments on bbea64250f6548, the RISCV relocation model does
something differently, and thus we need to emit linetables in a fully
symbolic way.
---
llvm/lib/MC/MCObjectStreamer.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 4aee1cedaf346..8d1eab03290a9 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -467,8 +467,10 @@ void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
// fragment, then the address-offset is already a fixed constant and is not
// relaxable. Emit the advance-line-addr data immediately to save time and
// memory.
+ // As per commit bbea64250f6548, RISCV always desires symbolic relocations.
MCFragment *LastFrag = LastLabel->getFragment();
- if (LastFrag->getKind() == MCFragment::FT_Data &&
+ if (!getAssembler().getContext().getTargetTriple().isRISCV() &&
+ LastFrag->getKind() == MCFragment::FT_Data &&
Label->getFragment() == LastFrag) {
uint64_t AddrDelta = Label->getOffset() - LastLabel->getOffset();
SmallString<16> Tmp;
More information about the llvm-commits
mailing list