forked from OSchip/llvm-project
[Dominators] Fix some edge cases for PostDomTree updating
These fix some odd cfg cases where batch-updating the post dom tree fails. Usually around infinite loops and roots ending up being different. Differential Revision: https://reviews.llvm.org/D42247 llvm-svn: 323034
This commit is contained in:
parent
81ac12d1b4
commit
990eb1fc94
|
@ -706,7 +706,7 @@ struct SemiNCAInfo {
|
|||
// algorithm does not really know or use the set of roots and can make a
|
||||
// different (implicit) decision about which nodes within an infinite loop
|
||||
// becomes a root.
|
||||
if (DT.isVirtualRoot(TN->getIDom())) {
|
||||
if (TN && !DT.isVirtualRoot(TN->getIDom())) {
|
||||
DEBUG(dbgs() << "Root " << BlockNamePrinter(R)
|
||||
<< " is not virtual root's child\n"
|
||||
<< "The entire tree needs to be rebuilt\n");
|
||||
|
@ -940,21 +940,21 @@ struct SemiNCAInfo {
|
|||
const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To);
|
||||
const TreeNodePtr NCD = DT.getNode(NCDBlock);
|
||||
|
||||
// To dominates From -- nothing to do.
|
||||
if (ToTN == NCD) return;
|
||||
// If To dominates From -- nothing to do.
|
||||
if (ToTN != NCD) {
|
||||
DT.DFSInfoValid = false;
|
||||
|
||||
DT.DFSInfoValid = false;
|
||||
const TreeNodePtr ToIDom = ToTN->getIDom();
|
||||
DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom "
|
||||
<< BlockNamePrinter(ToIDom) << "\n");
|
||||
|
||||
const TreeNodePtr ToIDom = ToTN->getIDom();
|
||||
DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom "
|
||||
<< BlockNamePrinter(ToIDom) << "\n");
|
||||
|
||||
// To remains reachable after deletion.
|
||||
// (Based on the caption under Figure 4. from the second paper.)
|
||||
if (FromTN != ToIDom || HasProperSupport(DT, BUI, ToTN))
|
||||
DeleteReachable(DT, BUI, FromTN, ToTN);
|
||||
else
|
||||
DeleteUnreachable(DT, BUI, ToTN);
|
||||
// To remains reachable after deletion.
|
||||
// (Based on the caption under Figure 4. from the second paper.)
|
||||
if (FromTN != ToIDom || HasProperSupport(DT, BUI, ToTN))
|
||||
DeleteReachable(DT, BUI, FromTN, ToTN);
|
||||
else
|
||||
DeleteUnreachable(DT, BUI, ToTN);
|
||||
}
|
||||
|
||||
if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI);
|
||||
}
|
||||
|
|
|
@ -258,3 +258,98 @@ TEST(DominatorTreeBatchUpdates, InsertDeleteExhaustive) {
|
|||
EXPECT_TRUE(PDT.verify());
|
||||
}
|
||||
}
|
||||
|
||||
// These are some odd flowgraphs, usually generated from csmith cases,
|
||||
// which are difficult on post dom trees.
|
||||
TEST(DominatorTreeBatchUpdates, InfiniteLoop) {
|
||||
std::vector<CFGBuilder::Arc> Arcs = {
|
||||
{"1", "2"},
|
||||
{"2", "3"},
|
||||
{"3", "6"}, {"3", "5"},
|
||||
{"4", "5"},
|
||||
{"5", "2"},
|
||||
{"6", "3"}, {"6", "4"}};
|
||||
|
||||
// SplitBlock on 3 -> 5
|
||||
std::vector<CFGBuilder::Update> Updates = {
|
||||
{CFGInsert, {"N", "5"}}, {CFGInsert, {"3", "N"}}, {CFGDelete, {"3", "5"}}};
|
||||
|
||||
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, DeadBlocks) {
|
||||
std::vector<CFGBuilder::Arc> Arcs = {
|
||||
{"1", "2"},
|
||||
{"2", "3"},
|
||||
{"3", "4"}, {"3", "7"},
|
||||
{"4", "4"},
|
||||
{"5", "6"}, {"5", "7"},
|
||||
{"6", "7"},
|
||||
{"7", "2"}, {"7", "8"}};
|
||||
|
||||
// Remove dead 5 and 7,
|
||||
// plus SplitBlock on 7 -> 8
|
||||
std::vector<CFGBuilder::Update> Updates = {
|
||||
{CFGDelete, {"6", "7"}}, {CFGDelete, {"5", "7"}}, {CFGDelete, {"5", "6"}},
|
||||
{CFGInsert, {"N", "8"}}, {CFGInsert, {"7", "N"}}, {CFGDelete, {"7", "8"}}};
|
||||
|
||||
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, InfiniteLoop2) {
|
||||
std::vector<CFGBuilder::Arc> Arcs = {
|
||||
{"1", "2"},
|
||||
{"2", "6"}, {"2", "3"},
|
||||
{"3", "4"},
|
||||
{"4", "5"}, {"4", "6"},
|
||||
{"5", "4"},
|
||||
{"6", "2"}};
|
||||
|
||||
// SplitBlock on 4 -> 6
|
||||
std::vector<CFGBuilder::Update> Updates = {
|
||||
{CFGInsert, {"N", "6"}}, {CFGInsert, {"4", "N"}}, {CFGDelete, {"4", "6"}}};
|
||||
|
||||
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());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue