nir: Migrate nir_dce to instr worklist

Shader-db runtime change avarage of five runs:
   Before 125,77 seconds (+/- 0,09%)
   After  124,48 seconds (+/- 0,07%)

Tested-by: Dieter Nützel <Dieter at nuetzel-hh.de>
Reviewed-by: Eric Anholt <eric at anholt.net>
This commit is contained in:
Thomas Helland
2018-01-30 21:35:50 +01:00
parent edb18564c7
commit 8d5cd91ca0

View File

@@ -26,45 +26,30 @@
*/ */
#include "nir.h" #include "nir.h"
#include "nir_worklist.h"
/* SSA-based mark-and-sweep dead code elimination */ /* SSA-based mark-and-sweep dead code elimination */
typedef struct {
struct exec_node node;
nir_instr *instr;
} worklist_elem;
static void 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); nir_instr_worklist_push_tail(wl, instr);
elem->instr = instr;
instr->pass_flags = 1; 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 static bool
mark_live_cb(nir_src *src, void *_state) 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) { if (src->is_ssa && !src->ssa->parent_instr->pass_flags)
worklist_push(worklist, src->ssa->parent_instr); mark_and_push(worklist, src->ssa->parent_instr);
}
return true; return true;
} }
static void 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_alu_instr *alu_instr;
nir_intrinsic_instr *intrin_instr; nir_intrinsic_instr *intrin_instr;
@@ -79,13 +64,13 @@ init_instr(nir_instr *instr, struct exec_list *worklist)
switch (instr->type) { switch (instr->type) {
case nir_instr_type_call: case nir_instr_type_call:
case nir_instr_type_jump: case nir_instr_type_jump:
worklist_push(worklist, instr); mark_and_push(worklist, instr);
break; break;
case nir_instr_type_alu: case nir_instr_type_alu:
alu_instr = nir_instr_as_alu(instr); alu_instr = nir_instr_as_alu(instr);
if (!alu_instr->dest.dest.is_ssa) if (!alu_instr->dest.dest.is_ssa)
worklist_push(worklist, instr); mark_and_push(worklist, instr);
break; break;
case nir_instr_type_intrinsic: case nir_instr_type_intrinsic:
@@ -94,17 +79,17 @@ init_instr(nir_instr *instr, struct exec_list *worklist)
NIR_INTRINSIC_CAN_ELIMINATE) { NIR_INTRINSIC_CAN_ELIMINATE) {
if (nir_intrinsic_infos[intrin_instr->intrinsic].has_dest && if (nir_intrinsic_infos[intrin_instr->intrinsic].has_dest &&
!intrin_instr->dest.is_ssa) { !intrin_instr->dest.is_ssa) {
worklist_push(worklist, instr); mark_and_push(worklist, instr);
} }
} else { } else {
worklist_push(worklist, instr); mark_and_push(worklist, instr);
} }
break; break;
case nir_instr_type_tex: case nir_instr_type_tex:
tex_instr = nir_instr_as_tex(instr); tex_instr = nir_instr_as_tex(instr);
if (!tex_instr->dest.is_ssa) if (!tex_instr->dest.is_ssa)
worklist_push(worklist, instr); mark_and_push(worklist, instr);
break; break;
default: default:
@@ -113,7 +98,7 @@ init_instr(nir_instr *instr, struct exec_list *worklist)
} }
static bool static bool
init_block(nir_block *block, struct exec_list *worklist) init_block(nir_block *block, nir_instr_worklist *worklist)
{ {
nir_foreach_instr(instr, block) nir_foreach_instr(instr, block)
init_instr(instr, worklist); init_instr(instr, worklist);
@@ -122,7 +107,7 @@ init_block(nir_block *block, struct exec_list *worklist)
if (following_if) { if (following_if) {
if (following_if->condition.is_ssa && if (following_if->condition.is_ssa &&
!following_if->condition.ssa->parent_instr->pass_flags) !following_if->condition.ssa->parent_instr->pass_flags)
worklist_push(worklist, following_if->condition.ssa->parent_instr); mark_and_push(worklist, following_if->condition.ssa->parent_instr);
} }
return true; return true;
@@ -131,19 +116,17 @@ init_block(nir_block *block, struct exec_list *worklist)
static bool static bool
nir_opt_dce_impl(nir_function_impl *impl) nir_opt_dce_impl(nir_function_impl *impl)
{ {
struct exec_list *worklist = rzalloc(NULL, struct exec_list); nir_instr_worklist *worklist = nir_instr_worklist_create();
exec_list_make_empty(worklist);
nir_foreach_block(block, impl) { nir_foreach_block(block, impl) {
init_block(block, worklist); init_block(block, worklist);
} }
while (!exec_list_is_empty(worklist)) { nir_instr *instr = NULL;
nir_instr *instr = worklist_pop(worklist); nir_instr_worklist_foreach(worklist, instr)
nir_foreach_src(instr, mark_live_cb, worklist); nir_foreach_src(instr, mark_live_cb, worklist);
}
ralloc_free(worklist); nir_instr_worklist_destroy(worklist);
bool progress = false; bool progress = false;