summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/IR
diff options
context:
space:
mode:
authorJakub Kuderski <kubakuderski@gmail.com>2017-08-16 16:12:52 +0000
committerJakub Kuderski <kubakuderski@gmail.com>2017-08-16 16:12:52 +0000
commit624463a0031ead3f9b7f35109f130eec9900fc5c (patch)
treeeadbe31f7950bc755689428451699782234b9558 /llvm/unittests/IR
parent9e54b7093abda564ddd88bb0c8ee2c97be50082a (diff)
downloadbcm5719-llvm-624463a0031ead3f9b7f35109f130eec9900fc5c.tar.gz
bcm5719-llvm-624463a0031ead3f9b7f35109f130eec9900fc5c.zip
[Dominators] Introduce batch updates
Summary: This patch introduces a way of informing the (Post)DominatorTree about multiple CFG updates that happened since the last tree update. This makes performing tree updates much easier, as it internally takes care of applying the updates in lockstep with the (virtual) updates to the CFG, which is done by reverse-applying future CFG updates. The batch updater is able to remove redundant updates that cancel each other out. In the future, it should be also possible to reorder updates to reduce the amount of work needed to perform the updates. Reviewers: dberlin, sanjoy, grosser, davide, brzycki Reviewed By: brzycki Subscribers: mgorny, llvm-commits Differential Revision: https://reviews.llvm.org/D36167 llvm-svn: 311015
Diffstat (limited to 'llvm/unittests/IR')
-rw-r--r--llvm/unittests/IR/CMakeLists.txt1
-rw-r--r--llvm/unittests/IR/DominatorTreeBatchUpdatesTest.cpp260
2 files changed, 261 insertions, 0 deletions
diff --git a/llvm/unittests/IR/CMakeLists.txt b/llvm/unittests/IR/CMakeLists.txt
index 92c9f8d3788..83f9dfd3176 100644
--- a/llvm/unittests/IR/CMakeLists.txt
+++ b/llvm/unittests/IR/CMakeLists.txt
@@ -16,6 +16,7 @@ set(IRSources
DebugInfoTest.cpp
DebugTypeODRUniquingTest.cpp
DominatorTreeTest.cpp
+ DominatorTreeBatchUpdatesTest.cpp
FunctionTest.cpp
PassBuilderCallbacksTest.cpp
IRBuilderTest.cpp
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