nir: Add all allocated instructions to a GC list.

Right now we're using ralloc to GC our NIR instructions, but ralloc has
significant overhead for its recursive nature so it would be nice to use a
simpler mechanism for GCing instructions.

Reviewed-by: Matt Turner <mattst88@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11776>
This commit is contained in:
Emma Anholt 2021-07-07 10:22:21 -07:00 committed by Marge Bot
parent 22788d68eb
commit d1a2870f78
5 changed files with 58 additions and 0 deletions

View file

@ -121,6 +121,8 @@ nir_shader_create(void *mem_ctx,
exec_list_make_empty(&shader->functions);
list_inithead(&shader->gc_list);
shader->num_inputs = 0;
shader->num_outputs = 0;
shader->num_uniforms = 0;
@ -576,6 +578,8 @@ nir_alu_instr_create(nir_shader *shader, nir_op op)
for (unsigned i = 0; i < num_srcs; i++)
alu_src_init(&instr->src[i]);
list_add(&instr->instr.gc_node, &shader->gc_list);
return instr;
}
@ -597,6 +601,8 @@ nir_deref_instr_create(nir_shader *shader, nir_deref_type deref_type)
dest_init(&instr->dest);
list_add(&instr->instr.gc_node, &shader->gc_list);
return instr;
}
@ -609,6 +615,9 @@ nir_jump_instr_create(nir_shader *shader, nir_jump_type type)
instr->type = type;
instr->target = NULL;
instr->else_target = NULL;
list_add(&instr->instr.gc_node, &shader->gc_list);
return instr;
}
@ -622,6 +631,8 @@ nir_load_const_instr_create(nir_shader *shader, unsigned num_components,
nir_ssa_def_init(&instr->instr, &instr->def, num_components, bit_size);
list_add(&instr->instr.gc_node, &shader->gc_list);
return instr;
}
@ -643,6 +654,8 @@ nir_intrinsic_instr_create(nir_shader *shader, nir_intrinsic_op op)
for (unsigned i = 0; i < num_srcs; i++)
src_init(&instr->src[i]);
list_add(&instr->instr.gc_node, &shader->gc_list);
return instr;
}
@ -660,6 +673,8 @@ nir_call_instr_create(nir_shader *shader, nir_function *callee)
for (unsigned i = 0; i < num_params; i++)
src_init(&instr->params[i]);
list_add(&instr->instr.gc_node, &shader->gc_list);
return instr;
}
@ -688,6 +703,8 @@ nir_tex_instr_create(nir_shader *shader, unsigned num_srcs)
instr->sampler_index = 0;
memcpy(instr->tg4_offsets, default_tg4_offsets, sizeof(instr->tg4_offsets));
list_add(&instr->instr.gc_node, &shader->gc_list);
return instr;
}
@ -746,6 +763,9 @@ nir_phi_instr_create(nir_shader *shader)
dest_init(&instr->dest);
exec_list_make_empty(&instr->srcs);
list_add(&instr->instr.gc_node, &shader->gc_list);
return instr;
}
@ -779,6 +799,8 @@ nir_parallel_copy_instr_create(nir_shader *shader)
exec_list_make_empty(&instr->entries);
list_add(&instr->instr.gc_node, &shader->gc_list);
return instr;
}
@ -792,6 +814,8 @@ nir_ssa_undef_instr_create(nir_shader *shader,
nir_ssa_def_init(&instr->instr, &instr->def, num_components, bit_size);
list_add(&instr->instr.gc_node, &shader->gc_list);
return instr;
}
@ -1093,6 +1117,7 @@ void nir_instr_remove_v(nir_instr *instr)
void nir_instr_free(nir_instr *instr)
{
list_del(&instr->gc_node);
ralloc_free(instr);
}

View file

@ -768,6 +768,7 @@ typedef enum PACKED {
typedef struct nir_instr {
struct exec_node node;
struct list_head gc_node;
struct nir_block *block;
nir_instr_type type;
@ -3812,6 +3813,8 @@ typedef struct nir_shader {
struct exec_list functions; /** < list of nir_function */
struct list_head gc_list; /** < list of all nir_instrs allocated on the shader but not yet freed. */
/**
* The size of the variable space for load_input_*, load_uniform_*, etc.
* intrinsics. This is in back-end specific units which is likely one of

View file

@ -798,6 +798,8 @@ nir_shader_replace(nir_shader *dst, nir_shader *src)
/* We have to move all the linked lists over separately because we need the
* pointers in the list elements to point to the lists in dst and not src.
*/
list_replace(&src->gc_list, &dst->gc_list);
list_inithead(&src->gc_list);
exec_list_move_nodes_to(&src->variables, &dst->variables);
/* Now move the functions over. This takes a tiny bit more work */

View file

@ -73,6 +73,9 @@ sweep_block(nir_shader *nir, nir_block *block)
block->live_out = NULL;
nir_foreach_instr(instr, block) {
list_del(&instr->gc_node);
list_add(&instr->gc_node, &nir->gc_list);
ralloc_steal(nir, instr);
nir_foreach_src(instr, sweep_src_indirect, nir);
@ -155,6 +158,12 @@ nir_sweep(nir_shader *nir)
{
void *rubbish = ralloc_context(NULL);
struct list_head instr_gc_list;
list_inithead(&instr_gc_list);
list_replace(&nir->gc_list, &instr_gc_list);
list_inithead(&nir->gc_list);
/* First, move ownership of all the memory to a temporary context; assume dead. */
ralloc_adopt(rubbish, nir);
@ -170,6 +179,16 @@ nir_sweep(nir_shader *nir)
sweep_function(nir, func);
}
/* Manually GCed instrs now before ralloc_free()ing the other rubbish, to
* ensure that the shader's GC list was maintained without ralloc_freeing any
* instrs behind our back. Note that the instr free routine will remove it
* from the list.
*/
list_for_each_entry_safe(nir_instr, instr, &instr_gc_list, gc_node) {
nir_instr_free(instr);
}
assert(list_is_empty(&instr_gc_list));
ralloc_steal(nir, nir->constant_data);
/* Free everything we didn't steal back. */

View file

@ -100,6 +100,8 @@ typedef struct {
/* map of instruction/var/etc to failed assert string */
struct hash_table *errors;
struct set *shader_gc_list;
} validate_state;
static void
@ -1073,6 +1075,8 @@ validate_instr(nir_instr *instr, validate_state *state)
state->instr = instr;
validate_assert(state, _mesa_set_search(state->shader_gc_list, instr));
switch (instr->type) {
case nir_instr_type_alu:
validate_alu_instr(nir_instr_as_alu(instr), state);
@ -1667,6 +1671,7 @@ init_validate_state(validate_state *state)
state->blocks = _mesa_pointer_set_create(state->mem_ctx);
state->var_defs = _mesa_pointer_hash_table_create(state->mem_ctx);
state->errors = _mesa_pointer_hash_table_create(state->mem_ctx);
state->shader_gc_list = _mesa_pointer_set_create(state->mem_ctx);
state->loop = NULL;
state->instr = NULL;
@ -1726,6 +1731,10 @@ nir_validate_shader(nir_shader *shader, const char *when)
validate_state state;
init_validate_state(&state);
list_for_each_entry(nir_instr, instr, &shader->gc_list, gc_node) {
_mesa_set_add(state.shader_gc_list, instr);
}
state.shader = shader;
nir_variable_mode valid_modes =