diff options
author | Fangrui Song <i@maskray.me> | 2024-07-21 15:42:27 -0700 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2024-07-21 15:42:27 -0700 |
commit | 1a47f3f3db66589c11f8ddacfeaecc03fb80c510 (patch) | |
tree | 330ffed41d0e82743f27e6fda3d3e2c0d93e0fca /llvm/lib/MC/MCAssembler.cpp | |
parent | 0387cd052b081d6bc9856ef756942a5df1a2a301 (diff) | |
download | llvm-1a47f3f3db66589c11f8ddacfeaecc03fb80c510.zip llvm-1a47f3f3db66589c11f8ddacfeaecc03fb80c510.tar.gz llvm-1a47f3f3db66589c11f8ddacfeaecc03fb80c510.tar.bz2 |
[MC] Compute fragment offsets eagerly
This builds on top of commit 9d0754ada5dbbc0c009bcc2f7824488419cc5530
("[MC] Relax fragments eagerly") and relaxes fragments eagerly to
eliminate MCSection::HasLayout and `getFragmentOffset` overhead.
Note: The removed `#ifndef NDEBUG` code (disabled by default) in
X86AsmBackend::finishLayout was problematic, as (a) !NDEBUG and NDEBUG
builds evaluated fragment offsets at different times before this patch
(b) one iteration might not be sufficient to converge. There might be
some edge cases that it did not handle. Anyhow, this patch probably
makes it work for more cases.
Diffstat (limited to 'llvm/lib/MC/MCAssembler.cpp')
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 77 |
1 files changed, 40 insertions, 37 deletions
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index e731dfc..a8652d2 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -438,28 +438,6 @@ void MCAssembler::layoutBundle(MCFragment *Prev, MCFragment *F) const { DF->Offset = EF->Offset; } -void MCAssembler::ensureValid(MCSection &Sec) const { - if (Sec.hasLayout()) - return; - Sec.setHasLayout(true); - MCFragment *Prev = nullptr; - uint64_t Offset = 0; - for (MCFragment &F : Sec) { - F.Offset = Offset; - if (isBundlingEnabled() && F.hasInstructions()) { - layoutBundle(Prev, &F); - Offset = F.Offset; - } - Offset += computeFragmentSize(F); - Prev = &F; - } -} - -uint64_t MCAssembler::getFragmentOffset(const MCFragment &F) const { - ensureValid(*F.getParent()); - return F.Offset; -} - // Simple getSymbolOffset helper for the non-variable case. static bool getLabelOffset(const MCAssembler &Asm, const MCSymbol &S, bool ReportError, uint64_t &Val) { @@ -944,22 +922,20 @@ void MCAssembler::layout() { // Layout until everything fits. this->HasLayout = true; + for (MCSection &Sec : *this) + layoutSection(Sec); while (layoutOnce()) { - if (getContext().hadError()) - return; - // Size of fragments in one section can depend on the size of fragments in - // another. If any fragment has changed size, we have to re-layout (and - // as a result possibly further relax) all. - for (MCSection &Sec : *this) - Sec.setHasLayout(false); } DEBUG_WITH_TYPE("mc-dump", { errs() << "assembler backend - post-relaxation\n--\n"; dump(); }); - // Finalize the layout, including fragment lowering. - getBackend().finishLayout(*this); + // Some targets might want to adjust fragment offsets. If so, perform another + // layout loop. + if (getBackend().finishLayout(*this)) + for (MCSection &Sec : *this) + layoutSection(Sec); DEBUG_WITH_TYPE("mc-dump", { errs() << "assembler backend - final-layout\n--\n"; @@ -1312,15 +1288,42 @@ bool MCAssembler::relaxFragment(MCFragment &F) { } } +void MCAssembler::layoutSection(MCSection &Sec) { + MCFragment *Prev = nullptr; + uint64_t Offset = 0; + for (MCFragment &F : Sec) { + F.Offset = Offset; + if (LLVM_UNLIKELY(isBundlingEnabled())) { + if (F.hasInstructions()) { + layoutBundle(Prev, &F); + Offset = F.Offset; + } + Prev = &F; + } + Offset += computeFragmentSize(F); + } +} + bool MCAssembler::layoutOnce() { ++stats::RelaxationSteps; - bool Changed = false; - for (MCSection &Sec : *this) - for (MCFragment &Frag : Sec) - if (relaxFragment(Frag)) - Changed = true; - return Changed; + // Size of fragments in one section can depend on the size of fragments in + // another. If any fragment has changed size, we have to re-layout (and + // as a result possibly further relax) all. + bool ChangedAny = false; + for (MCSection &Sec : *this) { + for (;;) { + bool Changed = false; + for (MCFragment &F : Sec) + if (relaxFragment(F)) + Changed = true; + ChangedAny |= Changed; + if (!Changed) + break; + layoutSection(Sec); + } + } + return ChangedAny; } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |