X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fnir%2Fnir_opt_dce.c;h=570e43000c08a5d9367404c7bccef460b737b5b2;hb=67c728f7a9450b04d4de1a29f1dcfb9265a7ebfd;hp=32436c18b60f6098ea528668178ce4c87b2f30a2;hpb=741744f691d6ef63e9f9a4c03136f969f2ffb0bf;p=mesa.git diff --git a/src/compiler/nir/nir_opt_dce.c b/src/compiler/nir/nir_opt_dce.c index 32436c18b60..570e43000c0 100644 --- a/src/compiler/nir/nir_opt_dce.c +++ b/src/compiler/nir/nir_opt_dce.c @@ -26,52 +26,37 @@ */ #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_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 +64,13 @@ 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_intrinsic: @@ -94,17 +79,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 +98,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,20 +116,28 @@ 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_instr *instr = NULL; + nir_instr_worklist_foreach(worklist, instr) 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); + + 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 | @@ -174,7 +150,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; }