nir: Make nir_search's dumping go to stderr.
[mesa.git] / src / compiler / nir / nir_opt_dce.c
index 32436c18b60f6098ea528668178ce4c87b2f30a2..724cf3f20349277e86ab8ae167e2e75695b3cf38 100644 (file)
  */
 
 #include "nir.h"
+#include "nir_worklist.h"
 
 /* SSA-based mark-and-sweep dead code elimination */
 
-typedef struct {
-   struct exec_node node;
-   nir_instr *instr;
-} worklist_elem;
-
 static void
-worklist_push(struct exec_list *worklist, nir_instr *instr)
+mark_and_push(nir_instr_worklist *wl, nir_instr *instr)
 {
-   worklist_elem *elem = ralloc(worklist, worklist_elem);
-   elem->instr = instr;
+   nir_instr_worklist_push_tail(wl, instr);
    instr->pass_flags = 1;
-   exec_list_push_tail(worklist, &elem->node);
-}
-
-static nir_instr *
-worklist_pop(struct exec_list *worklist)
-{
-   struct exec_node *node = exec_list_pop_head(worklist);
-   worklist_elem *elem = exec_node_data(worklist_elem, node, node);
-   return elem->instr;
 }
 
 static bool
 mark_live_cb(nir_src *src, void *_state)
 {
-   struct exec_list *worklist = (struct exec_list *) _state;
+   nir_instr_worklist *worklist = (nir_instr_worklist *) _state;
 
-   if (src->is_ssa && !src->ssa->parent_instr->pass_flags) {
-      worklist_push(worklist, src->ssa->parent_instr);
-   }
+   if (src->is_ssa && !src->ssa->parent_instr->pass_flags)
+      mark_and_push(worklist, src->ssa->parent_instr);
 
    return true;
 }
 
 static void
-init_instr(nir_instr *instr, struct exec_list *worklist)
+init_instr(nir_instr *instr, nir_instr_worklist *worklist)
 {
    nir_alu_instr *alu_instr;
+   nir_deref_instr *deref_instr;
    nir_intrinsic_instr *intrin_instr;
    nir_tex_instr *tex_instr;
 
    /* We use the pass_flags to store the live/dead information.  In DCE, we
-    * just treat it as a zero/non-zerl boolean for whether or not the
+    * just treat it as a zero/non-zero boolean for whether or not the
     * instruction is live.
     */
    instr->pass_flags = 0;
@@ -79,13 +65,19 @@ init_instr(nir_instr *instr, struct exec_list *worklist)
    switch (instr->type) {
    case nir_instr_type_call:
    case nir_instr_type_jump:
-      worklist_push(worklist, instr);
+      mark_and_push(worklist, instr);
       break;
 
    case nir_instr_type_alu:
       alu_instr = nir_instr_as_alu(instr);
       if (!alu_instr->dest.dest.is_ssa)
-         worklist_push(worklist, instr);
+         mark_and_push(worklist, instr);
+      break;
+
+   case nir_instr_type_deref:
+      deref_instr = nir_instr_as_deref(instr);
+      if (!deref_instr->dest.is_ssa)
+         mark_and_push(worklist, instr);
       break;
 
    case nir_instr_type_intrinsic:
@@ -94,17 +86,17 @@ init_instr(nir_instr *instr, struct exec_list *worklist)
           NIR_INTRINSIC_CAN_ELIMINATE) {
          if (nir_intrinsic_infos[intrin_instr->intrinsic].has_dest &&
              !intrin_instr->dest.is_ssa) {
-            worklist_push(worklist, instr);
+            mark_and_push(worklist, instr);
          }
       } else {
-         worklist_push(worklist, instr);
+         mark_and_push(worklist, instr);
       }
       break;
 
    case nir_instr_type_tex:
       tex_instr = nir_instr_as_tex(instr);
       if (!tex_instr->dest.is_ssa)
-         worklist_push(worklist, instr);
+         mark_and_push(worklist, instr);
       break;
 
    default:
@@ -113,33 +105,16 @@ init_instr(nir_instr *instr, struct exec_list *worklist)
 }
 
 static bool
-init_block_cb(nir_block *block, void *_state)
+init_block(nir_block *block, nir_instr_worklist *worklist)
 {
-   struct exec_list *worklist = (struct exec_list *) _state;
-
-   nir_foreach_instr(block, instr)
+   nir_foreach_instr(instr, block)
       init_instr(instr, worklist);
 
    nir_if *following_if = nir_block_get_following_if(block);
    if (following_if) {
       if (following_if->condition.is_ssa &&
           !following_if->condition.ssa->parent_instr->pass_flags)
-         worklist_push(worklist, following_if->condition.ssa->parent_instr);
-   }
-
-   return true;
-}
-
-static bool
-delete_block_cb(nir_block *block, void *_state)
-{
-   bool *progress = (bool *) _state;
-
-   nir_foreach_instr_safe(block, instr) {
-      if (!instr->pass_flags) {
-         nir_instr_remove(instr);
-         *progress = true;
-      }
+         mark_and_push(worklist, following_if->condition.ssa->parent_instr);
    }
 
    return true;
@@ -148,24 +123,36 @@ delete_block_cb(nir_block *block, void *_state)
 static bool
 nir_opt_dce_impl(nir_function_impl *impl)
 {
-   struct exec_list *worklist = ralloc(NULL, struct exec_list);
-   exec_list_make_empty(worklist);
+   nir_instr_worklist *worklist = nir_instr_worklist_create();
 
-   nir_foreach_block(impl, init_block_cb, worklist);
+   nir_foreach_block(block, impl) {
+      init_block(block, worklist);
+   }
 
-   while (!exec_list_is_empty(worklist)) {
-      nir_instr *instr = worklist_pop(worklist);
+   nir_foreach_instr_in_worklist(instr, worklist)
       nir_foreach_src(instr, mark_live_cb, worklist);
-   }
 
-   ralloc_free(worklist);
+   nir_instr_worklist_destroy(worklist);
 
    bool progress = false;
-   nir_foreach_block(impl, delete_block_cb, &progress);
 
-   if (progress)
+   nir_foreach_block(block, impl) {
+      nir_foreach_instr_safe(instr, block) {
+         if (!instr->pass_flags) {
+            nir_instr_remove(instr);
+            progress = true;
+         }
+      }
+   }
+
+   if (progress) {
       nir_metadata_preserve(impl, nir_metadata_block_index |
                                   nir_metadata_dominance);
+   } else {
+#ifndef NDEBUG
+      impl->valid_metadata &= ~nir_metadata_not_properly_reset;
+#endif
+   }
 
    return progress;
 }
@@ -174,7 +161,7 @@ bool
 nir_opt_dce(nir_shader *shader)
 {
    bool progress = false;
-   nir_foreach_function(shader, function) {
+   nir_foreach_function(function, shader) {
       if (function->impl && nir_opt_dce_impl(function->impl))
          progress = true;
    }