Skip to content

Commit 8710882

Browse files
committed
[Mem2Reg] Tied lexical borrow to initialization.
Previously, the lexical borrow scopes that were introduced to replace lexical stack allocations were tied to the uses of the stored value. That meant that the borrow scope could be both too long and also too short. It could be too long if there were uses of the value after the dealloc stack and it would be too short if there were not uses of the value while the value was still stored into the stack allocation. Here, instead, the lexical borrow scopes are tied to the storage of a value into the stack allocation. A value's lexical borrow scope begins when the storage is initialied with the value; its lexical borrow scope ends when the storage is deinitialized. That corresponds to the range during which a var in the Swift source has a particular value assigned to it. Mem2Reg's implementation is split into a few steps: (1) visiting the instructions in a basic block which contains all uses of an alloc_stack (2.a) visiting the instructions in each basic block which contains a use of the alloc_stack (2.b) adding phis (2.c) using the last stored values as arguments to the new outgoing phi arguments (2.c) replacing initial uses of the storage with the new incoming phi arguments And here, (1) amounts to a special case of (2.a). During (1) and (2.a): (a) lexical borrow scopes are begun after store instructions for the values that were stored (b) when possible, lexical borrow scopes are ended before instructions that deinitialize memory - destroy_addr - store [assign] - load [take] For (1), that is enough to create valid borrow scopes. For (2), there are two complications: (a) Borrow scopes that are begun may not be ended (when visiting a single block's instructions). For example, when visiting bb1: store %instance to [init] %addr br bb2 a borrow scope is started after the store but cannot be ended. (b) There may not be enough information available to end borrow scopes when visiting instructions that would typically introduce borrow scopes. For example, when visiting bb2: %copy = load [copy] %addr %instance = load [take] %addr br bb3 there is not enough information available to end the borrow scope that should be ended before the load [take] To resolve these issues, both sorts of instructions are tracked. For (a), in StackAllocationPromoter::initializationPoints. For (b), in StackAllocationPromoter::deinitializationPoints. Finally, a new step is added: (2.d) StackAllocationPromoter::endLexicalLifetimes does a forward CFG walk starting from the out-edge of each of the blocks which began but did not end lexical lifetimes. At an out-edge, we do a check regarding unreachables is done, and we may end the borrow scope. Otherwise, the walk continues to the in-edge of each successor. At an in-edge, we look for an instruction from (b) (in unprecedentedDeinitializations) above. If one is found, then we end the borrow scope before that instruction. Otherwise, the walk continues to the out-edge of the block.
1 parent 8b99d34 commit 8710882

File tree

5 files changed

+1650
-248
lines changed

5 files changed

+1650
-248
lines changed

0 commit comments

Comments
 (0)