*/
#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;
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:
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:
}
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;
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;
}
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;
}