Skip to content

Commit 6d47d32

Browse files
authored
Merge pull request #37657 from eeckstein/instruction-allocation
SIL: replace the notifyDeleteHandlers mechanism with delayed instruction deletion
2 parents 6efd419 + 4977850 commit 6d47d32

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+347
-839
lines changed

include/swift/Basic/ValueEnumerator.h

Lines changed: 0 additions & 61 deletions
This file was deleted.

include/swift/SIL/Notifications.h

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -239,27 +239,6 @@ class DeserializationNotificationHandlerSet final
239239
void didDeserialize(ModuleDecl *mod,
240240
SILDefaultWitnessTable *wtable) override;
241241
};
242-
243-
/// A protocol (or interface) for handling value deletion notifications.
244-
///
245-
/// This class is used as a base class for any class that need to accept
246-
/// instruction deletion notification messages. This is used by passes and
247-
/// analysis that need to invalidate data structures that contain pointers.
248-
/// This is similar to LLVM's ValueHandle.
249-
struct DeleteNotificationHandler {
250-
DeleteNotificationHandler() { }
251-
virtual ~DeleteNotificationHandler() {}
252-
253-
/// Handle the invalidation message for the value \p Value.
254-
virtual void handleDeleteNotification(SILNode *value) { }
255-
256-
/// Returns True if the pass, analysis or other entity wants to receive
257-
/// notifications. This callback is called once when the class is being
258-
/// registered, and not once per notification. Entities that implement
259-
/// this callback should always return a constant answer (true/false).
260-
virtual bool needsNotifications() { return false; }
261-
};
262-
263242
} // namespace swift
264243

265244
#endif

include/swift/SIL/SILBasicBlock.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,10 @@ public llvm::ilist_node<SILBasicBlock>, public SILAllocated<SILBasicBlock> {
127127
void push_back(SILInstruction *I);
128128
void push_front(SILInstruction *I);
129129
void remove(SILInstruction *I);
130-
iterator erase(SILInstruction *I);
130+
void erase(SILInstruction *I);
131+
void erase(SILInstruction *I, SILModule &module);
132+
133+
void eraseAllInstructions(SILModule &module);
131134

132135
SILInstruction &back() { return InstList.back(); }
133136
const SILInstruction &back() const {
@@ -439,8 +442,6 @@ public llvm::ilist_node<SILBasicBlock>, public SILAllocated<SILBasicBlock> {
439442
I.dropAllReferences();
440443
}
441444

442-
void eraseInstructions();
443-
444445
private:
445446
friend class SILArgument;
446447

include/swift/SIL/SILFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,10 @@ class SILFunction
981981

982982
void clear();
983983

984+
/// Like `clear`, but does not call `dropAllReferences`, which is the
985+
/// responsibility of the caller.
986+
void eraseAllBlocks();
987+
984988
/// Return the identity substitutions necessary to forward this call if it is
985989
/// generic.
986990
SubstitutionMap getForwardingSubstitutionMap();

include/swift/SIL/SILGlobalVariable.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ class SILGlobalVariable
181181
StaticInitializerBlock.dropAllReferences();
182182
}
183183

184+
void clear() {
185+
dropAllReferences();
186+
StaticInitializerBlock.eraseAllInstructions(Module);
187+
}
188+
184189
/// Return whether this variable corresponds to a Clang node.
185190
bool hasClangNode() const;
186191

include/swift/SIL/SILInstruction.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
320320
friend llvm::ilist_traits<SILInstruction>;
321321
friend llvm::ilist_traits<SILBasicBlock>;
322322
friend SILBasicBlock;
323+
friend SILModule;
323324

324325
/// A backreference to the containing basic block. This is maintained by
325326
/// ilist_traits<SILInstruction>.
@@ -381,6 +382,10 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
381382
return C.allocateInst(Bytes, Alignment);
382383
}
383384

385+
/// Returns true if this instruction is removed from its function and
386+
/// scheduled to be deleted.
387+
bool isDeleted() const { return !ParentBB; }
388+
384389
enum class MemoryBehavior {
385390
None,
386391
/// The instruction may read memory.

include/swift/SIL/SILModule.h

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,17 @@ class SILModule {
189189
/// For consistency checking.
190190
size_t numAllocatedSlabs = 0;
191191

192+
/// When an instruction is "deleted" from the SIL, it is put into this list.
193+
/// The instructions in this list are eventually deleted for real in
194+
/// flushDeletedInsts(), which is called by the pass manager after each pass
195+
/// run.
196+
/// In other words: instruction deletion is deferred to the end of a pass.
197+
///
198+
/// This avoids dangling instruction pointers within the run of a pass and in
199+
/// analysis caches. Note that the analysis invalidation mechanism ensures
200+
/// that analysis caches are invalidated before flushDeletedInsts().
201+
llvm::iplist<SILInstruction> scheduledForDeletion;
202+
192203
/// The swift Module associated with this SILModule.
193204
ModuleDecl *TheSwiftModule;
194205

@@ -334,10 +345,6 @@ class SILModule {
334345
/// Action to be executed for serializing the SILModule.
335346
ActionCallback SerializeSILAction;
336347

337-
/// A list of clients that need to be notified when an instruction
338-
/// invalidation message is sent.
339-
llvm::SetVector<DeleteNotificationHandler*> NotificationHandlers;
340-
341348
SILModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
342349
Lowering::TypeConverter &TC, const SILOptions &Options);
343350

@@ -413,16 +420,6 @@ class SILModule {
413420
/// Called after an instruction is moved from one function to another.
414421
void notifyMovedInstruction(SILInstruction *inst, SILFunction *fromFunction);
415422

416-
/// Add a delete notification handler \p Handler to the module context.
417-
void registerDeleteNotificationHandler(DeleteNotificationHandler* Handler);
418-
419-
/// Remove the delete notification handler \p Handler from the module context.
420-
void removeDeleteNotificationHandler(DeleteNotificationHandler* Handler);
421-
422-
/// Send the invalidation message that \p V is being deleted to all
423-
/// registered handlers. The order of handlers is deterministic but arbitrary.
424-
void notifyDeleteHandlers(SILNode *node);
425-
426423
/// Set a serialization action.
427424
void setSerializeSILAction(ActionCallback SerializeSILAction);
428425
ActionCallback getSerializeSILAction() const;
@@ -849,8 +846,17 @@ class SILModule {
849846
/// Allocate memory for an instruction using the module's internal allocator.
850847
void *allocateInst(unsigned Size, unsigned Align) const;
851848

852-
/// Deallocate memory of an instruction.
853-
void deallocateInst(SILInstruction *I);
849+
/// Called before \p I is removed from its basic block and scheduled for
850+
/// deletion.
851+
void willDeleteInstruction(SILInstruction *I);
852+
853+
/// Schedules the (already removed) instruction \p I for deletion.
854+
/// See scheduledForDeletion for details.
855+
void scheduleForDeletion(SILInstruction *I);
856+
857+
/// Deletes all scheuled instructions for real.
858+
/// See scheduledForDeletion for details.
859+
void flushDeletedInsts();
854860

855861
/// Looks up the llvm intrinsic ID and type for the builtin function.
856862
///

0 commit comments

Comments
 (0)