dominator_tree.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. // Copyright (c) 2017 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <iostream>
  15. #include <memory>
  16. #include <set>
  17. #include "source/cfa.h"
  18. #include "source/opt/dominator_tree.h"
  19. #include "source/opt/ir_context.h"
  20. // Calculates the dominator or postdominator tree for a given function.
  21. // 1 - Compute the successors and predecessors for each BasicBlock. We add a
  22. // dummy node for the start node or for postdominators the exit. This node will
  23. // point to all entry or all exit nodes.
  24. // 2 - Using the CFA::DepthFirstTraversal get a depth first postordered list of
  25. // all BasicBlocks. Using the successors (or for postdominator, predecessors)
  26. // calculated in step 1 to traverse the tree.
  27. // 3 - Pass the list calculated in step 2 to the CFA::CalculateDominators using
  28. // the predecessors list (or for postdominator, successors). This will give us a
  29. // vector of BB pairs. Each BB and its immediate dominator.
  30. // 4 - Using the list from 3 use those edges to build a tree of
  31. // DominatorTreeNodes. Each node containing a link to the parent dominator and
  32. // children which are dominated.
  33. // 5 - Using the tree from 4, perform a depth first traversal to calculate the
  34. // preorder and postorder index of each node. We use these indexes to compare
  35. // nodes against each other for domination checks.
  36. namespace spvtools {
  37. namespace opt {
  38. namespace {
  39. // Wrapper around CFA::DepthFirstTraversal to provide an interface to perform
  40. // depth first search on generic BasicBlock types. Will call post and pre order
  41. // user defined functions during traversal
  42. //
  43. // BBType - BasicBlock type. Will either be BasicBlock or DominatorTreeNode
  44. // SuccessorLambda - Lamdba matching the signature of 'const
  45. // std::vector<BBType>*(const BBType *A)'. Will return a vector of the nodes
  46. // succeding BasicBlock A.
  47. // PostLambda - Lamdba matching the signature of 'void (const BBType*)' will be
  48. // called on each node traversed AFTER their children.
  49. // PreLambda - Lamdba matching the signature of 'void (const BBType*)' will be
  50. // called on each node traversed BEFORE their children.
  51. template <typename BBType, typename SuccessorLambda, typename PreLambda,
  52. typename PostLambda>
  53. static void DepthFirstSearch(const BBType* bb, SuccessorLambda successors,
  54. PreLambda pre, PostLambda post) {
  55. // Ignore backedge operation.
  56. auto nop_backedge = [](const BBType*, const BBType*) {};
  57. CFA<BBType>::DepthFirstTraversal(bb, successors, pre, post, nop_backedge);
  58. }
  59. // Wrapper around CFA::DepthFirstTraversal to provide an interface to perform
  60. // depth first search on generic BasicBlock types. This overload is for only
  61. // performing user defined post order.
  62. //
  63. // BBType - BasicBlock type. Will either be BasicBlock or DominatorTreeNode
  64. // SuccessorLambda - Lamdba matching the signature of 'const
  65. // std::vector<BBType>*(const BBType *A)'. Will return a vector of the nodes
  66. // succeding BasicBlock A.
  67. // PostLambda - Lamdba matching the signature of 'void (const BBType*)' will be
  68. // called on each node traversed after their children.
  69. template <typename BBType, typename SuccessorLambda, typename PostLambda>
  70. static void DepthFirstSearchPostOrder(const BBType* bb,
  71. SuccessorLambda successors,
  72. PostLambda post) {
  73. // Ignore preorder operation.
  74. auto nop_preorder = [](const BBType*) {};
  75. DepthFirstSearch(bb, successors, nop_preorder, post);
  76. }
  77. // Small type trait to get the function class type.
  78. template <typename BBType>
  79. struct GetFunctionClass {
  80. using FunctionType = Function;
  81. };
  82. // Helper class to compute predecessors and successors for each Basic Block in a
  83. // function. Through GetPredFunctor and GetSuccessorFunctor it provides an
  84. // interface to get the successor and predecessor lists for each basic
  85. // block. This is required by the DepthFirstTraversal and ComputeDominator
  86. // functions which take as parameter an std::function returning the successors
  87. // and predecessors respectively.
  88. //
  89. // When computing the post-dominator tree, all edges are inverted. So successors
  90. // returned by this class will be predecessors in the original CFG.
  91. template <typename BBType>
  92. class BasicBlockSuccessorHelper {
  93. // This should eventually become const BasicBlock.
  94. using BasicBlock = BBType;
  95. using Function = typename GetFunctionClass<BBType>::FunctionType;
  96. using BasicBlockListTy = std::vector<BasicBlock*>;
  97. using BasicBlockMapTy = std::map<const BasicBlock*, BasicBlockListTy>;
  98. public:
  99. // For compliance with the dominance tree computation, entry nodes are
  100. // connected to a single dummy node.
  101. BasicBlockSuccessorHelper(Function& func, const BasicBlock* dummy_start_node,
  102. bool post);
  103. // CFA::CalculateDominators requires std::vector<BasicBlock*>.
  104. using GetBlocksFunction =
  105. std::function<const std::vector<BasicBlock*>*(const BasicBlock*)>;
  106. // Returns the list of predecessor functions.
  107. GetBlocksFunction GetPredFunctor() {
  108. return [this](const BasicBlock* bb) {
  109. BasicBlockListTy* v = &this->predecessors_[bb];
  110. return v;
  111. };
  112. }
  113. // Returns a vector of the list of successor nodes from a given node.
  114. GetBlocksFunction GetSuccessorFunctor() {
  115. return [this](const BasicBlock* bb) {
  116. BasicBlockListTy* v = &this->successors_[bb];
  117. return v;
  118. };
  119. }
  120. private:
  121. bool invert_graph_;
  122. BasicBlockMapTy successors_;
  123. BasicBlockMapTy predecessors_;
  124. // Build the successors and predecessors map for each basic blocks |f|.
  125. // If |invert_graph_| is true, all edges are reversed (successors becomes
  126. // predecessors and vice versa).
  127. // For convenience, the start of the graph is |dummy_start_node|.
  128. // The dominator tree construction requires a unique entry node, which cannot
  129. // be guaranteed for the postdominator graph. The |dummy_start_node| BB is
  130. // here to gather all entry nodes.
  131. void CreateSuccessorMap(Function& f, const BasicBlock* dummy_start_node);
  132. };
  133. template <typename BBType>
  134. BasicBlockSuccessorHelper<BBType>::BasicBlockSuccessorHelper(
  135. Function& func, const BasicBlock* dummy_start_node, bool invert)
  136. : invert_graph_(invert) {
  137. CreateSuccessorMap(func, dummy_start_node);
  138. }
  139. template <typename BBType>
  140. void BasicBlockSuccessorHelper<BBType>::CreateSuccessorMap(
  141. Function& f, const BasicBlock* dummy_start_node) {
  142. std::map<uint32_t, BasicBlock*> id_to_BB_map;
  143. auto GetSuccessorBasicBlock = [&f, &id_to_BB_map](uint32_t successor_id) {
  144. BasicBlock*& Succ = id_to_BB_map[successor_id];
  145. if (!Succ) {
  146. for (BasicBlock& BBIt : f) {
  147. if (successor_id == BBIt.id()) {
  148. Succ = &BBIt;
  149. break;
  150. }
  151. }
  152. }
  153. return Succ;
  154. };
  155. if (invert_graph_) {
  156. // For the post dominator tree, we see the inverted graph.
  157. // successors_ in the inverted graph are the predecessors in the CFG.
  158. // The tree construction requires 1 entry point, so we add a dummy node
  159. // that is connected to all function exiting basic blocks.
  160. // An exiting basic block is a block with an OpKill, OpUnreachable,
  161. // OpReturn or OpReturnValue as terminator instruction.
  162. for (BasicBlock& bb : f) {
  163. if (bb.hasSuccessor()) {
  164. BasicBlockListTy& pred_list = predecessors_[&bb];
  165. const auto& const_bb = bb;
  166. const_bb.ForEachSuccessorLabel(
  167. [this, &pred_list, &bb,
  168. &GetSuccessorBasicBlock](const uint32_t successor_id) {
  169. BasicBlock* succ = GetSuccessorBasicBlock(successor_id);
  170. // Inverted graph: our successors in the CFG
  171. // are our predecessors in the inverted graph.
  172. this->successors_[succ].push_back(&bb);
  173. pred_list.push_back(succ);
  174. });
  175. } else {
  176. successors_[dummy_start_node].push_back(&bb);
  177. predecessors_[&bb].push_back(const_cast<BasicBlock*>(dummy_start_node));
  178. }
  179. }
  180. } else {
  181. successors_[dummy_start_node].push_back(f.entry().get());
  182. predecessors_[f.entry().get()].push_back(
  183. const_cast<BasicBlock*>(dummy_start_node));
  184. for (BasicBlock& bb : f) {
  185. BasicBlockListTy& succ_list = successors_[&bb];
  186. const auto& const_bb = bb;
  187. const_bb.ForEachSuccessorLabel([&](const uint32_t successor_id) {
  188. BasicBlock* succ = GetSuccessorBasicBlock(successor_id);
  189. succ_list.push_back(succ);
  190. predecessors_[succ].push_back(&bb);
  191. });
  192. }
  193. }
  194. }
  195. } // namespace
  196. bool DominatorTree::StrictlyDominates(uint32_t a, uint32_t b) const {
  197. if (a == b) return false;
  198. return Dominates(a, b);
  199. }
  200. bool DominatorTree::StrictlyDominates(const BasicBlock* a,
  201. const BasicBlock* b) const {
  202. return DominatorTree::StrictlyDominates(a->id(), b->id());
  203. }
  204. bool DominatorTree::StrictlyDominates(const DominatorTreeNode* a,
  205. const DominatorTreeNode* b) const {
  206. if (a == b) return false;
  207. return Dominates(a, b);
  208. }
  209. bool DominatorTree::Dominates(uint32_t a, uint32_t b) const {
  210. // Check that both of the inputs are actual nodes.
  211. const DominatorTreeNode* a_node = GetTreeNode(a);
  212. const DominatorTreeNode* b_node = GetTreeNode(b);
  213. if (!a_node || !b_node) return false;
  214. return Dominates(a_node, b_node);
  215. }
  216. bool DominatorTree::Dominates(const DominatorTreeNode* a,
  217. const DominatorTreeNode* b) const {
  218. // Node A dominates node B if they are the same.
  219. if (a == b) return true;
  220. return a->dfs_num_pre_ < b->dfs_num_pre_ &&
  221. a->dfs_num_post_ > b->dfs_num_post_;
  222. }
  223. bool DominatorTree::Dominates(const BasicBlock* A, const BasicBlock* B) const {
  224. return Dominates(A->id(), B->id());
  225. }
  226. BasicBlock* DominatorTree::ImmediateDominator(const BasicBlock* A) const {
  227. return ImmediateDominator(A->id());
  228. }
  229. BasicBlock* DominatorTree::ImmediateDominator(uint32_t a) const {
  230. // Check that A is a valid node in the tree.
  231. auto a_itr = nodes_.find(a);
  232. if (a_itr == nodes_.end()) return nullptr;
  233. const DominatorTreeNode* node = &a_itr->second;
  234. if (node->parent_ == nullptr) {
  235. return nullptr;
  236. }
  237. return node->parent_->bb_;
  238. }
  239. DominatorTreeNode* DominatorTree::GetOrInsertNode(BasicBlock* bb) {
  240. DominatorTreeNode* dtn = nullptr;
  241. std::map<uint32_t, DominatorTreeNode>::iterator node_iter =
  242. nodes_.find(bb->id());
  243. if (node_iter == nodes_.end()) {
  244. dtn = &nodes_.emplace(std::make_pair(bb->id(), DominatorTreeNode{bb}))
  245. .first->second;
  246. } else {
  247. dtn = &node_iter->second;
  248. }
  249. return dtn;
  250. }
  251. void DominatorTree::GetDominatorEdges(
  252. const Function* f, const BasicBlock* dummy_start_node,
  253. std::vector<std::pair<BasicBlock*, BasicBlock*>>* edges) {
  254. // Each time the depth first traversal calls the postorder callback
  255. // std::function we push that node into the postorder vector to create our
  256. // postorder list.
  257. std::vector<const BasicBlock*> postorder;
  258. auto postorder_function = [&](const BasicBlock* b) {
  259. postorder.push_back(b);
  260. };
  261. // CFA::CalculateDominators requires std::vector<BasicBlock*>
  262. // BB are derived from F, so we need to const cast it at some point
  263. // no modification is made on F.
  264. BasicBlockSuccessorHelper<BasicBlock> helper{
  265. *const_cast<Function*>(f), dummy_start_node, postdominator_};
  266. // The successor function tells DepthFirstTraversal how to move to successive
  267. // nodes by providing an interface to get a list of successor nodes from any
  268. // given node.
  269. auto successor_functor = helper.GetSuccessorFunctor();
  270. // The predecessor functor does the same as the successor functor
  271. // but for all nodes preceding a given node.
  272. auto predecessor_functor = helper.GetPredFunctor();
  273. // If we're building a post dominator tree we traverse the tree in reverse
  274. // using the predecessor function in place of the successor function and vice
  275. // versa.
  276. DepthFirstSearchPostOrder(dummy_start_node, successor_functor,
  277. postorder_function);
  278. *edges = CFA<BasicBlock>::CalculateDominators(postorder, predecessor_functor);
  279. }
  280. void DominatorTree::InitializeTree(const CFG& cfg, const Function* f) {
  281. ClearTree();
  282. // Skip over empty functions.
  283. if (f->cbegin() == f->cend()) {
  284. return;
  285. }
  286. const BasicBlock* dummy_start_node =
  287. postdominator_ ? cfg.pseudo_exit_block() : cfg.pseudo_entry_block();
  288. // Get the immediate dominator for each node.
  289. std::vector<std::pair<BasicBlock*, BasicBlock*>> edges;
  290. GetDominatorEdges(f, dummy_start_node, &edges);
  291. // Transform the vector<pair> into the tree structure which we can use to
  292. // efficiently query dominance.
  293. for (auto edge : edges) {
  294. DominatorTreeNode* first = GetOrInsertNode(edge.first);
  295. if (edge.first == edge.second) {
  296. if (std::find(roots_.begin(), roots_.end(), first) == roots_.end())
  297. roots_.push_back(first);
  298. continue;
  299. }
  300. DominatorTreeNode* second = GetOrInsertNode(edge.second);
  301. first->parent_ = second;
  302. second->children_.push_back(first);
  303. }
  304. ResetDFNumbering();
  305. }
  306. void DominatorTree::ResetDFNumbering() {
  307. int index = 0;
  308. auto preFunc = [&index](const DominatorTreeNode* node) {
  309. const_cast<DominatorTreeNode*>(node)->dfs_num_pre_ = ++index;
  310. };
  311. auto postFunc = [&index](const DominatorTreeNode* node) {
  312. const_cast<DominatorTreeNode*>(node)->dfs_num_post_ = ++index;
  313. };
  314. auto getSucc = [](const DominatorTreeNode* node) { return &node->children_; };
  315. for (auto root : roots_) DepthFirstSearch(root, getSucc, preFunc, postFunc);
  316. }
  317. void DominatorTree::DumpTreeAsDot(std::ostream& out_stream) const {
  318. out_stream << "digraph {\n";
  319. Visit([&out_stream](const DominatorTreeNode* node) {
  320. // Print the node.
  321. if (node->bb_) {
  322. out_stream << node->bb_->id() << "[label=\"" << node->bb_->id()
  323. << "\"];\n";
  324. }
  325. // Print the arrow from the parent to this node. Entry nodes will not have
  326. // parents so draw them as children from the dummy node.
  327. if (node->parent_) {
  328. out_stream << node->parent_->bb_->id() << " -> " << node->bb_->id()
  329. << ";\n";
  330. }
  331. // Return true to continue the traversal.
  332. return true;
  333. });
  334. out_stream << "}\n";
  335. }
  336. } // namespace opt
  337. } // namespace spvtools