91
91
#define SWIFT_SILOPTIMIZER_UTILS_PRUNEDLIVENESS_H
92
92
93
93
#include " swift/SIL/SILBasicBlock.h"
94
+ #include " llvm/ADT/MapVector.h"
94
95
95
96
namespace swift {
96
97
@@ -221,11 +222,19 @@ class PrunedLiveness {
221
222
// they may be the last use in the block.
222
223
//
223
224
// Non-lifetime-ending within a LiveOut block are uninteresting.
224
- llvm::SmallDenseMap<SILInstruction *, bool , 8 > users;
225
+ llvm::SmallMapVector<SILInstruction *, bool , 8 > users;
226
+
227
+ // / A side array that stores any non lifetime ending uses we find in live out
228
+ // / blocks. This is used to enable our callers to emit errors on non-lifetime
229
+ // / ending uses that extend liveness into a loop body.
230
+ SmallSetVector<SILInstruction *, 8 > *nonLifetimeEndingUsesInLiveOut;
225
231
226
232
public:
227
- PrunedLiveness (SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr )
228
- : liveBlocks(discoveredBlocks) {}
233
+ PrunedLiveness (SmallVectorImpl<SILBasicBlock *> *discoveredBlocks = nullptr ,
234
+ SmallSetVector<SILInstruction *, 8 >
235
+ *nonLifetimeEndingUsesInLiveOut = nullptr )
236
+ : liveBlocks(discoveredBlocks),
237
+ nonLifetimeEndingUsesInLiveOut (nonLifetimeEndingUsesInLiveOut) {}
229
238
230
239
bool empty () const {
231
240
assert (!liveBlocks.empty () || users.empty ());
@@ -235,6 +244,8 @@ class PrunedLiveness {
235
244
void clear () {
236
245
liveBlocks.clear ();
237
246
users.clear ();
247
+ if (nonLifetimeEndingUsesInLiveOut)
248
+ nonLifetimeEndingUsesInLiveOut->clear ();
238
249
}
239
250
240
251
unsigned numLiveBlocks () const { return liveBlocks.numLiveBlocks (); }
@@ -245,6 +256,47 @@ class PrunedLiveness {
245
256
return liveBlocks.getDiscoveredBlocks ();
246
257
}
247
258
259
+ using NonLifetimeEndingUsesInLiveOutRange =
260
+ iterator_range<SILInstruction *const *>;
261
+
262
+ NonLifetimeEndingUsesInLiveOutRange
263
+ getNonLifetimeEndingUsesInLiveOut () const {
264
+ assert (nonLifetimeEndingUsesInLiveOut &&
265
+ " Called without passing in nonLifetimeEndingUsesInLiveOut to "
266
+ " constructor?!" );
267
+ return llvm::make_range (nonLifetimeEndingUsesInLiveOut->begin (),
268
+ nonLifetimeEndingUsesInLiveOut->end ());
269
+ }
270
+
271
+ using NonLifetimeEndingUsesInLiveOutBlocksRange =
272
+ TransformRange<NonLifetimeEndingUsesInLiveOutRange,
273
+ function_ref<SILBasicBlock *(const SILInstruction *&)>>;
274
+ NonLifetimeEndingUsesInLiveOutBlocksRange
275
+ getNonLifetimeEndingUsesInLiveOutBlocks () const {
276
+ function_ref<SILBasicBlock *(const SILInstruction *&)> op;
277
+ op = [](const SILInstruction *&ptr) -> SILBasicBlock * {
278
+ return ptr->getParent ();
279
+ };
280
+ return NonLifetimeEndingUsesInLiveOutBlocksRange (
281
+ getNonLifetimeEndingUsesInLiveOut (), op);
282
+ }
283
+
284
+ using UserRange = iterator_range<const std::pair<SILInstruction *, bool > *>;
285
+ UserRange getAllUsers () const {
286
+ return llvm::make_range (users.begin (), users.end ());
287
+ }
288
+
289
+ using UserBlockRange = TransformRange<
290
+ UserRange,
291
+ function_ref<SILBasicBlock *(const std::pair<SILInstruction *, bool > &)>>;
292
+ UserBlockRange getAllUserBlocks () const {
293
+ function_ref<SILBasicBlock *(const std::pair<SILInstruction *, bool > &)> op;
294
+ op = [](const std::pair<SILInstruction *, bool > &pair) -> SILBasicBlock * {
295
+ return pair.first ->getParent ();
296
+ };
297
+ return UserBlockRange (getAllUsers (), op);
298
+ }
299
+
248
300
void initializeDefBlock (SILBasicBlock *defBB) {
249
301
liveBlocks.initializeDefBlock (defBB);
250
302
}
0 commit comments