1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00
llvm-mirror/unittests/IR/DominatorTreeBatchUpdatesTest.cpp
Jakub Kuderski 02ea66d696 [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
2017-08-16 16:12:52 +00:00

261 lines
8.5 KiB
C++

//===- 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());
}
}