GenericIteratedDominanceFrontier.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- IteratedDominanceFrontier.h - Calculate IDF --------------*- 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. /// \file
  14. /// Compute iterated dominance frontiers using a linear time algorithm.
  15. ///
  16. /// The algorithm used here is based on:
  17. ///
  18. /// Sreedhar and Gao. A linear time algorithm for placing phi-nodes.
  19. /// In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of
  20. /// Programming Languages
  21. /// POPL '95. ACM, New York, NY, 62-73.
  22. ///
  23. /// It has been modified to not explicitly use the DJ graph data structure and
  24. /// to directly compute pruned SSA using per-variable liveness information.
  25. //
  26. //===----------------------------------------------------------------------===//
  27. #ifndef LLVM_SUPPORT_GENERICITERATEDDOMINANCEFRONTIER_H
  28. #define LLVM_SUPPORT_GENERICITERATEDDOMINANCEFRONTIER_H
  29. #include "llvm/ADT/DenseMap.h"
  30. #include "llvm/ADT/SmallPtrSet.h"
  31. #include "llvm/ADT/SmallVector.h"
  32. #include "llvm/Support/GenericDomTree.h"
  33. #include <queue>
  34. namespace llvm {
  35. namespace IDFCalculatorDetail {
  36. /// Generic utility class used for getting the children of a basic block.
  37. /// May be specialized if, for example, one wouldn't like to return nullpointer
  38. /// successors.
  39. template <class NodeTy, bool IsPostDom> struct ChildrenGetterTy {
  40. using NodeRef = typename GraphTraits<NodeTy *>::NodeRef;
  41. using ChildrenTy = SmallVector<NodeRef, 8>;
  42. ChildrenTy get(const NodeRef &N);
  43. };
  44. } // end of namespace IDFCalculatorDetail
  45. /// Determine the iterated dominance frontier, given a set of defining
  46. /// blocks, and optionally, a set of live-in blocks.
  47. ///
  48. /// In turn, the results can be used to place phi nodes.
  49. ///
  50. /// This algorithm is a linear time computation of Iterated Dominance Frontiers,
  51. /// pruned using the live-in set.
  52. /// By default, liveness is not used to prune the IDF computation.
  53. /// The template parameters should be of a CFG block type.
  54. template <class NodeTy, bool IsPostDom> class IDFCalculatorBase {
  55. public:
  56. using OrderedNodeTy =
  57. std::conditional_t<IsPostDom, Inverse<NodeTy *>, NodeTy *>;
  58. using ChildrenGetterTy =
  59. IDFCalculatorDetail::ChildrenGetterTy<NodeTy, IsPostDom>;
  60. IDFCalculatorBase(DominatorTreeBase<NodeTy, IsPostDom> &DT) : DT(DT) {}
  61. IDFCalculatorBase(DominatorTreeBase<NodeTy, IsPostDom> &DT,
  62. const ChildrenGetterTy &C)
  63. : DT(DT), ChildrenGetter(C) {}
  64. /// Give the IDF calculator the set of blocks in which the value is
  65. /// defined. This is equivalent to the set of starting blocks it should be
  66. /// calculating the IDF for (though later gets pruned based on liveness).
  67. ///
  68. /// Note: This set *must* live for the entire lifetime of the IDF calculator.
  69. void setDefiningBlocks(const SmallPtrSetImpl<NodeTy *> &Blocks) {
  70. DefBlocks = &Blocks;
  71. }
  72. /// Give the IDF calculator the set of blocks in which the value is
  73. /// live on entry to the block. This is used to prune the IDF calculation to
  74. /// not include blocks where any phi insertion would be dead.
  75. ///
  76. /// Note: This set *must* live for the entire lifetime of the IDF calculator.
  77. void setLiveInBlocks(const SmallPtrSetImpl<NodeTy *> &Blocks) {
  78. LiveInBlocks = &Blocks;
  79. useLiveIn = true;
  80. }
  81. /// Reset the live-in block set to be empty, and tell the IDF
  82. /// calculator to not use liveness anymore.
  83. void resetLiveInBlocks() {
  84. LiveInBlocks = nullptr;
  85. useLiveIn = false;
  86. }
  87. /// Calculate iterated dominance frontiers
  88. ///
  89. /// This uses the linear-time phi algorithm based on DJ-graphs mentioned in
  90. /// the file-level comment. It performs DF->IDF pruning using the live-in
  91. /// set, to avoid computing the IDF for blocks where an inserted PHI node
  92. /// would be dead.
  93. void calculate(SmallVectorImpl<NodeTy *> &IDFBlocks);
  94. private:
  95. DominatorTreeBase<NodeTy, IsPostDom> &DT;
  96. ChildrenGetterTy ChildrenGetter;
  97. bool useLiveIn = false;
  98. const SmallPtrSetImpl<NodeTy *> *LiveInBlocks;
  99. const SmallPtrSetImpl<NodeTy *> *DefBlocks;
  100. };
  101. //===----------------------------------------------------------------------===//
  102. // Implementation.
  103. //===----------------------------------------------------------------------===//
  104. namespace IDFCalculatorDetail {
  105. template <class NodeTy, bool IsPostDom>
  106. typename ChildrenGetterTy<NodeTy, IsPostDom>::ChildrenTy
  107. ChildrenGetterTy<NodeTy, IsPostDom>::get(const NodeRef &N) {
  108. using OrderedNodeTy =
  109. typename IDFCalculatorBase<NodeTy, IsPostDom>::OrderedNodeTy;
  110. auto Children = children<OrderedNodeTy>(N);
  111. return {Children.begin(), Children.end()};
  112. }
  113. } // end of namespace IDFCalculatorDetail
  114. template <class NodeTy, bool IsPostDom>
  115. void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
  116. SmallVectorImpl<NodeTy *> &IDFBlocks) {
  117. // Use a priority queue keyed on dominator tree level so that inserted nodes
  118. // are handled from the bottom of the dominator tree upwards. We also augment
  119. // the level with a DFS number to ensure that the blocks are ordered in a
  120. // deterministic way.
  121. using DomTreeNodePair =
  122. std::pair<DomTreeNodeBase<NodeTy> *, std::pair<unsigned, unsigned>>;
  123. using IDFPriorityQueue =
  124. std::priority_queue<DomTreeNodePair, SmallVector<DomTreeNodePair, 32>,
  125. less_second>;
  126. IDFPriorityQueue PQ;
  127. DT.updateDFSNumbers();
  128. SmallVector<DomTreeNodeBase<NodeTy> *, 32> Worklist;
  129. SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedPQ;
  130. SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedWorklist;
  131. for (NodeTy *BB : *DefBlocks)
  132. if (DomTreeNodeBase<NodeTy> *Node = DT.getNode(BB)) {
  133. PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
  134. VisitedWorklist.insert(Node);
  135. }
  136. while (!PQ.empty()) {
  137. DomTreeNodePair RootPair = PQ.top();
  138. PQ.pop();
  139. DomTreeNodeBase<NodeTy> *Root = RootPair.first;
  140. unsigned RootLevel = RootPair.second.first;
  141. // Walk all dominator tree children of Root, inspecting their CFG edges with
  142. // targets elsewhere on the dominator tree. Only targets whose level is at
  143. // most Root's level are added to the iterated dominance frontier of the
  144. // definition set.
  145. assert(Worklist.empty());
  146. Worklist.push_back(Root);
  147. while (!Worklist.empty()) {
  148. DomTreeNodeBase<NodeTy> *Node = Worklist.pop_back_val();
  149. NodeTy *BB = Node->getBlock();
  150. // Succ is the successor in the direction we are calculating IDF, so it is
  151. // successor for IDF, and predecessor for Reverse IDF.
  152. auto DoWork = [&](NodeTy *Succ) {
  153. DomTreeNodeBase<NodeTy> *SuccNode = DT.getNode(Succ);
  154. const unsigned SuccLevel = SuccNode->getLevel();
  155. if (SuccLevel > RootLevel)
  156. return;
  157. if (!VisitedPQ.insert(SuccNode).second)
  158. return;
  159. NodeTy *SuccBB = SuccNode->getBlock();
  160. if (useLiveIn && !LiveInBlocks->count(SuccBB))
  161. return;
  162. IDFBlocks.emplace_back(SuccBB);
  163. if (!DefBlocks->count(SuccBB))
  164. PQ.push(std::make_pair(
  165. SuccNode, std::make_pair(SuccLevel, SuccNode->getDFSNumIn())));
  166. };
  167. for (auto Succ : ChildrenGetter.get(BB))
  168. DoWork(Succ);
  169. for (auto DomChild : *Node) {
  170. if (VisitedWorklist.insert(DomChild).second)
  171. Worklist.push_back(DomChild);
  172. }
  173. }
  174. }
  175. }
  176. } // end of namespace llvm
  177. #endif
  178. #ifdef __GNUC__
  179. #pragma GCC diagnostic pop
  180. #endif