• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2018 Valve Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  */
24 
25 #ifndef ACO_DOMINANCE_CPP
26 #define ACO_DOMINANCE_CPP
27 
28 #include "aco_ir.h"
29 
30 /*
31  * Implements the algorithms for computing the dominator tree from
32  * "A Simple, Fast Dominance Algorithm" by Cooper, Harvey, and Kennedy.
33  *
34  * Different from the paper, our CFG allows to compute the dominator tree
35  * in a single pass as it is guaranteed that the dominating predecessors
36  * are processed before the current block.
37  */
38 
39 namespace aco {
40 
41 void
dominator_tree(Program * program)42 dominator_tree(Program* program)
43 {
44    for (unsigned i = 0; i < program->blocks.size(); i++) {
45       Block& block = program->blocks[i];
46 
47       /* If this block has no predecessor, it dominates itself by definition */
48       if (block.linear_preds.empty()) {
49          block.linear_idom = block.index;
50          block.logical_idom = block.index;
51          continue;
52       }
53 
54       int new_logical_idom = -1;
55       int new_linear_idom = -1;
56       for (unsigned pred_idx : block.logical_preds) {
57          if ((int)program->blocks[pred_idx].logical_idom == -1)
58             continue;
59 
60          if (new_logical_idom == -1) {
61             new_logical_idom = pred_idx;
62             continue;
63          }
64 
65          while ((int)pred_idx != new_logical_idom) {
66             if ((int)pred_idx > new_logical_idom)
67                pred_idx = program->blocks[pred_idx].logical_idom;
68             if ((int)pred_idx < new_logical_idom)
69                new_logical_idom = program->blocks[new_logical_idom].logical_idom;
70          }
71       }
72 
73       for (unsigned pred_idx : block.linear_preds) {
74          if ((int)program->blocks[pred_idx].linear_idom == -1)
75             continue;
76 
77          if (new_linear_idom == -1) {
78             new_linear_idom = pred_idx;
79             continue;
80          }
81 
82          while ((int)pred_idx != new_linear_idom) {
83             if ((int)pred_idx > new_linear_idom)
84                pred_idx = program->blocks[pred_idx].linear_idom;
85             if ((int)pred_idx < new_linear_idom)
86                new_linear_idom = program->blocks[new_linear_idom].linear_idom;
87          }
88       }
89 
90       block.logical_idom = new_logical_idom;
91       block.linear_idom = new_linear_idom;
92    }
93 }
94 
95 } // namespace aco
96 #endif
97