xref: /aosp_15_r20/external/mesa3d/src/freedreno/ir3/ir3_dominance.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2014 Intel Corporation
3*61046927SAndroid Build Coastguard Worker  * Copyright © 2021 Valve Corporation
4*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker  *
6*61046927SAndroid Build Coastguard Worker  */
7*61046927SAndroid Build Coastguard Worker 
8*61046927SAndroid Build Coastguard Worker #include "ir3.h"
9*61046927SAndroid Build Coastguard Worker #include "util/ralloc.h"
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker /*
12*61046927SAndroid Build Coastguard Worker  * Implements the algorithms for computing the dominance tree and the
13*61046927SAndroid Build Coastguard Worker  * dominance frontier from "A Simple, Fast Dominance Algorithm" by Cooper,
14*61046927SAndroid Build Coastguard Worker  * Harvey, and Kennedy.
15*61046927SAndroid Build Coastguard Worker  */
16*61046927SAndroid Build Coastguard Worker 
17*61046927SAndroid Build Coastguard Worker static struct ir3_block *
intersect(struct ir3_block * b1,struct ir3_block * b2)18*61046927SAndroid Build Coastguard Worker intersect(struct ir3_block *b1, struct ir3_block *b2)
19*61046927SAndroid Build Coastguard Worker {
20*61046927SAndroid Build Coastguard Worker    while (b1 != b2) {
21*61046927SAndroid Build Coastguard Worker       /*
22*61046927SAndroid Build Coastguard Worker        * Note, the comparisons here are the opposite of what the paper says
23*61046927SAndroid Build Coastguard Worker        * because we index blocks from beginning -> end (i.e. reverse
24*61046927SAndroid Build Coastguard Worker        * post-order) instead of post-order like they assume.
25*61046927SAndroid Build Coastguard Worker        */
26*61046927SAndroid Build Coastguard Worker       while (b1->index > b2->index)
27*61046927SAndroid Build Coastguard Worker          b1 = b1->imm_dom;
28*61046927SAndroid Build Coastguard Worker       while (b2->index > b1->index)
29*61046927SAndroid Build Coastguard Worker          b2 = b2->imm_dom;
30*61046927SAndroid Build Coastguard Worker    }
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker    return b1;
33*61046927SAndroid Build Coastguard Worker }
34*61046927SAndroid Build Coastguard Worker 
35*61046927SAndroid Build Coastguard Worker static bool
calc_dominance(struct ir3_block * block)36*61046927SAndroid Build Coastguard Worker calc_dominance(struct ir3_block *block)
37*61046927SAndroid Build Coastguard Worker {
38*61046927SAndroid Build Coastguard Worker    struct ir3_block *new_idom = NULL;
39*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
40*61046927SAndroid Build Coastguard Worker       struct ir3_block *pred = block->predecessors[i];
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker       if (pred->imm_dom) {
43*61046927SAndroid Build Coastguard Worker          if (new_idom)
44*61046927SAndroid Build Coastguard Worker             new_idom = intersect(pred, new_idom);
45*61046927SAndroid Build Coastguard Worker          else
46*61046927SAndroid Build Coastguard Worker             new_idom = pred;
47*61046927SAndroid Build Coastguard Worker       }
48*61046927SAndroid Build Coastguard Worker    }
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker    if (block->imm_dom != new_idom) {
51*61046927SAndroid Build Coastguard Worker       block->imm_dom = new_idom;
52*61046927SAndroid Build Coastguard Worker       return true;
53*61046927SAndroid Build Coastguard Worker    }
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker    return false;
56*61046927SAndroid Build Coastguard Worker }
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker static unsigned
calc_dfs_indices(struct ir3_block * block,unsigned index)59*61046927SAndroid Build Coastguard Worker calc_dfs_indices(struct ir3_block *block, unsigned index)
60*61046927SAndroid Build Coastguard Worker {
61*61046927SAndroid Build Coastguard Worker    block->dom_pre_index = index++;
62*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->dom_children_count; i++)
63*61046927SAndroid Build Coastguard Worker       index = calc_dfs_indices(block->dom_children[i], index);
64*61046927SAndroid Build Coastguard Worker    block->dom_post_index = index++;
65*61046927SAndroid Build Coastguard Worker    return index;
66*61046927SAndroid Build Coastguard Worker }
67*61046927SAndroid Build Coastguard Worker 
68*61046927SAndroid Build Coastguard Worker void
ir3_calc_dominance(struct ir3 * ir)69*61046927SAndroid Build Coastguard Worker ir3_calc_dominance(struct ir3 *ir)
70*61046927SAndroid Build Coastguard Worker {
71*61046927SAndroid Build Coastguard Worker    unsigned i = 0;
72*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
73*61046927SAndroid Build Coastguard Worker       block->index = i++;
74*61046927SAndroid Build Coastguard Worker       if (block == ir3_start_block(ir))
75*61046927SAndroid Build Coastguard Worker          block->imm_dom = block;
76*61046927SAndroid Build Coastguard Worker       else
77*61046927SAndroid Build Coastguard Worker          block->imm_dom = NULL;
78*61046927SAndroid Build Coastguard Worker       block->dom_children = NULL;
79*61046927SAndroid Build Coastguard Worker       block->dom_children_count = block->dom_children_sz = 0;
80*61046927SAndroid Build Coastguard Worker    }
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker    bool progress = true;
83*61046927SAndroid Build Coastguard Worker    while (progress) {
84*61046927SAndroid Build Coastguard Worker       progress = false;
85*61046927SAndroid Build Coastguard Worker       foreach_block (block, &ir->block_list) {
86*61046927SAndroid Build Coastguard Worker          if (block != ir3_start_block(ir))
87*61046927SAndroid Build Coastguard Worker             progress |= calc_dominance(block);
88*61046927SAndroid Build Coastguard Worker       }
89*61046927SAndroid Build Coastguard Worker    }
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker    ir3_start_block(ir)->imm_dom = NULL;
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
94*61046927SAndroid Build Coastguard Worker       if (block->imm_dom)
95*61046927SAndroid Build Coastguard Worker          array_insert(block->imm_dom, block->imm_dom->dom_children, block);
96*61046927SAndroid Build Coastguard Worker    }
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker    calc_dfs_indices(ir3_start_block(ir), 0);
99*61046927SAndroid Build Coastguard Worker }
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker /* Return true if a dominates b. This includes if a == b. */
102*61046927SAndroid Build Coastguard Worker bool
ir3_block_dominates(struct ir3_block * a,struct ir3_block * b)103*61046927SAndroid Build Coastguard Worker ir3_block_dominates(struct ir3_block *a, struct ir3_block *b)
104*61046927SAndroid Build Coastguard Worker {
105*61046927SAndroid Build Coastguard Worker    return a->dom_pre_index <= b->dom_pre_index &&
106*61046927SAndroid Build Coastguard Worker           a->dom_post_index >= b->dom_post_index;
107*61046927SAndroid Build Coastguard Worker }
108