24
24
#include " llvm/ADT/SmallVector.h"
25
25
#include " llvm/ADT/iterator.h"
26
26
#include " llvm/ADT/iterator_range.h"
27
- #include < iterator>
28
- #include < utility>
29
27
30
28
namespace llvm {
31
29
namespace bolt {
@@ -71,41 +69,28 @@ class FunctionFragment {
71
69
using FragmentListType = SmallVector<unsigned , 0 >;
72
70
73
71
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;
79
73
80
74
private:
81
- FunctionLayout *Layout;
82
75
FragmentNum Num;
83
- unsigned StartIndex;
84
- unsigned Size = 0 ;
76
+ const FunctionLayout &Layout;
85
77
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) {}
92
80
93
81
public:
94
82
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 ; }
99
85
100
- unsigned size () const { return Size ; };
101
- bool empty () const { return size () == 0 ; };
102
- iterator begin ();
86
+ unsigned size () const ;
87
+ bool empty () const ;
103
88
const_iterator begin () const ;
104
- iterator end ();
105
89
const_iterator end () const ;
106
- const BinaryBasicBlock *front () const ;
90
+ BinaryBasicBlock *front () const ;
107
91
108
92
friend class FunctionLayout ;
93
+ friend class FragmentIterator ;
109
94
};
110
95
111
96
// / The function layout represents the fragments we split a function into and
@@ -118,84 +103,102 @@ class FunctionFragment {
118
103
// / iterating either over fragments or over BinaryFunction::begin()..end().
119
104
class FunctionLayout {
120
105
private:
121
- using FragmentListType = SmallVector<FunctionFragment *, 0 >;
122
106
using BasicBlockListType = SmallVector<BinaryBasicBlock *, 0 >;
123
107
using block_iterator = BasicBlockListType::iterator;
108
+ using FragmentListType = SmallVector<unsigned , 0 >;
124
109
125
110
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;
134
155
using block_const_reverse_iterator =
135
- std::reverse_iterator<block_const_iterator> ;
156
+ BasicBlockListType::const_reverse_iterator ;
136
157
137
158
private:
138
- FragmentListType Fragments;
139
159
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 };
140
165
141
166
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
-
149
167
// / Add an empty fragment.
150
- FunctionFragment &addFragment ();
151
-
152
- // / Return the fragment identified by Num.
153
- FunctionFragment &getFragment (FragmentNum Num);
168
+ FunctionFragment addFragment ();
154
169
155
170
// / Return the fragment identified by Num.
156
- const FunctionFragment & getFragment (FragmentNum Num) const ;
171
+ FunctionFragment getFragment (FragmentNum Num) const ;
157
172
158
173
// / Get the fragment that contains all entry blocks and other blocks that
159
174
// / cannot be split.
160
- FunctionFragment & getMainFragment () {
175
+ FunctionFragment getMainFragment () const {
161
176
return getFragment (FragmentNum::main ());
162
177
}
163
178
164
179
// / Get the fragment that contains all entry blocks and other blocks that
165
180
// / 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 {
179
182
return {++fragment_begin (), fragment_end ()};
180
183
}
181
184
182
185
// / Find the fragment that contains BB.
183
- const FunctionFragment & findFragment (const BinaryBasicBlock *BB) const ;
186
+ FunctionFragment findFragment (const BinaryBasicBlock *BB) const ;
184
187
185
188
// / Add BB to the end of the last fragment.
186
189
void addBasicBlock (BinaryBasicBlock *BB);
187
190
188
191
// / Insert range of basic blocks after InsertAfter. If InsertAfter is nullptr,
189
192
// / the blocks will be inserted at the start of the function.
190
- void insertBasicBlocks (const BinaryBasicBlock *InsertAfter,
193
+ void insertBasicBlocks (BinaryBasicBlock *InsertAfter,
191
194
ArrayRef<BinaryBasicBlock *> NewBlocks);
192
195
193
196
// / Erase all blocks from the layout that are in ToErase. If this method
194
197
// / erases all blocks of a fragment, it will be removed as well.
195
198
void eraseBasicBlocks (const DenseSet<const BinaryBasicBlock *> ToErase);
196
199
197
200
// / Make sure fragments' and basic blocks' indices match the current layout.
198
- void updateLayoutIndices ();
201
+ void updateLayoutIndices () const ;
199
202
200
203
// / Replace the current layout with NewLayout. Uses the block's
201
204
// / self-identifying fragment number to assign blocks to infer function
@@ -206,25 +209,12 @@ class FunctionLayout {
206
209
// / Clear layout releasing memory.
207
210
void clear ();
208
211
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]; }
223
213
224
214
// / Returns the basic block after the given basic block in the layout or
225
215
// / 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 ;
228
218
229
219
// / True if the layout contains at least two non-empty fragments.
230
220
bool isSplit () const ;
@@ -240,49 +230,29 @@ class FunctionLayout {
240
230
bool isHotColdSplit () const { return fragment_size () <= 2 ; }
241
231
242
232
size_t fragment_size () const {
243
- assert (Fragments.size () >= 1 &&
233
+ assert (Fragments.size () >= 2 &&
244
234
" Layout should have at least one fragment." );
245
- return Fragments.size ();
235
+ return Fragments.size () - 1 ;
246
236
}
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 };
255
241
}
256
- iterator_range<fragment_const_iterator > fragments () const {
242
+ iterator_range<const_iterator > fragments () const {
257
243
return {fragment_begin (), fragment_end ()};
258
244
}
259
245
260
246
size_t block_size () const { return Blocks.size (); }
261
247
bool block_empty () const { return Blocks.empty (); }
262
-
263
- // / Required to return non-const qualified `BinaryBasicBlock *` for graph
264
- // / traits.
265
248
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 (); }
279
252
iterator_range<block_const_iterator> blocks () const {
280
253
return {block_begin (), block_end ()};
281
254
}
282
-
283
- block_reverse_iterator block_rbegin () { return Blocks.rbegin (); }
284
255
block_const_reverse_iterator block_rbegin () const { return Blocks.rbegin (); }
285
- block_reverse_iterator block_rend () { return Blocks.rend (); }
286
256
block_const_reverse_iterator block_rend () const { return Blocks.rend (); }
287
257
iterator_range<block_const_reverse_iterator> rblocks () const {
288
258
return {block_rbegin (), block_rend ()};
0 commit comments