1//===- DomTreeUpdater.h - DomTree/Post DomTree Updater ----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the DomTreeUpdater class, which provides a uniform way to
10// update dominator tree related data structures.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_ANALYSIS_DOMTREEUPDATER_H
15#define LLVM_ANALYSIS_DOMTREEUPDATER_H
16
17#include "llvm/ADT/SmallPtrSet.h"
18#include "llvm/IR/Dominators.h"
19#include "llvm/IR/ValueHandle.h"
20#include "llvm/Support/Compiler.h"
21#include <cstddef>
22#include <functional>
23#include <vector>
24
25namespace llvm {
26class PostDominatorTree;
27
28class DomTreeUpdater {
29public:
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;
86
87  ///@{
88  /// \name Mutation APIs
89  ///
90  /// These methods provide APIs for submitting updates to the DominatorTree and
91  /// the PostDominatorTree.
92  ///
93  /// Note: There are two strategies to update the DominatorTree and the
94  /// PostDominatorTree:
95  /// 1. Eager UpdateStrategy: Updates are submitted and then flushed
96  /// immediately.
97  /// 2. Lazy UpdateStrategy: Updates are submitted but only flushed when you
98  /// explicitly call Flush APIs. It is recommended to use this update strategy
99  /// when you submit a bunch of updates multiple times which can then
100  /// add up to a large number of updates between two queries on the
101  /// DominatorTree. The incremental updater can reschedule the updates or
102  /// decide to recalculate the dominator tree in order to speedup the updating
103  /// process depending on the number of updates.
104  ///
105  /// Although GenericDomTree provides several update primitives,
106  /// it is not encouraged to use these APIs directly.
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
153  /// \deprecated { Submit an edge insertion to all available trees. The Eager
154  /// Strategy flushes this update immediately while the Lazy Strategy queues
155  /// the update. An internal function checks if the edge exists in the CFG in
156  /// DEBUG mode. CAUTION! This function has to be called *after* making the
157  /// update on the actual CFG. It is illegal to submit any update that has
158  /// already been applied. }
159  LLVM_ATTRIBUTE_DEPRECATED(void insertEdge(BasicBlock *From, BasicBlock *To),
160                            "Use applyUpdates() instead.");
161
162  /// \deprecated {Submit an edge insertion to all available trees.
163  /// Under either Strategy, an invalid update will be discard silently.
164  /// Invalid update means inserting an edge that does not exist in the CFG.
165  /// The Eager Strategy flushes this update immediately while the Lazy Strategy
166  /// queues the update. It is only recommended to use this method when you
167  /// want to discard an invalid update.
168  /// CAUTION! It is illegal to submit any update that has already been
169  /// submitted. }
170  LLVM_ATTRIBUTE_DEPRECATED(void insertEdgeRelaxed(BasicBlock *From,
171                                                   BasicBlock *To),
172                            "Use applyUpdatesPermissive() instead.");
173
174  /// \deprecated { Submit an edge deletion to all available trees. The Eager
175  /// Strategy flushes this update immediately while the Lazy Strategy queues
176  /// the update. An internal function checks if the edge doesn't exist in the
177  /// CFG in DEBUG mode.
178  /// CAUTION! This function has to be called *after* making the update on the
179  /// actual CFG. It is illegal to submit any update that has already been
180  /// submitted. }
181  LLVM_ATTRIBUTE_DEPRECATED(void deleteEdge(BasicBlock *From, BasicBlock *To),
182                            "Use applyUpdates() instead.");
183
184  /// \deprecated { Submit an edge deletion to all available trees.
185  /// Under either Strategy, an invalid update will be discard silently.
186  /// Invalid update means deleting an edge that exists in the CFG.
187  /// The Eager Strategy flushes this update immediately while the Lazy Strategy
188  /// queues the update. It is only recommended to use this method when you
189  /// want to discard an invalid update.
190  /// CAUTION! It is illegal to submit any update that has already been
191  /// submitted. }
192  LLVM_ATTRIBUTE_DEPRECATED(void deleteEdgeRelaxed(BasicBlock *From,
193                                                   BasicBlock *To),
194                            "Use applyUpdatesPermissive() instead.");
195
196  /// Delete DelBB. DelBB will be removed from its Parent and
197  /// erased from available trees if it exists and finally get deleted.
198  /// Under Eager UpdateStrategy, DelBB will be processed immediately.
199  /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
200  /// all available trees are up-to-date. Assert if any instruction of DelBB is
201  /// modified while awaiting deletion. When both DT and PDT are nullptrs, DelBB
202  /// will be queued until flush() is called.
203  void deleteBB(BasicBlock *DelBB);
204
205  /// Delete DelBB. DelBB will be removed from its Parent and
206  /// erased from available trees if it exists. Then the callback will
207  /// be called. Finally, DelBB will be deleted.
208  /// Under Eager UpdateStrategy, DelBB will be processed immediately.
209  /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
210  /// all available trees are up-to-date. Assert if any instruction of DelBB is
211  /// modified while awaiting deletion. Multiple callbacks can be queued for one
212  /// DelBB under Lazy UpdateStrategy.
213  void callbackDeleteBB(BasicBlock *DelBB,
214                        std::function<void(BasicBlock *)> Callback);
215
216  ///@}
217
218  ///@{
219  /// \name Flush APIs
220  ///
221  /// CAUTION! By the moment these flush APIs are called, the current CFG needs
222  /// to be the same as the CFG which DTU is in sync with + all updates
223  /// submitted.
224
225  /// Flush DomTree updates and return DomTree.
226  /// It flushes Deleted BBs if both trees are up-to-date.
227  /// It must only be called when it has a DomTree.
228  DominatorTree &getDomTree();
229
230  /// Flush PostDomTree updates and return PostDomTree.
231  /// It flushes Deleted BBs if both trees are up-to-date.
232  /// It must only be called when it has a PostDomTree.
233  PostDominatorTree &getPostDomTree();
234
235  /// Apply all pending updates to available trees and flush all BasicBlocks
236  /// awaiting deletion.
237
238  void flush();
239
240  ///@}
241
242  /// Debug method to help view the internal state of this class.
243  LLVM_DUMP_METHOD void dump() const;
244
245private:
246  class CallBackOnDeletion final : public CallbackVH {
247  public:
248    CallBackOnDeletion(BasicBlock *V,
249                       std::function<void(BasicBlock *)> Callback)
250        : CallbackVH(V), DelBB(V), Callback_(Callback) {}
251
252  private:
253    BasicBlock *DelBB = nullptr;
254    std::function<void(BasicBlock *)> Callback_;
255
256    void deleted() override {
257      Callback_(DelBB);
258      CallbackVH::deleted();
259    }
260  };
261
262  SmallVector<DominatorTree::UpdateType, 16> PendUpdates;
263  size_t PendDTUpdateIndex = 0;
264  size_t PendPDTUpdateIndex = 0;
265  DominatorTree *DT = nullptr;
266  PostDominatorTree *PDT = nullptr;
267  const UpdateStrategy Strategy;
268  SmallPtrSet<BasicBlock *, 8> DeletedBBs;
269  std::vector<CallBackOnDeletion> Callbacks;
270  bool IsRecalculatingDomTree = false;
271  bool IsRecalculatingPostDomTree = false;
272
273  /// First remove all the instructions of DelBB and then make sure DelBB has a
274  /// valid terminator instruction which is necessary to have when DelBB still
275  /// has to be inside of its parent Function while awaiting deletion under Lazy
276  /// UpdateStrategy to prevent other routines from asserting the state of the
277  /// IR is inconsistent. Assert if DelBB is nullptr or has predecessors.
278  void validateDeleteBB(BasicBlock *DelBB);
279
280  /// Returns true if at least one BasicBlock is deleted.
281  bool forceFlushDeletedBB();
282
283  /// Helper function to apply all pending DomTree updates.
284  void applyDomTreeUpdates();
285
286  /// Helper function to apply all pending PostDomTree updates.
287  void applyPostDomTreeUpdates();
288
289  /// Helper function to flush deleted BasicBlocks if all available
290  /// trees are up-to-date.
291  void tryFlushDeletedBB();
292
293  /// Drop all updates applied by all available trees and delete BasicBlocks if
294  /// all available trees are up-to-date.
295  void dropOutOfDateUpdates();
296
297  /// Erase Basic Block node that has been unlinked from Function
298  /// in the DomTree and PostDomTree.
299  void eraseDelBBNode(BasicBlock *DelBB);
300
301  /// Returns true if the update appears in the LLVM IR.
302  /// It is used to check whether an update is valid in
303  /// insertEdge/deleteEdge or is unnecessary in the batch update.
304  bool isUpdateValid(DominatorTree::UpdateType Update) const;
305
306  /// Returns true if the update is self dominance.
307  bool isSelfDominance(DominatorTree::UpdateType Update) const;
308};
309} // namespace llvm
310
311#endif // LLVM_ANALYSIS_DOMTREEUPDATER_H
312