xref: /aosp_15_r20/external/mesa3d/src/compiler/nir/nir_liveness.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2014 Intel Corporation
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "nir.h"
25*61046927SAndroid Build Coastguard Worker #include "nir_vla.h"
26*61046927SAndroid Build Coastguard Worker #include "nir_worklist.h"
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker /*
29*61046927SAndroid Build Coastguard Worker  * Basic liveness analysis.  This works only in SSA form.
30*61046927SAndroid Build Coastguard Worker  *
31*61046927SAndroid Build Coastguard Worker  * This liveness pass treats phi nodes as being melded to the space between
32*61046927SAndroid Build Coastguard Worker  * blocks so that the destinations of a phi are in the livein of the block
33*61046927SAndroid Build Coastguard Worker  * in which it resides and the sources are in the liveout of the
34*61046927SAndroid Build Coastguard Worker  * corresponding block.  By formulating the liveness information in this
35*61046927SAndroid Build Coastguard Worker  * way, we ensure that the definition of any variable dominates its entire
36*61046927SAndroid Build Coastguard Worker  * live range.  This is true because the only way that the definition of an
37*61046927SAndroid Build Coastguard Worker  * SSA value may not dominate a use is if the use is in a phi node and the
38*61046927SAndroid Build Coastguard Worker  * uses in phi no are in the live-out of the corresponding predecessor
39*61046927SAndroid Build Coastguard Worker  * block but not in the live-in of the block containing the phi node.
40*61046927SAndroid Build Coastguard Worker  */
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker struct live_defs_state {
43*61046927SAndroid Build Coastguard Worker    unsigned bitset_words;
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker    /* Used in propagate_across_edge() */
46*61046927SAndroid Build Coastguard Worker    BITSET_WORD *tmp_live;
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker    nir_block_worklist worklist;
49*61046927SAndroid Build Coastguard Worker };
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker /* Initialize the liveness data to zero and add the given block to the
52*61046927SAndroid Build Coastguard Worker  * worklist.
53*61046927SAndroid Build Coastguard Worker  */
54*61046927SAndroid Build Coastguard Worker static void
init_liveness_block(nir_block * block,struct live_defs_state * state)55*61046927SAndroid Build Coastguard Worker init_liveness_block(nir_block *block,
56*61046927SAndroid Build Coastguard Worker                     struct live_defs_state *state)
57*61046927SAndroid Build Coastguard Worker {
58*61046927SAndroid Build Coastguard Worker    block->live_in = reralloc(block, block->live_in, BITSET_WORD,
59*61046927SAndroid Build Coastguard Worker                              state->bitset_words);
60*61046927SAndroid Build Coastguard Worker    memset(block->live_in, 0, state->bitset_words * sizeof(BITSET_WORD));
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker    block->live_out = reralloc(block, block->live_out, BITSET_WORD,
63*61046927SAndroid Build Coastguard Worker                               state->bitset_words);
64*61046927SAndroid Build Coastguard Worker    memset(block->live_out, 0, state->bitset_words * sizeof(BITSET_WORD));
65*61046927SAndroid Build Coastguard Worker 
66*61046927SAndroid Build Coastguard Worker    nir_block_worklist_push_head(&state->worklist, block);
67*61046927SAndroid Build Coastguard Worker }
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker static bool
set_src_live(nir_src * src,void * void_live)70*61046927SAndroid Build Coastguard Worker set_src_live(nir_src *src, void *void_live)
71*61046927SAndroid Build Coastguard Worker {
72*61046927SAndroid Build Coastguard Worker    BITSET_WORD *live = void_live;
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker    if (nir_src_is_undef(*src))
75*61046927SAndroid Build Coastguard Worker       return true; /* undefined variables are never live */
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker    BITSET_SET(live, src->ssa->index);
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker    return true;
80*61046927SAndroid Build Coastguard Worker }
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker static bool
set_ssa_def_dead(nir_def * def,void * void_live)83*61046927SAndroid Build Coastguard Worker set_ssa_def_dead(nir_def *def, void *void_live)
84*61046927SAndroid Build Coastguard Worker {
85*61046927SAndroid Build Coastguard Worker    BITSET_WORD *live = void_live;
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker    BITSET_CLEAR(live, def->index);
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker    return true;
90*61046927SAndroid Build Coastguard Worker }
91*61046927SAndroid Build Coastguard Worker 
92*61046927SAndroid Build Coastguard Worker /** Propagates the live in of succ across the edge to the live out of pred
93*61046927SAndroid Build Coastguard Worker  *
94*61046927SAndroid Build Coastguard Worker  * Phi nodes exist "between" blocks and all the phi nodes at the start of a
95*61046927SAndroid Build Coastguard Worker  * block act "in parallel".  When we propagate from the live_in of one
96*61046927SAndroid Build Coastguard Worker  * block to the live out of the other, we have to kill any writes from phis
97*61046927SAndroid Build Coastguard Worker  * and make live any sources.
98*61046927SAndroid Build Coastguard Worker  *
99*61046927SAndroid Build Coastguard Worker  * Returns true if updating live out of pred added anything
100*61046927SAndroid Build Coastguard Worker  */
101*61046927SAndroid Build Coastguard Worker static bool
propagate_across_edge(nir_block * pred,nir_block * succ,struct live_defs_state * state)102*61046927SAndroid Build Coastguard Worker propagate_across_edge(nir_block *pred, nir_block *succ,
103*61046927SAndroid Build Coastguard Worker                       struct live_defs_state *state)
104*61046927SAndroid Build Coastguard Worker {
105*61046927SAndroid Build Coastguard Worker    BITSET_WORD *live = state->tmp_live;
106*61046927SAndroid Build Coastguard Worker    memcpy(live, succ->live_in, state->bitset_words * sizeof *live);
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker    nir_foreach_phi(phi, succ) {
109*61046927SAndroid Build Coastguard Worker       set_ssa_def_dead(&phi->def, live);
110*61046927SAndroid Build Coastguard Worker    }
111*61046927SAndroid Build Coastguard Worker 
112*61046927SAndroid Build Coastguard Worker    nir_foreach_phi(phi, succ) {
113*61046927SAndroid Build Coastguard Worker       nir_foreach_phi_src(src, phi) {
114*61046927SAndroid Build Coastguard Worker          if (src->pred == pred) {
115*61046927SAndroid Build Coastguard Worker             set_src_live(&src->src, live);
116*61046927SAndroid Build Coastguard Worker             break;
117*61046927SAndroid Build Coastguard Worker          }
118*61046927SAndroid Build Coastguard Worker       }
119*61046927SAndroid Build Coastguard Worker    }
120*61046927SAndroid Build Coastguard Worker 
121*61046927SAndroid Build Coastguard Worker    BITSET_WORD progress = 0;
122*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < state->bitset_words; ++i) {
123*61046927SAndroid Build Coastguard Worker       progress |= live[i] & ~pred->live_out[i];
124*61046927SAndroid Build Coastguard Worker       pred->live_out[i] |= live[i];
125*61046927SAndroid Build Coastguard Worker    }
126*61046927SAndroid Build Coastguard Worker    return progress != 0;
127*61046927SAndroid Build Coastguard Worker }
128*61046927SAndroid Build Coastguard Worker 
129*61046927SAndroid Build Coastguard Worker void
nir_live_defs_impl(nir_function_impl * impl)130*61046927SAndroid Build Coastguard Worker nir_live_defs_impl(nir_function_impl *impl)
131*61046927SAndroid Build Coastguard Worker {
132*61046927SAndroid Build Coastguard Worker    struct live_defs_state state = {
133*61046927SAndroid Build Coastguard Worker       .bitset_words = BITSET_WORDS(impl->ssa_alloc),
134*61046927SAndroid Build Coastguard Worker    };
135*61046927SAndroid Build Coastguard Worker    state.tmp_live = rzalloc_array(impl, BITSET_WORD, state.bitset_words),
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker    /* Number the instructions so we can do cheap interference tests using the
138*61046927SAndroid Build Coastguard Worker     * instruction index.
139*61046927SAndroid Build Coastguard Worker     */
140*61046927SAndroid Build Coastguard Worker       nir_metadata_require(impl, nir_metadata_instr_index);
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker    nir_block_worklist_init(&state.worklist, impl->num_blocks, NULL);
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker    /* Allocate live_in and live_out sets and add all of the blocks to the
145*61046927SAndroid Build Coastguard Worker     * worklist.
146*61046927SAndroid Build Coastguard Worker     */
147*61046927SAndroid Build Coastguard Worker    nir_foreach_block(block, impl) {
148*61046927SAndroid Build Coastguard Worker       init_liveness_block(block, &state);
149*61046927SAndroid Build Coastguard Worker    }
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker    /* We're now ready to work through the worklist and update the liveness
152*61046927SAndroid Build Coastguard Worker     * sets of each of the blocks.  By the time we get to this point, every
153*61046927SAndroid Build Coastguard Worker     * block in the function implementation has been pushed onto the
154*61046927SAndroid Build Coastguard Worker     * worklist in reverse order.  As long as we keep the worklist
155*61046927SAndroid Build Coastguard Worker     * up-to-date as we go, everything will get covered.
156*61046927SAndroid Build Coastguard Worker     */
157*61046927SAndroid Build Coastguard Worker    while (!nir_block_worklist_is_empty(&state.worklist)) {
158*61046927SAndroid Build Coastguard Worker       /* We pop them off in the reverse order we pushed them on.  This way
159*61046927SAndroid Build Coastguard Worker        * the first walk of the instructions is backwards so we only walk
160*61046927SAndroid Build Coastguard Worker        * once in the case of no control flow.
161*61046927SAndroid Build Coastguard Worker        */
162*61046927SAndroid Build Coastguard Worker       nir_block *block = nir_block_worklist_pop_head(&state.worklist);
163*61046927SAndroid Build Coastguard Worker 
164*61046927SAndroid Build Coastguard Worker       memcpy(block->live_in, block->live_out,
165*61046927SAndroid Build Coastguard Worker              state.bitset_words * sizeof(BITSET_WORD));
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker       nir_if *following_if = nir_block_get_following_if(block);
168*61046927SAndroid Build Coastguard Worker       if (following_if)
169*61046927SAndroid Build Coastguard Worker          set_src_live(&following_if->condition, block->live_in);
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker       nir_foreach_instr_reverse(instr, block) {
172*61046927SAndroid Build Coastguard Worker          /* Phi nodes are handled seperately so we want to skip them.  Since
173*61046927SAndroid Build Coastguard Worker           * we are going backwards and they are at the beginning, we can just
174*61046927SAndroid Build Coastguard Worker           * break as soon as we see one.
175*61046927SAndroid Build Coastguard Worker           */
176*61046927SAndroid Build Coastguard Worker          if (instr->type == nir_instr_type_phi)
177*61046927SAndroid Build Coastguard Worker             break;
178*61046927SAndroid Build Coastguard Worker 
179*61046927SAndroid Build Coastguard Worker          nir_foreach_def(instr, set_ssa_def_dead, block->live_in);
180*61046927SAndroid Build Coastguard Worker          nir_foreach_src(instr, set_src_live, block->live_in);
181*61046927SAndroid Build Coastguard Worker       }
182*61046927SAndroid Build Coastguard Worker 
183*61046927SAndroid Build Coastguard Worker       /* Walk over all of the predecessors of the current block updating
184*61046927SAndroid Build Coastguard Worker        * their live in with the live out of this one.  If anything has
185*61046927SAndroid Build Coastguard Worker        * changed, add the predecessor to the work list so that we ensure
186*61046927SAndroid Build Coastguard Worker        * that the new information is used.
187*61046927SAndroid Build Coastguard Worker        */
188*61046927SAndroid Build Coastguard Worker       set_foreach(block->predecessors, entry) {
189*61046927SAndroid Build Coastguard Worker          nir_block *pred = (nir_block *)entry->key;
190*61046927SAndroid Build Coastguard Worker          if (propagate_across_edge(pred, block, &state))
191*61046927SAndroid Build Coastguard Worker             nir_block_worklist_push_tail(&state.worklist, pred);
192*61046927SAndroid Build Coastguard Worker       }
193*61046927SAndroid Build Coastguard Worker    }
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker    ralloc_free(state.tmp_live);
196*61046927SAndroid Build Coastguard Worker    nir_block_worklist_fini(&state.worklist);
197*61046927SAndroid Build Coastguard Worker }
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker /** Return the live set at a cursor
200*61046927SAndroid Build Coastguard Worker  *
201*61046927SAndroid Build Coastguard Worker  * Note: The bitset returned may be the live_in or live_out from the block in
202*61046927SAndroid Build Coastguard Worker  *       which the instruction lives.  Do not ralloc_free() it directly;
203*61046927SAndroid Build Coastguard Worker  *       instead, provide a mem_ctx and free that.
204*61046927SAndroid Build Coastguard Worker  */
205*61046927SAndroid Build Coastguard Worker const BITSET_WORD *
nir_get_live_defs(nir_cursor cursor,void * mem_ctx)206*61046927SAndroid Build Coastguard Worker nir_get_live_defs(nir_cursor cursor, void *mem_ctx)
207*61046927SAndroid Build Coastguard Worker {
208*61046927SAndroid Build Coastguard Worker    nir_block *block = nir_cursor_current_block(cursor);
209*61046927SAndroid Build Coastguard Worker    nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
210*61046927SAndroid Build Coastguard Worker    assert(impl->valid_metadata & nir_metadata_live_defs);
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker    switch (cursor.option) {
213*61046927SAndroid Build Coastguard Worker    case nir_cursor_before_block:
214*61046927SAndroid Build Coastguard Worker       return cursor.block->live_in;
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker    case nir_cursor_after_block:
217*61046927SAndroid Build Coastguard Worker       return cursor.block->live_out;
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    case nir_cursor_before_instr:
220*61046927SAndroid Build Coastguard Worker       if (cursor.instr == nir_block_first_instr(cursor.instr->block))
221*61046927SAndroid Build Coastguard Worker          return cursor.instr->block->live_in;
222*61046927SAndroid Build Coastguard Worker       break;
223*61046927SAndroid Build Coastguard Worker 
224*61046927SAndroid Build Coastguard Worker    case nir_cursor_after_instr:
225*61046927SAndroid Build Coastguard Worker       if (cursor.instr == nir_block_last_instr(cursor.instr->block))
226*61046927SAndroid Build Coastguard Worker          return cursor.instr->block->live_out;
227*61046927SAndroid Build Coastguard Worker       break;
228*61046927SAndroid Build Coastguard Worker    }
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker    /* If we got here, we're an instruction cursor mid-block */
231*61046927SAndroid Build Coastguard Worker    const unsigned bitset_words = BITSET_WORDS(impl->ssa_alloc);
232*61046927SAndroid Build Coastguard Worker    BITSET_WORD *live = ralloc_array(mem_ctx, BITSET_WORD, bitset_words);
233*61046927SAndroid Build Coastguard Worker    memcpy(live, block->live_out, bitset_words * sizeof(BITSET_WORD));
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker    nir_foreach_instr_reverse(instr, block) {
236*61046927SAndroid Build Coastguard Worker       if (cursor.option == nir_cursor_after_instr && instr == cursor.instr)
237*61046927SAndroid Build Coastguard Worker          break;
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker       /* If someone asked for liveness in the middle of a bunch of phis,
240*61046927SAndroid Build Coastguard Worker        * that's an error.  Since we are going backwards and they are at the
241*61046927SAndroid Build Coastguard Worker        * beginning, we can just blow up as soon as we see one.
242*61046927SAndroid Build Coastguard Worker        */
243*61046927SAndroid Build Coastguard Worker       assert(instr->type != nir_instr_type_phi);
244*61046927SAndroid Build Coastguard Worker       if (instr->type == nir_instr_type_phi)
245*61046927SAndroid Build Coastguard Worker          break;
246*61046927SAndroid Build Coastguard Worker 
247*61046927SAndroid Build Coastguard Worker       nir_foreach_def(instr, set_ssa_def_dead, live);
248*61046927SAndroid Build Coastguard Worker       nir_foreach_src(instr, set_src_live, live);
249*61046927SAndroid Build Coastguard Worker 
250*61046927SAndroid Build Coastguard Worker       if (cursor.option == nir_cursor_before_instr && instr == cursor.instr)
251*61046927SAndroid Build Coastguard Worker          break;
252*61046927SAndroid Build Coastguard Worker    }
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker    return live;
255*61046927SAndroid Build Coastguard Worker }
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker static bool
src_does_not_use_def(nir_src * src,void * def)258*61046927SAndroid Build Coastguard Worker src_does_not_use_def(nir_src *src, void *def)
259*61046927SAndroid Build Coastguard Worker {
260*61046927SAndroid Build Coastguard Worker    return src->ssa != (nir_def *)def;
261*61046927SAndroid Build Coastguard Worker }
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker static bool
search_for_use_after_instr(nir_instr * start,nir_def * def)264*61046927SAndroid Build Coastguard Worker search_for_use_after_instr(nir_instr *start, nir_def *def)
265*61046927SAndroid Build Coastguard Worker {
266*61046927SAndroid Build Coastguard Worker    /* Only look for a use strictly after the given instruction */
267*61046927SAndroid Build Coastguard Worker    struct exec_node *node = start->node.next;
268*61046927SAndroid Build Coastguard Worker    while (!exec_node_is_tail_sentinel(node)) {
269*61046927SAndroid Build Coastguard Worker       nir_instr *instr = exec_node_data(nir_instr, node, node);
270*61046927SAndroid Build Coastguard Worker       if (!nir_foreach_src(instr, src_does_not_use_def, def))
271*61046927SAndroid Build Coastguard Worker          return true;
272*61046927SAndroid Build Coastguard Worker       node = node->next;
273*61046927SAndroid Build Coastguard Worker    }
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker    /* If uses are considered to be in the block immediately preceding the if
276*61046927SAndroid Build Coastguard Worker     * so we need to also check the following if condition, if any.
277*61046927SAndroid Build Coastguard Worker     */
278*61046927SAndroid Build Coastguard Worker    nir_if *following_if = nir_block_get_following_if(start->block);
279*61046927SAndroid Build Coastguard Worker    if (following_if && following_if->condition.ssa == def)
280*61046927SAndroid Build Coastguard Worker       return true;
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker    return false;
283*61046927SAndroid Build Coastguard Worker }
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker /* Returns true if def is live at instr assuming that def comes before
286*61046927SAndroid Build Coastguard Worker  * instr in a pre DFS search of the dominance tree.
287*61046927SAndroid Build Coastguard Worker  */
288*61046927SAndroid Build Coastguard Worker static bool
nir_def_is_live_at(nir_def * def,nir_instr * instr)289*61046927SAndroid Build Coastguard Worker nir_def_is_live_at(nir_def *def, nir_instr *instr)
290*61046927SAndroid Build Coastguard Worker {
291*61046927SAndroid Build Coastguard Worker    if (BITSET_TEST(instr->block->live_out, def->index)) {
292*61046927SAndroid Build Coastguard Worker       /* Since def dominates instr, if def is in the liveout of the block,
293*61046927SAndroid Build Coastguard Worker        * it's live at instr
294*61046927SAndroid Build Coastguard Worker        */
295*61046927SAndroid Build Coastguard Worker       return true;
296*61046927SAndroid Build Coastguard Worker    } else {
297*61046927SAndroid Build Coastguard Worker       if (BITSET_TEST(instr->block->live_in, def->index) ||
298*61046927SAndroid Build Coastguard Worker           def->parent_instr->block == instr->block) {
299*61046927SAndroid Build Coastguard Worker          /* In this case it is either live coming into instr's block or it
300*61046927SAndroid Build Coastguard Worker           * is defined in the same block.  In this case, we simply need to
301*61046927SAndroid Build Coastguard Worker           * see if it is used after instr.
302*61046927SAndroid Build Coastguard Worker           */
303*61046927SAndroid Build Coastguard Worker          return search_for_use_after_instr(instr, def);
304*61046927SAndroid Build Coastguard Worker       } else {
305*61046927SAndroid Build Coastguard Worker          return false;
306*61046927SAndroid Build Coastguard Worker       }
307*61046927SAndroid Build Coastguard Worker    }
308*61046927SAndroid Build Coastguard Worker }
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker bool
nir_defs_interfere(nir_def * a,nir_def * b)311*61046927SAndroid Build Coastguard Worker nir_defs_interfere(nir_def *a, nir_def *b)
312*61046927SAndroid Build Coastguard Worker {
313*61046927SAndroid Build Coastguard Worker    if (a->parent_instr == b->parent_instr) {
314*61046927SAndroid Build Coastguard Worker       /* Two variables defined at the same time interfere assuming at
315*61046927SAndroid Build Coastguard Worker        * least one isn't dead.
316*61046927SAndroid Build Coastguard Worker        */
317*61046927SAndroid Build Coastguard Worker       return true;
318*61046927SAndroid Build Coastguard Worker    } else if (a->parent_instr->type == nir_instr_type_undef ||
319*61046927SAndroid Build Coastguard Worker               b->parent_instr->type == nir_instr_type_undef) {
320*61046927SAndroid Build Coastguard Worker       /* If either variable is an ssa_undef, then there's no interference */
321*61046927SAndroid Build Coastguard Worker       return false;
322*61046927SAndroid Build Coastguard Worker    } else if (a->parent_instr->index < b->parent_instr->index) {
323*61046927SAndroid Build Coastguard Worker       return nir_def_is_live_at(a, b->parent_instr);
324*61046927SAndroid Build Coastguard Worker    } else {
325*61046927SAndroid Build Coastguard Worker       return nir_def_is_live_at(b, a->parent_instr);
326*61046927SAndroid Build Coastguard Worker    }
327*61046927SAndroid Build Coastguard Worker }
328