DomTreeUpdater.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- DomTreeUpdater.h - DomTree/Post DomTree Updater ----------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file defines the DomTreeUpdater class, which provides a uniform way to
  15. // update dominator tree related data structures.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_ANALYSIS_DOMTREEUPDATER_H
  19. #define LLVM_ANALYSIS_DOMTREEUPDATER_H
  20. #include "llvm/ADT/SmallPtrSet.h"
  21. #include "llvm/IR/Dominators.h"
  22. #include "llvm/IR/ValueHandle.h"
  23. #include "llvm/Support/Compiler.h"
  24. #include <cstddef>
  25. #include <functional>
  26. #include <vector>
  27. namespace llvm {
  28. class PostDominatorTree;
  29. class DomTreeUpdater {
  30. public:
  31. enum class UpdateStrategy : unsigned char { Eager = 0, Lazy = 1 };
  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. ~DomTreeUpdater() { flush(); }
  48. /// Returns true if the current strategy is Lazy.
  49. bool isLazy() const { return Strategy == UpdateStrategy::Lazy; };
  50. /// Returns true if the current strategy is Eager.
  51. bool isEager() const { return Strategy == UpdateStrategy::Eager; };
  52. /// Returns true if it holds a DominatorTree.
  53. bool hasDomTree() const { return DT != nullptr; }
  54. /// Returns true if it holds a PostDominatorTree.
  55. bool hasPostDomTree() const { return PDT != nullptr; }
  56. /// Returns true if there is BasicBlock awaiting deletion.
  57. /// The deletion will only happen until a flush event and
  58. /// all available trees are up-to-date.
  59. /// Returns false under Eager UpdateStrategy.
  60. bool hasPendingDeletedBB() const { return !DeletedBBs.empty(); }
  61. /// Returns true if DelBB is awaiting deletion.
  62. /// Returns false under Eager UpdateStrategy.
  63. bool isBBPendingDeletion(BasicBlock *DelBB) const;
  64. /// Returns true if either of DT or PDT is valid and the tree has at
  65. /// least one update pending. If DT or PDT is nullptr it is treated
  66. /// as having no pending updates. This function does not check
  67. /// whether there is BasicBlock awaiting deletion.
  68. /// Returns false under Eager UpdateStrategy.
  69. bool hasPendingUpdates() const;
  70. /// Returns true if there are DominatorTree updates queued.
  71. /// Returns false under Eager UpdateStrategy or DT is nullptr.
  72. bool hasPendingDomTreeUpdates() const;
  73. /// Returns true if there are PostDominatorTree updates queued.
  74. /// Returns false under Eager UpdateStrategy or PDT is nullptr.
  75. bool hasPendingPostDomTreeUpdates() const;
  76. ///@{
  77. /// \name Mutation APIs
  78. ///
  79. /// These methods provide APIs for submitting updates to the DominatorTree and
  80. /// the PostDominatorTree.
  81. ///
  82. /// Note: There are two strategies to update the DominatorTree and the
  83. /// PostDominatorTree:
  84. /// 1. Eager UpdateStrategy: Updates are submitted and then flushed
  85. /// immediately.
  86. /// 2. Lazy UpdateStrategy: Updates are submitted but only flushed when you
  87. /// explicitly call Flush APIs. It is recommended to use this update strategy
  88. /// when you submit a bunch of updates multiple times which can then
  89. /// add up to a large number of updates between two queries on the
  90. /// DominatorTree. The incremental updater can reschedule the updates or
  91. /// decide to recalculate the dominator tree in order to speedup the updating
  92. /// process depending on the number of updates.
  93. ///
  94. /// Although GenericDomTree provides several update primitives,
  95. /// it is not encouraged to use these APIs directly.
  96. /// Submit updates to all available trees.
  97. /// The Eager Strategy flushes updates immediately while the Lazy Strategy
  98. /// queues the updates.
  99. ///
  100. /// Note: The "existence" of an edge in a CFG refers to the CFG which DTU is
  101. /// in sync with + all updates before that single update.
  102. ///
  103. /// CAUTION!
  104. /// 1. It is required for the state of the LLVM IR to be updated
  105. /// *before* submitting the updates because the internal update routine will
  106. /// analyze the current state of the CFG to determine whether an update
  107. /// is valid.
  108. /// 2. It is illegal to submit any update that has already been submitted,
  109. /// i.e., you are supposed not to insert an existent edge or delete a
  110. /// nonexistent edge.
  111. void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates);
  112. /// Submit updates to all available trees. It will also
  113. /// 1. discard duplicated updates,
  114. /// 2. remove invalid updates. (Invalid updates means deletion of an edge that
  115. /// still exists or insertion of an edge that does not exist.)
  116. /// The Eager Strategy flushes updates immediately while the Lazy Strategy
  117. /// queues the updates.
  118. ///
  119. /// Note: The "existence" of an edge in a CFG refers to the CFG which DTU is
  120. /// in sync with + all updates before that single update.
  121. ///
  122. /// CAUTION!
  123. /// 1. It is required for the state of the LLVM IR to be updated
  124. /// *before* submitting the updates because the internal update routine will
  125. /// analyze the current state of the CFG to determine whether an update
  126. /// is valid.
  127. /// 2. It is illegal to submit any update that has already been submitted,
  128. /// i.e., you are supposed not to insert an existent edge or delete a
  129. /// nonexistent edge.
  130. /// 3. It is only legal to submit updates to an edge in the order CFG changes
  131. /// are made. The order you submit updates on different edges is not
  132. /// restricted.
  133. void applyUpdatesPermissive(ArrayRef<DominatorTree::UpdateType> Updates);
  134. /// Notify DTU that the entry block was replaced.
  135. /// Recalculate all available trees and flush all BasicBlocks
  136. /// awaiting deletion immediately.
  137. void recalculate(Function &F);
  138. /// \deprecated { Submit an edge insertion to all available trees. The Eager
  139. /// Strategy flushes this update immediately while the Lazy Strategy queues
  140. /// the update. An internal function checks if the edge exists in the CFG in
  141. /// DEBUG mode. CAUTION! This function has to be called *after* making the
  142. /// update on the actual CFG. It is illegal to submit any update that has
  143. /// already been applied. }
  144. LLVM_ATTRIBUTE_DEPRECATED(void insertEdge(BasicBlock *From, BasicBlock *To),
  145. "Use applyUpdates() instead.");
  146. /// \deprecated {Submit an edge insertion to all available trees.
  147. /// Under either Strategy, an invalid update will be discard silently.
  148. /// Invalid update means inserting an edge that does not exist in the CFG.
  149. /// The Eager Strategy flushes this update immediately while the Lazy Strategy
  150. /// queues the update. It is only recommended to use this method when you
  151. /// want to discard an invalid update.
  152. /// CAUTION! It is illegal to submit any update that has already been
  153. /// submitted. }
  154. LLVM_ATTRIBUTE_DEPRECATED(void insertEdgeRelaxed(BasicBlock *From,
  155. BasicBlock *To),
  156. "Use applyUpdatesPermissive() instead.");
  157. /// \deprecated { Submit an edge deletion to all available trees. The Eager
  158. /// Strategy flushes this update immediately while the Lazy Strategy queues
  159. /// the update. An internal function checks if the edge doesn't exist in the
  160. /// CFG in DEBUG mode.
  161. /// CAUTION! This function has to be called *after* making the update on the
  162. /// actual CFG. It is illegal to submit any update that has already been
  163. /// submitted. }
  164. LLVM_ATTRIBUTE_DEPRECATED(void deleteEdge(BasicBlock *From, BasicBlock *To),
  165. "Use applyUpdates() instead.");
  166. /// \deprecated { Submit an edge deletion to all available trees.
  167. /// Under either Strategy, an invalid update will be discard silently.
  168. /// Invalid update means deleting an edge that exists in the CFG.
  169. /// The Eager Strategy flushes this update immediately while the Lazy Strategy
  170. /// queues the update. It is only recommended to use this method when you
  171. /// want to discard an invalid update.
  172. /// CAUTION! It is illegal to submit any update that has already been
  173. /// submitted. }
  174. LLVM_ATTRIBUTE_DEPRECATED(void deleteEdgeRelaxed(BasicBlock *From,
  175. BasicBlock *To),
  176. "Use applyUpdatesPermissive() instead.");
  177. /// Delete DelBB. DelBB will be removed from its Parent and
  178. /// erased from available trees if it exists and finally get deleted.
  179. /// Under Eager UpdateStrategy, DelBB will be processed immediately.
  180. /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
  181. /// all available trees are up-to-date. Assert if any instruction of DelBB is
  182. /// modified while awaiting deletion. When both DT and PDT are nullptrs, DelBB
  183. /// will be queued until flush() is called.
  184. void deleteBB(BasicBlock *DelBB);
  185. /// Delete DelBB. DelBB will be removed from its Parent and
  186. /// erased from available trees if it exists. Then the callback will
  187. /// be called. Finally, DelBB will be deleted.
  188. /// Under Eager UpdateStrategy, DelBB will be processed immediately.
  189. /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and
  190. /// all available trees are up-to-date. Assert if any instruction of DelBB is
  191. /// modified while awaiting deletion. Multiple callbacks can be queued for one
  192. /// DelBB under Lazy UpdateStrategy.
  193. void callbackDeleteBB(BasicBlock *DelBB,
  194. std::function<void(BasicBlock *)> Callback);
  195. ///@}
  196. ///@{
  197. /// \name Flush APIs
  198. ///
  199. /// CAUTION! By the moment these flush APIs are called, the current CFG needs
  200. /// to be the same as the CFG which DTU is in sync with + all updates
  201. /// submitted.
  202. /// Flush DomTree updates and return DomTree.
  203. /// It flushes Deleted BBs if both trees are up-to-date.
  204. /// It must only be called when it has a DomTree.
  205. DominatorTree &getDomTree();
  206. /// Flush PostDomTree updates and return PostDomTree.
  207. /// It flushes Deleted BBs if both trees are up-to-date.
  208. /// It must only be called when it has a PostDomTree.
  209. PostDominatorTree &getPostDomTree();
  210. /// Apply all pending updates to available trees and flush all BasicBlocks
  211. /// awaiting deletion.
  212. void flush();
  213. ///@}
  214. /// Debug method to help view the internal state of this class.
  215. LLVM_DUMP_METHOD void dump() const;
  216. private:
  217. class CallBackOnDeletion final : public CallbackVH {
  218. public:
  219. CallBackOnDeletion(BasicBlock *V,
  220. std::function<void(BasicBlock *)> Callback)
  221. : CallbackVH(V), DelBB(V), Callback_(Callback) {}
  222. private:
  223. BasicBlock *DelBB = nullptr;
  224. std::function<void(BasicBlock *)> Callback_;
  225. void deleted() override {
  226. Callback_(DelBB);
  227. CallbackVH::deleted();
  228. }
  229. };
  230. SmallVector<DominatorTree::UpdateType, 16> PendUpdates;
  231. size_t PendDTUpdateIndex = 0;
  232. size_t PendPDTUpdateIndex = 0;
  233. DominatorTree *DT = nullptr;
  234. PostDominatorTree *PDT = nullptr;
  235. const UpdateStrategy Strategy;
  236. SmallPtrSet<BasicBlock *, 8> DeletedBBs;
  237. std::vector<CallBackOnDeletion> Callbacks;
  238. bool IsRecalculatingDomTree = false;
  239. bool IsRecalculatingPostDomTree = false;
  240. /// First remove all the instructions of DelBB and then make sure DelBB has a
  241. /// valid terminator instruction which is necessary to have when DelBB still
  242. /// has to be inside of its parent Function while awaiting deletion under Lazy
  243. /// UpdateStrategy to prevent other routines from asserting the state of the
  244. /// IR is inconsistent. Assert if DelBB is nullptr or has predecessors.
  245. void validateDeleteBB(BasicBlock *DelBB);
  246. /// Returns true if at least one BasicBlock is deleted.
  247. bool forceFlushDeletedBB();
  248. /// Helper function to apply all pending DomTree updates.
  249. void applyDomTreeUpdates();
  250. /// Helper function to apply all pending PostDomTree updates.
  251. void applyPostDomTreeUpdates();
  252. /// Helper function to flush deleted BasicBlocks if all available
  253. /// trees are up-to-date.
  254. void tryFlushDeletedBB();
  255. /// Drop all updates applied by all available trees and delete BasicBlocks if
  256. /// all available trees are up-to-date.
  257. void dropOutOfDateUpdates();
  258. /// Erase Basic Block node that has been unlinked from Function
  259. /// in the DomTree and PostDomTree.
  260. void eraseDelBBNode(BasicBlock *DelBB);
  261. /// Returns true if the update appears in the LLVM IR.
  262. /// It is used to check whether an update is valid in
  263. /// insertEdge/deleteEdge or is unnecessary in the batch update.
  264. bool isUpdateValid(DominatorTree::UpdateType Update) const;
  265. /// Returns true if the update is self dominance.
  266. bool isSelfDominance(DominatorTree::UpdateType Update) const;
  267. };
  268. } // namespace llvm
  269. #endif // LLVM_ANALYSIS_DOMTREEUPDATER_H
  270. #ifdef __GNUC__
  271. #pragma GCC diagnostic pop
  272. #endif