summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/IR/DominatorTreeTest.cpp
diff options
context:
space:
mode:
authorMichael Zolotukhin <mzolotukhin@apple.com>2018-05-12 01:44:32 +0000
committerMichael Zolotukhin <mzolotukhin@apple.com>2018-05-12 01:44:32 +0000
commit046da9780665dd8e951b48e475ee03cf7da34fd4 (patch)
tree762226edcf8eec2b4c6fb1194d4e6c1045257b3c /llvm/unittests/IR/DominatorTreeTest.cpp
parent7012c246c10b456ee0b317b41d04c7addc3eb35b (diff)
downloadbcm5719-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.cpp70
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;
OpenPOWER on IntegriCloud