Skip to content

Commit 5065134

Browse files
author
Fabian Parzefall
committed
Revert "[BOLT] Allocate FunctionFragment on heap"
This reverts commit 101344a.
1 parent 6304e38 commit 5065134

File tree

9 files changed

+166
-271
lines changed

9 files changed

+166
-271
lines changed

bolt/include/bolt/Core/BinaryEmitter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ void emitBinaryContext(MCStreamer &Streamer, BinaryContext &BC,
3535
/// Emit \p BF function code. The caller is responsible for emitting function
3636
/// symbol(s) and setting the section to emit the code to.
3737
void emitFunctionBody(MCStreamer &Streamer, BinaryFunction &BF,
38-
FunctionFragment &FF, bool EmitCodeOnly);
38+
const FunctionFragment &FF, bool EmitCodeOnly);
3939

4040
} // namespace bolt
4141
} // namespace llvm

bolt/include/bolt/Core/FunctionLayout.h

Lines changed: 81 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
#include "llvm/ADT/SmallVector.h"
2525
#include "llvm/ADT/iterator.h"
2626
#include "llvm/ADT/iterator_range.h"
27-
#include <iterator>
28-
#include <utility>
2927

3028
namespace llvm {
3129
namespace bolt {
@@ -71,41 +69,28 @@ class FunctionFragment {
7169
using FragmentListType = SmallVector<unsigned, 0>;
7270

7371
public:
74-
using iterator = raw_pointer_iterator<BasicBlockListType::const_iterator,
75-
BinaryBasicBlock>;
76-
using const_iterator =
77-
raw_pointer_iterator<BasicBlockListType::const_iterator,
78-
const BinaryBasicBlock>;
72+
using const_iterator = BasicBlockListType::const_iterator;
7973

8074
private:
81-
FunctionLayout *Layout;
8275
FragmentNum Num;
83-
unsigned StartIndex;
84-
unsigned Size = 0;
76+
const FunctionLayout &Layout;
8577

86-
FunctionFragment(FunctionLayout &Layout, FragmentNum Num);
87-
FunctionFragment(const FunctionFragment &) = default;
88-
FunctionFragment(FunctionFragment &&) = default;
89-
FunctionFragment &operator=(const FunctionFragment &) = default;
90-
FunctionFragment &operator=(FunctionFragment &&) = default;
91-
~FunctionFragment() = default;
78+
FunctionFragment(FragmentNum Num, const FunctionLayout &Layout)
79+
: Num(Num), Layout(Layout) {}
9280

9381
public:
9482
FragmentNum getFragmentNum() const { return Num; }
95-
bool isMainFragment() const {
96-
return getFragmentNum() == FragmentNum::main();
97-
}
98-
bool isSplitFragment() const { return !isMainFragment(); }
83+
bool isMainFragment() const { return Num.get() == 0; }
84+
bool isSplitFragment() const { return Num.get() > 0; }
9985

100-
unsigned size() const { return Size; };
101-
bool empty() const { return size() == 0; };
102-
iterator begin();
86+
unsigned size() const;
87+
bool empty() const;
10388
const_iterator begin() const;
104-
iterator end();
10589
const_iterator end() const;
106-
const BinaryBasicBlock *front() const;
90+
BinaryBasicBlock *front() const;
10791

10892
friend class FunctionLayout;
93+
friend class FragmentIterator;
10994
};
11095

11196
/// The function layout represents the fragments we split a function into and
@@ -118,84 +103,102 @@ class FunctionFragment {
118103
/// iterating either over fragments or over BinaryFunction::begin()..end().
119104
class FunctionLayout {
120105
private:
121-
using FragmentListType = SmallVector<FunctionFragment *, 0>;
122106
using BasicBlockListType = SmallVector<BinaryBasicBlock *, 0>;
123107
using block_iterator = BasicBlockListType::iterator;
108+
using FragmentListType = SmallVector<unsigned, 0>;
124109

125110
public:
126-
using fragment_iterator = pointee_iterator<FragmentListType::const_iterator>;
127-
using fragment_const_iterator =
128-
pointee_iterator<FragmentListType::const_iterator,
129-
const FunctionFragment>;
130-
using block_const_iterator =
131-
raw_pointer_iterator<BasicBlockListType::const_iterator,
132-
const BinaryBasicBlock>;
133-
using block_reverse_iterator = std::reverse_iterator<block_iterator>;
111+
class FragmentIterator;
112+
113+
class FragmentIterator
114+
: public iterator_facade_base<
115+
FragmentIterator, std::bidirectional_iterator_tag, FunctionFragment,
116+
std::ptrdiff_t, FunctionFragment *, FunctionFragment> {
117+
FragmentNum Num;
118+
const FunctionLayout *Layout;
119+
120+
FragmentIterator(FragmentNum Num, const FunctionLayout *Layout)
121+
: Num(Num), Layout(Layout) {
122+
assert(Num.get() <= Layout->fragment_size() &&
123+
"Initializing iterator out of bounds");
124+
}
125+
126+
public:
127+
bool operator==(const FragmentIterator &Other) const {
128+
return Num == Other.Num;
129+
}
130+
131+
FunctionFragment operator*() const {
132+
assert(Num.get() < Layout->fragment_size() &&
133+
"Dereferencing end() iterator (or past it)");
134+
return FunctionFragment(Num, *Layout);
135+
}
136+
137+
FragmentIterator &operator++() {
138+
assert(Num.get() < Layout->fragment_size() &&
139+
"Incrementing iterator past end()");
140+
Num = FragmentNum(Num.get() + 1);
141+
return *this;
142+
}
143+
144+
FragmentIterator &operator--() {
145+
assert(Num.get() > 0 && "Decrementing iterator past begin()");
146+
Num = FragmentNum(Num.get() - 1);
147+
return *this;
148+
}
149+
150+
friend class FunctionLayout;
151+
};
152+
153+
using const_iterator = FragmentIterator;
154+
using block_const_iterator = BasicBlockListType::const_iterator;
134155
using block_const_reverse_iterator =
135-
std::reverse_iterator<block_const_iterator>;
156+
BasicBlockListType::const_reverse_iterator;
136157

137158
private:
138-
FragmentListType Fragments;
139159
BasicBlockListType Blocks;
160+
/// List of indices dividing block list into fragments. To simplify iteration,
161+
/// we have `Fragments.back()` equals `Blocks.size()`. Hence,
162+
/// `Fragments.size()` equals `this->size() + 1`. Always contains at least one
163+
/// fragment.
164+
FragmentListType Fragments = {0, 0};
140165

141166
public:
142-
FunctionLayout();
143-
FunctionLayout(const FunctionLayout &Other);
144-
FunctionLayout(FunctionLayout &&Other);
145-
FunctionLayout &operator=(const FunctionLayout &Other);
146-
FunctionLayout &operator=(FunctionLayout &&Other);
147-
~FunctionLayout();
148-
149167
/// Add an empty fragment.
150-
FunctionFragment &addFragment();
151-
152-
/// Return the fragment identified by Num.
153-
FunctionFragment &getFragment(FragmentNum Num);
168+
FunctionFragment addFragment();
154169

155170
/// Return the fragment identified by Num.
156-
const FunctionFragment &getFragment(FragmentNum Num) const;
171+
FunctionFragment getFragment(FragmentNum Num) const;
157172

158173
/// Get the fragment that contains all entry blocks and other blocks that
159174
/// cannot be split.
160-
FunctionFragment &getMainFragment() {
175+
FunctionFragment getMainFragment() const {
161176
return getFragment(FragmentNum::main());
162177
}
163178

164179
/// Get the fragment that contains all entry blocks and other blocks that
165180
/// cannot be split.
166-
const FunctionFragment &getMainFragment() const {
167-
return getFragment(FragmentNum::main());
168-
}
169-
170-
/// Get the fragment that contains all entry blocks and other blocks that
171-
/// cannot be split.
172-
iterator_range<fragment_iterator> getSplitFragments() {
173-
return {++fragment_begin(), fragment_end()};
174-
}
175-
176-
/// Get the fragment that contains all entry blocks and other blocks that
177-
/// cannot be split.
178-
iterator_range<fragment_const_iterator> getSplitFragments() const {
181+
iterator_range<const_iterator> getSplitFragments() const {
179182
return {++fragment_begin(), fragment_end()};
180183
}
181184

182185
/// Find the fragment that contains BB.
183-
const FunctionFragment &findFragment(const BinaryBasicBlock *BB) const;
186+
FunctionFragment findFragment(const BinaryBasicBlock *BB) const;
184187

185188
/// Add BB to the end of the last fragment.
186189
void addBasicBlock(BinaryBasicBlock *BB);
187190

188191
/// Insert range of basic blocks after InsertAfter. If InsertAfter is nullptr,
189192
/// the blocks will be inserted at the start of the function.
190-
void insertBasicBlocks(const BinaryBasicBlock *InsertAfter,
193+
void insertBasicBlocks(BinaryBasicBlock *InsertAfter,
191194
ArrayRef<BinaryBasicBlock *> NewBlocks);
192195

193196
/// Erase all blocks from the layout that are in ToErase. If this method
194197
/// erases all blocks of a fragment, it will be removed as well.
195198
void eraseBasicBlocks(const DenseSet<const BinaryBasicBlock *> ToErase);
196199

197200
/// Make sure fragments' and basic blocks' indices match the current layout.
198-
void updateLayoutIndices();
201+
void updateLayoutIndices() const;
199202

200203
/// Replace the current layout with NewLayout. Uses the block's
201204
/// self-identifying fragment number to assign blocks to infer function
@@ -206,25 +209,12 @@ class FunctionLayout {
206209
/// Clear layout releasing memory.
207210
void clear();
208211

209-
BinaryBasicBlock *getBlock(unsigned Index) { return Blocks[Index]; }
210-
211-
const BinaryBasicBlock *getBlock(unsigned Index) const {
212-
return Blocks[Index];
213-
}
214-
215-
/// Returns the basic block after the given basic block in the layout or
216-
/// nullptr if the last basic block is given.
217-
BinaryBasicBlock *getBasicBlockAfter(const BinaryBasicBlock *const BB,
218-
const bool IgnoreSplits = true) {
219-
return const_cast<BinaryBasicBlock *>(
220-
static_cast<const FunctionLayout &>(*this).getBasicBlockAfter(
221-
BB, IgnoreSplits));
222-
}
212+
BinaryBasicBlock *getBlock(unsigned Index) const { return Blocks[Index]; }
223213

224214
/// Returns the basic block after the given basic block in the layout or
225215
/// nullptr if the last basic block is given.
226-
const BinaryBasicBlock *getBasicBlockAfter(const BinaryBasicBlock *BB,
227-
bool IgnoreSplits = true) const;
216+
BinaryBasicBlock *getBasicBlockAfter(const BinaryBasicBlock *BB,
217+
bool IgnoreSplits = true) const;
228218

229219
/// True if the layout contains at least two non-empty fragments.
230220
bool isSplit() const;
@@ -240,49 +230,29 @@ class FunctionLayout {
240230
bool isHotColdSplit() const { return fragment_size() <= 2; }
241231

242232
size_t fragment_size() const {
243-
assert(Fragments.size() >= 1 &&
233+
assert(Fragments.size() >= 2 &&
244234
"Layout should have at least one fragment.");
245-
return Fragments.size();
235+
return Fragments.size() - 1;
246236
}
247-
bool fragment_empty() const { return fragment_size() == 0; }
248-
249-
fragment_iterator fragment_begin() { return Fragments.begin(); }
250-
fragment_const_iterator fragment_begin() const { return Fragments.begin(); }
251-
fragment_iterator fragment_end() { return Fragments.end(); }
252-
fragment_const_iterator fragment_end() const { return Fragments.end(); }
253-
iterator_range<fragment_iterator> fragments() {
254-
return {fragment_begin(), fragment_end()};
237+
bool fragment_empty() const { return Fragments.size() == 1; }
238+
const_iterator fragment_begin() const { return {FragmentNum(0), this}; }
239+
const_iterator fragment_end() const {
240+
return {FragmentNum(fragment_size()), this};
255241
}
256-
iterator_range<fragment_const_iterator> fragments() const {
242+
iterator_range<const_iterator> fragments() const {
257243
return {fragment_begin(), fragment_end()};
258244
}
259245

260246
size_t block_size() const { return Blocks.size(); }
261247
bool block_empty() const { return Blocks.empty(); }
262-
263-
/// Required to return non-const qualified `BinaryBasicBlock *` for graph
264-
/// traits.
265248
BinaryBasicBlock *block_front() const { return Blocks.front(); }
266-
const BinaryBasicBlock *block_back() const { return Blocks.back(); }
267-
268-
block_iterator block_begin() { return Blocks.begin(); }
269-
block_const_iterator block_begin() const {
270-
return block_const_iterator(Blocks.begin());
271-
}
272-
block_iterator block_end() { return Blocks.end(); }
273-
block_const_iterator block_end() const {
274-
return block_const_iterator(Blocks.end());
275-
}
276-
iterator_range<block_iterator> blocks() {
277-
return {block_begin(), block_end()};
278-
}
249+
BinaryBasicBlock *block_back() const { return Blocks.back(); }
250+
block_const_iterator block_begin() const { return Blocks.begin(); }
251+
block_const_iterator block_end() const { return Blocks.end(); }
279252
iterator_range<block_const_iterator> blocks() const {
280253
return {block_begin(), block_end()};
281254
}
282-
283-
block_reverse_iterator block_rbegin() { return Blocks.rbegin(); }
284255
block_const_reverse_iterator block_rbegin() const { return Blocks.rbegin(); }
285-
block_reverse_iterator block_rend() { return Blocks.rend(); }
286256
block_const_reverse_iterator block_rend() const { return Blocks.rend(); }
287257
iterator_range<block_const_reverse_iterator> rblocks() const {
288258
return {block_rbegin(), block_rend()};

bolt/lib/Core/BinaryContext.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2199,7 +2199,7 @@ BinaryContext::calculateEmittedSize(BinaryFunction &BF, bool FixBranches) {
21992199

22002200
using LabelRange = std::pair<const MCSymbol *, const MCSymbol *>;
22012201
SmallVector<LabelRange> SplitLabels;
2202-
for (FunctionFragment &FF : BF.getLayout().getSplitFragments()) {
2202+
for (const FunctionFragment FF : BF.getLayout().getSplitFragments()) {
22032203
MCSymbol *const SplitStartLabel = LocalCtx->createTempSymbol();
22042204
MCSymbol *const SplitEndLabel = LocalCtx->createTempSymbol();
22052205
SplitLabels.emplace_back(SplitStartLabel, SplitEndLabel);

bolt/lib/Core/BinaryEmitter.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,15 @@ class BinaryEmitter {
129129

130130
/// Emit function code. The caller is responsible for emitting function
131131
/// symbol(s) and setting the section to emit the code to.
132-
void emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF,
132+
void emitFunctionBody(BinaryFunction &BF, const FunctionFragment &FF,
133133
bool EmitCodeOnly = false);
134134

135135
private:
136136
/// Emit function code.
137137
void emitFunctions();
138138

139139
/// Emit a single function.
140-
bool emitFunction(BinaryFunction &BF, FunctionFragment &FF);
140+
bool emitFunction(BinaryFunction &BF, const FunctionFragment &FF);
141141

142142
/// Helper for emitFunctionBody to write data inside a function
143143
/// (used for AArch64)
@@ -234,7 +234,7 @@ void BinaryEmitter::emitFunctions() {
234234
!Function->hasValidProfile())
235235
Streamer.setAllowAutoPadding(false);
236236

237-
FunctionLayout &Layout = Function->getLayout();
237+
const FunctionLayout &Layout = Function->getLayout();
238238
Emitted |= emitFunction(*Function, Layout.getMainFragment());
239239

240240
if (Function->isSplit()) {
@@ -243,7 +243,7 @@ void BinaryEmitter::emitFunctions() {
243243

244244
assert((Layout.fragment_size() == 1 || Function->isSimple()) &&
245245
"Only simple functions can have fragments");
246-
for (FunctionFragment &FF : Layout.getSplitFragments()) {
246+
for (const FunctionFragment FF : Layout.getSplitFragments()) {
247247
// Skip empty fragments so no symbols and sections for empty fragments
248248
// are generated
249249
if (FF.empty() && !Function->hasConstantIsland())
@@ -280,7 +280,7 @@ void BinaryEmitter::emitFunctions() {
280280
}
281281

282282
bool BinaryEmitter::emitFunction(BinaryFunction &Function,
283-
FunctionFragment &FF) {
283+
const FunctionFragment &FF) {
284284
if (Function.size() == 0 && !Function.hasIslandsInfo())
285285
return false;
286286

@@ -402,7 +402,8 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function,
402402
return true;
403403
}
404404

405-
void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF,
405+
void BinaryEmitter::emitFunctionBody(BinaryFunction &BF,
406+
const FunctionFragment &FF,
406407
bool EmitCodeOnly) {
407408
if (!EmitCodeOnly && FF.isSplitFragment() && BF.hasConstantIsland()) {
408409
assert(BF.getLayout().isHotColdSplit() &&
@@ -1159,7 +1160,7 @@ void emitBinaryContext(MCStreamer &Streamer, BinaryContext &BC,
11591160
}
11601161

11611162
void emitFunctionBody(MCStreamer &Streamer, BinaryFunction &BF,
1162-
FunctionFragment &FF, bool EmitCodeOnly) {
1163+
const FunctionFragment &FF, bool EmitCodeOnly) {
11631164
BinaryEmitter(Streamer, BF.getBinaryContext())
11641165
.emitFunctionBody(BF, FF, EmitCodeOnly);
11651166
}

0 commit comments

Comments
 (0)