X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fcompiler%2Fnir%2Fnir_lower_vec_to_movs.c;h=bec7b1409a511ba4794e9b5eb604aa27e2d6a8e8;hp=f51cede3920c72d651fea849610ee2ae51a5708d;hb=e5d4bbd840622d43c25cf125aad2440abda3ccdc;hpb=70dff4a55e767de8b9ce10f055b94ebb1f6a9755 diff --git a/src/compiler/nir/nir_lower_vec_to_movs.c b/src/compiler/nir/nir_lower_vec_to_movs.c index f51cede3920..bec7b1409a5 100644 --- a/src/compiler/nir/nir_lower_vec_to_movs.c +++ b/src/compiler/nir/nir_lower_vec_to_movs.c @@ -26,17 +26,13 @@ */ #include "nir.h" +#include "nir_builder.h" /* * Implements a simple pass that lowers vecN instructions to a series of * moves with partial writes. */ -struct vec_to_movs_state { - nir_function_impl *impl; - bool progress; -}; - static bool src_matches_dest_reg(nir_dest *dest, nir_src *src) { @@ -62,7 +58,7 @@ insert_mov(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader) { assert(start_idx < nir_op_infos[vec->op].num_inputs); - nir_alu_instr *mov = nir_alu_instr_create(shader, nir_op_imov); + nir_alu_instr *mov = nir_alu_instr_create(shader, nir_op_mov); nir_alu_src_copy(&mov->src[0], &vec->src[start_idx], mov); nir_alu_dest_copy(&mov->dest, &vec->dest, mov); @@ -123,7 +119,7 @@ has_replicated_dest(nir_alu_instr *alu) * can then call insert_mov as normal. */ static unsigned -try_coalesce(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader) +try_coalesce(nir_alu_instr *vec, unsigned start_idx) { assert(start_idx < nir_op_infos[vec->op].num_inputs); @@ -136,7 +132,7 @@ try_coalesce(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader) /* If we are going to do a reswizzle, then the vecN operation must be the * only use of the source value. We also can't have any source modifiers. */ - nir_foreach_use(vec->src[start_idx].src.ssa, src) { + nir_foreach_use(src, vec->src[start_idx].src.ssa) { if (src->parent_instr != &vec->instr) return 0; @@ -145,7 +141,7 @@ try_coalesce(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader) return 0; } - if (!list_empty(&vec->src[start_idx].src.ssa->if_uses)) + if (!list_is_empty(&vec->src[start_idx].src.ssa->if_uses)) return 0; if (vec->src[start_idx].src.ssa->parent_instr->type != nir_instr_type_alu) @@ -215,98 +211,79 @@ try_coalesce(nir_alu_instr *vec, unsigned start_idx, nir_shader *shader) } static bool -lower_vec_to_movs_block(nir_block *block, void *void_state) +nir_lower_vec_to_movs_instr(nir_builder *b, nir_instr *instr, void *data) { - struct vec_to_movs_state *state = void_state; - nir_function_impl *impl = state->impl; - nir_shader *shader = impl->function->shader; - - nir_foreach_instr_safe(block, instr) { - if (instr->type != nir_instr_type_alu) - continue; - - nir_alu_instr *vec = nir_instr_as_alu(instr); - - switch (vec->op) { - case nir_op_vec2: - case nir_op_vec3: - case nir_op_vec4: - break; - default: - continue; /* The loop */ - } - - if (vec->dest.dest.is_ssa) { - /* Since we insert multiple MOVs, we have a register destination. */ - nir_register *reg = nir_local_reg_create(impl); - reg->num_components = vec->dest.dest.ssa.num_components; + if (instr->type != nir_instr_type_alu) + return false; - nir_ssa_def_rewrite_uses(&vec->dest.dest.ssa, nir_src_for_reg(reg)); + nir_alu_instr *vec = nir_instr_as_alu(instr); - nir_instr_rewrite_dest(&vec->instr, &vec->dest.dest, - nir_dest_for_reg(reg)); - } + switch (vec->op) { + case nir_op_vec2: + case nir_op_vec3: + case nir_op_vec4: + break; + default: + return false; + } - unsigned finished_write_mask = 0; + bool vec_had_ssa_dest = vec->dest.dest.is_ssa; + if (vec->dest.dest.is_ssa) { + /* Since we insert multiple MOVs, we have a register destination. */ + nir_register *reg = nir_local_reg_create(b->impl); + reg->num_components = vec->dest.dest.ssa.num_components; + reg->bit_size = vec->dest.dest.ssa.bit_size; - /* First, emit a MOV for all the src channels that are in the - * destination reg, in case other values we're populating in the dest - * might overwrite them. - */ - for (unsigned i = 0; i < 4; i++) { - if (!(vec->dest.write_mask & (1 << i))) - continue; + nir_ssa_def_rewrite_uses(&vec->dest.dest.ssa, nir_src_for_reg(reg)); - if (src_matches_dest_reg(&vec->dest.dest, &vec->src[i].src)) { - finished_write_mask |= insert_mov(vec, i, shader); - break; - } - } + nir_instr_rewrite_dest(&vec->instr, &vec->dest.dest, + nir_dest_for_reg(reg)); + } - /* Now, emit MOVs for all the other src channels. */ - for (unsigned i = 0; i < 4; i++) { - if (!(vec->dest.write_mask & (1 << i))) - continue; + unsigned finished_write_mask = 0; - if (!(finished_write_mask & (1 << i))) - finished_write_mask |= try_coalesce(vec, i, shader); + /* First, emit a MOV for all the src channels that are in the + * destination reg, in case other values we're populating in the dest + * might overwrite them. + */ + for (unsigned i = 0; i < 4; i++) { + if (!(vec->dest.write_mask & (1 << i))) + continue; - if (!(finished_write_mask & (1 << i))) - finished_write_mask |= insert_mov(vec, i, shader); + if (src_matches_dest_reg(&vec->dest.dest, &vec->src[i].src)) { + finished_write_mask |= insert_mov(vec, i, b->shader); + break; } - - nir_instr_remove(&vec->instr); - ralloc_free(vec); - state->progress = true; } - return true; -} - -static bool -nir_lower_vec_to_movs_impl(nir_function_impl *impl) -{ - struct vec_to_movs_state state = { impl, false }; + /* Now, emit MOVs for all the other src channels. */ + for (unsigned i = 0; i < 4; i++) { + if (!(vec->dest.write_mask & (1 << i))) + continue; - nir_foreach_block(impl, lower_vec_to_movs_block, &state); + /* Coalescing moves the register writes from the vec up to the ALU + * instruction in the source. We can only do this if the original + * vecN had an SSA destination. + */ + if (vec_had_ssa_dest && !(finished_write_mask & (1 << i))) + finished_write_mask |= try_coalesce(vec, i); - if (state.progress) { - nir_metadata_preserve(impl, nir_metadata_block_index | - nir_metadata_dominance); + if (!(finished_write_mask & (1 << i))) + finished_write_mask |= insert_mov(vec, i, b->shader); } - return state.progress; + nir_instr_remove(&vec->instr); + ralloc_free(vec); + + return true; } bool nir_lower_vec_to_movs(nir_shader *shader) { - bool progress = false; - - nir_foreach_function(shader, function) { - if (function->impl) - progress = nir_lower_vec_to_movs_impl(function->impl) || progress; - } - - return progress; + return nir_shader_instructions_pass(shader, + nir_lower_vec_to_movs_instr, + nir_metadata_block_index | + nir_metadata_dominance, + NULL); }