Skip to content

Commit de19f7b

Browse files
authored
[MC] Replace fragment ilist with singly-linked lists
Fragments are allocated with `operator new` and stored in an ilist with Prev/Next/Parent pointers. A more efficient representation would be an array of fragments without the overhead of Prev/Next pointers. As the first step, replace ilist with singly-linked lists. * `getPrevNode` uses have been eliminated by previous changes. * The last use of the `Prev` pointer remains: for each subsection, there is an insertion point and the current insertion point is stored at `CurInsertionPoint`. * `HexagonAsmBackend::finishLayout` needs a backward iterator. Save all fragments within `Frags`. Hexagon programs are usually small, and the performance does not matter that much. To eliminate `Prev`, change the subsection representation to singly-linked lists for subsections and a pointer to the active singly-linked list. The fragments from all subsections will be chained together at layout time. Since fragment lists are disconnected before layout time, we can remove `MCFragment::SubsectionNumber` (https://reviews.llvm.org/D69411). The current implementation of `AttemptToFoldSymbolOffsetDifference` requires future improvement for robustness. Pull Request: #95077
1 parent 4cf607f commit de19f7b

File tree

12 files changed

+123
-125
lines changed

12 files changed

+123
-125
lines changed

llvm/include/llvm/MC/MCFragment.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@
2323

2424
namespace llvm {
2525

26+
class MCAssembler;
2627
class MCSection;
2728
class MCSubtargetInfo;
2829
class MCSymbol;
2930

30-
class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
31+
class MCFragment {
3132
friend class MCAsmLayout;
33+
friend class MCAssembler;
34+
friend class MCSection;
3235

3336
public:
3437
enum FragmentType : uint8_t {
@@ -51,6 +54,9 @@ class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
5154
};
5255

5356
private:
57+
// The next fragment within the section.
58+
MCFragment *Next = nullptr;
59+
5460
/// The data for the section this fragment is in.
5561
MCSection *Parent;
5662

@@ -64,10 +70,6 @@ class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
6470
/// The layout order of this fragment.
6571
unsigned LayoutOrder;
6672

67-
/// The subsection this fragment belongs to. This is 0 if the fragment is not
68-
// in any subsection.
69-
unsigned SubsectionNumber = 0;
70-
7173
FragmentType Kind;
7274

7375
protected:
@@ -88,6 +90,8 @@ class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
8890
/// This method will dispatch to the appropriate subclass.
8991
void destroy();
9092

93+
MCFragment *getNext() const { return Next; }
94+
9195
FragmentType getKind() const { return Kind; }
9296

9397
MCSection *getParent() const { return Parent; }
@@ -104,9 +108,6 @@ class MCFragment : public ilist_node_with_parent<MCFragment, MCSection> {
104108
bool hasInstructions() const { return HasInstructions; }
105109

106110
void dump() const;
107-
108-
void setSubsectionNumber(unsigned Value) { SubsectionNumber = Value; }
109-
unsigned getSubsectionNumber() const { return SubsectionNumber; }
110111
};
111112

112113
class MCDummyFragment : public MCFragment {

llvm/include/llvm/MC/MCObjectStreamer.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ class raw_pwrite_stream;
4141
/// implementation.
4242
class MCObjectStreamer : public MCStreamer {
4343
std::unique_ptr<MCAssembler> Assembler;
44-
MCSection::iterator CurInsertionPoint;
4544
bool EmitEHFrame;
4645
bool EmitDebugFrame;
4746
SmallVector<MCSymbol *, 2> PendingLabels;
@@ -94,7 +93,7 @@ class MCObjectStreamer : public MCStreamer {
9493
void insert(MCFragment *F) {
9594
flushPendingLabels(F);
9695
MCSection *CurSection = getCurrentSectionOnly();
97-
CurSection->getFragmentList().insert(CurInsertionPoint, F);
96+
CurSection->addFragment(*F);
9897
F->setParent(CurSection);
9998
}
10099

llvm/include/llvm/MC/MCSection.h

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#define LLVM_MC_MCSECTION_H
1515

1616
#include "llvm/ADT/SmallVector.h"
17-
#include "llvm/ADT/ilist.h"
1817
#include "llvm/MC/MCFragment.h"
1918
#include "llvm/MC/SectionKind.h"
2019
#include "llvm/Support/Alignment.h"
@@ -24,20 +23,18 @@
2423
namespace llvm {
2524

2625
class MCAsmInfo;
26+
class MCAssembler;
2727
class MCContext;
2828
class MCExpr;
2929
class MCSymbol;
3030
class raw_ostream;
3131
class Triple;
3232

33-
template <> struct ilist_alloc_traits<MCFragment> {
34-
static void deleteNode(MCFragment *V);
35-
};
36-
3733
/// Instances of this class represent a uniqued identifier for a section in the
3834
/// current translation unit. The MCContext class uniques and creates these.
3935
class MCSection {
4036
public:
37+
friend MCAssembler;
4138
static constexpr unsigned NonUniqueID = ~0U;
4239

4340
enum SectionVariant {
@@ -58,12 +55,29 @@ class MCSection {
5855
BundleLockedAlignToEnd
5956
};
6057

61-
using FragmentListType = iplist<MCFragment>;
58+
struct iterator {
59+
MCFragment *F = nullptr;
60+
iterator() = default;
61+
explicit iterator(MCFragment *F) : F(F) {}
62+
MCFragment &operator*() const { return *F; }
63+
bool operator==(const iterator &O) const { return F == O.F; }
64+
bool operator!=(const iterator &O) const { return F != O.F; }
65+
iterator &operator++() {
66+
F = F->Next;
67+
return *this;
68+
}
69+
iterator operator++(int) { return iterator(F->Next); }
70+
};
6271

63-
using const_iterator = FragmentListType::const_iterator;
64-
using iterator = FragmentListType::iterator;
72+
struct FragList {
73+
MCFragment *Head = nullptr;
74+
MCFragment *Tail = nullptr;
75+
};
6576

6677
private:
78+
// At parse time, this holds the fragment list of the current subsection. At
79+
// layout time, this holds the concatenated fragment lists of all subsections.
80+
FragList *CurFragList;
6781
MCSymbol *Begin;
6882
MCSymbol *End = nullptr;
6983
/// The alignment requirement of this section.
@@ -92,11 +106,10 @@ class MCSection {
92106

93107
MCDummyFragment DummyFragment;
94108

95-
FragmentListType Fragments;
96-
97-
/// Mapping from subsection number to insertion point for subsection numbers
98-
/// below that number.
99-
SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap;
109+
// Mapping from subsection number to fragment list. At layout time, the
110+
// subsection 0 list is replaced with concatenated fragments from all
111+
// subsections.
112+
SmallVector<std::pair<unsigned, FragList>, 1> Subsections;
100113

101114
/// State for tracking labels that don't yet have Fragments
102115
struct PendingLabel {
@@ -171,29 +184,27 @@ class MCSection {
171184
bool isRegistered() const { return IsRegistered; }
172185
void setIsRegistered(bool Value) { IsRegistered = Value; }
173186

174-
MCSection::FragmentListType &getFragmentList() { return Fragments; }
175-
const MCSection::FragmentListType &getFragmentList() const {
176-
return const_cast<MCSection *>(this)->getFragmentList();
177-
}
178-
179-
/// Support for MCFragment::getNextNode().
180-
static FragmentListType MCSection::*getSublistAccess(MCFragment *) {
181-
return &MCSection::Fragments;
182-
}
183-
184187
const MCDummyFragment &getDummyFragment() const { return DummyFragment; }
185188
MCDummyFragment &getDummyFragment() { return DummyFragment; }
186189

187-
iterator begin() { return Fragments.begin(); }
188-
const_iterator begin() const { return Fragments.begin(); }
189-
190-
iterator end() { return Fragments.end(); }
191-
const_iterator end() const { return Fragments.end(); }
192-
bool empty() const { return Fragments.empty(); }
193-
194-
void addFragment(MCFragment &F) { Fragments.push_back(&F); }
190+
FragList *curFragList() const { return CurFragList; }
191+
iterator begin() const { return iterator(CurFragList->Head); }
192+
iterator end() const { return {}; }
193+
bool empty() const { return !CurFragList->Head; }
194+
195+
void addFragment(MCFragment &F) {
196+
// The formal layout order will be finalized in MCAssembler::layout.
197+
if (CurFragList->Tail) {
198+
CurFragList->Tail->Next = &F;
199+
F.setLayoutOrder(CurFragList->Tail->getLayoutOrder() + 1);
200+
} else {
201+
CurFragList->Head = &F;
202+
assert(F.getLayoutOrder() == 0);
203+
}
204+
CurFragList->Tail = &F;
205+
}
195206

196-
MCSection::iterator getSubsectionInsertionPoint(unsigned Subsection);
207+
void switchSubsection(unsigned Subsection);
197208

198209
void dump() const;
199210

llvm/lib/MC/MCAssembler.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,19 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
831831
MCSection *Sec = Layout.getSectionOrder()[i];
832832
Sec->setLayoutOrder(i);
833833

834+
// Chain together fragments from all subsections.
835+
MCDummyFragment Dummy(Sec);
836+
MCFragment *Tail = &Dummy;
837+
for (auto &[_, List] : Sec->Subsections) {
838+
if (!List.Head)
839+
continue;
840+
Tail->Next = List.Head;
841+
Tail = List.Tail;
842+
}
843+
Sec->Subsections.clear();
844+
Sec->Subsections.push_back({0u, {Dummy.getNext(), Tail}});
845+
Sec->CurFragList = &Sec->Subsections[0].second;
846+
834847
unsigned FragmentIndex = 0;
835848
for (MCFragment &Frag : *Sec)
836849
Frag.setLayoutOrder(FragmentIndex++);
@@ -1094,7 +1107,7 @@ bool MCAssembler::relaxBoundaryAlign(MCAsmLayout &Layout,
10941107

10951108
uint64_t AlignedOffset = Layout.getFragmentOffset(&BF);
10961109
uint64_t AlignedSize = 0;
1097-
for (const MCFragment *F = BF.getNextNode();; F = F->getNextNode()) {
1110+
for (const MCFragment *F = BF.getNext();; F = F->getNext()) {
10981111
AlignedSize += computeFragmentSize(Layout, *F);
10991112
if (F == BF.getLastFragment())
11001113
break;

llvm/lib/MC/MCExpr.cpp

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -661,25 +661,16 @@ static void AttemptToFoldSymbolOffsetDifference(
661661
// this is important when the Subtarget is changed and a new MCDataFragment
662662
// is created in the case of foo: instr; .arch_extension ext; instr .if . -
663663
// foo.
664-
if (SA.isVariable() || SB.isVariable() ||
665-
FA->getSubsectionNumber() != FB->getSubsectionNumber())
664+
if (SA.isVariable() || SB.isVariable())
666665
return;
667666

668667
// Try to find a constant displacement from FA to FB, add the displacement
669668
// between the offset in FA of SA and the offset in FB of SB.
670669
bool Reverse = false;
671-
if (FA == FB) {
670+
if (FA == FB)
672671
Reverse = SA.getOffset() < SB.getOffset();
673-
} else if (!isa<MCDummyFragment>(FA)) {
674-
// Testing FA < FB is slow. Use setLayoutOrder to speed up computation.
675-
// The formal layout order will be finalized in MCAssembler::layout.
676-
if (FA->getLayoutOrder() == 0 || FB->getLayoutOrder()== 0) {
677-
unsigned LayoutOrder = 0;
678-
for (MCFragment &F : *FA->getParent())
679-
F.setLayoutOrder(++LayoutOrder);
680-
}
672+
else if (!isa<MCDummyFragment>(FA))
681673
Reverse = FA->getLayoutOrder() < FB->getLayoutOrder();
682-
}
683674

684675
uint64_t SAOffset = SA.getOffset(), SBOffset = SB.getOffset();
685676
int64_t Displacement = SA.getOffset() - SB.getOffset();
@@ -695,7 +686,7 @@ static void AttemptToFoldSymbolOffsetDifference(
695686
// instruction, the difference cannot be resolved as it may be changed by
696687
// the linker.
697688
bool BBeforeRelax = false, AAfterRelax = false;
698-
for (auto FI = FB->getIterator(), FE = SecA.end(); FI != FE; ++FI) {
689+
for (auto FI = FB; FI; FI = FI->getNext()) {
699690
auto DF = dyn_cast<MCDataFragment>(FI);
700691
if (DF && DF->isLinkerRelaxable()) {
701692
if (&*FI != FB || SBOffset != DF->getContents().size())
@@ -726,12 +717,14 @@ static void AttemptToFoldSymbolOffsetDifference(
726717
return;
727718
}
728719
}
729-
// If the previous loop does not find FA, FA must be a dummy fragment not in
730-
// the fragment list (which means SA is a pending label (see
731-
// flushPendingLabels)). In either case, we can resolve the difference.
732-
assert(Found || isa<MCDummyFragment>(FA));
733-
Addend += Reverse ? -Displacement : Displacement;
734-
FinalizeFolding();
720+
// If FA and FB belong to the same subsection, either the previous loop
721+
// found FA, or FA is a dummy fragment not in the fragment list (which means
722+
// SA is a pending label (see flushPendingLabels)) or FA and FB belong to
723+
// different subsections. In either case, we can resolve the difference.
724+
if (Found || isa<MCDummyFragment>(FA)) {
725+
Addend += Reverse ? -Displacement : Displacement;
726+
FinalizeFolding();
727+
}
735728
}
736729
}
737730

llvm/lib/MC/MCFragment.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const {
141141

142142
uint64_t MCAsmLayout::getSectionAddressSize(const MCSection *Sec) const {
143143
// The size is the last fragment's end offset.
144-
const MCFragment &F = Sec->getFragmentList().back();
144+
const MCFragment &F = *Sec->curFragList()->Tail;
145145
return getFragmentOffset(&F) + getAssembler().computeFragmentSize(*this, F);
146146
}
147147

@@ -197,8 +197,6 @@ uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler,
197197

198198
/* *** */
199199

200-
void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); }
201-
202200
MCFragment::MCFragment(FragmentType Kind, bool HasInstructions,
203201
MCSection *Parent)
204202
: Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)), LayoutOrder(0),

llvm/lib/MC/MCObjectStreamer.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ void MCObjectStreamer::reset() {
180180
if (getContext().getTargetOptions())
181181
Assembler->setRelaxAll(getContext().getTargetOptions()->MCRelaxAll);
182182
}
183-
CurInsertionPoint = MCSection::iterator();
184183
EmitEHFrame = true;
185184
EmitDebugFrame = false;
186185
PendingLabels.clear();
@@ -200,12 +199,7 @@ void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) {
200199
}
201200

202201
MCFragment *MCObjectStreamer::getCurrentFragment() const {
203-
assert(getCurrentSectionOnly() && "No current section!");
204-
205-
if (CurInsertionPoint != getCurrentSectionOnly()->begin())
206-
return &*std::prev(CurInsertionPoint);
207-
208-
return nullptr;
202+
return getCurrentSectionOnly()->curFragList()->Tail;
209203
}
210204

211205
static bool canReuseDataFragment(const MCDataFragment &F,
@@ -391,8 +385,7 @@ bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
391385
}
392386

393387
CurSubsectionIdx = unsigned(IntSubsection);
394-
CurInsertionPoint =
395-
Section->getSubsectionInsertionPoint(CurSubsectionIdx);
388+
Section->switchSubsection(CurSubsectionIdx);
396389
return Created;
397390
}
398391

0 commit comments

Comments
 (0)