<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 14, 2015 at 2:34 PM, Connor Abbott <span dir="ltr"><<a href="mailto:cwabbott0@gmail.com" target="_blank">cwabbott0@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Wed, Jan 14, 2015 at 5:15 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
><br>
><br>
> On Sun, Jan 11, 2015 at 7:08 PM, Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>> wrote:<br>
>><br>
>> On Tue, Jan 6, 2015 at 5:21 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
>> wrote:<br>
>> ><br>
>> ><br>
>> > On Mon, Jan 5, 2015 at 10:00 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
>> > wrote:<br>
>> >><br>
>> >><br>
>> >><br>
>> >> On Mon, Jan 5, 2015 at 9:12 PM, Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>><br>
>> >> wrote:<br>
>> >>><br>
>> >>> Hi,<br>
>> >>><br>
>> >>> Was it your intention to not support non-per-component things like dot<br>
>> >>> product at all? I've made a few inline comments about how to do it,<br>
>> >>> and it doesn't seem like it's that hard.<br>
>> >><br>
>> >><br>
>> >> No, It was just never tested on them. All your comments seem valid<br>
>> >> enough. I'll try and incorperate them.<br>
>> >><br>
>> >>><br>
>> >>><br>
>> >>> On Tue, Dec 16, 2014 at 1:12 AM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
>> >>> wrote:<br>
>> >>> ><br>
>> >>> > This framework provides a simple way to do simple search-and-replace<br>
>> >>> > operations on NIR code. The nir_search.h header provides four<br>
>> >>> > simple<br>
>> >>> > data<br>
>> >>> > structures for representing expressions: nir_value and four<br>
>> >>> > subtypes:<br>
>> >>> > nir_variable, nir_constant, and nir_expression. An expression tree<br>
>> >>> > can<br>
>> >>><br>
>> >>> Make these be the actual names (nir_search_value, nir_search_variable,<br>
>> >>> etc.)<br>
>> >><br>
>> >><br>
>> >> Yeah, no problem.<br>
>> >><br>
>> >>><br>
>> >>><br>
>> >>> > then be represented by nesting these data structures as needed. The<br>
>> >>> > nir_replace_instr function takes an instruction, an expression, and<br>
>> >>> > a<br>
>> >>> > value; if the instruction matches the expression, it is replaced<br>
>> >>> > with a<br>
>> >>> > new<br>
>> >>> > chain of instructions to generate the given replacement value. The<br>
>> >>> > framework keeps track of swizzles on sources and automatically<br>
>> >>> > generates<br>
>> >>> > the currect swizzles for the replacement value.<br>
>> >>> > ---<br>
>> >>> > src/glsl/Makefile.sources | 2 +<br>
>> >>> > src/glsl/nir/nir_search.c | 337<br>
>> >>> > ++++++++++++++++++++++++++++++++++++++++++++++<br>
>> >>> > src/glsl/nir/nir_search.h | 80 +++++++++++<br>
>> >>> > 3 files changed, 419 insertions(+)<br>
>> >>> > create mode 100644 src/glsl/nir/nir_search.c<br>
>> >>> > create mode 100644 src/glsl/nir/nir_search.h<br>
>> >>> ><br>
>> >>> > diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources<br>
>> >>> > index 12c1d83..201330d 100644<br>
>> >>> > --- a/src/glsl/Makefile.sources<br>
>> >>> > +++ b/src/glsl/Makefile.sources<br>
>> >>> > @@ -41,6 +41,8 @@ NIR_FILES = \<br>
>> >>> > $(GLSL_SRCDIR)/nir/nir_opt_peephole_select.c \<br>
>> >>> > $(GLSL_SRCDIR)/nir/nir_print.c \<br>
>> >>> > $(GLSL_SRCDIR)/nir/nir_remove_dead_variables.c \<br>
>> >>> > + $(GLSL_SRCDIR)/nir/nir_search.c \<br>
>> >>> > + $(GLSL_SRCDIR)/nir/nir_search.h \<br>
>> >>> > $(GLSL_SRCDIR)/nir/nir_split_var_copies.c \<br>
>> >>> > $(GLSL_SRCDIR)/nir/nir_to_ssa.c \<br>
>> >>> > $(GLSL_SRCDIR)/nir/nir_validate.c \<br>
>> >>> > diff --git a/src/glsl/nir/nir_search.c b/src/glsl/nir/nir_search.c<br>
>> >>> > new file mode 100644<br>
>> >>> > index 0000000..257a53b<br>
>> >>> > --- /dev/null<br>
>> >>> > +++ b/src/glsl/nir/nir_search.c<br>
>> >>> > @@ -0,0 +1,337 @@<br>
>> >>> > +/*<br>
>> >>> > + * Copyright © 2014 Intel Corporation<br>
>> >>> > + *<br>
>> >>> > + * Permission is hereby granted, free of charge, to any person<br>
>> >>> > obtaining a<br>
>> >>> > + * copy of this software and associated documentation files (the<br>
>> >>> > "Software"),<br>
>> >>> > + * to deal in the Software without restriction, including without<br>
>> >>> > limitation<br>
>> >>> > + * the rights to use, copy, modify, merge, publish, distribute,<br>
>> >>> > sublicense,<br>
>> >>> > + * and/or sell copies of the Software, and to permit persons to<br>
>> >>> > whom<br>
>> >>> > the<br>
>> >>> > + * Software is furnished to do so, subject to the following<br>
>> >>> > conditions:<br>
>> >>> > + *<br>
>> >>> > + * The above copyright notice and this permission notice (including<br>
>> >>> > the next<br>
>> >>> > + * paragraph) shall be included in all copies or substantial<br>
>> >>> > portions<br>
>> >>> > of the<br>
>> >>> > + * Software.<br>
>> >>> > + *<br>
>> >>> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,<br>
>> >>> > EXPRESS OR<br>
>> >>> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br>
>> >>> > MERCHANTABILITY,<br>
>> >>> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO<br>
>> >>> > EVENT<br>
>> >>> > SHALL<br>
>> >>> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,<br>
>> >>> > DAMAGES<br>
>> >>> > OR OTHER<br>
>> >>> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,<br>
>> >>> > ARISING<br>
>> >>> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR<br>
>> >>> > OTHER<br>
>> >>> > DEALINGS<br>
>> >>> > + * IN THE SOFTWARE.<br>
>> >>> > + *<br>
>> >>> > + * Authors:<br>
>> >>> > + * Jason Ekstrand (<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>)<br>
>> >>> > + *<br>
>> >>> > + */<br>
>> >>> > +<br>
>> >>> > +#include "nir_search.h"<br>
>> >>> > +<br>
>> >>> > +struct match_state {<br>
>> >>> > + unsigned variables_seen;<br>
>> >>> > + nir_alu_src variables[NIR_SEARCH_MAX_VARIABLES];<br>
>> >>> > +};<br>
>> >>> > +<br>
>> >>> > +static bool<br>
>> >>> > +is_commutative_binop(nir_op op)<br>
>> >>> > +{<br>
>> >>> > + switch (op) {<br>
>> >>> > + case nir_op_fadd:<br>
>> >>> > + case nir_op_iadd:<br>
>> >>> > + case nir_op_fmul:<br>
>> >>> > + case nir_op_imul:<br>
>> >>> > + case nir_op_imul_high:<br>
>> >>> > + case nir_op_umul_high:<br>
>> >>> > + case nir_op_feq:<br>
>> >>> > + case nir_op_fne:<br>
>> >>> > + case nir_op_ieq:<br>
>> >>> > + case nir_op_ine:<br>
>> >>> > + case nir_op_fand:<br>
>> >>> > + case nir_op_for:<br>
>> >>> > + case nir_op_fxor:<br>
>> >>> > + case nir_op_iand:<br>
>> >>> > + case nir_op_ior:<br>
>> >>> > + case nir_op_ixor:<br>
>> >>> > + case nir_op_fmin:<br>
>> >>> > + case nir_op_fmax:<br>
>> >>> > + case nir_op_imin:<br>
>> >>> > + case nir_op_imax:<br>
>> >>> > + case nir_op_umin:<br>
>> >>> > + case nir_op_umax:<br>
>> >>> > + return true;<br>
>> >>> > + default:<br>
>> >>> > + return false;<br>
>> >>> > + }<br>
>> >>> > +}<br>
>> >>> > +<br>
>> >>> > +static bool<br>
>> >>> > +match_expression(const nir_search_expression *expr, nir_alu_instr<br>
>> >>> > *instr,<br>
>> >>> > + unsigned num_components, const uint8_t *swizzle,<br>
>> >>> > + struct match_state *state);<br>
>> >>> > +<br>
>> >>> > +static bool<br>
>> >>> > +match_value(const nir_search_value *value, nir_alu_instr *instr,<br>
>> >>> > unsigned src,<br>
>> >>> > + unsigned num_components, const uint8_t *swizzle,<br>
>> >>> > + struct match_state *state)<br>
>> >>> > +{<br>
>> >>> > + uint8_t new_swizzle[4];<br>
>> >>> > +<br>
>> >>> > + for (int i = 0; i < num_components; ++i)<br>
>> >>> > + new_swizzle[i] = instr->src[src].swizzle[swizzle[i]];<br>
>> >>> > +<br>
>> >>> > + switch (value->type) {<br>
>> >>> > + case nir_search_value_expression:<br>
>> >>> > + if (!instr->src[src].src.is_ssa)<br>
>> >>> > + return false;<br>
>> >>> > +<br>
>> >>> > + if (instr->src[src].src.ssa->parent_instr->type !=<br>
>> >>> > nir_instr_type_alu)<br>
>> >>> > + return false;<br>
>> >>> > +<br>
>> >>> > + return<br>
>> >>> > match_expression(nir_search_value_as_expression(value),<br>
>> >>> > +<br>
>> >>> > nir_instr_as_alu(instr->src[src].src.ssa->parent_instr),<br>
>> >>> > + num_components, new_swizzle, state);<br>
>> >>> > +<br>
>> >>> > + case nir_search_value_variable: {<br>
>> >>> > + nir_search_variable *var =<br>
>> >>> > nir_search_value_as_variable(value);<br>
>> >>> > +<br>
>> >>> > + if (state->variables_seen & (1 << var->variable)) {<br>
>> >>> > + if (!nir_srcs_equal(state->variables[0].src,<br>
>> >>> > instr->src[src].src))<br>
>> >>><br>
>> >>> I think you meant state->variables[var->variable].src here.<br>
>> >><br>
>> >><br>
>> >> Yes, I think you're right. Kind of curious that this worked...<br>
>> >><br>
>> >>><br>
>> >>><br>
>> >>> ><br>
>> >>> > + return false;<br>
>> >>> ><br>
>> >>> > +<br>
>> >>> > + assert(!instr->src[src].abs && !instr->src[src].negate);<br>
>> >>> > +<br>
>> >>> > + for (int i = 0; i < num_components; ++i) {<br>
>> >>> > + if (state->variables[var->variable].swizzle[i] !=<br>
>> >>> > new_swizzle[i])<br>
>> >>> > + return false;<br>
>> >>> > + }<br>
>> >>> > +<br>
>> >>> > + return true;<br>
>> >>> > + } else {<br>
>> >>> > + state->variables_seen |= (1 << var->variable);<br>
>> >>> > + state->variables[var->variable].src = instr->src[src].src;<br>
>> >>> > + state->variables[var->variable].abs = false;<br>
>> >>> > + state->variables[var->variable].negate = false;<br>
>> >>> > +<br>
>> >>> > + for (int i = 0; i < 4; ++i) {<br>
>> >>> > + if (i < num_components)<br>
>> >>> > + state->variables[var->variable].swizzle[i] =<br>
>> >>> > new_swizzle[i];<br>
>> >>> > + else<br>
>> >>> > + state->variables[var->variable].swizzle[i] = 0;<br>
>> >>> > + }<br>
>> >>> > +<br>
>> >>> > + return true;<br>
>> >>> > + }<br>
>> >>> > + }<br>
>> >>> > +<br>
>> >>> > + case nir_search_value_constant: {<br>
>> >>> > + nir_search_constant *const_val =<br>
>> >>> > nir_search_value_as_constant(value);<br>
>> >>> > +<br>
>> >>> > + if (!instr->src[src].src.is_ssa)<br>
>> >>> > + return false;<br>
>> >>> > +<br>
>> >>> > + if (instr->src[src].src.ssa->parent_instr->type !=<br>
>> >>> > nir_instr_type_load_const)<br>
>> >>> > + return false;<br>
>> >>> > +<br>
>> >>> > + nir_load_const_instr *load =<br>
>> >>> > +<br>
>> >>> > nir_instr_as_load_const(instr->src[src].src.ssa->parent_instr);<br>
>> >>> > +<br>
>> >>> > + switch (nir_op_infos[instr->op].input_types[src]) {<br>
>> >>> > + case nir_type_float:<br>
>> >>> > + for (unsigned i = 0; i < num_components; ++i) {<br>
>> >>> > + if (load->value.f[new_swizzle[i]] != const_val->data.f)<br>
>> >>> > + return false;<br>
>> >>> > + }<br>
>> >>> > + return true;<br>
>> >>> > + case nir_type_int:<br>
>> >>> > + case nir_type_unsigned:<br>
>> >>> > + case nir_type_bool:<br>
>> >>> > + for (unsigned i = 0; i < num_components; ++i) {<br>
>> >>> > + if (load->value.i[new_swizzle[i]] != const_val->data.i)<br>
>> >>> > + return false;<br>
>> >>> > + }<br>
>> >>> > + return true;<br>
>> >>> > + default:<br>
>> >>> > + unreachable("Invalid alu source type");<br>
>> >>> > + }<br>
>> >>> > + }<br>
>> >>> > +<br>
>> >>> > + default:<br>
>> >>> > + unreachable("Invalid search value type");<br>
>> >>> > + }<br>
>> >>> > +}<br>
>> >>> > +<br>
>> >>> > +static bool<br>
>> >>> > +match_expression(const nir_search_expression *expr, nir_alu_instr<br>
>> >>> > *instr,<br>
>> >>> > + unsigned num_components, const uint8_t *swizzle,<br>
>> >>> > + struct match_state *state)<br>
>> >>> > +{<br>
>> >>> > + if (instr->op != expr->opcode)<br>
>> >>> > + return false;<br>
>> >>> > +<br>
>> >>> > + assert(!instr->dest.saturate);<br>
>> >>> > + assert(nir_op_infos[instr->op].num_inputs > 0);<br>
>> >>><br>
>> >>><br>
>> >>> If the instruction has a sized destination, we ought to bail out if<br>
>> >>> the swizzle isn't the identity or num_components isn't equal to the<br>
>> >>> identity for those components. Alternately, we could assert that the<br>
>> >>> only instructions with non-per-component destinations are at the root,<br>
>> >>> since it doesn't seem like there are that many optimizations with a<br>
>> >>> non-per-component instruction like "dot" or "any" that's not at the<br>
>> >>> root of the tree.<br>
>> >><br>
>> >><br>
>> >> Good point.<br>
>> ><br>
>> ><br>
>> > Yes, we do need to bail on a non-trivial swizzle. However, I think not<br>
>> > using all the components is probably fine. The validator will ensure<br>
>> > that<br>
>> > it doesn't use more components and not using all of them shouldn't be a<br>
>> > problem.<br>
>><br>
>> On second thought, I think you're right. We only need to bail on a<br>
>> non-trivial swizzle.<br>
><br>
><br>
> FYI: I did make all those changes. They're sigging in my repo:<br>
> <a href="http://cgit.freedesktop.org/~jekstrand/mesa/tree/src/glsl/nir/nir_search.c?h=review/nir-v1" target="_blank">http://cgit.freedesktop.org/~jekstrand/mesa/tree/src/glsl/nir/nir_search.c?h=review/nir-v1</a><br>
><br>
> If you want me to resend, I can. Or you can review it there<br>
> --Jason<br>
<br>
</div></div>I don't think you need to resend them. The only thing is that:<br>
<br>
- In match_expression() line 152, change<br>
nir_op_infos[instr->op].output_size to num_components because we're<br>
only actually using num_components components of the value we're<br>
returning, so we only those components need to have the swizzle be the<br>
identity.<br>
- In construct_value(), we need to change the write_mask of the<br>
instruction to match its output_size (instead of num_components) if it<br>
isn't per-component. Otherwise the validator will complain if<br>
num_components < output_size.<br></blockquote><div><br></div><div>We also need to make sure the ssa def has enough components. All three problems fixed.<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Once you have that fixed,<br>
<br>
Reviewed-by: Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>><br>
<div class="HOEnZb"><div class="h5"><br>
><br>
>><br>
>><br>
>> ><br>
>> >><br>
>> >><br>
>> >>><br>
>> >>> > +<br>
>> >>> > + bool matched = true;<br>
>> >>> > + for (unsigned i = 0; i < nir_op_infos[instr->op].num_inputs;<br>
>> >>> > i++) {<br>
>> >>> > + if (!match_value(expr->srcs[i], instr, i, num_components,<br>
>> >>> > + swizzle, state)) {<br>
>> >>><br>
>> >>><br>
>> >>> I think we need to pass in the correct number of components if the<br>
>> >>> source isn't per-component, since if we don't any optimizations<br>
>> >>> involving dot products will be totally broken. Similarly, I think we<br>
>> >>> need to reset the swizzle to the identity here for non-per-component<br>
>> >>> inputs.<br>
>> >><br>
>> >><br>
>> >> Right<br>
>> >><br>
>> >>><br>
>> >>><br>
>> >>> ><br>
>> >>> > + matched = false;<br>
>> >>> > + break;<br>
>> >>> > + }<br>
>> >>> > + }<br>
>> >>> > +<br>
>> >>> > + if (matched)<br>
>> >>> > + return true;<br>
>> >>> > +<br>
>> >>> > + if (is_commutative_binop(instr->op)) {<br>
>> >>> > + if (!match_value(expr->srcs[0], instr, 1, num_components,<br>
>> >>> > + swizzle, state))<br>
>> >>> > + return false;<br>
>> >>> > +<br>
>> >>> > + return match_value(expr->srcs[1], instr, 0, num_components,<br>
>> >>> > + swizzle, state);<br>
>> >>> > + } else {<br>
>> >>> > + return false;<br>
>> >>> > + }<br>
>> >>> > +}<br>
>> >>> > +<br>
>> >>> > +static nir_alu_src<br>
>> >>> > +construct_value(const nir_search_value *value, nir_alu_type type,<br>
>> >>> > + unsigned num_components, struct match_state *state,<br>
>> >>> > + nir_instr *instr, void *mem_ctx)<br>
>> >>> > +{<br>
>> >>> > + switch (value->type) {<br>
>> >>> > + case nir_search_value_expression: {<br>
>> >>> > + const nir_search_expression *expr =<br>
>> >>> > nir_search_value_as_expression(value);<br>
>> >>> > +<br>
>> >>> > + nir_alu_instr *alu = nir_alu_instr_create(mem_ctx,<br>
>> >>> > expr->opcode);<br>
>> >>> > + alu->dest.dest.is_ssa = true;<br>
>> >>> > + nir_ssa_def_init(&alu->instr, &alu->dest.dest.ssa,<br>
>> >>> > num_components, NULL);<br>
>> >>> > + alu->dest.write_mask = (1 << num_components) - 1;<br>
>> >>> > + alu->dest.saturate = false;<br>
>> >>> > +<br>
>> >>> > + for (unsigned i = 0; i <<br>
>> >>> > nir_op_infos[expr->opcode].num_inputs;<br>
>> >>> > i++) {<br>
>> >>> > + alu->src[i] = construct_value(expr->srcs[i],<br>
>> >>> > +<br>
>> >>> > nir_op_infos[alu->op].input_types[i],<br>
>> >>> > + num_components,<br>
>> >>> > + state, instr, mem_ctx);<br>
>> >>><br>
>> >>> Similarly to my earlier comment, we need to set num_components<br>
>> >>> correctly here if the source is not per-component.<br>
>> >><br>
>> >><br>
>> >> Yup<br>
>> >><br>
>> >>><br>
>> >>><br>
>> >>> > + }<br>
>> >>> > +<br>
>> >>> > + nir_instr_insert_before(instr, &alu->instr);<br>
>> >>> > +<br>
>> >>> > + nir_alu_src val = {<br>
>> >>> > + .src.is_ssa = true,<br>
>> >>> > + .src.ssa = &alu->dest.dest.ssa,<br>
>> >>> > + .negate = false,<br>
>> >>> > + .abs = false,<br>
>> >>> > + .swizzle = { 0, 0, 0, 0 }<br>
>> >>> > + };<br>
>> >>> > +<br>
>> >>> > + /* No swizzling, but we can't have a swizzle value higher<br>
>> >>> > than<br>
>> >>> > + * num_components or the validator will get cranky.<br>
>> >>> > + */<br>
>> >>> > + for (unsigned i = 0; i < num_components; ++i)<br>
>> >>> > + val.swizzle[i] = i;<br>
>> >>><br>
>> >>><br>
>> >>> The validator only checks swizzle values that are actually being used,<br>
>> >>> so we can just do<br>
>> >>><br>
>> >>> .swizzle = {0, 1, 2, 3}<br>
>> >>><br>
>> >>> here and it should be fine.<br>
>> >><br>
>> >><br>
>> >> Yeah, that should be ok.<br>
>> >><br>
>> >>><br>
>> >>><br>
>> >>> ><br>
>> >>> > +<br>
>> >>> > + return val;<br>
>> >>> > + }<br>
>> >>> > +<br>
>> >>> > + case nir_search_value_variable: {<br>
>> >>> > + const nir_search_variable *var =<br>
>> >>> > nir_search_value_as_variable(value);<br>
>> >>> > + assert(state->variables_seen & (1 << var->variable));<br>
>> >>> > +<br>
>> >>> > + nir_alu_src val = state->variables[var->variable];<br>
>> >>> > + val.src = nir_src_copy(val.src, mem_ctx);<br>
>> >>> > +<br>
>> >>> > + return val;<br>
>> >>> > + }<br>
>> >>> > +<br>
>> >>> > + case nir_search_value_constant: {<br>
>> >>> > + const nir_search_constant *c =<br>
>> >>> > nir_search_value_as_constant(value);<br>
>> >>> > + nir_load_const_instr *load =<br>
>> >>> > nir_load_const_instr_create(mem_ctx);<br>
>> >>> > + load->dest.is_ssa = true;<br>
>> >>> > + nir_ssa_def_init(&load->instr, &load->dest.ssa, 1, NULL);<br>
>> >>> > +<br>
>> >>> > + switch (type) {<br>
>> >>> > + case nir_type_float:<br>
>> >>> > + load-><a href="http://dest.ssa.name" target="_blank">dest.ssa.name</a> = ralloc_asprintf(mem_ctx, "%f",<br>
>> >>> > c->data.f);<br>
>> >>> > + load->value.f[0] = c->data.f;<br>
>> >>> > + break;<br>
>> >>> > + case nir_type_int:<br>
>> >>> > + load-><a href="http://dest.ssa.name" target="_blank">dest.ssa.name</a> = ralloc_asprintf(mem_ctx, "%d",<br>
>> >>> > c->data.i);<br>
>> >>> > + load->value.i[0] = c->data.i;<br>
>> >>> > + break;<br>
>> >>> > + case nir_type_unsigned:<br>
>> >>> > + case nir_type_bool:<br>
>> >>> > + load->value.u[0] = c->data.u;<br>
>> >>> > + break;<br>
>> >>> > + default:<br>
>> >>> > + unreachable("Invalid alu source type");<br>
>> >>> > + }<br>
>> >>> > +<br>
>> >>> > + nir_instr_insert_before(instr, &load->instr);<br>
>> >>> > +<br>
>> >>> > + nir_alu_src val = {<br>
>> >>> > + .src.is_ssa = true,<br>
>> >>> > + .src.ssa = &load->dest.ssa,<br>
>> >>> > + .negate = false,<br>
>> >>> > + .abs = false,<br>
>> >>> > + .swizzle = { 0, 0, 0, 0 } /* Splatted scalar */<br>
>> >>> > + };<br>
>> >>> > +<br>
>> >>> > + return val;<br>
>> >>> > + }<br>
>> >>> > +<br>
>> >>> > + default:<br>
>> >>> > + unreachable("Invalid search value type");<br>
>> >>> > + }<br>
>> >>> > +}<br>
>> >>> > +<br>
>> >>> > +nir_alu_instr *<br>
>> >>> > +nir_replace_instr(nir_alu_instr *instr, const nir_search_expression<br>
>> >>> > *search,<br>
>> >>> > + const nir_search_value *replace, void *mem_ctx)<br>
>> >>> > +{<br>
>> >>> > + uint8_t swizzle[4] = { 0, 0, 0, 0 };<br>
>> >>> > +<br>
>> >>> > + for (unsigned i = 0; i < instr->dest.dest.ssa.num_components;<br>
>> >>> > ++i)<br>
>> >>> > + swizzle[i] = i;<br>
>> >>> > +<br>
>> >>> > + assert(instr->dest.dest.is_ssa);<br>
>> >>> > +<br>
>> >>> > + struct match_state state;<br>
>> >>> > + state.variables_seen = 0;<br>
>> >>> > +<br>
>> >>> > + if (!match_expression(search, instr,<br>
>> >>> > instr->dest.dest.ssa.num_components,<br>
>> >>> > + swizzle, &state))<br>
>> >>> > + return NULL;<br>
>> >>> > +<br>
>> >>> > + /* Inserting a mov may be unnecessary. However, it's much<br>
>> >>> > easier<br>
>> >>> > to<br>
>> >>> > + * simply let copy propagation clean this up than to try to go<br>
>> >>> > through<br>
>> >>> > + * and rewrite swizzles ourselves.<br>
>> >>> > + */<br>
>> >>> > + nir_alu_instr *mov = nir_alu_instr_create(mem_ctx, nir_op_imov);<br>
>> >>> > + mov->dest.write_mask = instr->dest.write_mask;<br>
>> >>> > + mov->dest.dest.is_ssa = true;<br>
>> >>> > + nir_ssa_def_init(&mov->instr, &mov->dest.dest.ssa,<br>
>> >>> > + instr->dest.dest.ssa.num_components, NULL);<br>
>> >>> > +<br>
>> >>> > + mov->src[0] = construct_value(replace,<br>
>> >>> > nir_op_infos[instr->op].output_type,<br>
>> >>> > +<br>
>> >>> > instr->dest.dest.ssa.num_components,<br>
>> >>> > &state,<br>
>> >>> > + &instr->instr, mem_ctx);<br>
>> >>> > + nir_instr_insert_before(&instr->instr, &mov->instr);<br>
>> >>> > +<br>
>> >>> > + nir_src replace_src = {<br>
>> >>> > + .is_ssa = true,<br>
>> >>> > + .ssa = &mov->dest.dest.ssa,<br>
>> >>> > + };<br>
>> >>> > +<br>
>> >>> > + nir_ssa_def_rewrite_uses(&instr->dest.dest.ssa, replace_src,<br>
>> >>> > mem_ctx);<br>
>> >>> > +<br>
>> >>> > + /* We know this one has no more uses because we just rewrote<br>
>> >>> > them<br>
>> >>> > all,<br>
>> >>> > + * so we can remove it. The rest of the matched expression,<br>
>> >>> > however, we<br>
>> >>> > + * don't know so much about. We'll just let dead code clean<br>
>> >>> > them<br>
>> >>> > up.<br>
>> >>> > + */<br>
>> >>> > + nir_instr_remove(&instr->instr);<br>
>> >>> > +<br>
>> >>> > + return mov;<br>
>> >>> > +}<br>
>> >>> > diff --git a/src/glsl/nir/nir_search.h b/src/glsl/nir/nir_search.h<br>
>> >>> > new file mode 100644<br>
>> >>> > index 0000000..8ec58b0<br>
>> >>> > --- /dev/null<br>
>> >>> > +++ b/src/glsl/nir/nir_search.h<br>
>> >>> > @@ -0,0 +1,80 @@<br>
>> >>> > +/*<br>
>> >>> > + * Copyright © 2014 Intel Corporation<br>
>> >>> > + *<br>
>> >>> > + * Permission is hereby granted, free of charge, to any person<br>
>> >>> > obtaining a<br>
>> >>> > + * copy of this software and associated documentation files (the<br>
>> >>> > "Software"),<br>
>> >>> > + * to deal in the Software without restriction, including without<br>
>> >>> > limitation<br>
>> >>> > + * the rights to use, copy, modify, merge, publish, distribute,<br>
>> >>> > sublicense,<br>
>> >>> > + * and/or sell copies of the Software, and to permit persons to<br>
>> >>> > whom<br>
>> >>> > the<br>
>> >>> > + * Software is furnished to do so, subject to the following<br>
>> >>> > conditions:<br>
>> >>> > + *<br>
>> >>> > + * The above copyright notice and this permission notice (including<br>
>> >>> > the next<br>
>> >>> > + * paragraph) shall be included in all copies or substantial<br>
>> >>> > portions<br>
>> >>> > of the<br>
>> >>> > + * Software.<br>
>> >>> > + *<br>
>> >>> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,<br>
>> >>> > EXPRESS OR<br>
>> >>> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br>
>> >>> > MERCHANTABILITY,<br>
>> >>> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO<br>
>> >>> > EVENT<br>
>> >>> > SHALL<br>
>> >>> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,<br>
>> >>> > DAMAGES<br>
>> >>> > OR OTHER<br>
>> >>> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,<br>
>> >>> > ARISING<br>
>> >>> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR<br>
>> >>> > OTHER<br>
>> >>> > DEALINGS<br>
>> >>> > + * IN THE SOFTWARE.<br>
>> >>> > + *<br>
>> >>> > + * Authors:<br>
>> >>> > + * Jason Ekstrand (<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>)<br>
>> >>> > + *<br>
>> >>> > + */<br>
>> >>> > +<br>
>> >>> > +#ifndef _NIR_SEARCH_<br>
>> >>> > +#define _NIR_SEARCH_<br>
>> >>> > +<br>
>> >>> > +#include "nir.h"<br>
>> >>> > +<br>
>> >>> > +#define NIR_SEARCH_MAX_VARIABLES 16<br>
>> >>> > +<br>
>> >>> > +typedef enum {<br>
>> >>> > + nir_search_value_expression,<br>
>> >>> > + nir_search_value_variable,<br>
>> >>> > + nir_search_value_constant,<br>
>> >>> > +} nir_search_value_type;<br>
>> >>> > +<br>
>> >>> > +typedef struct {<br>
>> >>> > + nir_search_value_type type;<br>
>> >>> > +} nir_search_value;<br>
>> >>> > +<br>
>> >>> > +typedef struct {<br>
>> >>> > + nir_search_value value;<br>
>> >>> > +<br>
>> >>> > + /** The variable index; Must be less than<br>
>> >>> > NIR_SEARCH_MAX_VARIABLES<br>
>> >>> > */<br>
>> >>> > + unsigned variable;<br>
>> >>> > +} nir_search_variable;<br>
>> >>> > +<br>
>> >>> > +typedef struct {<br>
>> >>> > + nir_search_value value;<br>
>> >>> > +<br>
>> >>> > + union {<br>
>> >>> > + uint32_t u;<br>
>> >>> > + int32_t i;<br>
>> >>> > + float f;<br>
>> >>> > + } data;<br>
>> >>> > +} nir_search_constant;<br>
>> >>> > +<br>
>> >>> > +typedef struct {<br>
>> >>> > + nir_search_value value;<br>
>> >>> > +<br>
>> >>> > + nir_op opcode;<br>
>> >>> > + const nir_search_value *srcs[4];<br>
>> >>> > +} nir_search_expression;<br>
>> >>> > +<br>
>> >>> > +NIR_DEFINE_CAST(nir_search_value_as_variable, nir_search_value,<br>
>> >>> > + nir_search_variable, value)<br>
>> >>> > +NIR_DEFINE_CAST(nir_search_value_as_constant, nir_search_value,<br>
>> >>> > + nir_search_constant, value)<br>
>> >>> > +NIR_DEFINE_CAST(nir_search_value_as_expression, nir_search_value,<br>
>> >>> > + nir_search_expression, value)<br>
>> >>> > +<br>
>> >>> > +nir_alu_instr *<br>
>> >>> > +nir_replace_instr(nir_alu_instr *instr, const nir_search_expression<br>
>> >>> > *search,<br>
>> >>> > + const nir_search_value *replace, void *mem_ctx);<br>
>> >>> > +<br>
>> >>> > +#endif /* _NIR_SEARCH_ */<br>
>> >>> > --<br>
>> >>> > 2.2.0<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" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
>> >><br>
>> >><br>
>> ><br>
><br>
><br>
</div></div></blockquote></div><br></div></div>