Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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
 
25
namespace llvm {
26
class PostDominatorTree;
27
 
28
class DomTreeUpdater {
29
public:
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
  /// Delete DelBB. DelBB will be removed from its Parent and
154
  /// erased from available trees if it exists and finally get deleted.
155
  /// Under Eager UpdateStrategy, DelBB will be processed immediately.
156
  /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
157
  /// all available trees are up-to-date. Assert if any instruction of DelBB is
158
  /// modified while awaiting deletion. When both DT and PDT are nullptrs, DelBB
159
  /// will be queued until flush() is called.
160
  void deleteBB(BasicBlock *DelBB);
161
 
162
  /// Delete DelBB. DelBB will be removed from its Parent and
163
  /// erased from available trees if it exists. Then the callback will
164
  /// be called. Finally, DelBB will be deleted.
165
  /// Under Eager UpdateStrategy, DelBB will be processed immediately.
166
  /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
167
  /// all available trees are up-to-date. Assert if any instruction of DelBB is
168
  /// modified while awaiting deletion. Multiple callbacks can be queued for one
169
  /// DelBB under Lazy UpdateStrategy.
170
  void callbackDeleteBB(BasicBlock *DelBB,
171
                        std::function<void(BasicBlock *)> Callback);
172
 
173
  ///@}
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
 
202
private:
203
  class CallBackOnDeletion final : public CallbackVH {
204
  public:
205
    CallBackOnDeletion(BasicBlock *V,
206
                       std::function<void(BasicBlock *)> Callback)
207
        : CallbackVH(V), DelBB(V), Callback_(Callback) {}
208
 
209
  private:
210
    BasicBlock *DelBB = nullptr;
211
    std::function<void(BasicBlock *)> Callback_;
212
 
213
    void deleted() override {
214
      Callback_(DelBB);
215
      CallbackVH::deleted();
216
    }
217
  };
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;
226
  std::vector<CallBackOnDeletion> Callbacks;
227
  bool IsRecalculatingDomTree = false;
228
  bool IsRecalculatingPostDomTree = false;
229
 
230
  /// First remove all the instructions of DelBB and then make sure DelBB has a
231
  /// valid terminator instruction which is necessary to have when DelBB still
232
  /// has to be inside of its parent Function while awaiting deletion under Lazy
233
  /// UpdateStrategy to prevent other routines from asserting the state of the
234
  /// IR is inconsistent. Assert if DelBB is nullptr or has predecessors.
235
  void validateDeleteBB(BasicBlock *DelBB);
236
 
237
  /// Returns true if at least one BasicBlock is deleted.
238
  bool forceFlushDeletedBB();
239
 
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();
249
 
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
};
266
} // namespace llvm
267
 
268
#endif // LLVM_ANALYSIS_DOMTREEUPDATER_H