Skip to content

SIL: replace the notifyDeleteHandlers mechanism with delayed instruction deletion #37657

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 0 additions & 61 deletions include/swift/Basic/ValueEnumerator.h

This file was deleted.

21 changes: 0 additions & 21 deletions include/swift/SIL/Notifications.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,27 +239,6 @@ class DeserializationNotificationHandlerSet final
void didDeserialize(ModuleDecl *mod,
SILDefaultWitnessTable *wtable) override;
};

/// A protocol (or interface) for handling value deletion notifications.
///
/// This class is used as a base class for any class that need to accept
/// instruction deletion notification messages. This is used by passes and
/// analysis that need to invalidate data structures that contain pointers.
/// This is similar to LLVM's ValueHandle.
struct DeleteNotificationHandler {
DeleteNotificationHandler() { }
virtual ~DeleteNotificationHandler() {}

/// Handle the invalidation message for the value \p Value.
virtual void handleDeleteNotification(SILNode *value) { }

/// Returns True if the pass, analysis or other entity wants to receive
/// notifications. This callback is called once when the class is being
/// registered, and not once per notification. Entities that implement
/// this callback should always return a constant answer (true/false).
virtual bool needsNotifications() { return false; }
};

} // namespace swift

#endif
7 changes: 4 additions & 3 deletions include/swift/SIL/SILBasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,10 @@ public llvm::ilist_node<SILBasicBlock>, public SILAllocated<SILBasicBlock> {
void push_back(SILInstruction *I);
void push_front(SILInstruction *I);
void remove(SILInstruction *I);
iterator erase(SILInstruction *I);
void erase(SILInstruction *I);
void erase(SILInstruction *I, SILModule &module);

void eraseAllInstructions(SILModule &module);

SILInstruction &back() { return InstList.back(); }
const SILInstruction &back() const {
Expand Down Expand Up @@ -439,8 +442,6 @@ public llvm::ilist_node<SILBasicBlock>, public SILAllocated<SILBasicBlock> {
I.dropAllReferences();
}

void eraseInstructions();

private:
friend class SILArgument;

Expand Down
4 changes: 4 additions & 0 deletions include/swift/SIL/SILFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,10 @@ class SILFunction

void clear();

/// Like `clear`, but does not call `dropAllReferences`, which is the
/// responsibility of the caller.
void eraseAllBlocks();

/// Return the identity substitutions necessary to forward this call if it is
/// generic.
SubstitutionMap getForwardingSubstitutionMap();
Expand Down
5 changes: 5 additions & 0 deletions include/swift/SIL/SILGlobalVariable.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ class SILGlobalVariable
StaticInitializerBlock.dropAllReferences();
}

void clear() {
dropAllReferences();
StaticInitializerBlock.eraseAllInstructions(Module);
}

/// Return whether this variable corresponds to a Clang node.
bool hasClangNode() const;

Expand Down
5 changes: 5 additions & 0 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
friend llvm::ilist_traits<SILInstruction>;
friend llvm::ilist_traits<SILBasicBlock>;
friend SILBasicBlock;
friend SILModule;

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

/// Returns true if this instruction is removed from its function and
/// scheduled to be deleted.
bool isDeleted() const { return !ParentBB; }

enum class MemoryBehavior {
None,
/// The instruction may read memory.
Expand Down
38 changes: 22 additions & 16 deletions include/swift/SIL/SILModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,17 @@ class SILModule {
/// For consistency checking.
size_t numAllocatedSlabs = 0;

/// When an instruction is "deleted" from the SIL, it is put into this list.
/// The instructions in this list are eventually deleted for real in
/// flushDeletedInsts(), which is called by the pass manager after each pass
/// run.
/// In other words: instruction deletion is deferred to the end of a pass.
///
/// This avoids dangling instruction pointers within the run of a pass and in
/// analysis caches. Note that the analysis invalidation mechanism ensures
/// that analysis caches are invalidated before flushDeletedInsts().
llvm::iplist<SILInstruction> scheduledForDeletion;

/// The swift Module associated with this SILModule.
ModuleDecl *TheSwiftModule;

Expand Down Expand Up @@ -334,10 +345,6 @@ class SILModule {
/// Action to be executed for serializing the SILModule.
ActionCallback SerializeSILAction;

/// A list of clients that need to be notified when an instruction
/// invalidation message is sent.
llvm::SetVector<DeleteNotificationHandler*> NotificationHandlers;

SILModule(llvm::PointerUnion<FileUnit *, ModuleDecl *> context,
Lowering::TypeConverter &TC, const SILOptions &Options);

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

/// Add a delete notification handler \p Handler to the module context.
void registerDeleteNotificationHandler(DeleteNotificationHandler* Handler);

/// Remove the delete notification handler \p Handler from the module context.
void removeDeleteNotificationHandler(DeleteNotificationHandler* Handler);

/// Send the invalidation message that \p V is being deleted to all
/// registered handlers. The order of handlers is deterministic but arbitrary.
void notifyDeleteHandlers(SILNode *node);

/// Set a serialization action.
void setSerializeSILAction(ActionCallback SerializeSILAction);
ActionCallback getSerializeSILAction() const;
Expand Down Expand Up @@ -849,8 +846,17 @@ class SILModule {
/// Allocate memory for an instruction using the module's internal allocator.
void *allocateInst(unsigned Size, unsigned Align) const;

/// Deallocate memory of an instruction.
void deallocateInst(SILInstruction *I);
/// Called before \p I is removed from its basic block and scheduled for
/// deletion.
void willDeleteInstruction(SILInstruction *I);

/// Schedules the (already removed) instruction \p I for deletion.
/// See scheduledForDeletion for details.
void scheduleForDeletion(SILInstruction *I);

/// Deletes all scheuled instructions for real.
/// See scheduledForDeletion for details.
void flushDeletedInsts();

/// Looks up the llvm intrinsic ID and type for the builtin function.
///
Expand Down
Loading