Skip to content

Commit d2e371f

Browse files
committed
[Dominators] Visit affected node candidates found at different root levels
Summary: This patch attempts to fix the DomTree incremental insertion bug found here [[ https://bugs.llvm.org/show_bug.cgi?id=35969 | PR35969 ]] . When performing an insertion into a piece of unreachable CFG, we may find the same not at different levels. When this happens, the node can turn out to be affected when we find it starting from a node with a lower level in the tree. The level at which we start visitation affects if we consider a node affected or not. This patch tracks the lowest level at which each node was visited during insertion and allows it to be visited multiple times, if it can cause it to be considered affected. Reviewers: brzycki, davide, dberlin, grosser Reviewed By: brzycki Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D42231 llvm-svn: 322993
1 parent a499c3c commit d2e371f

File tree

4 files changed

+172
-9
lines changed

4 files changed

+172
-9
lines changed

llvm/include/llvm/Support/GenericDomTreeConstruction.h

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ struct SemiNCAInfo {
628628
DecreasingLevel>
629629
Bucket; // Queue of tree nodes sorted by level in descending order.
630630
SmallDenseSet<TreeNodePtr, 8> Affected;
631-
SmallDenseSet<TreeNodePtr, 8> Visited;
631+
SmallDenseMap<TreeNodePtr, unsigned, 8> Visited;
632632
SmallVector<TreeNodePtr, 8> AffectedQueue;
633633
SmallVector<TreeNodePtr, 8> VisitedNotAffectedQueue;
634634
};
@@ -753,14 +753,16 @@ struct SemiNCAInfo {
753753

754754
while (!II.Bucket.empty()) {
755755
const TreeNodePtr CurrentNode = II.Bucket.top().second;
756+
const unsigned CurrentLevel = CurrentNode->getLevel();
756757
II.Bucket.pop();
757758
DEBUG(dbgs() << "\tAdding to Visited and AffectedQueue: "
758759
<< BlockNamePrinter(CurrentNode) << "\n");
759-
II.Visited.insert(CurrentNode);
760+
761+
II.Visited.insert({CurrentNode, CurrentLevel});
760762
II.AffectedQueue.push_back(CurrentNode);
761763

762764
// Discover and collect affected successors of the current node.
763-
VisitInsertion(DT, BUI, CurrentNode, CurrentNode->getLevel(), NCD, II);
765+
VisitInsertion(DT, BUI, CurrentNode, CurrentLevel, NCD, II);
764766
}
765767

766768
// Finish by updating immediate dominators and levels.
@@ -772,33 +774,49 @@ struct SemiNCAInfo {
772774
const TreeNodePtr TN, const unsigned RootLevel,
773775
const TreeNodePtr NCD, InsertionInfo &II) {
774776
const unsigned NCDLevel = NCD->getLevel();
775-
DEBUG(dbgs() << "Visiting " << BlockNamePrinter(TN) << "\n");
777+
DEBUG(dbgs() << "Visiting " << BlockNamePrinter(TN) << ", RootLevel "
778+
<< RootLevel << "\n");
776779

777780
SmallVector<TreeNodePtr, 8> Stack = {TN};
778781
assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!");
779782

783+
SmallPtrSet<TreeNodePtr, 8> Processed;
784+
780785
do {
781786
TreeNodePtr Next = Stack.pop_back_val();
787+
DEBUG(dbgs() << " Next: " << BlockNamePrinter(Next) << "\n");
782788

783789
for (const NodePtr Succ :
784790
ChildrenGetter<IsPostDom>::Get(Next->getBlock(), BUI)) {
785791
const TreeNodePtr SuccTN = DT.getNode(Succ);
786792
assert(SuccTN && "Unreachable successor found at reachable insertion");
787793
const unsigned SuccLevel = SuccTN->getLevel();
788794

789-
DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ)
790-
<< ", level = " << SuccLevel << "\n");
795+
DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ) << ", level = "
796+
<< SuccLevel << "\n");
797+
798+
// Do not process the same node multiple times.
799+
if (Processed.count(Next) > 0)
800+
continue;
791801

792802
// Succ dominated by subtree From -- not affected.
793803
// (Based on the lemma 2.5 from the second paper.)
794804
if (SuccLevel > RootLevel) {
795805
DEBUG(dbgs() << "\t\tDominated by subtree From\n");
796-
if (II.Visited.count(SuccTN) != 0)
797-
continue;
806+
if (II.Visited.count(SuccTN) != 0) {
807+
DEBUG(dbgs() << "\t\t\talready visited at level "
808+
<< II.Visited[SuccTN] << "\n\t\t\tcurrent level "
809+
<< RootLevel << ")\n");
810+
811+
// A node can be necessary to visit again if we see it again at
812+
// a lower level than before.
813+
if (II.Visited[SuccTN] >= RootLevel)
814+
continue;
815+
}
798816

799817
DEBUG(dbgs() << "\t\tMarking visited not affected "
800818
<< BlockNamePrinter(Succ) << "\n");
801-
II.Visited.insert(SuccTN);
819+
II.Visited.insert({SuccTN, RootLevel});
802820
II.VisitedNotAffectedQueue.push_back(SuccTN);
803821
Stack.push_back(SuccTN);
804822
} else if ((SuccLevel > NCDLevel + 1) &&
@@ -809,6 +827,8 @@ struct SemiNCAInfo {
809827
II.Bucket.push({SuccLevel, SuccTN});
810828
}
811829
}
830+
831+
Processed.insert(Next);
812832
} while (!Stack.empty());
813833
}
814834

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
; RUN: opt < %s -jump-threading -disable-output -verify-dom-info
2+
3+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4+
target triple = "x86_64-unknown-linux-gnu"
5+
6+
@global = external local_unnamed_addr global i64, align 8
7+
@global.1 = external local_unnamed_addr global i64, align 8
8+
@global.2 = external local_unnamed_addr global i64, align 8
9+
10+
; Function Attrs: norecurse noreturn nounwind uwtable
11+
define void @hoge() local_unnamed_addr #0 {
12+
bb:
13+
br label %bb1
14+
15+
bb1: ; preds = %bb26, %bb
16+
%tmp = load i64, i64* @global, align 8, !tbaa !1
17+
%tmp2 = icmp eq i64 %tmp, 0
18+
br i1 %tmp2, label %bb27, label %bb3
19+
20+
bb3: ; preds = %bb1
21+
%tmp4 = load i64, i64* @global.1, align 8, !tbaa !1
22+
%tmp5 = icmp eq i64 %tmp4, 0
23+
br i1 %tmp5, label %bb23, label %bb23
24+
25+
bb23: ; preds = %bb3, %bb3
26+
br label %bb26
27+
28+
bb26: ; preds = %bb27, %bb23
29+
br label %bb1
30+
31+
bb27: ; preds = %bb1
32+
br label %bb26
33+
}
34+
35+
attributes #0 = { norecurse noreturn nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
36+
37+
!llvm.ident = !{!0}
38+
39+
!0 = !{!"clang version 7.0.0 "}
40+
!1 = !{!2, !2, i64 0}
41+
!2 = !{!"long", !3, i64 0}
42+
!3 = !{!"omnipotent char", !4, i64 0}
43+
!4 = !{!"Simple C/C++ TBAA"}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
; RUN: opt < %s -jump-threading -disable-output -verify-dom-info
2+
@global = external global i64, align 8
3+
4+
define void @f() {
5+
bb:
6+
br label %bb1
7+
8+
bb1:
9+
%tmp = load i64, i64* @global, align 8
10+
%tmp2 = icmp eq i64 %tmp, 0
11+
br i1 %tmp2, label %bb27, label %bb3
12+
13+
bb3:
14+
%tmp4 = load i64, i64* @global, align 8
15+
%tmp5 = icmp eq i64 %tmp4, 0
16+
br i1 %tmp5, label %bb6, label %bb7
17+
18+
bb6:
19+
br label %bb7
20+
21+
bb7:
22+
%tmp8 = phi i1 [ true, %bb3 ], [ undef, %bb6 ]
23+
%tmp9 = select i1 %tmp8, i64 %tmp4, i64 0
24+
br i1 false, label %bb10, label %bb23
25+
26+
bb10:
27+
%tmp11 = load i64, i64* @global, align 8
28+
%tmp12 = icmp slt i64 %tmp11, 5
29+
br i1 %tmp12, label %bb13, label %bb17
30+
31+
bb13:
32+
br label %bb14
33+
34+
bb14:
35+
br i1 undef, label %bb15, label %bb16
36+
37+
bb15:
38+
unreachable
39+
40+
bb16:
41+
br label %bb10
42+
43+
bb17:
44+
br label %bb18
45+
46+
bb18:
47+
br i1 undef, label %bb22, label %bb13
48+
49+
bb19:
50+
br i1 undef, label %bb20, label %bb21
51+
52+
bb20:
53+
unreachable
54+
55+
bb21:
56+
br label %bb18
57+
58+
bb22:
59+
br label %bb23
60+
61+
bb23:
62+
br i1 undef, label %bb24, label %bb13
63+
64+
bb24:
65+
br i1 undef, label %bb26, label %bb25
66+
67+
bb25:
68+
br label %bb19
69+
70+
bb26:
71+
br label %bb1
72+
73+
bb27:
74+
br label %bb24
75+
}

llvm/unittests/IR/DominatorTreeTest.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,3 +925,28 @@ TEST(DominatorTree, InsertDeleteExhaustive) {
925925
}
926926
}
927927
}
928+
929+
TEST(DominatorTree, InsertIntoIrreducible) {
930+
std::vector<CFGBuilder::Arc> Arcs = {
931+
{"0", "1"},
932+
{"1", "27"}, {"1", "7"},
933+
{"10", "18"},
934+
{"13", "10"},
935+
{"18", "13"}, {"18", "23"},
936+
{"23", "13"}, {"23", "24"},
937+
{"24", "1"}, {"24", "18"},
938+
{"27", "24"}};
939+
940+
CFGHolder Holder;
941+
CFGBuilder B(Holder.F, Arcs, {{Insert, {"7", "23"}}});
942+
DominatorTree DT(*Holder.F);
943+
EXPECT_TRUE(DT.verify());
944+
945+
B.applyUpdate();
946+
BasicBlock *From = B.getOrAddBlock("7");
947+
BasicBlock *To = B.getOrAddBlock("23");
948+
DT.insertEdge(From, To);
949+
950+
EXPECT_TRUE(DT.verify());
951+
}
952+

0 commit comments

Comments
 (0)