summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/IR/DominatorTreeBatchUpdatesTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/unittests/IR/DominatorTreeBatchUpdatesTest.cpp')
-rw-r--r--llvm/unittests/IR/DominatorTreeBatchUpdatesTest.cpp260
1 files changed, 260 insertions, 0 deletions
diff --git a/llvm/unittests/IR/DominatorTreeBatchUpdatesTest.cpp b/llvm/unittests/IR/DominatorTreeBatchUpdatesTest.cpp
new file mode 100644
index 00000000000..4ad1f69030c
--- /dev/null
+++ b/llvm/unittests/IR/DominatorTreeBatchUpdatesTest.cpp
@@ -0,0 +1,260 @@
+//===- llvm/unittests/IR/DominatorTreeBatchUpdatesTest.cpp ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <random>
+#include "CFGBuilder.h"
+#include "gtest/gtest.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/Support/GenericDomTreeConstruction.h"
+
+#define DEBUG_TYPE "batch-update-tests"
+
+using namespace llvm;
+
+namespace {
+const auto CFGInsert = CFGBuilder::ActionKind::Insert;
+const auto CFGDelete = CFGBuilder::ActionKind::Delete;
+
+struct PostDomTree : PostDomTreeBase<BasicBlock> {
+ PostDomTree(Function &F) { recalculate(F); }
+};
+
+using DomUpdate = DominatorTree::UpdateType;
+static_assert(
+ std::is_same<DomUpdate, PostDomTree::UpdateType>::value,
+ "Trees differing only in IsPostDom should have the same update types");
+using DomSNCA = DomTreeBuilder::SemiNCAInfo<DomTreeBuilder::BBDomTree>;
+using PostDomSNCA = DomTreeBuilder::SemiNCAInfo<DomTreeBuilder::BBPostDomTree>;
+const auto Insert = DominatorTree::Insert;
+const auto Delete = DominatorTree::Delete;
+
+std::vector<DomUpdate> ToDomUpdates(CFGBuilder &B,
+ std::vector<CFGBuilder::Update> &In) {
+ std::vector<DomUpdate> Res;
+ Res.reserve(In.size());
+
+ for (const auto &CFGU : In)
+ Res.push_back({CFGU.Action == CFGInsert ? Insert : Delete,
+ B.getOrAddBlock(CFGU.Edge.From),
+ B.getOrAddBlock(CFGU.Edge.To)});
+ return Res;
+}
+} // namespace
+
+TEST(DominatorTreeBatchUpdates, LegalizeDomUpdates) {
+ CFGHolder Holder;
+ CFGBuilder Builder(Holder.F, {{"A", "B"}}, {});
+
+ BasicBlock *A = Builder.getOrAddBlock("A");
+ BasicBlock *B = Builder.getOrAddBlock("B");
+ BasicBlock *C = Builder.getOrAddBlock("C");
+ BasicBlock *D = Builder.getOrAddBlock("D");
+
+ std::vector<DomUpdate> Updates = {
+ {Insert, B, C}, {Insert, C, D}, {Delete, B, C}, {Insert, B, C},
+ {Insert, B, D}, {Delete, C, D}, {Delete, A, B}};
+ SmallVector<DomUpdate, 4> Legalized;
+ DomSNCA::LegalizeUpdates(Updates, Legalized);
+ DEBUG(dbgs() << "Legalized updates:\t");
+ DEBUG(for (auto &U : Legalized) dbgs() << U << ", ");
+ DEBUG(dbgs() << "\n");
+ EXPECT_EQ(Legalized.size(), 3UL);
+ EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, B, C}), Legalized.end());
+ EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, B, D}), Legalized.end());
+ EXPECT_NE(llvm::find(Legalized, DomUpdate{Delete, A, B}), Legalized.end());
+}
+
+TEST(DominatorTreeBatchUpdates, LegalizePostDomUpdates) {
+ CFGHolder Holder;
+ CFGBuilder Builder(Holder.F, {{"A", "B"}}, {});
+
+ BasicBlock *A = Builder.getOrAddBlock("A");
+ BasicBlock *B = Builder.getOrAddBlock("B");
+ BasicBlock *C = Builder.getOrAddBlock("C");
+ BasicBlock *D = Builder.getOrAddBlock("D");
+
+ std::vector<DomUpdate> Updates = {
+ {Insert, B, C}, {Insert, C, D}, {Delete, B, C}, {Insert, B, C},
+ {Insert, B, D}, {Delete, C, D}, {Delete, A, B}};
+ SmallVector<DomUpdate, 4> Legalized;
+ PostDomSNCA::LegalizeUpdates(Updates, Legalized);
+ DEBUG(dbgs() << "Legalized postdom updates:\t");
+ DEBUG(for (auto &U : Legalized) dbgs() << U << ", ");
+ DEBUG(dbgs() << "\n");
+ EXPECT_EQ(Legalized.size(), 3UL);
+ EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, C, B}), Legalized.end());
+ EXPECT_NE(llvm::find(Legalized, DomUpdate{Insert, D, B}), Legalized.end());
+ EXPECT_NE(llvm::find(Legalized, DomUpdate{Delete, B, A}), Legalized.end());
+}
+
+TEST(DominatorTreeBatchUpdates, SingleInsertion) {
+ CFGHolder Holder;
+ CFGBuilder Builder(Holder.F, {{"A", "B"}}, {{CFGInsert, {"B", "C"}}});
+
+ DominatorTree DT(*Holder.F);
+ EXPECT_TRUE(DT.verify());
+ PostDomTree PDT(*Holder.F);
+ EXPECT_TRUE(DT.verify());
+
+ BasicBlock *B = Builder.getOrAddBlock("B");
+ BasicBlock *C = Builder.getOrAddBlock("C");
+ std::vector<DomUpdate> Updates = {{Insert, B, C}};
+
+ ASSERT_TRUE(Builder.applyUpdate());
+
+ DT.applyUpdates(Updates);
+ EXPECT_TRUE(DT.verify());
+ PDT.applyUpdates(Updates);
+ EXPECT_TRUE(PDT.verify());
+}
+
+TEST(DominatorTreeBatchUpdates, SingleDeletion) {
+ CFGHolder Holder;
+ CFGBuilder Builder(Holder.F, {{"A", "B"}, {"B", "C"}},
+ {{CFGDelete, {"B", "C"}}});
+
+ DominatorTree DT(*Holder.F);
+ EXPECT_TRUE(DT.verify());
+ PostDomTree PDT(*Holder.F);
+ EXPECT_TRUE(DT.verify());
+
+ BasicBlock *B = Builder.getOrAddBlock("B");
+ BasicBlock *C = Builder.getOrAddBlock("C");
+ std::vector<DomUpdate> Updates = {{Delete, B, C}};
+
+ ASSERT_TRUE(Builder.applyUpdate());
+
+ DT.applyUpdates(Updates);
+ EXPECT_TRUE(DT.verify());
+ PDT.applyUpdates(Updates);
+ EXPECT_TRUE(PDT.verify());
+}
+
+TEST(DominatorTreeBatchUpdates, FewInsertion) {
+ std::vector<CFGBuilder::Update> CFGUpdates = {{CFGInsert, {"B", "C"}},
+ {CFGInsert, {"C", "B"}},
+ {CFGInsert, {"C", "D"}},
+ {CFGInsert, {"D", "E"}}};
+
+ CFGHolder Holder;
+ CFGBuilder Builder(Holder.F, {{"A", "B"}}, CFGUpdates);
+
+ DominatorTree DT(*Holder.F);
+ EXPECT_TRUE(DT.verify());
+ PostDomTree PDT(*Holder.F);
+ EXPECT_TRUE(PDT.verify());
+
+ BasicBlock *B = Builder.getOrAddBlock("B");
+ BasicBlock *C = Builder.getOrAddBlock("C");
+ BasicBlock *D = Builder.getOrAddBlock("D");
+ BasicBlock *E = Builder.getOrAddBlock("E");
+
+ std::vector<DomUpdate> Updates = {
+ {Insert, B, C}, {Insert, C, B}, {Insert, C, D}, {Insert, D, E}};
+
+ while (Builder.applyUpdate())
+ ;
+
+ DT.applyUpdates(Updates);
+ EXPECT_TRUE(DT.verify());
+ PDT.applyUpdates(Updates);
+ EXPECT_TRUE(PDT.verify());
+}
+
+TEST(DominatorTreeBatchUpdates, FewDeletions) {
+ std::vector<CFGBuilder::Update> CFGUpdates = {{CFGDelete, {"B", "C"}},
+ {CFGDelete, {"C", "B"}},
+ {CFGDelete, {"B", "D"}},
+ {CFGDelete, {"D", "E"}}};
+
+ CFGHolder Holder;
+ CFGBuilder Builder(
+ Holder.F, {{"A", "B"}, {"B", "C"}, {"B", "D"}, {"D", "E"}, {"C", "B"}},
+ CFGUpdates);
+
+ DominatorTree DT(*Holder.F);
+ EXPECT_TRUE(DT.verify());
+ PostDomTree PDT(*Holder.F);
+ EXPECT_TRUE(PDT.verify());
+
+ auto Updates = ToDomUpdates(Builder, CFGUpdates);
+
+ while (Builder.applyUpdate())
+ ;
+
+ DT.applyUpdates(Updates);
+ EXPECT_TRUE(DT.verify());
+ PDT.applyUpdates(Updates);
+ EXPECT_TRUE(PDT.verify());
+}
+
+TEST(DominatorTreeBatchUpdates, 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 = {
+ {CFGInsert, {"2", "4"}}, {CFGInsert, {"12", "10"}},
+ {CFGInsert, {"10", "9"}}, {CFGInsert, {"7", "6"}},
+ {CFGInsert, {"7", "5"}}, {CFGDelete, {"3", "8"}},
+ {CFGInsert, {"10", "7"}}, {CFGInsert, {"2", "8"}},
+ {CFGDelete, {"3", "4"}}, {CFGDelete, {"8", "9"}},
+ {CFGDelete, {"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());
+
+ while (B.applyUpdate())
+ ;
+
+ auto DomUpdates = ToDomUpdates(B, Updates);
+ DT.applyUpdates(DomUpdates);
+ EXPECT_TRUE(DT.verify());
+ PDT.applyUpdates(DomUpdates);
+ EXPECT_TRUE(PDT.verify());
+}
+
+TEST(DominatorTreeBatchUpdates, 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 = {
+ {CFGInsert, {"2", "4"}}, {CFGInsert, {"12", "10"}},
+ {CFGInsert, {"10", "9"}}, {CFGInsert, {"7", "6"}},
+ {CFGInsert, {"7", "5"}}, {CFGDelete, {"3", "8"}},
+ {CFGInsert, {"10", "7"}}, {CFGInsert, {"2", "8"}},
+ {CFGDelete, {"3", "4"}}, {CFGDelete, {"8", "9"}},
+ {CFGDelete, {"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());
+
+ while (B.applyUpdate())
+ ;
+
+ auto DomUpdates = ToDomUpdates(B, Updates);
+ DT.applyUpdates(DomUpdates);
+ EXPECT_TRUE(DT.verify());
+ PDT.applyUpdates(DomUpdates);
+ EXPECT_TRUE(PDT.verify());
+ }
+}
OpenPOWER on IntegriCloud