15
15
#define LLVM_ANALYSIS_DOMTREEUPDATER_H
16
16
17
17
#include " llvm/ADT/SmallPtrSet.h"
18
- #include " llvm/Analysis/GenericDomTreeUpdater.h"
19
- #include " llvm/Analysis/PostDominators.h"
20
18
#include " llvm/IR/Dominators.h"
21
19
#include " llvm/IR/ValueHandle.h"
22
20
#include " llvm/Support/Compiler.h"
25
23
#include < vector>
26
24
27
25
namespace llvm {
26
+ class PostDominatorTree ;
28
27
29
- class DomTreeUpdater
30
- : public GenericDomTreeUpdater<DomTreeUpdater, DominatorTree,
31
- PostDominatorTree> {
32
- friend GenericDomTreeUpdater<DomTreeUpdater, DominatorTree,
33
- PostDominatorTree>;
34
-
28
+ class DomTreeUpdater {
35
29
public:
36
- using Base =
37
- GenericDomTreeUpdater<DomTreeUpdater, DominatorTree, PostDominatorTree>;
38
- using Base::Base;
30
+ enum class UpdateStrategy : unsigned char { Eager = 0 , Lazy = 1 };
31
+
32
+ explicit DomTreeUpdater (UpdateStrategy Strategy_) : Strategy(Strategy_) {}
33
+ DomTreeUpdater (DominatorTree &DT_, UpdateStrategy Strategy_)
34
+ : DT(&DT_), Strategy(Strategy_) {}
35
+ DomTreeUpdater (DominatorTree *DT_, UpdateStrategy Strategy_)
36
+ : DT(DT_), Strategy(Strategy_) {}
37
+ DomTreeUpdater (PostDominatorTree &PDT_, UpdateStrategy Strategy_)
38
+ : PDT(&PDT_), Strategy(Strategy_) {}
39
+ DomTreeUpdater (PostDominatorTree *PDT_, UpdateStrategy Strategy_)
40
+ : PDT(PDT_), Strategy(Strategy_) {}
41
+ DomTreeUpdater (DominatorTree &DT_, PostDominatorTree &PDT_,
42
+ UpdateStrategy Strategy_)
43
+ : DT(&DT_), PDT(&PDT_), Strategy(Strategy_) {}
44
+ DomTreeUpdater (DominatorTree *DT_, PostDominatorTree *PDT_,
45
+ UpdateStrategy Strategy_)
46
+ : DT(DT_), PDT(PDT_), Strategy(Strategy_) {}
47
+
48
+ ~DomTreeUpdater () { flush (); }
49
+
50
+ // / Returns true if the current strategy is Lazy.
51
+ bool isLazy () const { return Strategy == UpdateStrategy::Lazy; };
52
+
53
+ // / Returns true if the current strategy is Eager.
54
+ bool isEager () const { return Strategy == UpdateStrategy::Eager; };
55
+
56
+ // / Returns true if it holds a DominatorTree.
57
+ bool hasDomTree () const { return DT != nullptr ; }
58
+
59
+ // / Returns true if it holds a PostDominatorTree.
60
+ bool hasPostDomTree () const { return PDT != nullptr ; }
61
+
62
+ // / Returns true if there is BasicBlock awaiting deletion.
63
+ // / The deletion will only happen until a flush event and
64
+ // / all available trees are up-to-date.
65
+ // / Returns false under Eager UpdateStrategy.
66
+ bool hasPendingDeletedBB () const { return !DeletedBBs.empty (); }
67
+
68
+ // / Returns true if DelBB is awaiting deletion.
69
+ // / Returns false under Eager UpdateStrategy.
70
+ bool isBBPendingDeletion (BasicBlock *DelBB) const ;
71
+
72
+ // / Returns true if either of DT or PDT is valid and the tree has at
73
+ // / least one update pending. If DT or PDT is nullptr it is treated
74
+ // / as having no pending updates. This function does not check
75
+ // / whether there is BasicBlock awaiting deletion.
76
+ // / Returns false under Eager UpdateStrategy.
77
+ bool hasPendingUpdates () const ;
78
+
79
+ // / Returns true if there are DominatorTree updates queued.
80
+ // / Returns false under Eager UpdateStrategy or DT is nullptr.
81
+ bool hasPendingDomTreeUpdates () const ;
82
+
83
+ // / Returns true if there are PostDominatorTree updates queued.
84
+ // / Returns false under Eager UpdateStrategy or PDT is nullptr.
85
+ bool hasPendingPostDomTreeUpdates () const ;
39
86
40
87
// /@{
41
88
// / \name Mutation APIs
@@ -58,6 +105,51 @@ class DomTreeUpdater
58
105
// / Although GenericDomTree provides several update primitives,
59
106
// / it is not encouraged to use these APIs directly.
60
107
108
+ // / Submit updates to all available trees.
109
+ // / The Eager Strategy flushes updates immediately while the Lazy Strategy
110
+ // / queues the updates.
111
+ // /
112
+ // / Note: The "existence" of an edge in a CFG refers to the CFG which DTU is
113
+ // / in sync with + all updates before that single update.
114
+ // /
115
+ // / CAUTION!
116
+ // / 1. It is required for the state of the LLVM IR to be updated
117
+ // / *before* submitting the updates because the internal update routine will
118
+ // / analyze the current state of the CFG to determine whether an update
119
+ // / is valid.
120
+ // / 2. It is illegal to submit any update that has already been submitted,
121
+ // / i.e., you are supposed not to insert an existent edge or delete a
122
+ // / nonexistent edge.
123
+ void applyUpdates (ArrayRef<DominatorTree::UpdateType> Updates);
124
+
125
+ // / Submit updates to all available trees. It will also
126
+ // / 1. discard duplicated updates,
127
+ // / 2. remove invalid updates. (Invalid updates means deletion of an edge that
128
+ // / still exists or insertion of an edge that does not exist.)
129
+ // / The Eager Strategy flushes updates immediately while the Lazy Strategy
130
+ // / queues the updates.
131
+ // /
132
+ // / Note: The "existence" of an edge in a CFG refers to the CFG which DTU is
133
+ // / in sync with + all updates before that single update.
134
+ // /
135
+ // / CAUTION!
136
+ // / 1. It is required for the state of the LLVM IR to be updated
137
+ // / *before* submitting the updates because the internal update routine will
138
+ // / analyze the current state of the CFG to determine whether an update
139
+ // / is valid.
140
+ // / 2. It is illegal to submit any update that has already been submitted,
141
+ // / i.e., you are supposed not to insert an existent edge or delete a
142
+ // / nonexistent edge.
143
+ // / 3. It is only legal to submit updates to an edge in the order CFG changes
144
+ // / are made. The order you submit updates on different edges is not
145
+ // / restricted.
146
+ void applyUpdatesPermissive (ArrayRef<DominatorTree::UpdateType> Updates);
147
+
148
+ // / Notify DTU that the entry block was replaced.
149
+ // / Recalculate all available trees and flush all BasicBlocks
150
+ // / awaiting deletion immediately.
151
+ void recalculate (Function &F);
152
+
61
153
// / Delete DelBB. DelBB will be removed from its Parent and
62
154
// / erased from available trees if it exists and finally get deleted.
63
155
// / Under Eager UpdateStrategy, DelBB will be processed immediately.
@@ -80,6 +172,33 @@ class DomTreeUpdater
80
172
81
173
// /@}
82
174
175
+ // /@{
176
+ // / \name Flush APIs
177
+ // /
178
+ // / CAUTION! By the moment these flush APIs are called, the current CFG needs
179
+ // / to be the same as the CFG which DTU is in sync with + all updates
180
+ // / submitted.
181
+
182
+ // / Flush DomTree updates and return DomTree.
183
+ // / It flushes Deleted BBs if both trees are up-to-date.
184
+ // / It must only be called when it has a DomTree.
185
+ DominatorTree &getDomTree ();
186
+
187
+ // / Flush PostDomTree updates and return PostDomTree.
188
+ // / It flushes Deleted BBs if both trees are up-to-date.
189
+ // / It must only be called when it has a PostDomTree.
190
+ PostDominatorTree &getPostDomTree ();
191
+
192
+ // / Apply all pending updates to available trees and flush all BasicBlocks
193
+ // / awaiting deletion.
194
+
195
+ void flush ();
196
+
197
+ // /@}
198
+
199
+ // / Debug method to help view the internal state of this class.
200
+ LLVM_DUMP_METHOD void dump () const ;
201
+
83
202
private:
84
203
class CallBackOnDeletion final : public CallbackVH {
85
204
public:
@@ -97,7 +216,16 @@ class DomTreeUpdater
97
216
}
98
217
};
99
218
219
+ SmallVector<DominatorTree::UpdateType, 16 > PendUpdates;
220
+ size_t PendDTUpdateIndex = 0 ;
221
+ size_t PendPDTUpdateIndex = 0 ;
222
+ DominatorTree *DT = nullptr ;
223
+ PostDominatorTree *PDT = nullptr ;
224
+ const UpdateStrategy Strategy;
225
+ SmallPtrSet<BasicBlock *, 8 > DeletedBBs;
100
226
std::vector<CallBackOnDeletion> Callbacks;
227
+ bool IsRecalculatingDomTree = false ;
228
+ bool IsRecalculatingPostDomTree = false ;
101
229
102
230
// / First remove all the instructions of DelBB and then make sure DelBB has a
103
231
// / valid terminator instruction which is necessary to have when DelBB still
@@ -109,28 +237,32 @@ class DomTreeUpdater
109
237
// / Returns true if at least one BasicBlock is deleted.
110
238
bool forceFlushDeletedBB ();
111
239
112
- // / Debug method to help view the internal state of this class.
113
- LLVM_DUMP_METHOD void dump () const {
114
- Base::dump ();
115
- #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
116
- raw_ostream &OS = dbgs ();
117
- OS << " Pending Callbacks:\n " ;
118
- int Index = 0 ;
119
- for (const auto &BB : Callbacks) {
120
- OS << " " << Index << " : " ;
121
- ++Index;
122
- if (BB->hasName ())
123
- OS << BB->getName () << " (" ;
124
- else
125
- OS << " (no_name)(" ;
126
- OS << BB << " )\n " ;
127
- }
128
- #endif
129
- }
130
- };
240
+ // / Helper function to apply all pending DomTree updates.
241
+ void applyDomTreeUpdates ();
242
+
243
+ // / Helper function to apply all pending PostDomTree updates.
244
+ void applyPostDomTreeUpdates ();
245
+
246
+ // / Helper function to flush deleted BasicBlocks if all available
247
+ // / trees are up-to-date.
248
+ void tryFlushDeletedBB ();
131
249
132
- extern template class GenericDomTreeUpdater <DomTreeUpdater, DominatorTree,
133
- PostDominatorTree>;
250
+ // / Drop all updates applied by all available trees and delete BasicBlocks if
251
+ // / all available trees are up-to-date.
252
+ void dropOutOfDateUpdates ();
253
+
254
+ // / Erase Basic Block node that has been unlinked from Function
255
+ // / in the DomTree and PostDomTree.
256
+ void eraseDelBBNode (BasicBlock *DelBB);
257
+
258
+ // / Returns true if the update appears in the LLVM IR.
259
+ // / It is used to check whether an update is valid in
260
+ // / insertEdge/deleteEdge or is unnecessary in the batch update.
261
+ bool isUpdateValid (DominatorTree::UpdateType Update) const ;
262
+
263
+ // / Returns true if the update is self dominance.
264
+ bool isSelfDominance (DominatorTree::UpdateType Update) const ;
265
+ };
134
266
} // namespace llvm
135
267
136
268
#endif // LLVM_ANALYSIS_DOMTREEUPDATER_H
0 commit comments