~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/compiler/nir/nir_opt_dead_cf.c

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

Lines of Context:
83
83
static void
84
84
opt_constant_if(nir_if *if_stmt, bool condition)
85
85
{
86
 
   /* First, we need to remove any phi nodes after the if by rewriting uses to
87
 
    * point to the correct source.
88
 
    */
89
 
   nir_block *after = nir_cf_node_as_block(nir_cf_node_next(&if_stmt->cf_node));
90
86
   nir_block *last_block = condition ? nir_if_last_then_block(if_stmt)
91
87
                                     : nir_if_last_else_block(if_stmt);
92
88
 
93
 
   nir_foreach_instr_safe(instr, after) {
94
 
      if (instr->type != nir_instr_type_phi)
95
 
         break;
96
 
 
97
 
      nir_phi_instr *phi = nir_instr_as_phi(instr);
98
 
      nir_ssa_def *def = NULL;
99
 
      nir_foreach_phi_src(phi_src, phi) {
100
 
         if (phi_src->pred != last_block)
101
 
            continue;
102
 
 
103
 
         assert(phi_src->src.is_ssa);
104
 
         def = phi_src->src.ssa;
105
 
      }
106
 
 
107
 
      assert(def);
108
 
      assert(phi->dest.is_ssa);
109
 
      nir_ssa_def_rewrite_uses(&phi->dest.ssa, def);
110
 
      nir_instr_remove(instr);
111
 
   }
112
 
 
113
89
   /* The control flow list we're about to paste in may include a jump at the
114
90
    * end, and in that case we have to delete the rest of the control flow
115
91
    * list after the if since it's unreachable and the validator will balk if
116
92
    * we don't.
117
93
    */
118
94
 
119
 
   if (!exec_list_is_empty(&last_block->instr_list)) {
120
 
      nir_instr *last_instr = nir_block_last_instr(last_block);
121
 
      if (last_instr->type == nir_instr_type_jump)
122
 
         remove_after_cf_node(&if_stmt->cf_node);
 
95
   if (nir_block_ends_in_jump(last_block)) {
 
96
      remove_after_cf_node(&if_stmt->cf_node);
 
97
   } else {
 
98
      /* Remove any phi nodes after the if by rewriting uses to point to the
 
99
       * correct source.
 
100
       */
 
101
      nir_block *after = nir_cf_node_as_block(nir_cf_node_next(&if_stmt->cf_node));
 
102
      nir_foreach_phi_safe(phi, after) {
 
103
         nir_ssa_def *def = NULL;
 
104
         nir_foreach_phi_src(phi_src, phi) {
 
105
            if (phi_src->pred != last_block)
 
106
               continue;
 
107
 
 
108
            assert(phi_src->src.is_ssa);
 
109
            def = phi_src->src.ssa;
 
110
         }
 
111
 
 
112
         assert(def);
 
113
         assert(phi->dest.is_ssa);
 
114
         nir_ssa_def_rewrite_uses(&phi->dest.ssa, def);
 
115
         nir_instr_remove(&phi->instr);
 
116
      }
123
117
   }
124
118
 
125
119
   /* Finally, actually paste in the then or else branch and delete the if. */
281
275
static bool
282
276
dead_cf_block(nir_block *block)
283
277
{
 
278
   /* opt_constant_if() doesn't handle this case. */
 
279
   if (nir_block_ends_in_jump(block) &&
 
280
       !exec_node_is_tail_sentinel(block->cf_node.node.next)) {
 
281
      remove_after_cf_node(&block->cf_node);
 
282
      return true;
 
283
   }
 
284
 
284
285
   nir_if *following_if = nir_block_get_following_if(block);
285
286
   if (following_if) {
286
287
      if (nir_src_is_const(following_if->condition)) {
317
318
      switch (cur->type) {
318
319
      case nir_cf_node_block: {
319
320
         nir_block *block = nir_cf_node_as_block(cur);
320
 
         if (dead_cf_block(block)) {
321
 
            /* We just deleted the if or loop after this block, so we may have
322
 
             * deleted the block before or after it -- which one is an
323
 
             * implementation detail. Therefore, to recover the place we were
324
 
             * at, we have to use the previous cf_node.
 
321
         while (dead_cf_block(block)) {
 
322
            /* We just deleted the if or loop after this block.
 
323
             * nir_cf_node_remove may have deleted the block before
 
324
             * or after it -- which one is an implementation detail.
 
325
             * Therefore, to recover the place we were at, we have
 
326
             * to use the previous cf_node.
325
327
             */
326
328
 
327
329
            if (prev) {
337
339
         }
338
340
 
339
341
         if (nir_block_ends_in_jump(block)) {
 
342
            assert(exec_node_is_tail_sentinel(cur->node.next));
340
343
            *list_ends_in_jump = true;
341
 
 
342
 
            if (!exec_node_is_tail_sentinel(cur->node.next)) {
343
 
               remove_after_cf_node(cur);
344
 
               return true;
345
 
            }
346
344
         }
347
345
 
348
346
         break;
401
399
 
402
400
   if (progress) {
403
401
      nir_metadata_preserve(impl, nir_metadata_none);
 
402
      nir_rematerialize_derefs_in_use_blocks_impl(impl);
404
403
 
405
404
      /* The CF manipulation code called by this pass is smart enough to keep
406
405
       * from breaking any SSA use/def chains by replacing any uses of removed
424
423
{
425
424
   bool progress = false;
426
425
 
427
 
   nir_foreach_function(function, shader)
428
 
      if (function->impl)
429
 
         progress |= opt_dead_cf_impl(function->impl);
 
426
   nir_foreach_function_impl(impl, shader)
 
427
      progress |= opt_dead_cf_impl(impl);
430
428
 
431
429
   return progress;
432
430
}