mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
SIL: simplify deleting instruction while iterating over instructions.
Add `deletableInstructions()` and `reverseDeletableInstructions()` in SILBasicBlock. It allows deleting instructions while iterating over all instructions of the block. This is a replacement for `InstructionDeleter::updatingRange()`. It's a simpler implementation than the existing `UpdatingListIterator` and `UpdatingInstructionIteratorRegistry`, because it just needs to keep the prev/next pointers for "deleted" instructions instead of the iterator-registration machinery. It's also safer, because it doesn't require to delete instructions via a specific instance of an InstructionDeleter (which can be missed easily).
This commit is contained in:
@@ -31,6 +31,51 @@ class SILFunction;
|
||||
class SILArgument;
|
||||
class SILPrintContext;
|
||||
|
||||
/// Instruction iterator which allows to "delete" instructions while iterating
|
||||
/// over the instruction list.
|
||||
///
|
||||
/// Iteration with this iterator allows to delete the current, the next or any
|
||||
/// instruction in the list while iterating.
|
||||
/// This works because instruction deletion is deferred (for details see
|
||||
/// `SILModule::scheduledForDeletion`) and removing an instruction from the list
|
||||
/// keeps the prev/next pointers (see `SILInstructionListBase`).
|
||||
template <typename IteratorBase>
|
||||
class DeletableInstructionsIterator {
|
||||
using Self = DeletableInstructionsIterator<IteratorBase>;
|
||||
|
||||
IteratorBase base;
|
||||
IteratorBase end;
|
||||
|
||||
public:
|
||||
using value_type = typename IteratorBase::value_type;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = value_type *;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
DeletableInstructionsIterator(IteratorBase base, IteratorBase end)
|
||||
: base(base), end(end) {}
|
||||
|
||||
value_type &operator*() const { return *base; }
|
||||
|
||||
SILInstruction *operator->() const { return base.operator->(); }
|
||||
|
||||
Self &operator++() {
|
||||
// If the current instruction is "deleted" (which means: removed from the
|
||||
// list), it's prev/next pointers still point to the next instruction which
|
||||
// is still in the list - or "deleted", too.
|
||||
++base;
|
||||
// Skip over all deleted instructions. Eventually we reach an instruction
|
||||
// is still in the list (= not "deleted") or the end iterator.
|
||||
while (base != end && base->isDeleted()) {
|
||||
++base;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Self &rhs) const { return base == rhs.base; }
|
||||
bool operator!=(const Self &rhs) const { return !(*this == rhs); }
|
||||
};
|
||||
|
||||
class SILBasicBlock :
|
||||
public llvm::ilist_node<SILBasicBlock>, public SILAllocated<SILBasicBlock>,
|
||||
public SwiftObjectHeader {
|
||||
@@ -184,6 +229,20 @@ public:
|
||||
const_reverse_iterator rbegin() const { return InstList.rbegin(); }
|
||||
const_reverse_iterator rend() const { return InstList.rend(); }
|
||||
|
||||
/// Allows deleting instructions while iterating over all instructions of the
|
||||
/// block.
|
||||
///
|
||||
/// For details see `DeletableInstructionsIterator`.
|
||||
llvm::iterator_range<DeletableInstructionsIterator<iterator>>
|
||||
deletableInstructions() { return {{begin(), end()}, {end(), end()}}; }
|
||||
|
||||
/// Allows deleting instructions while iterating over all instructions of the
|
||||
/// block in reverse order.
|
||||
///
|
||||
/// For details see `DeletableInstructionsIterator`.
|
||||
llvm::iterator_range<DeletableInstructionsIterator<reverse_iterator>>
|
||||
reverseDeletableInstructions() { return {{rbegin(), rend()}, {rend(), rend()}}; }
|
||||
|
||||
TermInst *getTerminator() {
|
||||
assert(!InstList.empty() && "Can't get successors for malformed block");
|
||||
return cast<TermInst>(&InstList.back());
|
||||
|
||||
Reference in New Issue
Block a user