@@ -116,7 +116,6 @@ void PhiStorageOptimizer::optimize() {
116116 coalescedPhi.coalescedOperands .push_back (phi.getOperand (predecessor));
117117 return ;
118118 }
119- occupiedBlocks.insert (phi.phiBlock );
120119 for (auto *incomingPred : phi.phiBlock ->getPredecessorBlocks ()) {
121120 tryCoalesceOperand (incomingPred);
122121 }
@@ -145,14 +144,15 @@ bool PhiStorageOptimizer::canCoalesceValue(SILValue incomingVal) {
145144
146145 auto &incomingStorage = valueStorageMap.getStorage (incomingVal);
147146
148- // If the incoming use is pre-allocated it can't be coalesced.
149- // This also handles incoming values that are already coalesced with
150- // another use.
147+ // If the incoming use directly reuses its def storage, projects out of its
148+ // def storage, or is pre-allocated, then it can't be coalesced. When incoming
149+ // storage is directly reused, isAllocated() is false. isProjection() covers
150+ // the other cases.
151151 //
152152 // Coalescing use projections from incomingVal into its other non-phi uses
153- // would require by recursively following uses across projections when
154- // computing liveness.
155- if (incomingStorage.isProjection ())
153+ // could be handled, but would require by recursively following uses across
154+ // projections when computing liveness.
155+ if (!incomingStorage. isAllocated () || incomingStorage.isProjection ())
156156 return false ;
157157
158158 auto *defInst = incomingVal->getDefiningInstruction ();
@@ -163,7 +163,6 @@ bool PhiStorageOptimizer::canCoalesceValue(SILValue incomingVal) {
163163 // analysis of the whole phi web before coalescing phi operands.
164164 return false ;
165165 }
166- assert (incomingStorage.isAllocated () && " nonphi must be allocated" );
167166
168167 // Don't coalesce an incoming value unless it's storage is from a stack
169168 // allocation, which can be replaced with another alloc_stack.
@@ -213,7 +212,11 @@ bool PhiStorageOptimizer::recordUseLiveness(SILValue incomingVal,
213212 for (auto *use : incomingVal->getUses ()) {
214213 StackList<SILBasicBlock *> liveBBWorklist (getFunction ());
215214
215+ // If \p liveBB is already occupied by another value, return
216+ // false. Otherwise, mark \p liveBB live and push it onto liveBBWorklist.
216217 auto visitLiveBlock = [&](SILBasicBlock *liveBB) {
218+ assert (liveBB != phi.phiBlock && " phi operands are consumed" );
219+
217220 if (occupiedBlocks.contains (liveBB))
218221 return false ;
219222
0 commit comments