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