Skip to content

[SSADestroyHoisting] Handle loops. #58791

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 6 commits into from
May 24, 2022
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
78 changes: 77 additions & 1 deletion include/swift/SIL/BasicBlockUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
#ifndef SWIFT_SIL_BASICBLOCKUTILS_H
#define SWIFT_SIL_BASICBLOCKUTILS_H

#include "swift/SIL/SILValue.h"
#include "swift/SIL/BasicBlockBits.h"
#include "swift/SIL/BasicBlockDatastructures.h"
#include "swift/SIL/SILValue.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
Expand Down Expand Up @@ -155,6 +156,81 @@ void findJointPostDominatingSet(
bool checkDominates(SILBasicBlock *sourceBlock, SILBasicBlock *destBlock);
#endif

/// Walk depth-first the region backwards reachable from the provided roots
/// constrained by \p region's \p isInRegion member function.
///
/// interface Region {
/// /// Whether the indicated basic block is within the region of the graph
/// /// that should be traversed.
/// bool isInRegion(SILBasicBlock *)
/// }
template <typename Region>
struct SILCFGBackwardDFS {
Region &region;
ArrayRef<SILBasicBlock *> roots;
Optional<SmallVector<SILBasicBlock *, 16>> cachedPostOrder;
Optional<BasicBlockSet> cachedVisited;

SILCFGBackwardDFS(Region &region, ArrayRef<SILBasicBlock *> roots)
: region(region), roots(roots) {}

/// Visit the blocks of the region in post-order.
///
/// interface Visitor {
/// /// Visit each block in topological order.
/// void visit(SILBasicBlock *)
/// }
template <typename Visitor>
void visitPostOrder(Visitor &visitor) {
if (roots.empty())
return;
auto *function = roots.front()->getParent();
cachedVisited.emplace(function);
for (auto *root : roots) {
SmallVector<std::pair<SILBasicBlock *, SILBasicBlock::pred_iterator>, 32>
stack;
if (!region.isInRegion(root))
continue;
stack.push_back({root, root->pred_begin()});
while (!stack.empty()) {
while (stack.back().second != stack.back().first->pred_end()) {
auto predecessor = *stack.back().second;
stack.back().second++;
if (!region.isInRegion(predecessor))
continue;
if (cachedVisited->insert(predecessor))
stack.push_back({predecessor, predecessor->pred_begin()});
}
visitor.visit(stack.back().first);
stack.pop_back();
}
}
}

/// Visit the region in post-order and cache the visited blocks.
void cachePostOrder() {
if (cachedPostOrder)
return;
struct Visitor {
SILCFGBackwardDFS<Region> &dfs;
void visit(SILBasicBlock *block) {
dfs.cachedPostOrder->push_back(block);
}
};
cachedPostOrder.emplace();
Visitor visitor{*this};
visitPostOrder(visitor);
}

/// The region in post-order.
ArrayRef<SILBasicBlock *> postOrder() {
cachePostOrder();
return *cachedPostOrder;
};

/// The region in reverse post-order.
auto reversePostOrder() { return llvm::reverse(postOrder()); }
};
} // namespace swift

#endif
2 changes: 1 addition & 1 deletion include/swift/SIL/SILBasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public SwiftObjectHeader {
/// A backreference to the containing SILFunction.
SILFunction *Parent;

/// PrevList - This is a list of all of the terminator operands that are
/// PredList - This is a list of all of the terminator operands that are
/// branching to this block, forming the predecessor list. This is
/// automatically managed by the SILSuccessor class.
SILSuccessor *PredList = nullptr;
Expand Down
Loading