@@ -127,67 +127,123 @@ bool PrunedLiveness::updateForBorrowingOperand(Operand *op) {
127
127
}
128
128
129
129
void PrunedLiveness::extendAcrossLiveness (PrunedLiveness &otherLivesness) {
130
- // update this liveness for all the interesting users in otherLivesness .
130
+ // update this liveness for all the interesting users in otherLiveness .
131
131
for (std::pair<SILInstruction *, bool > userAndEnd : otherLivesness.users ) {
132
132
updateForUse (userAndEnd.first , userAndEnd.second );
133
133
}
134
134
}
135
135
136
- bool PrunedLiveness::isWithinBoundary (SILInstruction *inst) const {
136
+ bool PrunedLiveness::isWithinBoundaryHelper (SILInstruction *inst,
137
+ SILValue def) const {
137
138
SILBasicBlock *block = inst->getParent ();
139
+
140
+ // / Returns true if \p inst is before \p def in this block.
141
+ auto foundInBlockBeforeDef = [](SILInstruction *inst, SILBasicBlock *block,
142
+ SILValue def) {
143
+ if (!def || def->getParentBlock () != block) {
144
+ return false ;
145
+ }
146
+ auto *defInst = def->getDefiningInstruction ();
147
+ if (!defInst) {
148
+ return false ;
149
+ }
150
+ for (SILInstruction &it :
151
+ make_range (block->begin (), defInst->getIterator ())) {
152
+ if (&it == inst) {
153
+ return true ;
154
+ }
155
+ }
156
+ return false ;
157
+ };
158
+
138
159
switch (getBlockLiveness (block)) {
139
160
case PrunedLiveBlocks::Dead:
140
161
return false ;
141
- case PrunedLiveBlocks::LiveWithin:
142
- break ;
143
162
case PrunedLiveBlocks::LiveOut:
144
- return true ;
145
- }
146
- // The boundary is within this block. This instruction is before the boundary
147
- // iff any interesting uses occur after it.
148
- for (SILInstruction &inst :
163
+ return !foundInBlockBeforeDef (inst, block, def);
164
+ case PrunedLiveBlocks::LiveWithin:
165
+ if (foundInBlockBeforeDef (inst, block, def)) {
166
+ return false ;
167
+ }
168
+ // The boundary is within this block. This instruction is before the
169
+ // boundary iff any interesting uses occur after it.
170
+ for (SILInstruction &it :
149
171
make_range (std::next (inst->getIterator ()), block->end ())) {
150
- switch (isInterestingUser (&inst)) {
151
- case PrunedLiveness::NonUser:
152
- break ;
153
- case PrunedLiveness::NonLifetimeEndingUse:
154
- case PrunedLiveness::LifetimeEndingUse:
155
- return true ;
172
+ switch (isInterestingUser (&it)) {
173
+ case PrunedLiveness::NonUser:
174
+ break ;
175
+ case PrunedLiveness::NonLifetimeEndingUse:
176
+ case PrunedLiveness::LifetimeEndingUse:
177
+ return true ;
178
+ }
156
179
}
180
+ return false ;
157
181
}
158
- return false ;
159
182
}
160
183
161
- bool PrunedLiveness::areUsesWithinBoundary (ArrayRef<Operand *> uses,
162
- DeadEndBlocks *deadEndBlocks) const {
184
+ bool PrunedLiveness::isWithinBoundary (SILInstruction *inst) const {
185
+ return isWithinBoundaryHelper (inst);
186
+ }
187
+
188
+ bool PrunedLiveness::isWithinBoundaryOfDef (SILInstruction *inst,
189
+ SILValue def) const {
190
+ return isWithinBoundaryHelper (inst, def);
191
+ }
192
+
193
+ bool PrunedLiveness::areUsesWithinBoundaryHelper (
194
+ ArrayRef<Operand *> uses, SILValue def,
195
+ DeadEndBlocks *deadEndBlocks) const {
163
196
auto checkDeadEnd = [deadEndBlocks](SILInstruction *inst) {
164
197
return deadEndBlocks && deadEndBlocks->isDeadEnd (inst->getParent ());
165
198
};
166
199
167
200
for (auto *use : uses) {
168
201
auto *user = use->getUser ();
169
- if (!isWithinBoundary (user) && !checkDeadEnd (user))
202
+ if (!isWithinBoundaryHelper (user, def ) && !checkDeadEnd (user))
170
203
return false ;
171
204
}
172
205
return true ;
173
206
}
174
207
175
- bool PrunedLiveness::areUsesOutsideBoundary (
176
- ArrayRef<Operand *> uses, DeadEndBlocks *deadEndBlocks) const {
208
+ bool PrunedLiveness::areUsesWithinBoundary (ArrayRef<Operand *> uses,
209
+ DeadEndBlocks *deadEndBlocks) const {
210
+ return areUsesWithinBoundaryHelper (uses, SILValue (), deadEndBlocks);
211
+ }
212
+
213
+ bool PrunedLiveness::areUsesWithinBoundaryOfDef (
214
+ ArrayRef<Operand *> uses, SILValue def,
215
+ DeadEndBlocks *deadEndBlocks) const {
216
+ return areUsesWithinBoundaryHelper (uses, def, deadEndBlocks);
217
+ }
218
+
219
+ bool PrunedLiveness::areUsesOutsideBoundaryHelper (
220
+ ArrayRef<Operand *> uses, SILValue def,
221
+ DeadEndBlocks *deadEndBlocks) const {
177
222
auto checkDeadEnd = [deadEndBlocks](SILInstruction *inst) {
178
223
return deadEndBlocks && deadEndBlocks->isDeadEnd (inst->getParent ());
179
224
};
180
225
181
226
for (auto *use : uses) {
182
227
auto *user = use->getUser ();
183
- if (isWithinBoundary (user) || checkDeadEnd (user))
228
+ if (isWithinBoundaryHelper (user, def ) || checkDeadEnd (user))
184
229
return false ;
185
230
}
186
231
return true ;
187
232
}
188
233
189
- // An SSA def meets all the criteria for pruned liveness--def dominates all uses
190
- // with no holes in the liverange. The lifetime-ending uses are also
234
+ bool PrunedLiveness::areUsesOutsideBoundary (
235
+ ArrayRef<Operand *> uses, DeadEndBlocks *deadEndBlocks) const {
236
+ return areUsesOutsideBoundaryHelper (uses, SILValue (), deadEndBlocks);
237
+ }
238
+
239
+ bool PrunedLiveness::areUsesOutsideBoundaryOfDef (
240
+ ArrayRef<Operand *> uses, SILValue def,
241
+ DeadEndBlocks *deadEndBlocks) const {
242
+ return areUsesOutsideBoundaryHelper (uses, def, deadEndBlocks);
243
+ }
244
+
245
+ // An SSA def meets all the criteria for pruned liveness--def dominates all
246
+ // uses with no holes in the liverange. The lifetime-ending uses are also
191
247
// recorded--destroy_value or end_borrow. However destroy_values may not
192
248
// jointly-post dominate if dead-end blocks are present.
193
249
void PrunedLiveness::computeSSALiveness (SILValue def) {
@@ -278,8 +334,8 @@ void PrunedLivenessBoundary::compute(const PrunedLiveness &liveness,
278
334
// Process each block that has not been visited and is not LiveOut.
279
335
switch (liveness.getBlockLiveness (bb)) {
280
336
case PrunedLiveBlocks::LiveOut:
281
- // A lifetimeEndBlock may be determined to be LiveOut after analyzing the
282
- // extended liveness. It is irrelevant for finding the boundary.
337
+ // A lifetimeEndBlock may be determined to be LiveOut after analyzing
338
+ // the extended liveness. It is irrelevant for finding the boundary.
283
339
break ;
284
340
case PrunedLiveBlocks::LiveWithin: {
285
341
// The liveness boundary is inside this block. Insert a final destroy
0 commit comments