}
nir_ssa_def_rewrite_uses(def, nir_src_for_reg(reg));
- assert(list_empty(&def->uses) && list_empty(&def->if_uses));
+ assert(list_is_empty(&def->uses) && list_is_empty(&def->if_uses));
if (def->parent_instr->type == nir_instr_type_ssa_undef) {
/* If it's an ssa_undef instruction, remove it since we know we just got
int a = pred[b];
emit_copy(&state->builder, values[loc[a]], values[b]);
- /* If any other copies want a they can find it at b */
- loc[a] = b;
-
/* b has been filled, mark it as not needing to be copied */
pred[b] = -1;
- /* If a needs to be filled, it's ready for copying now */
- if (pred[a] != -1)
+ /* If a needs to be filled... */
+ if (pred[a] != -1) {
+ /* If any other copies want a they can find it at b */
+ loc[a] = b;
+
+ /* It's ready for copying now */
ready[++ready_idx] = a;
+ }
}
int b = to_do[to_do_idx--];
if (pred[b] == -1)
static void
-place_phi_read(nir_shader *shader, nir_register *reg,
- nir_ssa_def *def, nir_block *block)
+place_phi_read(nir_builder *b, nir_register *reg,
+ nir_ssa_def *def, nir_block *block, unsigned depth)
{
if (block != def->parent_instr->block) {
/* Try to go up the single-successor tree */
}
}
- if (all_single_successors) {
+ if (all_single_successors && depth < 32) {
/* All predecessors of this block have exactly one successor and it
* is this block so they must eventually lead here without
* intersecting each other. Place the reads in the predecessors
* instead of this block.
+ *
+ * We only let this function recurse 32 times because it can recurse
+ * indefinitely in the presence of infinite loops. Because we're
+ * crawling a single-successor chain, it doesn't matter where we
+ * place it so it's ok to stop at an arbitrary distance.
+ *
+ * TODO: One day, we could detect back edges and avoid the recursion
+ * that way.
*/
- set_foreach(block->predecessors, entry)
- place_phi_read(shader, reg, def, (nir_block *)entry->key);
+ set_foreach(block->predecessors, entry) {
+ place_phi_read(b, reg, def, (nir_block *)entry->key, depth + 1);
+ }
return;
}
}
- nir_alu_instr *mov = nir_alu_instr_create(shader, nir_op_mov);
- mov->src[0].src = nir_src_for_ssa(def);
- mov->dest.dest = nir_dest_for_reg(reg);
- mov->dest.write_mask = (1 << reg->num_components) - 1;
- nir_instr_insert(nir_after_block_before_jump(block), &mov->instr);
+ b->cursor = nir_after_block_before_jump(block);
+ nir_store_reg(b, reg, def, ~0);
}
/** Lower all of the phi nodes in a block to imovs to and from a register
bool
nir_lower_phis_to_regs_block(nir_block *block)
{
- nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
- nir_shader *shader = impl->function->shader;
+ nir_builder b;
+ nir_builder_init(&b, nir_cf_node_get_function(&block->cf_node));
bool progress = false;
nir_foreach_instr_safe(instr, block) {
nir_phi_instr *phi = nir_instr_as_phi(instr);
assert(phi->dest.is_ssa);
- nir_register *reg = create_reg_for_ssa_def(&phi->dest.ssa, impl);
+ nir_register *reg = create_reg_for_ssa_def(&phi->dest.ssa, b.impl);
- nir_alu_instr *mov = nir_alu_instr_create(shader, nir_op_mov);
- mov->src[0].src = nir_src_for_reg(reg);
- mov->dest.write_mask = (1 << phi->dest.ssa.num_components) - 1;
- nir_ssa_dest_init(&mov->instr, &mov->dest.dest,
- phi->dest.ssa.num_components, phi->dest.ssa.bit_size,
- phi->dest.ssa.name);
- nir_instr_insert(nir_after_instr(&phi->instr), &mov->instr);
+ b.cursor = nir_after_instr(&phi->instr);
+ nir_ssa_def *def = nir_load_reg(&b, reg);
- nir_ssa_def_rewrite_uses(&phi->dest.ssa,
- nir_src_for_ssa(&mov->dest.dest.ssa));
+ nir_ssa_def_rewrite_uses(&phi->dest.ssa, nir_src_for_ssa(def));
nir_foreach_phi_src(src, phi) {
assert(src->src.is_ssa);
- place_phi_read(shader, reg, src->src.ssa, src->pred);
+ place_phi_read(&b, reg, src->src.ssa, src->pred, 0);
}
nir_instr_remove(&phi->instr);
}
}
- if (!list_empty(&def->if_uses))
+ if (!list_is_empty(&def->if_uses))
return false;
return true;