@@ -127,67 +127,124 @@ bool PrunedLiveness::updateForBorrowingOperand(Operand *op) {
127127}
128128
129129void 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 .
131131 for (std::pair<SILInstruction *, bool > userAndEnd : otherLivesness.users ) {
132132 updateForUse (userAndEnd.first , userAndEnd.second );
133133 }
134134}
135135
136- bool PrunedLiveness::isWithinBoundary (SILInstruction *inst) const {
136+ bool PrunedLiveness::isWithinBoundaryHelper (SILInstruction *inst,
137+ SILValue def) const {
137138 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+
138160 switch (getBlockLiveness (block)) {
139161 case PrunedLiveBlocks::Dead:
140162 return false ;
141- case PrunedLiveBlocks::LiveWithin:
142- break ;
143163 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 :
149172 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+ }
156180 }
181+ return false ;
157182 }
158- return false ;
159183}
160184
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 {
163197 auto checkDeadEnd = [deadEndBlocks](SILInstruction *inst) {
164198 return deadEndBlocks && deadEndBlocks->isDeadEnd (inst->getParent ());
165199 };
166200
167201 for (auto *use : uses) {
168202 auto *user = use->getUser ();
169- if (!isWithinBoundary (user) && !checkDeadEnd (user))
203+ if (!isWithinBoundaryHelper (user, def ) && !checkDeadEnd (user))
170204 return false ;
171205 }
172206 return true ;
173207}
174208
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 {
177223 auto checkDeadEnd = [deadEndBlocks](SILInstruction *inst) {
178224 return deadEndBlocks && deadEndBlocks->isDeadEnd (inst->getParent ());
179225 };
180226
181227 for (auto *use : uses) {
182228 auto *user = use->getUser ();
183- if (isWithinBoundary (user) || checkDeadEnd (user))
229+ if (isWithinBoundaryHelper (user, def ) || checkDeadEnd (user))
184230 return false ;
185231 }
186232 return true ;
187233}
188234
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
191248// recorded--destroy_value or end_borrow. However destroy_values may not
192249// jointly-post dominate if dead-end blocks are present.
193250void PrunedLiveness::computeSSALiveness (SILValue def) {
@@ -278,8 +335,8 @@ void PrunedLivenessBoundary::compute(const PrunedLiveness &liveness,
278335 // Process each block that has not been visited and is not LiveOut.
279336 switch (liveness.getBlockLiveness (bb)) {
280337 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.
283340 break ;
284341 case PrunedLiveBlocks::LiveWithin: {
285342 // The liveness boundary is inside this block. Insert a final destroy
0 commit comments