Skip to content

Commit bd28b0e

Browse files
committed
SILCloner and SILInliner rewrite.
Mostly functionally neutral: - may fix latent bugs. - may reduce useless basic blocks after inlining. This rewrite encapsulates the cloner's internal state, providing a clean API for the CRTP subclasses. The subclasses are rewritten to use the exposed API and extension points. This makes it much easier to understand, work with, and extend SIL cloners, which are central to many optimization passes. Basic SIL invariants are now clearly expressed and enforced. There is no longer a intricate dance between multiple levels of subclasses operating on underlying low-level data structures. All of the logic needed to keep the original SIL in a consistent state is contained within the SILCloner itself. Subclasses only need to be responsible for their own modifications. The immediate motiviation is to make CFG updates self-contained so that SIL remains in a valid state. This will allow the removal of critical edge splitting hacks and will allow general SIL utilities to take advantage of the fact that we don't allow critical edges. This rewrite establishes a simple principal that should be followed everywhere: aside from the primitive mutation APIs on SIL data types, each SIL utility is responsibile for leaving SIL in a valid state and the logic for doing so should exist in one central location. This includes, for example: - Generating a valid CFG, splitting edges if needed. - Returning a valid instruction iterator if any instructions are removed. - Updating dominance. - Updating SSA (block arguments). (Dominance info and SSA properties are fundamental to SIL verification). LoopInfo is also somewhat fundamental to SIL, and should generally be updated, but it isn't required. This also fixes some latent bugs related to iterator invalidation in recursivelyDeleteTriviallyDeadInstructions and SILInliner. Note that the SILModule deletion callback should be avoided. It can be useful as a simple cache invalidation mechanism, but it is otherwise bug prone, too limited to be very useful, and basically bad design. Utilities that mutate should return a valid instruction iterator and provide their own deletion callbacks.
1 parent 4700241 commit bd28b0e

22 files changed

+1038
-810
lines changed

Diff for: include/swift/SIL/DebugUtils.h

+6-5
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ inline SILInstruction *getSingleNonDebugUser(SILValue V) {
169169
/// Erases the instruction \p I from it's parent block and deletes it, including
170170
/// all debug instructions which use \p I.
171171
/// Precondition: The instruction may only have debug instructions as uses.
172-
/// If the iterator \p InstIter references any deleted debug instruction, it is
172+
/// If the iterator \p InstIter references any deleted instruction, it is
173173
/// incremented.
174174
inline void eraseFromParentWithDebugInsts(SILInstruction *I,
175175
SILBasicBlock::iterator &InstIter) {
@@ -183,16 +183,17 @@ inline void eraseFromParentWithDebugInsts(SILInstruction *I,
183183
foundAny = true;
184184
auto *User = result->use_begin()->getUser();
185185
assert(User->isDebugInstruction());
186-
if (InstIter != SILBasicBlock::iterator() &&
187-
InstIter != I->getParent()->end() &&
188-
&*InstIter == User) {
186+
if (InstIter == User->getIterator())
189187
InstIter++;
190-
}
188+
191189
User->eraseFromParent();
192190
}
193191
}
194192
} while (foundAny);
195193

194+
if (InstIter == I->getIterator())
195+
++InstIter;
196+
196197
I->eraseFromParent();
197198
}
198199

0 commit comments

Comments
 (0)