Skip to content

Commit 07d2709

Browse files
committed
Revert "[MC] Compute fragment offsets eagerly"
This reverts commit be5a845. This causes large code size regressions, which were not present in the initial version of this change.
1 parent 4094098 commit 07d2709

File tree

8 files changed

+123
-127
lines changed

8 files changed

+123
-127
lines changed

llvm/include/llvm/MC/MCAsmBackend.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,8 @@ class MCAsmBackend {
217217
virtual bool writeNopData(raw_ostream &OS, uint64_t Count,
218218
const MCSubtargetInfo *STI) const = 0;
219219

220-
// Return true if fragment offsets have been adjusted and an extra layout
221-
// iteration is needed.
222-
virtual bool finishLayout(const MCAssembler &Asm) const { return false; }
220+
/// Give backend an opportunity to finish layout after relaxation
221+
virtual void finishLayout(MCAssembler const &Asm) const {}
223222

224223
/// Handle any target-specific assembler flags. By default, do nothing.
225224
virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {}

llvm/include/llvm/MC/MCAssembler.h

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ class MCAssembler {
6565

6666
bool HasLayout = false;
6767
bool RelaxAll = false;
68-
unsigned RelaxSteps = 0;
6968

7069
SectionListType Sections;
7170

@@ -114,18 +113,19 @@ class MCAssembler {
114113

115114
/// Perform one layout iteration and return true if any offsets
116115
/// were adjusted.
117-
bool relaxOnce();
118-
119-
/// Perform relaxation on a single fragment.
120-
void relaxFragment(MCFragment &F);
121-
void relaxInstruction(MCRelaxableFragment &IF);
122-
void relaxLEB(MCLEBFragment &IF);
123-
void relaxBoundaryAlign(MCBoundaryAlignFragment &BF);
124-
void relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF);
125-
void relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF);
126-
void relaxCVInlineLineTable(MCCVInlineLineTableFragment &DF);
127-
void relaxCVDefRange(MCCVDefRangeFragment &DF);
128-
void relaxPseudoProbeAddr(MCPseudoProbeAddrFragment &DF);
116+
bool layoutOnce();
117+
118+
/// Perform relaxation on a single fragment - returns true if the fragment
119+
/// changes as a result of relaxation.
120+
bool relaxFragment(MCFragment &F);
121+
bool relaxInstruction(MCRelaxableFragment &IF);
122+
bool relaxLEB(MCLEBFragment &IF);
123+
bool relaxBoundaryAlign(MCBoundaryAlignFragment &BF);
124+
bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF);
125+
bool relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF);
126+
bool relaxCVInlineLineTable(MCCVInlineLineTableFragment &DF);
127+
bool relaxCVDefRange(MCCVDefRangeFragment &DF);
128+
bool relaxPseudoProbeAddr(MCPseudoProbeAddrFragment &DF);
129129

130130
std::tuple<MCValue, uint64_t, bool>
131131
handleFixup(MCFragment &F, const MCFixup &Fixup, const MCSubtargetInfo *STI);
@@ -147,9 +147,10 @@ class MCAssembler {
147147
uint64_t computeFragmentSize(const MCFragment &F) const;
148148

149149
void layoutBundle(MCFragment *Prev, MCFragment *F) const;
150+
void ensureValid(MCSection &Sec) const;
150151

151152
// Get the offset of the given fragment inside its containing section.
152-
uint64_t getFragmentOffset(const MCFragment &F) const { return F.Offset; }
153+
uint64_t getFragmentOffset(const MCFragment &F) const;
153154

154155
uint64_t getSectionAddressSize(const MCSection &Sec) const;
155156
uint64_t getSectionFileSize(const MCSection &Sec) const;

llvm/include/llvm/MC/MCSection.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ class MCSection {
9999
/// Whether this section has had instructions emitted into it.
100100
bool HasInstructions : 1;
101101

102+
bool HasLayout : 1;
103+
102104
bool IsRegistered : 1;
103105

104106
bool IsText : 1;
@@ -167,6 +169,9 @@ class MCSection {
167169
bool hasInstructions() const { return HasInstructions; }
168170
void setHasInstructions(bool Value) { HasInstructions = Value; }
169171

172+
bool hasLayout() const { return HasLayout; }
173+
void setHasLayout(bool Value) { HasLayout = Value; }
174+
170175
bool isRegistered() const { return IsRegistered; }
171176
void setIsRegistered(bool Value) { IsRegistered = Value; }
172177

llvm/lib/MC/MCAssembler.cpp

Lines changed: 68 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -261,11 +261,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const {
261261
}
262262
int64_t Size = NumValues * FF.getValueSize();
263263
if (Size < 0) {
264-
// The expression might use symbol values which have not yet converged.
265-
// Allow the first few iterations to have temporary negative values. The
266-
// limit is somewhat arbitrary but allows contrived interdependency.
267-
if (RelaxSteps >= 2)
268-
getContext().reportError(FF.getLoc(), "invalid number of bytes");
264+
getContext().reportError(FF.getLoc(), "invalid number of bytes");
269265
return 0;
270266
}
271267
return Size;
@@ -432,6 +428,28 @@ void MCAssembler::layoutBundle(MCFragment *Prev, MCFragment *F) const {
432428
DF->Offset = EF->Offset;
433429
}
434430

431+
void MCAssembler::ensureValid(MCSection &Sec) const {
432+
if (Sec.hasLayout())
433+
return;
434+
Sec.setHasLayout(true);
435+
MCFragment *Prev = nullptr;
436+
uint64_t Offset = 0;
437+
for (MCFragment &F : Sec) {
438+
F.Offset = Offset;
439+
if (isBundlingEnabled() && F.hasInstructions()) {
440+
layoutBundle(Prev, &F);
441+
Offset = F.Offset;
442+
}
443+
Offset += computeFragmentSize(F);
444+
Prev = &F;
445+
}
446+
}
447+
448+
uint64_t MCAssembler::getFragmentOffset(const MCFragment &F) const {
449+
ensureValid(*F.getParent());
450+
return F.Offset;
451+
}
452+
435453
// Simple getSymbolOffset helper for the non-variable case.
436454
static bool getLabelOffset(const MCAssembler &Asm, const MCSymbol &S,
437455
bool ReportError, uint64_t &Val) {
@@ -911,38 +929,22 @@ void MCAssembler::layout() {
911929

912930
// Layout until everything fits.
913931
this->HasLayout = true;
914-
for (MCSection &Sec : *this) {
915-
MCFragment *Prev = nullptr;
916-
uint64_t Offset = 0;
917-
for (MCFragment &F : Sec) {
918-
F.Offset = Offset;
919-
if (LLVM_UNLIKELY(isBundlingEnabled())) {
920-
if (F.hasInstructions()) {
921-
layoutBundle(Prev, &F);
922-
Offset = F.Offset;
923-
}
924-
Prev = &F;
925-
}
926-
Offset += computeFragmentSize(F);
927-
}
928-
}
929-
while (relaxOnce())
932+
while (layoutOnce()) {
930933
if (getContext().hadError())
931934
return;
935+
// Size of fragments in one section can depend on the size of fragments in
936+
// another. If any fragment has changed size, we have to re-layout (and
937+
// as a result possibly further relax) all.
938+
for (MCSection &Sec : *this)
939+
Sec.setHasLayout(false);
940+
}
932941

933942
DEBUG_WITH_TYPE("mc-dump", {
934943
errs() << "assembler backend - post-relaxation\n--\n";
935944
dump(); });
936945

937-
// Some targets might want to adjust fragment offsets. If so, perform another
938-
// relaxation loop.
939-
if (getBackend().finishLayout(*this))
940-
while (relaxOnce())
941-
if (getContext().hadError())
942-
return;
943-
944-
// Trigger computeFragmentSize errors.
945-
RelaxSteps = UINT_MAX;
946+
// Finalize the layout, including fragment lowering.
947+
getBackend().finishLayout(*this);
946948

947949
DEBUG_WITH_TYPE("mc-dump", {
948950
errs() << "assembler backend - final-layout\n--\n";
@@ -1071,11 +1073,11 @@ bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F) const {
10711073
return false;
10721074
}
10731075

1074-
void MCAssembler::relaxInstruction(MCRelaxableFragment &F) {
1076+
bool MCAssembler::relaxInstruction(MCRelaxableFragment &F) {
10751077
assert(getEmitterPtr() &&
10761078
"Expected CodeEmitter defined for relaxInstruction");
10771079
if (!fragmentNeedsRelaxation(&F))
1078-
return;
1080+
return false;
10791081

10801082
++stats::RelaxedInstructions;
10811083

@@ -1093,9 +1095,10 @@ void MCAssembler::relaxInstruction(MCRelaxableFragment &F) {
10931095
F.getContents().clear();
10941096
getEmitter().encodeInstruction(Relaxed, F.getContents(), F.getFixups(),
10951097
*F.getSubtargetInfo());
1098+
return true;
10961099
}
10971100

1098-
void MCAssembler::relaxLEB(MCLEBFragment &LF) {
1101+
bool MCAssembler::relaxLEB(MCLEBFragment &LF) {
10991102
const unsigned OldSize = static_cast<unsigned>(LF.getContents().size());
11001103
unsigned PadTo = OldSize;
11011104
int64_t Value;
@@ -1131,6 +1134,7 @@ void MCAssembler::relaxLEB(MCLEBFragment &LF) {
11311134
encodeSLEB128(Value, OSE, PadTo);
11321135
else
11331136
encodeULEB128(Value, OSE, PadTo);
1137+
return OldSize != LF.getContents().size();
11341138
}
11351139

11361140
/// Check if the branch crosses the boundary.
@@ -1170,11 +1174,11 @@ static bool needPadding(uint64_t StartAddr, uint64_t Size,
11701174
isAgainstBoundary(StartAddr, Size, BoundaryAlignment);
11711175
}
11721176

1173-
void MCAssembler::relaxBoundaryAlign(MCBoundaryAlignFragment &BF) {
1177+
bool MCAssembler::relaxBoundaryAlign(MCBoundaryAlignFragment &BF) {
11741178
// BoundaryAlignFragment that doesn't need to align any fragment should not be
11751179
// relaxed.
11761180
if (!BF.getLastFragment())
1177-
return;
1181+
return false;
11781182

11791183
uint64_t AlignedOffset = getFragmentOffset(BF);
11801184
uint64_t AlignedSize = 0;
@@ -1188,15 +1192,19 @@ void MCAssembler::relaxBoundaryAlign(MCBoundaryAlignFragment &BF) {
11881192
uint64_t NewSize = needPadding(AlignedOffset, AlignedSize, BoundaryAlignment)
11891193
? offsetToAlignment(AlignedOffset, BoundaryAlignment)
11901194
: 0U;
1195+
if (NewSize == BF.getSize())
1196+
return false;
11911197
BF.setSize(NewSize);
1198+
return true;
11921199
}
11931200

1194-
void MCAssembler::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF) {
1201+
bool MCAssembler::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF) {
11951202
bool WasRelaxed;
11961203
if (getBackend().relaxDwarfLineAddr(*this, DF, WasRelaxed))
1197-
return;
1204+
return WasRelaxed;
11981205

11991206
MCContext &Context = getContext();
1207+
uint64_t OldSize = DF.getContents().size();
12001208
int64_t AddrDelta;
12011209
bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, *this);
12021210
assert(Abs && "We created a line delta with an invalid expression");
@@ -1209,12 +1217,13 @@ void MCAssembler::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF) {
12091217

12101218
MCDwarfLineAddr::encode(Context, getDWARFLinetableParams(), LineDelta,
12111219
AddrDelta, Data);
1220+
return OldSize != Data.size();
12121221
}
12131222

1214-
void MCAssembler::relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF) {
1223+
bool MCAssembler::relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF) {
12151224
bool WasRelaxed;
12161225
if (getBackend().relaxDwarfCFA(*this, DF, WasRelaxed))
1217-
return;
1226+
return WasRelaxed;
12181227

12191228
MCContext &Context = getContext();
12201229
int64_t Value;
@@ -1223,25 +1232,31 @@ void MCAssembler::relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF) {
12231232
getContext().reportError(DF.getAddrDelta().getLoc(),
12241233
"invalid CFI advance_loc expression");
12251234
DF.setAddrDelta(MCConstantExpr::create(0, Context));
1226-
return;
1235+
return false;
12271236
}
12281237

12291238
SmallVectorImpl<char> &Data = DF.getContents();
1239+
uint64_t OldSize = Data.size();
12301240
Data.clear();
12311241
DF.getFixups().clear();
12321242

12331243
MCDwarfFrameEmitter::encodeAdvanceLoc(Context, Value, Data);
1244+
return OldSize != Data.size();
12341245
}
12351246

1236-
void MCAssembler::relaxCVInlineLineTable(MCCVInlineLineTableFragment &F) {
1247+
bool MCAssembler::relaxCVInlineLineTable(MCCVInlineLineTableFragment &F) {
1248+
unsigned OldSize = F.getContents().size();
12371249
getContext().getCVContext().encodeInlineLineTable(*this, F);
1250+
return OldSize != F.getContents().size();
12381251
}
12391252

1240-
void MCAssembler::relaxCVDefRange(MCCVDefRangeFragment &F) {
1253+
bool MCAssembler::relaxCVDefRange(MCCVDefRangeFragment &F) {
1254+
unsigned OldSize = F.getContents().size();
12411255
getContext().getCVContext().encodeDefRange(*this, F);
1256+
return OldSize != F.getContents().size();
12421257
}
12431258

1244-
void MCAssembler::relaxPseudoProbeAddr(MCPseudoProbeAddrFragment &PF) {
1259+
bool MCAssembler::relaxPseudoProbeAddr(MCPseudoProbeAddrFragment &PF) {
12451260
uint64_t OldSize = PF.getContents().size();
12461261
int64_t AddrDelta;
12471262
bool Abs = PF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, *this);
@@ -1254,12 +1269,13 @@ void MCAssembler::relaxPseudoProbeAddr(MCPseudoProbeAddrFragment &PF) {
12541269

12551270
// AddrDelta is a signed integer
12561271
encodeSLEB128(AddrDelta, OSE, OldSize);
1272+
return OldSize != Data.size();
12571273
}
12581274

1259-
void MCAssembler::relaxFragment(MCFragment &F) {
1275+
bool MCAssembler::relaxFragment(MCFragment &F) {
12601276
switch(F.getKind()) {
12611277
default:
1262-
return;
1278+
return false;
12631279
case MCFragment::FT_Relaxable:
12641280
assert(!getRelaxAll() &&
12651281
"Did not expect a MCRelaxableFragment in RelaxAll mode");
@@ -1281,57 +1297,15 @@ void MCAssembler::relaxFragment(MCFragment &F) {
12811297
}
12821298
}
12831299

1284-
bool MCAssembler::relaxOnce() {
1300+
bool MCAssembler::layoutOnce() {
12851301
++stats::RelaxationSteps;
1286-
++RelaxSteps;
1287-
1288-
// Size of fragments in one section can depend on the size of fragments in
1289-
// another. If any fragment has changed size, we have to re-layout (and
1290-
// as a result possibly further relax) all sections.
1291-
bool ChangedAny = false, Changed;
1292-
for (MCSection &Sec : *this) {
1293-
// Assume each iteration finalizes at least one extra fragment. If the
1294-
// layout does not converge after N+1 iterations, bail out.
1295-
auto MaxIter = Sec.curFragList()->Tail->getLayoutOrder() + 1;
1296-
uint64_t OldSize = getSectionAddressSize(Sec);
1297-
do {
1298-
uint64_t Offset = 0;
1299-
Changed = false;
1300-
if (LLVM_UNLIKELY(isBundlingEnabled())) {
1301-
MCFragment *Prev = nullptr;
1302-
for (MCFragment &F : Sec) {
1303-
F.Offset = Offset;
1304-
relaxFragment(F);
1305-
if (F.hasInstructions()) {
1306-
layoutBundle(Prev, &F);
1307-
Offset = F.Offset;
1308-
}
1309-
Prev = &F;
1310-
if (F.Offset != Offset) {
1311-
F.Offset = Offset;
1312-
Changed = true;
1313-
}
1314-
Offset += computeFragmentSize(F);
1315-
}
1316-
} else {
1317-
for (MCFragment &F : Sec) {
1318-
if (F.Offset != Offset) {
1319-
F.Offset = Offset;
1320-
Changed = true;
1321-
}
1322-
relaxFragment(F);
1323-
Offset += computeFragmentSize(F);
1324-
}
1325-
}
13261302

1327-
Changed |= OldSize != Offset;
1328-
ChangedAny |= Changed;
1329-
OldSize = Offset;
1330-
} while (Changed && --MaxIter);
1331-
if (MaxIter == 0)
1332-
return false;
1333-
}
1334-
return ChangedAny;
1303+
bool Changed = false;
1304+
for (MCSection &Sec : *this)
1305+
for (MCFragment &Frag : Sec)
1306+
if (relaxFragment(Frag))
1307+
Changed = true;
1308+
return Changed;
13351309
}
13361310

13371311
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

llvm/lib/MC/MCSection.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ using namespace llvm;
2323
MCSection::MCSection(SectionVariant V, StringRef Name, bool IsText,
2424
bool IsVirtual, MCSymbol *Begin)
2525
: Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false),
26-
IsRegistered(false), IsText(IsText), IsVirtual(IsVirtual), Name(Name),
27-
Variant(V) {
26+
HasLayout(false), IsRegistered(false), IsText(IsText),
27+
IsVirtual(IsVirtual), Name(Name), Variant(V) {
2828
DummyFragment.setParent(this);
2929
// The initial subsection number is 0. Create a fragment list.
3030
CurFragList = &Subsections.emplace_back(0u, FragList{}).second;

0 commit comments

Comments
 (0)