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