diff options
author | Michael Zolotukhin <mzolotukhin@apple.com> | 2018-05-12 01:44:32 +0000 |
---|---|---|
committer | Michael Zolotukhin <mzolotukhin@apple.com> | 2018-05-12 01:44:32 +0000 |
commit | 046da9780665dd8e951b48e475ee03cf7da34fd4 (patch) | |
tree | 762226edcf8eec2b4c6fb1194d4e6c1045257b3c /llvm/unittests/IR/DominatorTreeTest.cpp | |
parent | 7012c246c10b456ee0b317b41d04c7addc3eb35b (diff) | |
download | bcm5719-llvm-046da9780665dd8e951b48e475ee03cf7da34fd4.tar.gz bcm5719-llvm-046da9780665dd8e951b48e475ee03cf7da34fd4.zip |
[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
llvm-svn: 332167
Diffstat (limited to 'llvm/unittests/IR/DominatorTreeTest.cpp')
-rw-r--r-- | llvm/unittests/IR/DominatorTreeTest.cpp | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/llvm/unittests/IR/DominatorTreeTest.cpp b/llvm/unittests/IR/DominatorTreeTest.cpp index d7f77af27b1..6a8cc55e5d5 100644 --- a/llvm/unittests/IR/DominatorTreeTest.cpp +++ b/llvm/unittests/IR/DominatorTreeTest.cpp @@ -9,6 +9,7 @@ #include <random> #include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/IteratedDominanceFrontier.h" #include "llvm/AsmParser/Parser.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Dominators.h" @@ -598,6 +599,75 @@ TEST(DominatorTree, DeletingEdgesIntroducesInfiniteLoop2) { }); } +// Verify that the IDF returns blocks in a deterministic way. +// +// Test case: +// +// CFG +// +// (A) +// / \ +// / \ +// (B) (C) +// |\ /| +// | X | +// |/ \| +// (D) (E) +// +// IDF for block B is {D, E}, and the order of blocks in this list is defined by +// their 1) level in dom-tree and 2) DFSIn number if the level is the same. +// +TEST(DominatorTree, IDFDeterminismTest) { + StringRef ModuleString = + "define void @f() {\n" + "A:\n" + " br i1 undef, label %B, label %C\n" + "B:\n" + " br i1 undef, label %D, label %E\n" + "C:\n" + " br i1 undef, label %D, label %E\n" + "D:\n" + " ret void\n" + "E:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString); + + runWithDomTree( + *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) { + Function::iterator FI = F.begin(); + + BasicBlock *A = &*FI++; + BasicBlock *B = &*FI++; + BasicBlock *C = &*FI++; + BasicBlock *D = &*FI++; + BasicBlock *E = &*FI++; + (void)C; + + DT->updateDFSNumbers(); + ForwardIDFCalculator IDF(*DT); + SmallPtrSet<BasicBlock *, 1> DefBlocks; + DefBlocks.insert(B); + IDF.setDefiningBlocks(DefBlocks); + + SmallVector<BasicBlock *, 32> IDFBlocks; + SmallPtrSet<BasicBlock *, 32> LiveInBlocks; + IDF.resetLiveInBlocks(); + IDF.calculate(IDFBlocks); + + + EXPECT_EQ(IDFBlocks.size(), 2UL); + EXPECT_EQ(DT->getNode(A)->getDFSNumIn(), 0UL); + EXPECT_EQ(IDFBlocks[0], D); + EXPECT_EQ(IDFBlocks[1], E); + EXPECT_TRUE(DT->getNode(IDFBlocks[0])->getDFSNumIn() < + DT->getNode(IDFBlocks[1])->getDFSNumIn()); + }); +} + namespace { const auto Insert = CFGBuilder::ActionKind::Insert; const auto Delete = CFGBuilder::ActionKind::Delete; |