9191#define SWIFT_SILOPTIMIZER_UTILS_PRUNEDLIVENESS_H
9292
9393#include " swift/SIL/SILBasicBlock.h"
94+ #include " llvm/ADT/MapVector.h"
9495
9596namespace swift {
9697
@@ -221,11 +222,19 @@ class PrunedLiveness {
221222 // they may be the last use in the block.
222223 //
223224 // 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;
225231
226232public:
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) {}
229238
230239 bool empty () const {
231240 assert (!liveBlocks.empty () || users.empty ());
@@ -235,6 +244,8 @@ class PrunedLiveness {
235244 void clear () {
236245 liveBlocks.clear ();
237246 users.clear ();
247+ if (nonLifetimeEndingUsesInLiveOut)
248+ nonLifetimeEndingUsesInLiveOut->clear ();
238249 }
239250
240251 unsigned numLiveBlocks () const { return liveBlocks.numLiveBlocks (); }
@@ -245,6 +256,47 @@ class PrunedLiveness {
245256 return liveBlocks.getDiscoveredBlocks ();
246257 }
247258
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+
248300 void initializeDefBlock (SILBasicBlock *defBB) {
249301 liveBlocks.initializeDefBlock (defBB);
250302 }
0 commit comments