xref: /aosp_15_r20/external/mesa3d/src/amd/compiler/aco_dominance.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2018 Valve Corporation
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker  */
6*61046927SAndroid Build Coastguard Worker 
7*61046927SAndroid Build Coastguard Worker #ifndef ACO_DOMINANCE_CPP
8*61046927SAndroid Build Coastguard Worker #define ACO_DOMINANCE_CPP
9*61046927SAndroid Build Coastguard Worker 
10*61046927SAndroid Build Coastguard Worker #include "aco_ir.h"
11*61046927SAndroid Build Coastguard Worker 
12*61046927SAndroid Build Coastguard Worker /*
13*61046927SAndroid Build Coastguard Worker  * Implements the algorithms for computing the dominator tree from
14*61046927SAndroid Build Coastguard Worker  * "A Simple, Fast Dominance Algorithm" by Cooper, Harvey, and Kennedy.
15*61046927SAndroid Build Coastguard Worker  *
16*61046927SAndroid Build Coastguard Worker  * Different from the paper, our CFG allows to compute the dominator tree
17*61046927SAndroid Build Coastguard Worker  * in a single pass as it is guaranteed that the dominating predecessors
18*61046927SAndroid Build Coastguard Worker  * are processed before the current block.
19*61046927SAndroid Build Coastguard Worker  */
20*61046927SAndroid Build Coastguard Worker 
21*61046927SAndroid Build Coastguard Worker namespace aco {
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker namespace {
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker struct block_dom_info {
26*61046927SAndroid Build Coastguard Worker    uint32_t logical_descendants = 0;
27*61046927SAndroid Build Coastguard Worker    uint32_t linear_descendants = 0;
28*61046927SAndroid Build Coastguard Worker    uint32_t logical_depth = 0;
29*61046927SAndroid Build Coastguard Worker    uint32_t linear_depth = 0;
30*61046927SAndroid Build Coastguard Worker    small_vec<uint32_t, 4> logical_children;
31*61046927SAndroid Build Coastguard Worker    small_vec<uint32_t, 4> linear_children;
32*61046927SAndroid Build Coastguard Worker };
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker void
calc_indices(Program * program)35*61046927SAndroid Build Coastguard Worker calc_indices(Program* program)
36*61046927SAndroid Build Coastguard Worker {
37*61046927SAndroid Build Coastguard Worker    std::vector<block_dom_info> info(program->blocks.size());
38*61046927SAndroid Build Coastguard Worker 
39*61046927SAndroid Build Coastguard Worker    /* Create the linear and logical dominance trees. Calculating logical_descendants and
40*61046927SAndroid Build Coastguard Worker     * linear_descendants requires no recursion because the immediate dominator of each block has a
41*61046927SAndroid Build Coastguard Worker     * lower index. */
42*61046927SAndroid Build Coastguard Worker    for (int i = program->blocks.size() - 1; i >= 0; i--) {
43*61046927SAndroid Build Coastguard Worker       Block& block = program->blocks[i];
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker       /* Add this as a child node of the parent. */
46*61046927SAndroid Build Coastguard Worker       if (block.logical_idom != i && block.logical_idom != -1) {
47*61046927SAndroid Build Coastguard Worker          assert(i > block.logical_idom);
48*61046927SAndroid Build Coastguard Worker          info[block.logical_idom].logical_children.push_back(i);
49*61046927SAndroid Build Coastguard Worker          /* Add this node's descendants and itself to the parent. */
50*61046927SAndroid Build Coastguard Worker          info[block.logical_idom].logical_descendants += info[i].logical_descendants + 1;
51*61046927SAndroid Build Coastguard Worker       }
52*61046927SAndroid Build Coastguard Worker       if (block.linear_idom != i) {
53*61046927SAndroid Build Coastguard Worker          assert(i > block.linear_idom);
54*61046927SAndroid Build Coastguard Worker          info[block.linear_idom].linear_children.push_back(i);
55*61046927SAndroid Build Coastguard Worker          info[block.linear_idom].linear_descendants += info[i].linear_descendants + 1;
56*61046927SAndroid Build Coastguard Worker       }
57*61046927SAndroid Build Coastguard Worker    }
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker    /* Fill in the indices that would be obtained in a preorder and postorder traversal of the
60*61046927SAndroid Build Coastguard Worker     * dominance trees. */
61*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < program->blocks.size(); i++) {
62*61046927SAndroid Build Coastguard Worker       Block& block = program->blocks[i];
63*61046927SAndroid Build Coastguard Worker       /* Because of block_kind_resume, the root node's indices start at the block index to avoid
64*61046927SAndroid Build Coastguard Worker        * reusing indices. */
65*61046927SAndroid Build Coastguard Worker       if (block.logical_idom == (int)i)
66*61046927SAndroid Build Coastguard Worker          block.logical_dom_pre_index = i;
67*61046927SAndroid Build Coastguard Worker       if (block.linear_idom == (int)i)
68*61046927SAndroid Build Coastguard Worker          block.linear_dom_pre_index = i;
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker       /* Visit each child and assign it's preorder indices and depth. */
71*61046927SAndroid Build Coastguard Worker       unsigned start = block.logical_dom_pre_index + 1;
72*61046927SAndroid Build Coastguard Worker       for (unsigned j = 0; j < info[i].logical_children.size(); j++) {
73*61046927SAndroid Build Coastguard Worker          unsigned child = info[i].logical_children[j];
74*61046927SAndroid Build Coastguard Worker          info[child].logical_depth = info[i].logical_depth + 1;
75*61046927SAndroid Build Coastguard Worker          program->blocks[child].logical_dom_pre_index = start;
76*61046927SAndroid Build Coastguard Worker          start += info[child].logical_descendants + 1;
77*61046927SAndroid Build Coastguard Worker       }
78*61046927SAndroid Build Coastguard Worker       start = block.linear_dom_pre_index + 1;
79*61046927SAndroid Build Coastguard Worker       for (unsigned j = 0; j < info[i].linear_children.size(); j++) {
80*61046927SAndroid Build Coastguard Worker          unsigned child = info[i].linear_children[j];
81*61046927SAndroid Build Coastguard Worker          info[child].linear_depth = info[i].linear_depth + 1;
82*61046927SAndroid Build Coastguard Worker          program->blocks[child].linear_dom_pre_index = start;
83*61046927SAndroid Build Coastguard Worker          start += info[child].linear_descendants + 1;
84*61046927SAndroid Build Coastguard Worker       }
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker       /* The postorder traversal is the same as the preorder traversal, except that when this block
87*61046927SAndroid Build Coastguard Worker        * is visited, we haven't visited it's ancestors and have already visited it's descendants.
88*61046927SAndroid Build Coastguard Worker        * This means that the postorder_index is preorder_index-depth+descendants. */
89*61046927SAndroid Build Coastguard Worker       block.logical_dom_post_index =
90*61046927SAndroid Build Coastguard Worker          block.logical_dom_pre_index - info[i].logical_depth + info[i].logical_descendants;
91*61046927SAndroid Build Coastguard Worker       block.linear_dom_post_index =
92*61046927SAndroid Build Coastguard Worker          block.linear_dom_pre_index - info[i].linear_depth + info[i].linear_descendants;
93*61046927SAndroid Build Coastguard Worker    }
94*61046927SAndroid Build Coastguard Worker }
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker } /* end namespace */
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker void
dominator_tree(Program * program)99*61046927SAndroid Build Coastguard Worker dominator_tree(Program* program)
100*61046927SAndroid Build Coastguard Worker {
101*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < program->blocks.size(); i++) {
102*61046927SAndroid Build Coastguard Worker       Block& block = program->blocks[i];
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker       /* If this block has no predecessor, it dominates itself by definition */
105*61046927SAndroid Build Coastguard Worker       if (block.linear_preds.empty()) {
106*61046927SAndroid Build Coastguard Worker          block.linear_idom = block.index;
107*61046927SAndroid Build Coastguard Worker          block.logical_idom = block.index;
108*61046927SAndroid Build Coastguard Worker          continue;
109*61046927SAndroid Build Coastguard Worker       }
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker       int new_logical_idom = -1;
112*61046927SAndroid Build Coastguard Worker       int new_linear_idom = -1;
113*61046927SAndroid Build Coastguard Worker       for (unsigned pred_idx : block.logical_preds) {
114*61046927SAndroid Build Coastguard Worker          if ((int)program->blocks[pred_idx].logical_idom == -1)
115*61046927SAndroid Build Coastguard Worker             continue;
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker          if (new_logical_idom == -1) {
118*61046927SAndroid Build Coastguard Worker             new_logical_idom = pred_idx;
119*61046927SAndroid Build Coastguard Worker             continue;
120*61046927SAndroid Build Coastguard Worker          }
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker          while ((int)pred_idx != new_logical_idom) {
123*61046927SAndroid Build Coastguard Worker             if ((int)pred_idx > new_logical_idom)
124*61046927SAndroid Build Coastguard Worker                pred_idx = program->blocks[pred_idx].logical_idom;
125*61046927SAndroid Build Coastguard Worker             if ((int)pred_idx < new_logical_idom)
126*61046927SAndroid Build Coastguard Worker                new_logical_idom = program->blocks[new_logical_idom].logical_idom;
127*61046927SAndroid Build Coastguard Worker          }
128*61046927SAndroid Build Coastguard Worker       }
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker       for (unsigned pred_idx : block.linear_preds) {
131*61046927SAndroid Build Coastguard Worker          if ((int)program->blocks[pred_idx].linear_idom == -1)
132*61046927SAndroid Build Coastguard Worker             continue;
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker          if (new_linear_idom == -1) {
135*61046927SAndroid Build Coastguard Worker             new_linear_idom = pred_idx;
136*61046927SAndroid Build Coastguard Worker             continue;
137*61046927SAndroid Build Coastguard Worker          }
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker          while ((int)pred_idx != new_linear_idom) {
140*61046927SAndroid Build Coastguard Worker             if ((int)pred_idx > new_linear_idom)
141*61046927SAndroid Build Coastguard Worker                pred_idx = program->blocks[pred_idx].linear_idom;
142*61046927SAndroid Build Coastguard Worker             if ((int)pred_idx < new_linear_idom)
143*61046927SAndroid Build Coastguard Worker                new_linear_idom = program->blocks[new_linear_idom].linear_idom;
144*61046927SAndroid Build Coastguard Worker          }
145*61046927SAndroid Build Coastguard Worker       }
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker       block.logical_idom = new_logical_idom;
148*61046927SAndroid Build Coastguard Worker       block.linear_idom = new_linear_idom;
149*61046927SAndroid Build Coastguard Worker    }
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker    calc_indices(program);
152*61046927SAndroid Build Coastguard Worker }
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker } // namespace aco
155*61046927SAndroid Build Coastguard Worker #endif
156