Skip to content

Commit 380db37

Browse files
committed
DeadCodeElimination: replace recursive post-dominator walks with iterative worklist algorithms.
This fixes stack-overflow crashes when compiling large functions. rdar://problem/56268570
1 parent 1c64770 commit 380db37

File tree

1 file changed

+71
-47
lines changed

1 file changed

+71
-47
lines changed

lib/SILOptimizer/Transforms/DeadCodeElimination.cpp

Lines changed: 71 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,10 @@ class DCE : public SILFunctionTransform {
162162
void addReverseDependency(SILInstruction *From, SILInstruction *To);
163163
bool removeDead(SILFunction &F);
164164

165-
void computeLevelNumbers(PostDomTreeNode *Node, unsigned Level);
165+
void computeLevelNumbers(PostDomTreeNode *root);
166166
bool hasInfiniteLoops(SILFunction &F);
167167
void computePredecessorDependence(SILFunction &F);
168-
unsigned computeMinPredecessorLevels(PostDomTreeNode *Node);
168+
void computeMinPredecessorLevels(PostDomTreeNode *root);
169169
void insertControllingInfo(SILBasicBlock *Block, unsigned Level);
170170

171171
void markValueLive(SILNode *V);
@@ -175,7 +175,7 @@ class DCE : public SILFunctionTransform {
175175
void propagateLiveBlockArgument(SILArgument *Arg);
176176
void propagateLiveness(SILInstruction *I);
177177
void collectControllingBlocksInTree(ControllingInfo &QueryInfo,
178-
PostDomTreeNode *Node,
178+
PostDomTreeNode *root,
179179
llvm::SmallPtrSetImpl<SILBasicBlock *> &Controlling);
180180
void collectControllingBlocks(SILBasicBlock *Block,
181181
llvm::SmallPtrSetImpl<SILBasicBlock *> &);
@@ -537,7 +537,7 @@ bool DCE::removeDead(SILFunction &F) {
537537
// Returns true upon success, false if nodes that are not present in the
538538
// post-dominator tree are detected.
539539
bool DCE::precomputeControlInfo(SILFunction &F) {
540-
computeLevelNumbers(PDT->getRootNode(), 0);
540+
computeLevelNumbers(PDT->getRootNode());
541541
if (hasInfiniteLoops(F))
542542
return false;
543543
computePredecessorDependence(F);
@@ -557,12 +557,22 @@ void DCE::insertControllingInfo(SILBasicBlock *Block, unsigned Level) {
557557
ControllingInfoMap[Block] = Info;
558558
}
559559

560-
// Assign a level number to each node in the post-dominator tree, and
561-
void DCE::computeLevelNumbers(PostDomTreeNode *Node, unsigned Level) {
562-
insertControllingInfo(Node->getBlock(), Level);
563-
564-
for (auto Child = Node->begin(), End = Node->end(); Child != End; ++Child)
565-
computeLevelNumbers(*Child, Level + 1);
560+
// Assign a level number to each node in the post-dominator tree.
561+
void DCE::computeLevelNumbers(PostDomTreeNode *root) {
562+
llvm::SmallVector<std::pair<PostDomTreeNode *, unsigned>, 32> workList;
563+
workList.push_back({root, 0});
564+
565+
while (!workList.empty()) {
566+
auto entry = workList.pop_back_val();
567+
PostDomTreeNode *node = entry.first;
568+
unsigned level = entry.second;
569+
570+
insertControllingInfo(node->getBlock(), level);
571+
572+
for (PostDomTreeNode *child : *node) {
573+
workList.push_back({child, level + 1});
574+
}
575+
}
566576
}
567577

568578
// Structurally infinite loops like:
@@ -605,51 +615,65 @@ void DCE::computePredecessorDependence(SILFunction &F) {
605615
}
606616
}
607617

608-
// Return the minimum post-dominator tree level of any of the
609-
// direct controlling predecessors of this node or any child.
610-
unsigned DCE::computeMinPredecessorLevels(PostDomTreeNode *Node) {
611-
unsigned Min = -1;
612-
613-
auto *Block = Node->getBlock();
614-
615-
assert(ControllingInfoMap.find(Block) != ControllingInfoMap.end() &&
616-
"Expected to have map entry for node!");
618+
// Assign the minimum post-dominator tree level to each node in the tree.
619+
void DCE::computeMinPredecessorLevels(PostDomTreeNode *root) {
620+
llvm::SmallVector<PostDomTreeNode *, 32> postDomOrder;
621+
postDomOrder.reserve(ControllingInfoMap.size());
622+
postDomOrder.push_back(root);
617623

618-
auto &MapElement = ControllingInfoMap[Block];
619-
for (auto &PredInfo : MapElement.ControllingPreds)
620-
Min = std::min(Min, PredInfo.second);
621-
622-
for (auto Child = Node->begin(), End = Node->end(); Child != End; ++Child)
623-
Min = std::min(Min, computeMinPredecessorLevels(*Child));
624+
for (unsigned idx = 0; idx < postDomOrder.size(); ++idx) {
625+
PostDomTreeNode *node = postDomOrder[idx];
626+
for (PostDomTreeNode *child : *node) {
627+
postDomOrder.push_back(child);
628+
}
629+
}
624630

625-
MapElement.MinTreePredLevel = Min;
631+
for (PostDomTreeNode *node : llvm::reverse(postDomOrder)) {
632+
SILBasicBlock *block = node->getBlock();
633+
assert(ControllingInfoMap.find(block) != ControllingInfoMap.end() &&
634+
"Expected to have map entry for node!");
626635

627-
return Min;
636+
ControllingInfo &nodeInfo = ControllingInfoMap[block];
637+
for (auto &pred : nodeInfo.ControllingPreds) {
638+
nodeInfo.MinTreePredLevel = std::min(nodeInfo.MinTreePredLevel, pred.second);
639+
}
640+
if (PostDomTreeNode *parentNode = node->getIDom()) {
641+
ControllingInfo &parentInfo = ControllingInfoMap[parentNode->getBlock()];
642+
parentInfo.MinTreePredLevel = std::min(parentInfo.MinTreePredLevel, nodeInfo.MinTreePredLevel);
643+
}
644+
}
628645
}
629646

630647
void DCE::collectControllingBlocksInTree(ControllingInfo &QueryInfo,
631-
PostDomTreeNode *Node,
648+
PostDomTreeNode *root,
632649
llvm::SmallPtrSetImpl<SILBasicBlock *> &Controlling) {
633-
auto *Block = Node->getBlock();
634-
635-
assert(ControllingInfoMap.find(Block) != ControllingInfoMap.end() &&
636-
"Expected to have map entry for node!");
637-
638-
auto &MapEntry = ControllingInfoMap[Block];
639-
if (MapEntry.MinTreePredLevel > QueryInfo.Level)
640-
return;
641-
642-
for (auto &PredInfo : MapEntry.ControllingPreds)
643-
if (PredInfo.second <= QueryInfo.Level) {
644-
assert(PDT->properlyDominates(
645-
PDT->getNode(PredInfo.first)->getIDom()->getBlock(),
646-
QueryInfo.Block) &&
647-
"Expected predecessor's post-dominator to post-dominate node.");
648-
Controlling.insert(PredInfo.first);
650+
llvm::SmallVector<PostDomTreeNode *, 32> workList;
651+
workList.push_back(root);
652+
653+
while (!workList.empty()) {
654+
PostDomTreeNode *node = workList.pop_back_val();
655+
SILBasicBlock *block = node->getBlock();
656+
657+
assert(ControllingInfoMap.find(block) != ControllingInfoMap.end() &&
658+
"Expected to have map entry for node!");
659+
660+
auto &nodeInfo = ControllingInfoMap[block];
661+
if (nodeInfo.MinTreePredLevel > QueryInfo.Level)
662+
continue;
663+
664+
for (auto &PredInfo : nodeInfo.ControllingPreds) {
665+
if (PredInfo.second <= QueryInfo.Level) {
666+
assert(PDT->properlyDominates(
667+
PDT->getNode(PredInfo.first)->getIDom()->getBlock(),
668+
QueryInfo.Block) &&
669+
"Expected predecessor's post-dominator to post-dominate node.");
670+
Controlling.insert(PredInfo.first);
671+
}
649672
}
650-
651-
for (auto Child = Node->begin(), End = Node->end(); Child != End; ++Child)
652-
collectControllingBlocksInTree(QueryInfo, (*Child), Controlling);
673+
for (PostDomTreeNode *child : *node) {
674+
workList.push_back(child);
675+
}
676+
}
653677
}
654678

655679
// Walk the post-dominator tree from the query block down, building

0 commit comments

Comments
 (0)