Skip to content

[SIL] Perf: Cache basic block during SILSuccessor iteration #16869

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
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
9 changes: 9 additions & 0 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -8094,6 +8094,15 @@ inline EnumElementDecl **SelectEnumInstBase::getEnumElementDeclStorage() {
llvm_unreachable("Unhandled SelectEnumInstBase subclass");
}

inline void SILSuccessor::pred_iterator::cacheBasicBlock() {
if (Cur != nullptr) {
Block = Cur->ContainingInst->getParent();
assert(Block != nullptr);
} else {
Block = nullptr;
}
}

} // end swift namespace

//===----------------------------------------------------------------------===//
Expand Down
26 changes: 19 additions & 7 deletions include/swift/SIL/SILSuccessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,33 +87,45 @@ class SILSuccessor {
class pred_iterator {
SILSuccessor *Cur;

// Cache the basic block to avoid repeated pointer chasing.
SILBasicBlock *Block;

void cacheBasicBlock();

public:
using difference_type = std::ptrdiff_t;
using value_type = SILBasicBlock *;
using pointer = SILBasicBlock **;
using reference = SILBasicBlock *&;
using iterator_category = std::forward_iterator_tag;

pred_iterator(SILSuccessor *Cur = 0) : Cur(Cur) {}
pred_iterator(SILSuccessor *Cur = nullptr) : Cur(Cur), Block(nullptr) {
cacheBasicBlock();
}

bool operator==(pred_iterator I2) const { return Cur == I2.Cur; }
bool operator!=(pred_iterator I2) const { return Cur != I2.Cur; }

pred_iterator &operator++() {
assert(Cur && "Trying to advance past end");
assert(Cur != nullptr);
Cur = Cur->Next;
cacheBasicBlock();
return *this;
}

pred_iterator operator++(int) {
pred_iterator copy = *this;
++*this;
pred_iterator operator+(unsigned distance) const {
auto copy = *this;
if (distance == 0)
return copy;
do {
copy.Cur = Cur->Next;
} while (--distance > 0);
copy.cacheBasicBlock();
return copy;
}

SILSuccessor *getSuccessorRef() const { return Cur; }
SILBasicBlock *operator*();
const SILBasicBlock *operator*() const;
SILBasicBlock *operator*() const { return Block; }
};
};

Expand Down
12 changes: 0 additions & 12 deletions lib/SIL/SILSuccessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,3 @@ void SILSuccessor::operator=(SILBasicBlock *BB) {

SuccessorBlock = BB;
}

// Dereferencing the pred_iterator returns the predecessor's SILBasicBlock.
SILBasicBlock *SILSuccessor::pred_iterator::operator*() {
assert(Cur && "Can't deference end (or default constructed) iterator");
return Cur->ContainingInst->getParent();
}

// Dereferencing the pred_iterator returns the predecessor's SILBasicBlock.
const SILBasicBlock *SILSuccessor::pred_iterator::operator*() const {
assert(Cur && "Can't deference end (or default constructed) iterator");
return Cur->ContainingInst->getParent();
}