llvm.org GIT mirror llvm / 105e762
[IDF] Enforce the returned blocks to be sorted. Summary: Currently the order of blocks returned by `IDF::calculate` can be non-deterministic. This was discovered in several attempts to enable SSAUpdaterBulk for JumpThreading (which led to miscompare in bootstrap between stage 3 and stage4). Originally, the blocks were put into a priority queue with a depth level as their key, and this patch adds a DFSIn number as a second key to specify a deterministic order across blocks from one level. The solution was suggested by Daniel Berlin. Reviewers: dberlin, davide Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D46646 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@332167 91177308-0d34-0410-b5e6-96231b3b80d8 Michael Zolotukhin 1 year, 5 months ago
2 changed file(s) with 81 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
2020 void IDFCalculator::calculate(
2121 SmallVectorImpl &PHIBlocks) {
2222 // Use a priority queue keyed on dominator tree level so that inserted nodes
23 // are handled from the bottom of the dominator tree upwards.
24 typedef std::pair DomTreeNodePair;
23 // are handled from the bottom of the dominator tree upwards. We also augment
24 // the level with a DFS number to ensure that the blocks are ordered in a
25 // deterministic way.
26 typedef std::pair>
27 DomTreeNodePair;
2528 typedef std::priority_queue,
2629 less_second> IDFPriorityQueue;
2730 IDFPriorityQueue PQ;
2831
32 DT.updateDFSNumbers();
33
2934 for (BasicBlock *BB : *DefBlocks) {
3035 if (DomTreeNode *Node = DT.getNode(BB))
31 PQ.push({Node, Node->getLevel()});
36 PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
3237 }
3338
3439 SmallVector Worklist;
3944 DomTreeNodePair RootPair = PQ.top();
4045 PQ.pop();
4146 DomTreeNode *Root = RootPair.first;
42 unsigned RootLevel = RootPair.second;
47 unsigned RootLevel = RootPair.second.first;
4348
4449 // Walk all dominator tree children of Root, inspecting their CFG edges with
4550 // targets elsewhere on the dominator tree. Only targets whose level is at
7681
7782 PHIBlocks.emplace_back(SuccBB);
7883 if (!DefBlocks->count(SuccBB))
79 PQ.push(std::make_pair(SuccNode, SuccLevel));
84 PQ.push(std::make_pair(
85 SuccNode, std::make_pair(SuccLevel, SuccNode->getDFSNumIn())));
8086 }
8187
8288 for (auto DomChild : *Node) {
88
99 #include
1010 #include "llvm/Analysis/PostDominators.h"
11 #include "llvm/Analysis/IteratedDominanceFrontier.h"
1112 #include "llvm/AsmParser/Parser.h"
1213 #include "llvm/IR/Constants.h"
1314 #include "llvm/IR/Dominators.h"
597598 });
598599 }
599600
601 // Verify that the IDF returns blocks in a deterministic way.
602 //
603 // Test case:
604 //
605 // CFG
606 //
607 // (A)
608 // / \
609 // / \
610 // (B) (C)
611 // |\ /|
612 // | X |
613 // |/ \|
614 // (D) (E)
615 //
616 // IDF for block B is {D, E}, and the order of blocks in this list is defined by
617 // their 1) level in dom-tree and 2) DFSIn number if the level is the same.
618 //
619 TEST(DominatorTree, IDFDeterminismTest) {
620 StringRef ModuleString =
621 "define void @f() {\n"
622 "A:\n"
623 " br i1 undef, label %B, label %C\n"
624 "B:\n"
625 " br i1 undef, label %D, label %E\n"
626 "C:\n"
627 " br i1 undef, label %D, label %E\n"
628 "D:\n"
629 " ret void\n"
630 "E:\n"
631 " ret void\n"
632 "}\n";
633
634 // Parse the module.
635 LLVMContext Context;
636 std::unique_ptr M = makeLLVMModule(Context, ModuleString);
637
638 runWithDomTree(
639 *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
640 Function::iterator FI = F.begin();
641
642 BasicBlock *A = &*FI++;
643 BasicBlock *B = &*FI++;
644 BasicBlock *C = &*FI++;
645 BasicBlock *D = &*FI++;
646 BasicBlock *E = &*FI++;
647 (void)C;
648
649 DT->updateDFSNumbers();
650 ForwardIDFCalculator IDF(*DT);
651 SmallPtrSet DefBlocks;
652 DefBlocks.insert(B);
653 IDF.setDefiningBlocks(DefBlocks);
654
655 SmallVector IDFBlocks;
656 SmallPtrSet LiveInBlocks;
657 IDF.resetLiveInBlocks();
658 IDF.calculate(IDFBlocks);
659
660
661 EXPECT_EQ(IDFBlocks.size(), 2UL);
662 EXPECT_EQ(DT->getNode(A)->getDFSNumIn(), 0UL);
663 EXPECT_EQ(IDFBlocks[0], D);
664 EXPECT_EQ(IDFBlocks[1], E);
665 EXPECT_TRUE(DT->getNode(IDFBlocks[0])->getDFSNumIn() <
666 DT->getNode(IDFBlocks[1])->getDFSNumIn());
667 });
668 }
669
600670 namespace {
601671 const auto Insert = CFGBuilder::ActionKind::Insert;
602672 const auto Delete = CFGBuilder::ActionKind::Delete;