Skip to content

Commit 0407a4e

Browse files
committed
Add UpdatingInstructionIterator.
Track in-use iterators and update them both when instructions are deleted and when they are added. Safe iteration in the presence of arbitrary changes now looks like this: for (SILInstruction *inst : deleter.updatingRange(&bb)) { modify(inst); }
1 parent 4a8cb7a commit 0407a4e

File tree

15 files changed

+360
-94
lines changed

15 files changed

+360
-94
lines changed

include/swift/SILOptimizer/Analysis/SimplifyInstruction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
namespace swift {
2626

2727
class SILInstruction;
28-
class InstModCallbacks;
28+
struct InstModCallbacks;
2929

3030
/// Replace an instruction with a simplified result and erase it. If the
3131
/// instruction initiates a scope, do not replace the end of its scope; it will

include/swift/SILOptimizer/Utils/CFGOptUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace swift {
3636
class DominanceInfo;
3737
class SILLoop;
3838
class SILLoopInfo;
39-
class InstModCallbacks;
39+
struct InstModCallbacks;
4040

4141
/// Adds a new argument to an edge between a branch and a destination
4242
/// block. Allows for user injected callbacks via \p callbacks.

include/swift/SILOptimizer/Utils/InstModCallbacks.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ namespace swift {
6868
/// default operation inline. What is nice about this from a perf perspective is
6969
/// that in a loop this property should predict well since you have a single
7070
/// branch that is going to go the same way everytime.
71-
class InstModCallbacks {
71+
struct InstModCallbacks {
7272
/// A function that is called to notify that a new function was created.
7373
///
7474
/// Default implementation is a no-op, but we still mark madeChange.
@@ -135,7 +135,6 @@ class InstModCallbacks {
135135
/// A boolean that tracks if any of our callbacks were ever called.
136136
bool wereAnyCallbacksInvoked = false;
137137

138-
public:
139138
InstModCallbacks() = default;
140139
~InstModCallbacks() = default;
141140
InstModCallbacks(const InstModCallbacks &) = default;

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@
2020
#ifndef SWIFT_SILOPTIMIZER_UTILS_INSTOPTUTILS_H
2121
#define SWIFT_SILOPTIMIZER_UTILS_INSTOPTUTILS_H
2222

23-
#include "swift/SILOptimizer/Utils/InstModCallbacks.h"
2423
#include "swift/SIL/BasicBlockUtils.h"
2524
#include "swift/SIL/SILBuilder.h"
2625
#include "swift/SIL/SILInstruction.h"
2726
#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
2827
#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h"
2928
#include "swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h"
3029
#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h"
30+
#include "swift/SILOptimizer/Utils/InstModCallbacks.h"
31+
#include "swift/SILOptimizer/Utils/UpdatingInstructionIterator.h"
3132
#include "llvm/ADT/SmallPtrSet.h"
3233

3334
namespace swift {
@@ -208,8 +209,6 @@ bool tryCheckedCastBrJumpThreading(
208209
/// deleter.deleteIfDead(instruction);
209210
/// deleter.cleanupDeadInstructions();
210211
///
211-
///
212-
///
213212
/// This is designed to be used with a single 'onDelete' callback, which is
214213
/// invoked consistently just before deleting each instruction. It's usually
215214
/// used to avoid iterator invalidation (see the updatingIterator() factory
@@ -230,37 +229,36 @@ bool tryCheckedCastBrJumpThreading(
230229
/// Note that the forceDelete* APIs only invoke notifyWillBeDeletedFunc() when
231230
/// an operand's definition will become dead after force-deleting the specified
232231
/// instruction. Some clients force-delete related instructions one at a
233-
/// time. They may not force-deleted. It's the client's responsiblity to invoke
234-
/// notifyWillBeDeletedFunc() on those explicitly deleted instructions if
235-
/// needed.
236-
///
232+
/// time. It is the client's responsiblity to invoke notifyWillBeDeletedFunc()
233+
/// on those explicitly deleted instructions if needed.
237234
class InstructionDeleter {
238-
public:
239-
static InstructionDeleter updatingIterator(SILBasicBlock::iterator &iter) {
240-
auto onDelete = InstModCallbacks().onDelete([&](SILInstruction *deadInst) {
241-
if (deadInst->getIterator() == iter)
242-
++iter;
243-
deadInst->eraseFromParent();
244-
});
245-
return InstructionDeleter(onDelete);
246-
}
247-
248-
private:
249235
/// A set vector of instructions that are found to be dead. The ordering of
250236
/// instructions in this set is important as when a dead instruction is
251237
/// removed, new instructions will be generated to fix the lifetime of the
252238
/// instruction's operands. This has to be deterministic.
253239
SmallSetVector<SILInstruction *, 8> deadInstructions;
254240

255-
/// Callbacks used when adding/deleting instructions.
256-
InstModCallbacks callbacks;
241+
UpdatingInstructionIteratorRegistry iteratorRegistry;
257242

258243
public:
259-
InstructionDeleter() : deadInstructions(), callbacks() {}
260-
InstructionDeleter(InstModCallbacks callbacks)
261-
: deadInstructions(), callbacks(callbacks) {}
244+
InstructionDeleter(InstModCallbacks chainedCallbacks = InstModCallbacks())
245+
: deadInstructions(), iteratorRegistry(chainedCallbacks) {}
246+
247+
InstModCallbacks &getCallbacks() { return iteratorRegistry.getCallbacks(); }
248+
249+
UpdatingInstructionIteratorRegistry &getIteratorRegistry() {
250+
return iteratorRegistry;
251+
}
262252

263-
InstModCallbacks &getCallbacks() { return callbacks; }
253+
llvm::iterator_range<UpdatingInstructionIterator>
254+
updatingRange(SILBasicBlock *bb) {
255+
return iteratorRegistry.makeIteratorRange(bb);
256+
}
257+
258+
llvm::iterator_range<UpdatingReverseInstructionIterator>
259+
updatingReverseRange(SILBasicBlock *bb) {
260+
return iteratorRegistry.makeReverseIteratorRange(bb);
261+
}
264262

265263
/// If the instruction \p inst is dead, record it so that it can be cleaned
266264
/// up.

0 commit comments

Comments
 (0)