What happens if you have something like foo = vec3(foo.z, bar.x, foo.x)? I don't think emitting vector mov's for only the contiguous components is enough.
On Thu, Jan 22, 2015 at 4:51 PM, Eric Anholt <e...@anholt.net> wrote: > It now emits vector MOVs instead of a series of individual MOVs, which > should be useful to any vector backends. This pushes the problem of > src/dest aliasing of channels on a scalar chip to the backend, but if > there are any vector operations in your shader then you needed to be > handling this already. > > Fixes fs-swap-problem with my scalarizing patches. > --- > src/glsl/nir/nir_lower_vec_to_movs.c | 74 > +++++++++++++++++++++++++++++++----- > 1 file changed, 64 insertions(+), 10 deletions(-) > > diff --git a/src/glsl/nir/nir_lower_vec_to_movs.c > b/src/glsl/nir/nir_lower_vec_to_movs.c > index 022889e..489901e 100644 > --- a/src/glsl/nir/nir_lower_vec_to_movs.c > +++ b/src/glsl/nir/nir_lower_vec_to_movs.c > @@ -33,6 +33,49 @@ > */ > > static bool > +src_matches_dest_reg(nir_dest *dest, nir_src *src) > +{ > + if (dest->is_ssa || src->is_ssa) > + return false; > + > + return (dest->reg.reg == src->reg.reg && > + dest->reg.base_offset == src->reg.base_offset && > + !dest->reg.indirect && > + !src->reg.indirect); > +} > + > +static unsigned > +insert_movs(nir_alu_instr *vec, unsigned start_channel, > + unsigned start_src_idx, void *mem_ctx) > +{ > + unsigned src_idx = start_src_idx; > + assert(src_idx < nir_op_infos[vec->op].num_inputs); > + > + nir_alu_instr *mov = nir_alu_instr_create(mem_ctx, nir_op_imov); > + nir_alu_src_copy(&mov->src[0], &vec->src[src_idx], mem_ctx); > + nir_alu_dest_copy(&mov->dest, &vec->dest, mem_ctx); > + > + mov->dest.write_mask = (1u << start_channel); > + mov->src[0].swizzle[start_channel] = vec->src[src_idx].swizzle[0]; > + src_idx++; > + > + for (unsigned i = start_channel + 1; i < 4; i++) { > + if (!(vec->dest.write_mask & (1 << i))) > + continue; > + > + if (nir_srcs_equal(vec->src[src_idx].src, > vec->src[start_src_idx].src)) { > + mov->dest.write_mask |= (1 << i); > + mov->src[0].swizzle[i] = vec->src[src_idx].swizzle[0]; > + } > + src_idx++; > + } > + > + nir_instr_insert_before(&vec->instr, &mov->instr); > + > + return mov->dest.write_mask; > +} > + > +static bool > lower_vec_to_movs_block(nir_block *block, void *mem_ctx) > { > nir_foreach_instr_safe(block, instr) { > @@ -50,22 +93,33 @@ lower_vec_to_movs_block(nir_block *block, void *mem_ctx) > continue; /* The loop */ > } > > + /* Since we insert multiple MOVs, we have to be non-SSA. */ > + assert(!vec->dest.dest.is_ssa); > + > + unsigned finished_write_mask = 0; > + > + /* 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, src_idx = 0; i < 4; i++) { > if (!(vec->dest.write_mask & (1 << i))) > continue; > > - assert(src_idx < nir_op_infos[vec->op].num_inputs); > - > - nir_alu_instr *mov = nir_alu_instr_create(mem_ctx, nir_op_imov); > - nir_alu_src_copy(&mov->src[0], &vec->src[src_idx], mem_ctx); > - > - /* We only care about the one swizzle */ > - mov->src[0].swizzle[i] = vec->src[src_idx].swizzle[0]; > + if (src_matches_dest_reg(&vec->dest.dest, &vec->src[src_idx].src)) { > + finished_write_mask |= insert_movs(vec, i, src_idx, mem_ctx); > + break; > + } > + src_idx++; > + } > > - nir_alu_dest_copy(&mov->dest, &vec->dest, mem_ctx); > - mov->dest.write_mask = (1u << i); > + /* Now, emit MOVs for all the other src channels. */ > + for (unsigned i = 0, src_idx = 0; i < 4; i++) { > + if (!(vec->dest.write_mask & (1 << i))) > + continue; > > - nir_instr_insert_before(&vec->instr, &mov->instr); > + if (!(finished_write_mask & (1 << i))) > + finished_write_mask |= insert_movs(vec, i, src_idx, mem_ctx); > > src_idx++; > } > -- > 2.1.3 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev