llvm.org GIT mirror llvm / 2081dbc
[MemorySSA] Cleanup trivial phis. Summary: This is unfortunately needed for correctness, if we are to extend the tolerance of the update API to the way simple loop unswitch is doing cloning. In simple loop unswitch (as opposed to loop unswitch), not all blocks are cloned. This can create unreachable cloned blocks (no predecessor), which are later cleaned up. In MemorySSA, the APIs for supporting these kind of updates (clone + update exit blocks), make certain assumption on the integrity of the CFG. When cloning, if something was not cloned, it's values in MemorySSA default to LiveOnEntry. When updating exit blocks, it is safe to assume that we can first insert phis in the blocks merging two clones, then add additional phis in the IDF of the blocks that received phis. This no longer holds true if one of the clones being merged comes from an unreachable block. We'd conservatively need to add all phis before filling in their incoming definitions. In practice this restriction can be relaxed if we clean up trivial phis after the first round of insertion. Reviewers: george.burgess.iv Subscribers: jlebar, Prazek, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63354 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363880 91177308-0d34-0410-b5e6-96231b3b80d8 Alina Sbirlea 2 months ago
2 changed file(s) with 121 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
865865 for (auto *BB : NewBlocks)
866866 PredMap.erase(BB);
867867
868 SmallVector BlocksToProcess;
869868 SmallVector BlocksWithDefsToReplace;
870869 SmallVector InsertedPhis;
871870
941940 for (auto *Pred : PrevBlockSet)
942941 for (int I = 0, E = EdgeCountMap[{Pred, BB}]; I < E; ++I)
943942 NewPhi->addIncoming(DefP1, Pred);
944
945 // Insert BB in the set of blocks that now have definition. We'll use this
946 // to compute IDF and add Phis there next.
947 BlocksToProcess.push_back(BB);
948943 }
949944
950945 // Get all blocks that used to dominate BB and no longer do after adding
958953 "New idom should dominate old idom");
959954 GetNoLongerDomBlocks(PrevIDom, NewIDom, BlocksWithDefsToReplace);
960955 }
956
957 tryRemoveTrivialPhis(InsertedPhis);
958 // Create the set of blocks that now have a definition. We'll use this to
959 // compute IDF and add Phis there next.
960 SmallVector BlocksToProcess;
961 for (auto &VH : InsertedPhis)
962 if (auto *MPhi = cast_or_null(VH))
963 BlocksToProcess.push_back(MPhi->getBlock());
961964
962965 // Compute IDF and add Phis in all IDF blocks that do not have one.
963966 SmallVector IDFBlocks;
0 ; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -verify-memoryssa -S %s | FileCheck %s
1 ; REQUIRES: asserts
2
3 target triple = "x86_64-unknown-linux-gnu"
4
5 declare void @foo()
6
7 ; In Test1, there are no definitions. MemorySSA updates insert trivial phis and remove them.
8 ; Verify all are removed, considering the SLU pass leaves unreachable blocks hanging when the MSSA updates are done.
9 ; CHECK-LABEL: @Test1
10 define void @Test1(i32) {
11 header:
12 br label %outer
13
14 outer.loopexit.split: ; preds = %continue
15 br label %outer.loopexit
16
17 outer.loopexit: ; preds = %outer.loopexit.split.us, %outer.loopexit.split
18 br label %outer
19
20 outer: ; preds = %outer.loopexit, %header
21 br i1 false, label %outer.split.us, label %outer.split
22
23 outer.split.us: ; preds = %outer
24 br label %inner.us
25
26 inner.us: ; preds = %continue.us, %outer.split.us
27 br label %overflow.us
28
29 overflow.us: ; preds = %inner.us
30 br label %continue.us
31
32 continue.us: ; preds = %overflow.us
33 br i1 true, label %outer.loopexit.split.us, label %inner.us
34
35 outer.loopexit.split.us: ; preds = %continue.us
36 br label %outer.loopexit
37
38 outer.split: ; preds = %outer
39 br label %inner
40
41 inner: ; preds = %continue, %outer.split
42 br label %switchme
43
44 switchme: ; preds = %inner
45 switch i32 %0, label %continue [
46 i32 88, label %go_out
47 i32 99, label %case2
48 ]
49
50 case2: ; preds = %switchme
51 br label %continue
52
53 continue: ; preds = %case2, %switchme
54 br i1 true, label %outer.loopexit.split, label %inner
55
56 go_out: ; preds = %switchme
57 unreachable
58 }
59
60 ; In Test2 there is a single def (call to foo). There are already Phis in place that are cloned when unswitching.
61 ; Ensure MemorySSA remains correct. Due to SLU's pruned cloning, continue.us2 becomes unreachable, with an empty Phi that is later cleaned.
62 ; CHECK-LABEL: @Test2
63 define void @Test2(i32) {
64 header:
65 br label %outer
66
67 outer.loopexit.split: ; preds = %continue
68 br label %outer.loopexit
69
70 outer.loopexit: ; preds = %outer.loopexit.split.us, %outer.loopexit.split
71 br label %outer
72
73 outer: ; preds = %outer.loopexit, %header
74 br i1 false, label %outer.split.us, label %outer.split
75
76 outer.split.us: ; preds = %outer
77 br label %inner.us
78
79 inner.us: ; preds = %continue.us, %outer.split.us
80 br label %overflow.us
81
82 overflow.us: ; preds = %inner.us
83 br label %continue.us
84
85 continue.us: ; preds = %overflow.us
86 br i1 true, label %outer.loopexit.split.us, label %inner.us
87
88 outer.loopexit.split.us: ; preds = %continue.us
89 br label %outer.loopexit
90
91 outer.split: ; preds = %outer
92 br label %inner
93
94 inner: ; preds = %continue, %outer.split
95 br label %switchme
96
97 switchme: ; preds = %inner
98 switch i32 %0, label %continue [
99 i32 88, label %go_out
100 i32 99, label %case2
101 ]
102
103 case2: ; preds = %switchme
104 call void @foo()
105 br label %continue
106
107 continue: ; preds = %case2, %switchme
108 br i1 true, label %outer.loopexit.split, label %inner
109
110 go_out: ; preds = %switchme
111 unreachable
112 }