diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-07-19 07:02:10 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-07-19 07:02:10 +0000 |
commit | 93c91e39b29142dec1d03a30df9f6e757f56c193 (patch) | |
tree | 33a9b014a327e64450b3c9ed46d8c5bdb78ad345 /unittests/IR/DominatorTreeTest.cpp | |
parent | ca089b24d48ef6fa8da2d0bb8c25bb802c4a95c0 (diff) |
Notes
Diffstat (limited to 'unittests/IR/DominatorTreeTest.cpp')
-rw-r--r-- | unittests/IR/DominatorTreeTest.cpp | 300 |
1 files changed, 289 insertions, 11 deletions
diff --git a/unittests/IR/DominatorTreeTest.cpp b/unittests/IR/DominatorTreeTest.cpp index fa3dad8a2ab1..df1e2993dc85 100644 --- a/unittests/IR/DominatorTreeTest.cpp +++ b/unittests/IR/DominatorTreeTest.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include <random> #include "llvm/Analysis/PostDominators.h" #include "llvm/AsmParser/Parser.h" #include "llvm/IR/Constants.h" @@ -15,22 +16,24 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/SourceMgr.h" +#include "CFGBuilder.h" #include "gtest/gtest.h" using namespace llvm; +struct PostDomTree : PostDomTreeBase<BasicBlock> { + PostDomTree(Function &F) { recalculate(F); } +}; + /// Build the dominator tree for the function and run the Test. -static void -runWithDomTree(Module &M, StringRef FuncName, - function_ref<void(Function &F, DominatorTree *DT, - DominatorTreeBase<BasicBlock> *PDT)> - Test) { +static void runWithDomTree( + Module &M, StringRef FuncName, + function_ref<void(Function &F, DominatorTree *DT, PostDomTree *PDT)> Test) { auto *F = M.getFunction(FuncName); ASSERT_NE(F, nullptr) << "Could not find " << FuncName; // Compute the dominator tree for the function. DominatorTree DT(*F); - DominatorTreeBase<BasicBlock> PDT(/*isPostDom*/ true); - PDT.recalculate(*F); + PostDomTree PDT(*F); Test(*F, &DT, &PDT); } @@ -72,8 +75,7 @@ TEST(DominatorTree, Unreachable) { std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString); runWithDomTree( - *M, "f", - [&](Function &F, DominatorTree *DT, DominatorTreeBase<BasicBlock> *PDT) { + *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) { Function::iterator FI = F.begin(); BasicBlock *BB0 = &*FI++; @@ -293,8 +295,7 @@ TEST(DominatorTree, NonUniqueEdges) { std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString); runWithDomTree( - *M, "f", - [&](Function &F, DominatorTree *DT, DominatorTreeBase<BasicBlock> *PDT) { + *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) { Function::iterator FI = F.begin(); BasicBlock *BB0 = &*FI++; @@ -324,3 +325,280 @@ TEST(DominatorTree, NonUniqueEdges) { EXPECT_FALSE(DT->dominates(Edge_BB0_BB1_b, BB2)); }); } + +namespace { +const auto Insert = CFGBuilder::ActionKind::Insert; +const auto Delete = CFGBuilder::ActionKind::Delete; + +bool CompUpdates(const CFGBuilder::Update &A, const CFGBuilder::Update &B) { + return std::tie(A.Action, A.Edge.From, A.Edge.To) < + std::tie(B.Action, B.Edge.From, B.Edge.To); +} +} // namespace + +TEST(DominatorTree, InsertReachable) { + CFGHolder Holder; + std::vector<CFGBuilder::Arc> Arcs = { + {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"}, + {"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}}; + + std::vector<CFGBuilder::Update> Updates = {{Insert, {"12", "10"}}, + {Insert, {"10", "9"}}, + {Insert, {"7", "6"}}, + {Insert, {"7", "5"}}}; + CFGBuilder B(Holder.F, Arcs, Updates); + DominatorTree DT(*Holder.F); + EXPECT_TRUE(DT.verify()); + PostDomTree PDT(*Holder.F); + EXPECT_TRUE(PDT.verify()); + + Optional<CFGBuilder::Update> LastUpdate; + while ((LastUpdate = B.applyUpdate())) { + EXPECT_EQ(LastUpdate->Action, Insert); + BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From); + BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To); + DT.insertEdge(From, To); + EXPECT_TRUE(DT.verify()); + PDT.insertEdge(From, To); + EXPECT_TRUE(PDT.verify()); + } +} + +TEST(DominatorTree, InsertReachable2) { + CFGHolder Holder; + std::vector<CFGBuilder::Arc> Arcs = { + {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"}, + {"7", "5"}, {"2", "8"}, {"8", "11"}, {"11", "12"}, {"12", "10"}, + {"10", "9"}, {"9", "10"}}; + + std::vector<CFGBuilder::Update> Updates = {{Insert, {"10", "7"}}}; + CFGBuilder B(Holder.F, Arcs, Updates); + DominatorTree DT(*Holder.F); + EXPECT_TRUE(DT.verify()); + PostDomTree PDT(*Holder.F); + EXPECT_TRUE(PDT.verify()); + + Optional<CFGBuilder::Update> LastUpdate = B.applyUpdate(); + EXPECT_TRUE(LastUpdate); + + EXPECT_EQ(LastUpdate->Action, Insert); + BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From); + BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To); + DT.insertEdge(From, To); + EXPECT_TRUE(DT.verify()); + PDT.insertEdge(From, To); + EXPECT_TRUE(PDT.verify()); +} + +TEST(DominatorTree, InsertUnreachable) { + CFGHolder Holder; + std::vector<CFGBuilder::Arc> Arcs = {{"1", "2"}, {"2", "3"}, {"3", "4"}, + {"5", "6"}, {"5", "7"}, {"3", "8"}, + {"9", "10"}, {"11", "12"}}; + + std::vector<CFGBuilder::Update> Updates = {{Insert, {"4", "5"}}, + {Insert, {"8", "9"}}, + {Insert, {"10", "12"}}, + {Insert, {"10", "11"}}}; + CFGBuilder B(Holder.F, Arcs, Updates); + DominatorTree DT(*Holder.F); + EXPECT_TRUE(DT.verify()); + PostDomTree PDT(*Holder.F); + EXPECT_TRUE(PDT.verify()); + + Optional<CFGBuilder::Update> LastUpdate; + while ((LastUpdate = B.applyUpdate())) { + EXPECT_EQ(LastUpdate->Action, Insert); + BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From); + BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To); + DT.insertEdge(From, To); + EXPECT_TRUE(DT.verify()); + PDT.insertEdge(From, To); + EXPECT_TRUE(PDT.verify()); + } +} + +TEST(DominatorTree, InsertMixed) { + CFGHolder Holder; + std::vector<CFGBuilder::Arc> Arcs = { + {"1", "2"}, {"2", "3"}, {"3", "4"}, {"5", "6"}, {"5", "7"}, + {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}, {"7", "3"}}; + + std::vector<CFGBuilder::Update> Updates = { + {Insert, {"4", "5"}}, {Insert, {"2", "5"}}, {Insert, {"10", "9"}}, + {Insert, {"12", "10"}}, {Insert, {"12", "10"}}, {Insert, {"7", "8"}}, + {Insert, {"7", "5"}}}; + CFGBuilder B(Holder.F, Arcs, Updates); + DominatorTree DT(*Holder.F); + EXPECT_TRUE(DT.verify()); + PostDomTree PDT(*Holder.F); + EXPECT_TRUE(PDT.verify()); + + Optional<CFGBuilder::Update> LastUpdate; + while ((LastUpdate = B.applyUpdate())) { + EXPECT_EQ(LastUpdate->Action, Insert); + BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From); + BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To); + DT.insertEdge(From, To); + EXPECT_TRUE(DT.verify()); + PDT.insertEdge(From, To); + EXPECT_TRUE(PDT.verify()); + } +} + +TEST(DominatorTree, InsertPermut) { + std::vector<CFGBuilder::Arc> Arcs = { + {"1", "2"}, {"2", "3"}, {"3", "4"}, {"5", "6"}, {"5", "7"}, + {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}, {"7", "3"}}; + + std::vector<CFGBuilder::Update> Updates = {{Insert, {"4", "5"}}, + {Insert, {"2", "5"}}, + {Insert, {"10", "9"}}, + {Insert, {"12", "10"}}}; + + while (std::next_permutation(Updates.begin(), Updates.end(), CompUpdates)) { + CFGHolder Holder; + CFGBuilder B(Holder.F, Arcs, Updates); + DominatorTree DT(*Holder.F); + EXPECT_TRUE(DT.verify()); + PostDomTree PDT(*Holder.F); + EXPECT_TRUE(PDT.verify()); + + Optional<CFGBuilder::Update> LastUpdate; + while ((LastUpdate = B.applyUpdate())) { + EXPECT_EQ(LastUpdate->Action, Insert); + BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From); + BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To); + DT.insertEdge(From, To); + EXPECT_TRUE(DT.verify()); + PDT.insertEdge(From, To); + EXPECT_TRUE(PDT.verify()); + } + } +} + +TEST(DominatorTree, DeleteReachable) { + CFGHolder Holder; + std::vector<CFGBuilder::Arc> Arcs = { + {"1", "2"}, {"2", "3"}, {"2", "4"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, + {"5", "7"}, {"7", "8"}, {"3", "8"}, {"8", "9"}, {"9", "10"}, {"10", "2"}}; + + std::vector<CFGBuilder::Update> Updates = { + {Delete, {"2", "4"}}, {Delete, {"7", "8"}}, {Delete, {"10", "2"}}}; + CFGBuilder B(Holder.F, Arcs, Updates); + DominatorTree DT(*Holder.F); + EXPECT_TRUE(DT.verify()); + PostDomTree PDT(*Holder.F); + EXPECT_TRUE(PDT.verify()); + + Optional<CFGBuilder::Update> LastUpdate; + while ((LastUpdate = B.applyUpdate())) { + EXPECT_EQ(LastUpdate->Action, Delete); + BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From); + BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To); + DT.deleteEdge(From, To); + EXPECT_TRUE(DT.verify()); + PDT.deleteEdge(From, To); + EXPECT_TRUE(PDT.verify()); + } +} + +TEST(DominatorTree, DeleteUnreachable) { + CFGHolder Holder; + std::vector<CFGBuilder::Arc> Arcs = { + {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"}, + {"7", "8"}, {"3", "8"}, {"8", "9"}, {"9", "10"}, {"10", "2"}}; + + std::vector<CFGBuilder::Update> Updates = { + {Delete, {"8", "9"}}, {Delete, {"7", "8"}}, {Delete, {"3", "4"}}}; + CFGBuilder B(Holder.F, Arcs, Updates); + DominatorTree DT(*Holder.F); + EXPECT_TRUE(DT.verify()); + PostDomTree PDT(*Holder.F); + EXPECT_TRUE(PDT.verify()); + + Optional<CFGBuilder::Update> LastUpdate; + while ((LastUpdate = B.applyUpdate())) { + EXPECT_EQ(LastUpdate->Action, Delete); + BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From); + BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To); + DT.deleteEdge(From, To); + EXPECT_TRUE(DT.verify()); + PDT.deleteEdge(From, To); + EXPECT_TRUE(PDT.verify()); + } +} + +TEST(DominatorTree, InsertDelete) { + std::vector<CFGBuilder::Arc> Arcs = { + {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"}, + {"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}}; + + std::vector<CFGBuilder::Update> Updates = { + {Insert, {"2", "4"}}, {Insert, {"12", "10"}}, {Insert, {"10", "9"}}, + {Insert, {"7", "6"}}, {Insert, {"7", "5"}}, {Delete, {"3", "8"}}, + {Insert, {"10", "7"}}, {Insert, {"2", "8"}}, {Delete, {"3", "4"}}, + {Delete, {"8", "9"}}, {Delete, {"11", "12"}}}; + + CFGHolder Holder; + CFGBuilder B(Holder.F, Arcs, Updates); + DominatorTree DT(*Holder.F); + EXPECT_TRUE(DT.verify()); + PostDomTree PDT(*Holder.F); + EXPECT_TRUE(PDT.verify()); + + Optional<CFGBuilder::Update> LastUpdate; + while ((LastUpdate = B.applyUpdate())) { + BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From); + BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To); + if (LastUpdate->Action == Insert) { + DT.insertEdge(From, To); + PDT.insertEdge(From, To); + } else { + DT.deleteEdge(From, To); + PDT.deleteEdge(From, To); + } + + EXPECT_TRUE(DT.verify()); + EXPECT_TRUE(PDT.verify()); + } +} + +TEST(DominatorTree, InsertDeleteExhaustive) { + std::vector<CFGBuilder::Arc> Arcs = { + {"1", "2"}, {"2", "3"}, {"3", "4"}, {"4", "5"}, {"5", "6"}, {"5", "7"}, + {"3", "8"}, {"8", "9"}, {"9", "10"}, {"8", "11"}, {"11", "12"}}; + + std::vector<CFGBuilder::Update> Updates = { + {Insert, {"2", "4"}}, {Insert, {"12", "10"}}, {Insert, {"10", "9"}}, + {Insert, {"7", "6"}}, {Insert, {"7", "5"}}, {Delete, {"3", "8"}}, + {Insert, {"10", "7"}}, {Insert, {"2", "8"}}, {Delete, {"3", "4"}}, + {Delete, {"8", "9"}}, {Delete, {"11", "12"}}}; + + std::mt19937 Generator(0); + for (unsigned i = 0; i < 16; ++i) { + std::shuffle(Updates.begin(), Updates.end(), Generator); + CFGHolder Holder; + CFGBuilder B(Holder.F, Arcs, Updates); + DominatorTree DT(*Holder.F); + EXPECT_TRUE(DT.verify()); + PostDomTree PDT(*Holder.F); + EXPECT_TRUE(PDT.verify()); + + Optional<CFGBuilder::Update> LastUpdate; + while ((LastUpdate = B.applyUpdate())) { + BasicBlock *From = B.getOrAddBlock(LastUpdate->Edge.From); + BasicBlock *To = B.getOrAddBlock(LastUpdate->Edge.To); + if (LastUpdate->Action == Insert) { + DT.insertEdge(From, To); + PDT.insertEdge(From, To); + } else { + DT.deleteEdge(From, To); + PDT.deleteEdge(From, To); + } + + EXPECT_TRUE(DT.verify()); + EXPECT_TRUE(PDT.verify()); + } + } +} |