Skip to content

Commit 9f66ebe

Browse files
committed
MC: Eliminate redundant fragment relaxation
The relaxOnce function now returns the index of the last modified section, allowing subsequent calls to skip already stable sections. This optimization can often save redundant iteration for trailing .debug_ sections, leading to minor instructions:u decrease. https://llvm-compile-time-tracker.com/compare.php?from=aec88832df5e8c1dcbe259a6cb3d82d44b89ff23&to=8012fb16eff93cba48e5f08166762c5333bd1d42&stat=instructions:u
1 parent aec8883 commit 9f66ebe

File tree

2 files changed

+19
-13
lines changed

2 files changed

+19
-13
lines changed

llvm/include/llvm/MC/MCAssembler.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ class MCAssembler {
113113
bool fragmentNeedsRelaxation(const MCRelaxableFragment &) const;
114114

115115
void layoutSection(MCSection &Sec);
116-
/// Perform one layout iteration and return true if any offsets
117-
/// were adjusted.
118-
bool relaxOnce();
116+
/// Perform one layout iteration and return the index of the first stable
117+
/// section for subsequent optimization.
118+
unsigned relaxOnce(unsigned FirstStable);
119119

120120
/// Perform relaxation on a single fragment.
121121
bool relaxFragment(MCFragment &F);

llvm/lib/MC/MCAssembler.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,8 @@ void MCAssembler::layout() {
795795
this->HasLayout = true;
796796
for (MCSection &Sec : *this)
797797
layoutSection(Sec);
798-
while (relaxOnce())
798+
unsigned FirstStable = Sections.size();
799+
while ((FirstStable = relaxOnce(FirstStable)) > 0)
799800
if (getContext().hadError())
800801
return;
801802

@@ -1127,31 +1128,36 @@ void MCAssembler::layoutSection(MCSection &Sec) {
11271128
}
11281129
}
11291130

1130-
bool MCAssembler::relaxOnce() {
1131+
unsigned MCAssembler::relaxOnce(unsigned FirstStable) {
11311132
++stats::RelaxationSteps;
11321133
PendingErrors.clear();
11331134

1134-
// Size of fragments in one section can depend on the size of fragments in
1135-
// another. If any fragment has changed size, we have to re-layout (and
1136-
// as a result possibly further relax) all sections.
1137-
bool ChangedAny = false;
1138-
for (MCSection &Sec : *this) {
1135+
unsigned Res = 0;
1136+
for (unsigned I = 0; I != FirstStable; ++I) {
11391137
// Assume each iteration finalizes at least one extra fragment. If the
11401138
// layout does not converge after N+1 iterations, bail out.
1139+
auto &Sec = *Sections[I];
11411140
auto MaxIter = Sec.curFragList()->Tail->getLayoutOrder() + 1;
11421141
for (;;) {
11431142
bool Changed = false;
11441143
for (MCFragment &F : Sec)
11451144
if (relaxFragment(F))
11461145
Changed = true;
11471146

1148-
ChangedAny |= Changed;
1149-
if (!Changed || --MaxIter == 0)
1147+
if (!Changed)
1148+
break;
1149+
// If any fragment changed size, it might impact the layout of subsequent
1150+
// sections. Therefore, we must re-evaluate all sections.
1151+
FirstStable = Sections.size();
1152+
Res = I;
1153+
if (--MaxIter == 0)
11501154
break;
11511155
layoutSection(Sec);
11521156
}
11531157
}
1154-
return ChangedAny;
1158+
// The subsequent relaxOnce call only needs to visit Sections [0,Res) if no
1159+
// change occurred.
1160+
return Res;
11551161
}
11561162

11571163
void MCAssembler::reportError(SMLoc L, const Twine &Msg) const {

0 commit comments

Comments
 (0)