From 046da9780665dd8e951b48e475ee03cf7da34fd4 Mon Sep 17 00:00:00 2001 From: Michael Zolotukhin Date: Sat, 12 May 2018 01:44:32 +0000 Subject: [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 --- llvm/unittests/IR/DominatorTreeTest.cpp | 70 +++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'llvm/unittests/IR/DominatorTreeTest.cpp') 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 #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 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 DefBlocks; + DefBlocks.insert(B); + IDF.setDefiningBlocks(DefBlocks); + + SmallVector IDFBlocks; + SmallPtrSet 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; -- cgit v1.2.3