On 19/09/15 16:34, Jason Ekstrand wrote: > > > On Sep 18, 2015 10:12 AM, "Alejandro Piñeiro" <apinhe...@igalia.com > <mailto:apinhe...@igalia.com>> wrote: > > > > SEL and MOV instructions, as long as they don't have source > modifiers, are > > just copying bits around. So those kind of instruction could be > propagated > > even if there are type mismatches. This is needed because NIR generates > > integer SEL and MOV instructions whenever it doesn't know what else to > > generate. > > > > This commit adds support for copy propagation using previous instruction > > as reference. > > > > v2: using 'arg' index to get the from inst was wrong, as pointed > > by Jason Ekstrand > > v3: rebased against last change on the previous patch of theh series > > --- > > > > v3 is just a rebase against the first patch on the series. I also > > realized that yesterday I did a mess when I sent the v2 of this > > patch (answering to the wrong email, not including v3 on the subject), > > so I will copy the text I had on that email here. Sorry for the noise. > > > > From the review: > > >> if (has_source_modifiers && > > >> value.type != inst->src[arg].type && > > >> - !can_change_source_types(inst)) > > >> + !can_change_source_types(inst) && > > >> + !can_change_source_types(entry->inst[arg])) > > > > > This isn't right. The entry->inst array is indexed on vec4 component > > > but arg is the argument of the instruction. I think what you want to > > > do is add something to the loop above to loop over 0...3 and check > > > them all. > > > > Yes you are right. At that moment I misunderstood 'arg' as the channel > > being used at that moment, and as piglit didn't correct me with a > > regression I never realized that I was wrong. This v2 computes > > the instruction we are looking for corrrectly, with the a loop > > as suggested. > > > > > Also, how this is different from has_source_modifiers? > > > > It is different because at that moment has_source_modifiers has > > been computed using the src_reg value that had their modifiers > > changed to the ones at the current string: > > > > if (inst->src[arg].abs) { > > value.negate = false; > > value.abs = true; > > } > > if (inst->src[arg].negate) > > value.negate = !value.negate; > > > > bool has_source_modifiers = value.negate || value.abs; > > > > While can_change_source_types with the from instruction is > > using the original ones, and checking that is a mov, so "safe" > > to going on with the propagation. > > > > That means that there is an alternative to track the instructions > > at copy_entry. I could maintain a copy of value without being > > modified, or compute has_source_modifiers (ie: > original_has_source_modifiers). > > I think I would prefer that if we can make it work. >
Ok. > > But I would still need to check if the opcode is a MOV on the from > > instruction, so I would need to track opcode on the copy_entry struct. > > Tracking inst also have the advantage that I can reuse the > > function can_change_source_types. > > The copy_entry struct shouldn't get filled out. In particular, we > only set the source if is_direct_copy() returns true. > Oh true, if I have a source, that means that it came from a MOV. Good catch. Thanks for the hints. > > > > > Obviously, it is (the shader-db numbers say so) but I'm not seeing it. > > > Could you please provide an example. > > > > Ok. On a shader like this: > > > > uniform vec4 inData; > > > > void main(void) > > { > > gl_Position = gl_Vertex - inData; > > } > > > > VS-0001-00-start is like this: > > 0: mov vgrf0.0:F, attr0.xyzw:F > > 1: mov vgrf1.0:UD, u0.xyzw:UD > > 2: add vgrf2.0:F, vgrf0.xyzw:F, -vgrf1.xyzw:F > > 3: mov m2:D, 0D > > 4: mov m3:F, vgrf2.xyzw:F > > 5: vs_urb_write (null):UD > > > > When we are at instruction #2, has_source_modifiers is true > > even for the value u0 because as I mentioned, it is copying the > > modifiers at the same instruction (the modifiers of > > vgrf1 at #2). But in any case, it is "safe" to do the copy > > propagation from instruction #1 to instruction #2. > > Thanks, that makes sense. > --Jason > > > > > .../drivers/dri/i965/brw_vec4_copy_propagation.cpp | 47 > ++++++++++++++++------ > > 1 file changed, 35 insertions(+), 12 deletions(-) > > > > diff --git a/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp > b/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp > > index 1522eea..dabc25f 100644 > > --- a/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp > > +++ b/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp > > @@ -39,6 +39,7 @@ namespace brw { > > > > struct copy_entry { > > src_reg *value[4]; > > + vec4_instruction *inst[4]; > > int saturatemask; > > }; > > > > @@ -251,7 +252,8 @@ try_constant_propagate(const struct > brw_device_info *devinfo, > > static bool > > can_change_source_types(vec4_instruction *inst) > > { > > - return inst->dst.type == inst->src[0].type && > > + return inst != NULL && > > + inst->dst.type == inst->src[0].type && > > !inst->src[0].abs && !inst->src[0].negate && !inst->saturate && > > (inst->opcode == BRW_OPCODE_MOV || > > (inst->opcode == BRW_OPCODE_SEL && > > @@ -271,6 +273,8 @@ try_copy_propagate(const struct brw_device_info > *devinfo, > > * vectors better. > > */ > > src_reg value = *entry->value[0]; > > + vec4_instruction *from_inst = entry->inst[0]; > > + > > for (int i = 1; i < 4; i++) { > > /* This is equals() except we don't care about the swizzle. */ > > if (value.file != entry->value[i]->file || > > @@ -283,6 +287,13 @@ try_copy_propagate(const struct brw_device_info > *devinfo, > > } > > } > > > > + for (int i = 1; i < 4; i++) { > > + if (from_inst != entry->inst[i]) { > > + from_inst = NULL; > > + break; > > + } > > + } > > + > > /* Compute the swizzle of the original register by swizzling the > > * component loaded from each value according to the swizzle of > > * operand we're going to change. > > @@ -322,7 +333,8 @@ try_copy_propagate(const struct brw_device_info > *devinfo, > > > > if (has_source_modifiers && > > value.type != inst->src[arg].type && > > - !can_change_source_types(inst)) > > + !can_change_source_types(inst) && > > + !can_change_source_types(from_inst)) > > return false; > > > > if (has_source_modifiers && > > @@ -340,7 +352,8 @@ try_copy_propagate(const struct brw_device_info > *devinfo, > > * instead. See also resolve_ud_negate(). > > */ > > if (value.negate && > > - value.type == BRW_REGISTER_TYPE_UD) > > + value.type == BRW_REGISTER_TYPE_UD && > > + !can_change_source_types(from_inst)) > > return false; > > > > /* Don't report progress if this is a noop. */ > > @@ -378,17 +391,25 @@ try_copy_propagate(const struct > brw_device_info *devinfo, > > > > if (has_source_modifiers && > > value.type != inst->src[arg].type) { > > - /* We are propagating source modifiers from a MOV with a > different > > - * type. If we got here, then we can just change the source and > > - * destination types of the instruction and keep going. > > + /* We are propagating source modifiers from a safe > instruction with a > > + * different type. If we got here, then we can just change > the source > > + * and destination types of the current instruction or the > instruction > > + * from we are propagating. > > */ > > - assert(can_change_source_types(inst)); > > - for (int i = 0; i < 3; i++) { > > - inst->src[i].type = value.type; > > + assert(can_change_source_types(inst) || > > + can_change_source_types(from_inst)); > > + > > + if (can_change_source_types(inst)) { > > + for (int i = 0; i < 3; i++) { > > + inst->src[i].type = value.type; > > + } > > + inst->dst.type = value.type; > > + } else { > > + value.type = inst->src[arg].type; > > } > > - inst->dst.type = value.type; > > - } else > > + } else { > > value.type = inst->src[arg].type; > > + } > > inst->src[arg] = value; > > return true; > > } > > @@ -441,7 +462,7 @@ vec4_visitor::opt_copy_propagation(bool > do_constant_prop) > > for (c = 0; c < 4; c++) { > > int channel = BRW_GET_SWZ(inst->src[i].swizzle, c); > > entry.value[c] = entries[reg].value[channel]; > > - > > + entry.inst[c] = entries[reg].inst[channel]; > > /* If there's no available copy for this channel, bail. > > * We could be more aggressive here -- some channels might > > * not get used based on the destination writemask. > > @@ -486,6 +507,7 @@ vec4_visitor::opt_copy_propagation(bool > do_constant_prop) > > entries[reg].value[i] = direct_copy ? &inst->src[0] > : NULL; > > entries[reg].saturatemask |= > > inst->saturate && direct_copy ? 1 << i : 0; > > + entries[reg].inst[i] = direct_copy ? inst : NULL; > > } > > } > > > > @@ -500,6 +522,7 @@ vec4_visitor::opt_copy_propagation(bool > do_constant_prop) > > if (is_channel_updated(inst, entries[i].value, j)) { > > entries[i].value[j] = NULL; > > entries[i].saturatemask &= ~(1 << j); > > + entries[i].inst[j] = NULL; > > } > > } > > } > > -- > > 2.1.4 > > > > _______________________________________________ > > mesa-dev mailing list > > mesa-dev@lists.freedesktop.org <mailto:mesa-dev@lists.freedesktop.org> > > http://lists.freedesktop.org/mailman/listinfo/mesa-dev > -- Alejandro Piñeiro (apinhe...@igalia.com)
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev