mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Often times when one is working with ownership one has a value V and a set of use points Uses where you want V's lifetime to end at, but those Uses together (while not reachable from each other) only partially post-dominate V. JointPostDominanceSetComputer is a struct that implements a general solution to that operation at the block level. The struct itself is just a set of state that the computation uses so that a pass can clear the state (allowing for us to avoid needing to remalloc if we had any small data structures that went big). To get into the semantics, the API JointPostDominanceSetComputer::findJointPostDominatingSet() takes in a "dominating block" and a "dominated block set" and returns two things to the user: 1. A set of blocks that together with the "dominated block set" jointly-postdominate the "dominating block". 2. A list of blocks in the "dominated block set" that were reachable from any of the other "dominated blocks", including itself in the case of a block in aloop. Conceptually we are performing a backwards walk up the CFG towards the "dominating block" starting at each block in the "dominated block set". As we go, we track successor blocks and report any successor blocks that we do not hit during our traversal as result blocks and are passed to the result callback. Now what does this actually mean: 1. All blocks in the "dominated blockset" that are at the same loop nest level as our dominating block will always be part of the final post-dominating block set. 2. All "lifetime ending" blocks that are at a different loop nest level than our dominating block are not going to be in our final result set. Let LifetimeEndingBlock be such a block. Then note that our assumed condition implies that there must be a sub-loop, SubLoop, at the same level of the loop-nest as the dominating block that contains LifetimeEndingBlock. The algorithm will yield to the caller the exiting blocks of that loop. It will also flag the blocks that were found to be a different use level, so the caller can introduce a copy at that point if needed. NOTE: Part of the reason why I am writing this rather than using the linear lifetime checker (LLChecker) is that LLChecker is being used in too many places because it is convenient. Its original true use was for emitting diagnostics and that can be seen through the implementation. I don't want to add more contortions to that code, so as I am finding new use cases where I could either write something new or add contortions to the LLChecker, I am doing the former.
17 KiB
17 KiB