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