/* map from SSA value -> original register */
struct hash_table *ssa_map;
-
- /* predicate for this instruction */
- nir_src *predicate;
} rewrite_state;
static nir_ssa_def *get_ssa_src(nir_register *reg, rewrite_state *state)
* We're using an undefined register, create a new undefined SSA value
* to preserve the information that this source is undefined
*/
- nir_ssa_undef_instr *instr = nir_ssa_undef_instr_create(state->mem_ctx);
- instr->def.index = state->impl->ssa_alloc++;
- instr->def.num_components = reg->num_components;
- instr->def.uses = _mesa_set_create(state->mem_ctx,
- _mesa_key_pointer_equal);
- instr->def.if_uses = _mesa_set_create(state->mem_ctx,
- _mesa_key_pointer_equal);
+ nir_ssa_undef_instr *instr =
+ nir_ssa_undef_instr_create(state->mem_ctx, reg->num_components);
+
/*
* We could just insert the undefined instruction before the instruction
* we're rewriting, but we could be rewriting a phi source in which case
if (state->states[index].stack == NULL)
return true;
- nir_alu_instr *csel = NULL;
- if (state->predicate) {
- /*
- * To capture the information that we may or may not overwrite this
- * register due to the predicate, we need to emit a conditional select
- * that takes the old version of the register and the new version.
- * This is basically a watered-down version of the Psi-SSA
- * representation, without any of the optimizations.
- *
- * TODO: do we actually need full-blown Psi-SSA?
- */
- csel = nir_alu_instr_create(state->mem_ctx, nir_op_bcsel);
- csel->dest.dest.reg.reg = dest->reg.reg;
- csel->dest.write_mask = (1 << dest->reg.reg->num_components) - 1;
- csel->src[0].src = nir_src_copy(*state->predicate, state->mem_ctx);
- if (csel->src[0].src.is_ssa)
- _mesa_set_add(csel->src[0].src.ssa->uses,
- _mesa_hash_pointer(&csel->instr), &csel->instr);
- csel->src[2].src.is_ssa = true;
- csel->src[2].src.ssa = get_ssa_src(dest->reg.reg, state);
- _mesa_set_add(csel->src[2].src.ssa->uses,
- _mesa_hash_pointer(&csel->instr), &csel->instr);
- }
-
dest->is_ssa = true;
char *name = NULL;
name = ralloc_asprintf(state->mem_ctx, "%s_%u", dest->reg.reg->name,
state->states[index].num_defs);
- dest->ssa.index = state->impl->ssa_alloc++;
- dest->ssa.num_components = reg->num_components;
- dest->ssa.parent_instr = state->parent_instr;
- dest->ssa.uses = _mesa_set_create(state->mem_ctx, _mesa_key_pointer_equal);
- dest->ssa.if_uses = _mesa_set_create(state->mem_ctx,
- _mesa_key_pointer_equal);
- dest->ssa.name = name;
+ nir_ssa_def_init(state->parent_instr, &dest->ssa,
+ reg->num_components, name);
/* push our SSA destination on the stack */
state->states[index].index++;
_mesa_hash_table_insert(state->ssa_map, &dest->ssa, reg);
- if (state->predicate) {
- csel->src[1].src.is_ssa = true;
- csel->src[1].src.ssa = &dest->ssa;
- _mesa_set_add(dest->ssa.uses, _mesa_hash_pointer(&csel->instr),
- &csel->instr);
-
- nir_instr *old_parent_instr = state->parent_instr;
- nir_src *old_predicate = state->predicate;
- state->parent_instr = &csel->instr;
- state->predicate = NULL;
- rewrite_def_forwards(&csel->dest.dest, state);
- state->parent_instr = old_parent_instr;
- state->predicate = old_predicate;
-
- nir_instr_insert_after(state->parent_instr, &csel->instr);
- }
-
return true;
}
rewrite_alu_instr_forward(nir_alu_instr *instr, rewrite_state *state)
{
state->parent_instr = &instr->instr;
- state->predicate = instr->has_predicate ? &instr->predicate : NULL;
nir_foreach_src(&instr->instr, rewrite_use, state);
instr->dest.write_mask = (1 << num_components) - 1;
instr->dest.dest.is_ssa = true;
- instr->dest.dest.ssa.index = state->impl->ssa_alloc++;
- instr->dest.dest.ssa.num_components = num_components;
- instr->dest.dest.ssa.name = name;
- instr->dest.dest.ssa.parent_instr = &instr->instr;
- instr->dest.dest.ssa.uses = _mesa_set_create(state->mem_ctx,
- _mesa_key_pointer_equal);
- instr->dest.dest.ssa.if_uses = _mesa_set_create(state->mem_ctx,
- _mesa_key_pointer_equal);
+ nir_ssa_def_init(&instr->instr, &instr->dest.dest.ssa,
+ num_components, name);
if (nir_op_infos[instr->op].output_size == 0) {
/*
vec->src[i].src.ssa = old_src;
vec->src[i].swizzle[0] = i;
}
-
- _mesa_set_add(vec->src[i].src.ssa->uses,
- _mesa_hash_pointer(&vec->instr), &vec->instr);
- }
-
- vec->has_predicate = instr->has_predicate;
- if (instr->has_predicate) {
- vec->predicate = nir_src_copy(instr->predicate, state->mem_ctx);
- if (vec->predicate.is_ssa)
- _mesa_set_add(vec->predicate.ssa->uses,
- _mesa_hash_pointer(&vec->instr), &vec->instr);
}
nir_instr_insert_after(&instr->instr, &vec->instr);
state->parent_instr = &vec->instr;
- state->predicate = vec->has_predicate ? &vec->predicate : NULL;
rewrite_def_forwards(&vec->dest.dest, state);
} else {
rewrite_def_forwards(&instr->dest.dest, state);
rewrite_phi_instr(nir_phi_instr *instr, rewrite_state *state)
{
state->parent_instr = &instr->instr;
- state->predicate = NULL;
rewrite_def_forwards(&instr->dest, state);
}
-static nir_src *
-get_instr_predicate(nir_instr *instr)
-{
- nir_alu_instr *alu_instr;
- nir_load_const_instr *load_const_instr;
- nir_intrinsic_instr *intrinsic_instr;
- nir_tex_instr *tex_instr;
-
- switch (instr->type) {
- case nir_instr_type_alu:
- alu_instr = nir_instr_as_alu(instr);
- if (alu_instr->has_predicate)
- return &alu_instr->predicate;
- else
- return NULL;
-
- case nir_instr_type_load_const:
- load_const_instr = nir_instr_as_load_const(instr);
- if (load_const_instr->has_predicate)
- return &load_const_instr->predicate;
- else
- return NULL;
-
- case nir_instr_type_intrinsic:
- intrinsic_instr = nir_instr_as_intrinsic(instr);
- if (intrinsic_instr->has_predicate)
- return &intrinsic_instr->predicate;
- else
- return NULL;
-
- case nir_instr_type_texture:
- tex_instr = nir_instr_as_texture(instr);
- if (tex_instr->has_predicate)
- return &tex_instr->predicate;
- else
- return NULL;
-
- default:
- break;
- }
-
- return NULL;
-}
-
static void
rewrite_instr_forward(nir_instr *instr, rewrite_state *state)
{
}
state->parent_instr = instr;
- state->predicate = get_instr_predicate(instr);
nir_foreach_src(instr, rewrite_use, state);
nir_foreach_dest(instr, rewrite_def_forwards, state);
* called after phi nodes are inserted so we can count phi node
* definitions too.
*/
- unsigned stack_size = 0;
- struct set_entry *entry;
- set_foreach(reg->defs, entry) {
- nir_instr *def = (nir_instr *) entry->key;
-
- stack_size++;
-
- /*
- * predicates generate an additional predicate destination that
- * gets pushed on the stack
- *
- * Note: ALU instructions generate an additional instruction too,
- * but as of now only the additional instruction is pushed onto
- * the stack, and not the original instruction because it doesn't
- * need to be (actually, we could do the same with predicates,
- * but it was easier to just use the existing codepath).
- */
-
- if (def->type == nir_instr_type_intrinsic) {
- nir_intrinsic_instr *intrinsic_instr =
- nir_instr_as_intrinsic(def);
- if (nir_intrinsic_infos[intrinsic_instr->intrinsic].has_dest &&
- intrinsic_instr->has_predicate)
- stack_size++;
- } else {
- if (get_instr_predicate(def) != NULL)
- stack_size++;
- }
- }
+ unsigned stack_size = reg->defs->entries;
state->states[reg->index].stack = ralloc_array(state->states,
nir_ssa_def *,
void
nir_convert_to_ssa_impl(nir_function_impl *impl)
{
- nir_calc_dominance_impl(impl);
+ nir_metadata_require(impl, nir_metadata_dominance);
insert_phi_nodes(impl);
remove_unused_regs(impl, &state);
+ nir_metadata_preserve(impl, nir_metadata_block_index |
+ nir_metadata_dominance);
+
destroy_rewrite_state(&state);
}