@@ -116,7 +116,6 @@ void PhiStorageOptimizer::optimize() {
116
116
coalescedPhi.coalescedOperands .push_back (phi.getOperand (predecessor));
117
117
return ;
118
118
}
119
- occupiedBlocks.insert (phi.phiBlock );
120
119
for (auto *incomingPred : phi.phiBlock ->getPredecessorBlocks ()) {
121
120
tryCoalesceOperand (incomingPred);
122
121
}
@@ -145,14 +144,15 @@ bool PhiStorageOptimizer::canCoalesceValue(SILValue incomingVal) {
145
144
146
145
auto &incomingStorage = valueStorageMap.getStorage (incomingVal);
147
146
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.
151
151
//
152
152
// 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 ())
156
156
return false ;
157
157
158
158
auto *defInst = incomingVal->getDefiningInstruction ();
@@ -163,7 +163,6 @@ bool PhiStorageOptimizer::canCoalesceValue(SILValue incomingVal) {
163
163
// analysis of the whole phi web before coalescing phi operands.
164
164
return false ;
165
165
}
166
- assert (incomingStorage.isAllocated () && " nonphi must be allocated" );
167
166
168
167
// Don't coalesce an incoming value unless it's storage is from a stack
169
168
// allocation, which can be replaced with another alloc_stack.
@@ -213,7 +212,11 @@ bool PhiStorageOptimizer::recordUseLiveness(SILValue incomingVal,
213
212
for (auto *use : incomingVal->getUses ()) {
214
213
StackList<SILBasicBlock *> liveBBWorklist (getFunction ());
215
214
215
+ // If \p liveBB is already occupied by another value, return
216
+ // false. Otherwise, mark \p liveBB live and push it onto liveBBWorklist.
216
217
auto visitLiveBlock = [&](SILBasicBlock *liveBB) {
218
+ assert (liveBB != phi.phiBlock && " phi operands are consumed" );
219
+
217
220
if (occupiedBlocks.contains (liveBB))
218
221
return false ;
219
222
0 commit comments