aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2024-07-21 15:42:27 -0700
committerFangrui Song <i@maskray.me>2024-07-21 15:42:27 -0700
commit1a47f3f3db66589c11f8ddacfeaecc03fb80c510 (patch)
tree330ffed41d0e82743f27e6fda3d3e2c0d93e0fca /llvm/lib/MC/MCAssembler.cpp
parent0387cd052b081d6bc9856ef756942a5df1a2a301 (diff)
downloadllvm-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.cpp77
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)