mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Move InstructionDeleter into its own header.
Add file-level comments on the utility's purpose and intended API usage. Cleanup API comments.
This commit is contained in:
@@ -28,7 +28,6 @@
|
||||
#include "swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h"
|
||||
#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h"
|
||||
#include "swift/SILOptimizer/Utils/InstModCallbacks.h"
|
||||
#include "swift/SILOptimizer/Utils/UpdatingInstructionIterator.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
|
||||
namespace swift {
|
||||
@@ -76,6 +75,20 @@ bool hasOnlyEndOfScopeOrEndOfLifetimeUses(SILInstruction *inst);
|
||||
/// Return the number of @inout arguments passed to the given apply site.
|
||||
unsigned getNumInOutArguments(FullApplySite applySite);
|
||||
|
||||
/// If \c inst is dead, delete it and recursively eliminate all code that
|
||||
/// becomes dead because of that. If more than one instruction must
|
||||
/// be checked/deleted use the \c InstructionDeleter utility.
|
||||
///
|
||||
/// This function will add necessary compensation code to fix the lifetimes of
|
||||
/// the operands of the deleted instructions.
|
||||
///
|
||||
/// \pre the SIL function containing the instruction is assumed to be
|
||||
/// consistent, i.e., does not have under or over releases.
|
||||
///
|
||||
/// \p callbacks.onDelete() is invoked to delete each instruction.
|
||||
void eliminateDeadInstruction(SILInstruction *inst,
|
||||
InstModCallbacks callbacks = InstModCallbacks());
|
||||
|
||||
/// For each of the given instructions, if they are dead delete them
|
||||
/// along with their dead operands. Note this utility must be phased out and
|
||||
/// replaced by \c eliminateDeadInstruction and
|
||||
@@ -85,6 +98,8 @@ unsigned getNumInOutArguments(FullApplySite applySite);
|
||||
/// \param force If Force is set, don't check if the top level instructions
|
||||
/// are considered dead - delete them regardless.
|
||||
/// \param callbacks The inst mod callbacks used to delete instructions.
|
||||
///
|
||||
/// Deprecated: Use InstructionDeleter instead.
|
||||
void recursivelyDeleteTriviallyDeadInstructions(
|
||||
ArrayRef<SILInstruction *> inst, bool force = false,
|
||||
InstModCallbacks callbacks = InstModCallbacks());
|
||||
@@ -98,6 +113,8 @@ void recursivelyDeleteTriviallyDeadInstructions(
|
||||
/// \param force If Force is set, don't check if the top level instruction is
|
||||
/// considered dead - delete it regardless.
|
||||
/// \param callbacks InstModCallback used to delete instructions.
|
||||
///
|
||||
/// Deprecated: Use InstructionDeleter instead.
|
||||
void recursivelyDeleteTriviallyDeadInstructions(
|
||||
SILInstruction *inst, bool force = false,
|
||||
InstModCallbacks callbacks = InstModCallbacks());
|
||||
@@ -207,181 +224,6 @@ bool tryCheckedCastBrJumpThreading(
|
||||
SmallVectorImpl<SILBasicBlock *> &blocksForWorklist,
|
||||
bool EnableOSSARewriteTerminator);
|
||||
|
||||
/// A utility for deleting one or more instructions belonging to a function, and
|
||||
/// cleaning up any dead code resulting from deleting those instructions. Use
|
||||
/// this utility instead of \p recursivelyDeleteTriviallyDeadInstruction
|
||||
/// as follows:
|
||||
/// InstructionDeleter deleter;
|
||||
/// deleter.deleteIfDead(instruction);
|
||||
/// deleter.cleanupDeadInstructions();
|
||||
///
|
||||
/// This is designed to be used with a single 'onDelete' callback, which is
|
||||
/// invoked consistently just before deleting each instruction. It's usually
|
||||
/// used to avoid iterator invalidation (see the updatingIterator() factory
|
||||
/// method). The other InstModCallbacks should generally be handled at a higher
|
||||
/// level, and avoided altogether if possible. The following two are supported
|
||||
/// for flexibility:
|
||||
///
|
||||
/// callbacks.createdNewInst() is invoked incrementally when it fixes lifetimes
|
||||
/// while deleting a set of instructions, but the SIL may still be invalid
|
||||
/// relative to the new instruction.
|
||||
///
|
||||
/// callbacks.notifyWillBeDeletedFunc() is invoked when a dead instruction is
|
||||
/// first recognized and was not already passed in by the client. During the
|
||||
/// callback, the to-be-deleted instruction has valid SIL. It's operands and
|
||||
/// uses can be inspected and cached. It will be deleted later during
|
||||
/// cleanupDeadInstructions().
|
||||
///
|
||||
/// Note that the forceDelete* APIs only invoke notifyWillBeDeletedFunc() when
|
||||
/// an operand's definition will become dead after force-deleting the specified
|
||||
/// instruction. Some clients force-delete related instructions one at a
|
||||
/// time. It is the client's responsiblity to invoke notifyWillBeDeletedFunc()
|
||||
/// on those explicitly deleted instructions if needed.
|
||||
class InstructionDeleter {
|
||||
/// A set vector of instructions that are found to be dead. The ordering of
|
||||
/// instructions in this set is important as when a dead instruction is
|
||||
/// removed, new instructions will be generated to fix the lifetime of the
|
||||
/// instruction's operands. This has to be deterministic.
|
||||
SmallSetVector<SILInstruction *, 8> deadInstructions;
|
||||
|
||||
UpdatingInstructionIteratorRegistry iteratorRegistry;
|
||||
|
||||
public:
|
||||
InstructionDeleter(InstModCallbacks chainedCallbacks = InstModCallbacks())
|
||||
: deadInstructions(), iteratorRegistry(chainedCallbacks) {}
|
||||
|
||||
UpdatingInstructionIteratorRegistry &getIteratorRegistry() {
|
||||
return iteratorRegistry;
|
||||
}
|
||||
|
||||
InstModCallbacks &getCallbacks() { return iteratorRegistry.getCallbacks(); }
|
||||
|
||||
llvm::iterator_range<UpdatingInstructionIterator>
|
||||
updatingRange(SILBasicBlock *bb) {
|
||||
return iteratorRegistry.makeIteratorRange(bb);
|
||||
}
|
||||
|
||||
llvm::iterator_range<UpdatingReverseInstructionIterator>
|
||||
updatingReverseRange(SILBasicBlock *bb) {
|
||||
return iteratorRegistry.makeReverseIteratorRange(bb);
|
||||
}
|
||||
|
||||
bool hadCallbackInvocation() const {
|
||||
return const_cast<InstructionDeleter *>(this)
|
||||
->getCallbacks()
|
||||
.hadCallbackInvocation();
|
||||
}
|
||||
|
||||
/// If the instruction \p inst is dead, record it so that it can be cleaned
|
||||
/// up.
|
||||
///
|
||||
/// Calls callbacks.notifyWillBeDeleted().
|
||||
bool trackIfDead(SILInstruction *inst);
|
||||
|
||||
/// Track this instruction as dead even if it has side effects. Used to enable
|
||||
/// the deletion of a bunch of instructions at the same time.
|
||||
///
|
||||
/// Calls callbacks.notifyWillBeDeleted().
|
||||
void forceTrackAsDead(SILInstruction *inst);
|
||||
|
||||
/// If the instruction \p inst is dead, delete it immediately along with its
|
||||
/// destroys and scope-ending uses. If any operand definitions will become
|
||||
/// dead after deleting this instruction, track them so they can be deleted
|
||||
/// later during cleanUpDeadInstructions().
|
||||
///
|
||||
/// Calls callbacks.notifyWillBeDeleted().
|
||||
bool deleteIfDead(SILInstruction *inst);
|
||||
|
||||
/// Delete the instruction \p inst, ignoring its side effects. If any operand
|
||||
/// definitions will become dead after deleting this instruction, track them
|
||||
/// so they can be deleted later during cleanUpDeadInstructions(). This
|
||||
/// function will add necessary ownership instructions to fix the lifetimes of
|
||||
/// the operands of \p inst to compensate for its deletion.
|
||||
///
|
||||
/// \pre the function containing \p inst must be using ownership SIL.
|
||||
/// \pre the instruction to be deleted must not have any use other than
|
||||
/// incidental uses.
|
||||
///
|
||||
/// callbacks.notifyWillBeDeleted will not be called for \p inst but will be
|
||||
/// called for any other instructions that become dead as a result.
|
||||
void forceDeleteAndFixLifetimes(SILInstruction *inst);
|
||||
|
||||
/// Delete the instruction \p inst and record instructions that may become
|
||||
/// dead because of the removal of \c inst. If in ownership SIL, use the
|
||||
/// \c forceDeleteAndFixLifetimes function instead, unless under special
|
||||
/// circumstances where the client must handle fixing lifetimes of the
|
||||
/// operands of the deleted instructions. This function will not fix the
|
||||
/// lifetimes of the operands of \c inst once it is deleted. This function
|
||||
/// will not clean up dead code resulting from the instruction's removal. To
|
||||
/// do so, invoke the method \c cleanupDeadCode of this instance, once the SIL
|
||||
/// of the contaning function is made consistent.
|
||||
///
|
||||
/// \pre the instruction to be deleted must not have any use other than
|
||||
/// incidental uses.
|
||||
///
|
||||
/// callbacks.notifyWillBeDeleted will not be called for \p inst but will be
|
||||
/// called for any other instructions that become dead as a result.
|
||||
void forceDelete(SILInstruction *inst);
|
||||
|
||||
/// Recursively delete all of the uses of the instruction before deleting the
|
||||
/// instruction itself. Does not fix lifetimes.
|
||||
///
|
||||
/// callbacks.notifyWillBeDeleted will not be called for \p inst but will
|
||||
/// be called for any other instructions that become dead as a result.
|
||||
void forceDeleteWithUsers(SILInstruction *inst) {
|
||||
deleteWithUses(inst, /*fixLifetimes*/ false, /*forceDeleteUsers*/ true);
|
||||
}
|
||||
|
||||
/// Clean up dead instructions that are tracked by this instance and all
|
||||
/// instructions that transitively become dead.
|
||||
///
|
||||
/// \pre the function contaning dead instructions must be consistent (i.e., no
|
||||
/// under or over releases). Note that if \c forceDelete call leaves the
|
||||
/// function body in an inconsistent state, it needs to be made consistent
|
||||
/// before this method is invoked.
|
||||
///
|
||||
/// callbacks.notifyWillBeDeletedFunc will only be called for instructions
|
||||
/// that become dead during cleanup but were not already tracked.
|
||||
void cleanupDeadInstructions();
|
||||
|
||||
/// Recursively visit users of \p inst and delete instructions that are dead
|
||||
/// including \p inst.
|
||||
///
|
||||
/// callbacks.notifyWillBeDeletedFunc will be called for any dead
|
||||
/// instructions.
|
||||
void recursivelyDeleteUsersIfDead(SILInstruction *inst);
|
||||
|
||||
/// Recursively visit users of \p inst and force delete them including \p
|
||||
/// inst. Also, destroy the consumed operands of the deleted instructions
|
||||
/// whenever necessary.
|
||||
///
|
||||
/// callbacks.notifyWillBeDeletedFunc will not be called for \p inst or its
|
||||
/// users but will be called for any other instructions that become dead as a
|
||||
/// result.
|
||||
void recursivelyForceDeleteUsersAndFixLifetimes(SILInstruction *inst);
|
||||
|
||||
private:
|
||||
void deleteWithUses(SILInstruction *inst, bool fixLifetimes,
|
||||
bool forceDeleteUsers = false);
|
||||
};
|
||||
|
||||
/// If \c inst is dead, delete it and recursively eliminate all code that
|
||||
/// becomes dead because of that. If more than one instruction must
|
||||
/// be checked/deleted use the \c InstructionDeleter utility.
|
||||
///
|
||||
/// This function will add necessary compensation code to fix the lifetimes of
|
||||
/// the operands of the deleted instructions.
|
||||
///
|
||||
/// \pre the SIL function containing the instruction is assumed to be
|
||||
/// consistent, i.e., does not have under or over releases.
|
||||
///
|
||||
/// \p callbacks is used to delete each instruction. However, the callback
|
||||
/// cannot be used to update instruction iterators since other instructions to
|
||||
/// be deleted remain in the instruction list. If set to nullptr, we use the
|
||||
/// default instruction modification callback structure.
|
||||
void eliminateDeadInstruction(SILInstruction *inst,
|
||||
InstModCallbacks callbacks = InstModCallbacks());
|
||||
|
||||
/// Get all consumed arguments of a partial_apply.
|
||||
///
|
||||
/// These are basically all arguments, except inout arguments and arguments
|
||||
@@ -731,4 +573,4 @@ bool eliminateDeadAllocations(SILFunction &fn);
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif
|
||||
#endif // SWIFT_SILOPTIMIZER_UTILS_INSTOPTUTILS_H
|
||||
|
||||
Reference in New Issue
Block a user