1111// ===----------------------------------------------------------------------===//
1212
1313#include " swift/SILOptimizer/Utils/ValueLifetime.h"
14+ #include " swift/Basic/STLExtras.h"
1415#include " swift/SIL/BasicBlockUtils.h"
1516#include " swift/SILOptimizer/Utils/CFGOptUtils.h"
1617
1718using namespace swift ;
1819
1920void ValueLifetimeAnalysis::propagateLiveness () {
21+ bool defIsInstruction = defValue.is <SILInstruction *>();
2022 assert (liveBlocks.empty () && " frontier computed twice" );
21- assert (!userSet.count (defValue) && " definition cannot be its own use" );
23+ assert (
24+ (!defIsInstruction || !userSet.count (defValue.get <SILInstruction *>())) &&
25+ " definition cannot be its own use" );
2226
23- auto defBB = defValue->getParentBlock ();
24- llvm::SmallVector<SILBasicBlock *, 64 > worklist;
27+ // Compute the def block only if we have a SILInstruction. If we have a
28+ // SILArgument, this will be nullptr.
29+ auto *defBB = getDefValueParentBlock ();
30+ SmallVector<SILBasicBlock *, 64 > worklist;
2531 int numUsersBeforeDef = 0 ;
2632
2733 // Find the initial set of blocks where the value is live, because
@@ -31,20 +37,28 @@ void ValueLifetimeAnalysis::propagateLiveness() {
3137 if (liveBlocks.insert (userBlock))
3238 worklist.push_back (userBlock);
3339
34- // A user in the defBB could potentially be located before the defValue.
35- if (userBlock == defBB)
40+ // A user in the defBB could potentially be located before the defValue. If
41+ // we had a SILArgument, defBB will be nullptr, so we should always have
42+ // numUsersBeforeDef is 0. We assert this at the end of the loop.
43+ if (defIsInstruction && userBlock == defBB)
3644 ++numUsersBeforeDef;
3745 }
38- // Don't count any users in the defBB which are actually located _after_
39- // the defValue.
40- auto instIter = defValue->getIterator ();
41- while (numUsersBeforeDef > 0 && ++instIter != defBB->end ()) {
42- if (userSet.count (&*instIter))
43- --numUsersBeforeDef;
46+ assert ((defValue.is <SILInstruction *>() || (numUsersBeforeDef == 0 )) &&
47+ " Non SILInstruction defValue with users before the def?!" );
48+
49+ // Don't count any users in the defBB which are actually located _after_ the
50+ // defValue.
51+ if (defIsInstruction) {
52+ auto instIter = defValue.get <SILInstruction *>()->getIterator ();
53+ while (numUsersBeforeDef > 0 && ++instIter != defBB->end ()) {
54+ if (userSet.count (&*instIter))
55+ --numUsersBeforeDef;
56+ }
4457 }
4558
4659 // Initialize the hasUsersBeforeDef field.
4760 hasUsersBeforeDef = numUsersBeforeDef > 0 ;
61+ assert (defIsInstruction || !hasUsersBeforeDef);
4862
4963 // Now propagate liveness backwards until we hit the block that defines the
5064 // value.
@@ -55,30 +69,31 @@ void ValueLifetimeAnalysis::propagateLiveness() {
5569 if (bb == defBB && !hasUsersBeforeDef)
5670 continue ;
5771
58- for (SILBasicBlock *Pred : bb->getPredecessorBlocks ()) {
72+ for (auto *predBB : bb->getPredecessorBlocks ()) {
5973 // If it's already in the set, then we've already queued and/or
6074 // processed the predecessors.
61- if (liveBlocks.insert (Pred ))
62- worklist.push_back (Pred );
75+ if (liveBlocks.insert (predBB ))
76+ worklist.push_back (predBB );
6377 }
6478 }
6579}
6680
6781SILInstruction *ValueLifetimeAnalysis::findLastUserInBlock (SILBasicBlock *bb) {
6882 // Walk backwards in bb looking for last use of the value.
69- for (auto ii = bb->rbegin (); ii != bb->rend (); ++ii) {
70- assert (defValue != &*ii && " Found def before finding use!" );
83+ for (auto &inst : llvm::reverse (*bb)) {
84+ assert (defValue.dyn_cast <SILInstruction *>() != &inst &&
85+ " Found def before finding use!" );
7186
72- if (userSet.count (&*ii ))
73- return &*ii ;
87+ if (userSet.count (&inst ))
88+ return &inst ;
7489 }
7590 llvm_unreachable (" Expected to find use of value in block!" );
7691}
7792
7893bool ValueLifetimeAnalysis::computeFrontier (Frontier &frontier, Mode mode,
7994 DeadEndBlocks *deBlocks) {
80- assert (!isAliveAtBeginOfBlock (defValue-> getFunction ()->getEntryBlock ())
81- && " Can't compute frontier for def which does not dominate all uses" );
95+ assert (!isAliveAtBeginOfBlock (getFunction ()->getEntryBlock ()) &&
96+ " Can't compute frontier for def which does not dominate all uses" );
8297
8398 bool noCriticalEdges = true ;
8499
@@ -101,10 +116,16 @@ bool ValueLifetimeAnalysis::computeFrontier(Frontier &frontier, Mode mode,
101116 for (const SILSuccessor &succ : bb->getSuccessors ()) {
102117 if (isAliveAtBeginOfBlock (succ)) {
103118 liveInSucc = true ;
104- if (succ == defValue-> getParent ()) {
119+ if (succ == getDefValueParentBlock ()) {
105120 // Here, the basic block bb uses the value but also redefines the
106121 // value inside bb. The new value could be used by the successors
107122 // of succ and therefore could be live at the end of succ as well.
123+ //
124+ // This should never happen if we have a SILArgument since the
125+ // SILArgument can not have any uses before it in a block.
126+ assert (defValue.is <SILInstruction *>() &&
127+ " SILArguments dominate all instructions in their defining "
128+ " blocks" );
108129 usedAndRedefinedInSucc = true ;
109130 }
110131 } else if (!deBlocks || !deBlocks->isDeadEnd (succ)) {
@@ -115,7 +136,10 @@ bool ValueLifetimeAnalysis::computeFrontier(Frontier &frontier, Mode mode,
115136 // Here, the basic block bb uses the value and later redefines the value.
116137 // Therefore, this value's lifetime ends after its last use preceding the
117138 // re-definition of the value.
118- auto ii = defValue->getReverseIterator ();
139+ //
140+ // We know that we can not have a SILArgument here since the SILArgument
141+ // dominates all instructions in the same block.
142+ auto ii = defValue.get <SILInstruction *>()->getReverseIterator ();
119143 for (; ii != bb->rend (); ++ii) {
120144 if (userSet.count (&*ii)) {
121145 frontier.push_back (&*std::next (ii));
@@ -245,15 +269,19 @@ bool ValueLifetimeAnalysis::isWithinLifetime(SILInstruction *inst) {
245269// Searches \p bb backwards from the instruction before \p frontierInst
246270// to the beginning of the list and returns true if we find a dealloc_ref
247271// /before/ we find \p defValue (the instruction that defines our target value).
248- static bool blockContainsDeallocRef (SILBasicBlock *bb, SILInstruction *defValue,
249- SILInstruction *frontierInst) {
272+ static bool
273+ blockContainsDeallocRef (SILBasicBlock *bb,
274+ PointerUnion<SILInstruction *, SILArgument *> defValue,
275+ SILInstruction *frontierInst) {
250276 SILBasicBlock::reverse_iterator End = bb->rend ();
251277 SILBasicBlock::reverse_iterator iter = frontierInst->getReverseIterator ();
252278 for (++iter; iter != End; ++iter) {
253279 SILInstruction *inst = &*iter;
254280 if (isa<DeallocRefInst>(inst))
255281 return true ;
256- if (inst == defValue)
282+ // We know that inst is not a nullptr, so if we have a SILArgument, this
283+ // will always fail as we want.
284+ if (inst == defValue.dyn_cast <SILInstruction *>())
257285 return false ;
258286 }
259287 return false ;
@@ -281,9 +309,14 @@ bool ValueLifetimeAnalysis::containsDeallocRef(const Frontier &frontier) {
281309}
282310
283311void ValueLifetimeAnalysis::dump () const {
284- llvm::errs () << " lifetime of def: " << *defValue;
285- for (SILInstruction *Use : userSet) {
286- llvm::errs () << " use: " << *Use;
312+ llvm::errs () << " lifetime of def: " ;
313+ if (auto *ii = defValue.dyn_cast <SILInstruction *>()) {
314+ llvm::errs () << *ii;
315+ } else {
316+ llvm::errs () << *defValue.get <SILArgument *>();
317+ }
318+ for (SILInstruction *use : userSet) {
319+ llvm::errs () << " use: " << *use;
287320 }
288321 llvm::errs () << " live blocks:" ;
289322 for (SILBasicBlock *bb : liveBlocks) {
0 commit comments