<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, May 16, 2016 at 9:09 AM, Rob Clark <span dir="ltr"><<a href="mailto:robdclark@gmail.com" target="_blank">robdclark@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 Mon, May 16, 2016 at 10:45 AM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
><br>
> On May 16, 2016 7:29 AM, "Rob Clark" <<a href="mailto:robdclark@gmail.com">robdclark@gmail.com</a>> wrote:<br>
>><br>
>> On Sat, May 14, 2016 at 4:03 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
>> wrote:<br>
>> ><br>
>> ><br>
>> > On Sat, May 14, 2016 at 12:20 PM, Rob Clark <<a href="mailto:robdclark@gmail.com">robdclark@gmail.com</a>> wrote:<br>
>> >><br>
>> >> On Thu, May 12, 2016 at 10:55 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
>> >> wrote:<br>
>> >> ><br>
>> >> ><br>
>> >> > On Tue, May 10, 2016 at 11:57 AM, Rob Clark <<a href="mailto:robdclark@gmail.com">robdclark@gmail.com</a>><br>
>> >> > wrote:<br>
>> >> >><br>
>> >> >> From: Rob Clark <<a href="mailto:robclark@freedesktop.org">robclark@freedesktop.org</a>><br>
>> >> >><br>
>> >> >> Some optimizations, like converting integer multiply/divide into<br>
>> >> >> left/<br>
>> >> >> right shifts, have additional constraints on the search expression.<br>
>> >> >> Like requiring that a variable is a constant power of two.  Support<br>
>> >> >> these cases by allowing a fxn name to be appended to the search var<br>
>> >> >> expression (ie. "a#32(is_power_of_two)").<br>
>> >> >><br>
>> >> >> TODO update doc/comment explaining search var syntax<br>
>> >> >> TODO the eagle-eyed viewer might have noticed that this could also<br>
>> >> >> replace the existing const syntax (ie. "#a").  Not sure if we should<br>
>> >> >> keep that.. we could make it syntactic sugar (ie '#' automatically<br>
>> >> >> sets<br>
>> >> >> the cond fxn ptr to 'is_const') or just get rid of it entirely?<br>
>> >> >> Maybe<br>
>> >> >> that is a follow-on clean-up patch?<br>
>> >> >><br>
>> >> >> Signed-off-by: Rob Clark <<a href="mailto:robclark@freedesktop.org">robclark@freedesktop.org</a>><br>
>> >> >> ---<br>
>> >> >>  src/compiler/nir/nir_algebraic.py     |  8 +++--<br>
>> >> >>  src/compiler/nir/nir_opt_algebraic.py |  5 +++<br>
>> >> >>  src/compiler/nir/nir_search.c         |  3 ++<br>
>> >> >>  src/compiler/nir/nir_search.h         | 10 ++++++<br>
>> >> >>  src/compiler/nir/nir_search_helpers.h | 66<br>
>> >> >> +++++++++++++++++++++++++++++++++++<br>
>> >> >>  5 files changed, 90 insertions(+), 2 deletions(-)<br>
>> >> >>  create mode 100644 src/compiler/nir/nir_search_helpers.h<br>
>> >> >><br>
>> >> >> diff --git a/src/compiler/nir/nir_algebraic.py<br>
>> >> >> b/src/compiler/nir/nir_algebraic.py<br>
>> >> >> index 285f853..19ac6ee 100644<br>
>> >> >> --- a/src/compiler/nir/nir_algebraic.py<br>
>> >> >> +++ b/src/compiler/nir/nir_algebraic.py<br>
>> >> >> @@ -76,6 +76,7 @@ class Value(object):<br>
>> >> >>           return Constant(val, name_base)<br>
>> >> >><br>
>> >> >>     __template = mako.template.Template("""<br>
>> >> >> +#include "compiler/nir/nir_search_helpers.h"<br>
>> >> >>  static const ${val.c_type} ${<a href="http://val.name" rel="noreferrer" target="_blank">val.name</a>} = {<br>
>> >> >>     { ${val.type_enum}, ${val.bit_size} },<br>
>> >> >>  % if isinstance(val, Constant):<br>
>> >> >> @@ -84,6 +85,7 @@ static const ${val.c_type} ${<a href="http://val.name" rel="noreferrer" target="_blank">val.name</a>} = {<br>
>> >> >>     ${val.index}, /* ${val.var_name} */<br>
>> >> >>     ${'true' if val.is_constant else 'false'},<br>
>> >> >>     ${val.type() or 'nir_type_invalid' },<br>
>> >> >> +   ${val.cond if val.cond else 'NULL'},<br>
>> >> >>  % elif isinstance(val, Expression):<br>
>> >> >>     ${'true' if val.inexact else 'false'},<br>
>> >> >>     nir_op_${val.opcode},<br>
>> >> >> @@ -113,7 +115,7 @@ static const ${val.c_type} ${<a href="http://val.name" rel="noreferrer" target="_blank">val.name</a>} = {<br>
>> >> >>                                      Variable=Variable,<br>
>> >> >>                                      Expression=Expression)<br>
>> >> >><br>
>> >> >> -_constant_re = re.compile(r"(?P<value>[^@]+)(?:@(?P<bits>\d+))?")<br>
>> >> >> +_constant_re = re.compile(r"(?P<value>[^@\(]+)(?:@(?P<bits>\d+))?")<br>
>> >> ><br>
>> >> ><br>
>> >> > Spurious change?<br>
>> >> ><br>
>> >><br>
>> >> I thought it needed to avoid matching something like<br>
>> >> a(is_power_of_two).. but it seems to work with that hunk reverted so I<br>
>> >> guess I can drop it..<br>
>> >><br>
>> >> >><br>
>> >> >><br>
>> >> >>  class Constant(Value):<br>
>> >> >>     def __init__(self, val, name):<br>
>> >> >> @@ -150,7 +152,8 @@ class Constant(Value):<br>
>> >> >>           return "nir_type_float"<br>
>> >> >><br>
>> >> >>  _var_name_re = re.compile(r"(?P<const>#)?(?P<name>\w+)"<br>
>> >> >> -<br>
>> >> >> r"(?:@(?P<type>int|uint|bool|float)?(?P<bits>\d+)?)?")<br>
>> >> >> +<br>
>> >> >> r"(?:@(?P<type>int|uint|bool|float)?(?P<bits>\d+)?)?"<br>
>> >> >> +                          r"(?P<cond>\([^\)]+\))?")<br>
>> >> >><br>
>> >> >>  class Variable(Value):<br>
>> >> >>     def __init__(self, val, name, varset):<br>
>> >> >> @@ -161,6 +164,7 @@ class Variable(Value):<br>
>> >> >><br>
>> >> >>        self.var_name = m.group('name')<br>
>> >> >>        self.is_constant = m.group('const') is not None<br>
>> >> >> +      self.cond = m.group('cond')<br>
>> >> >>        self.required_type = m.group('type')<br>
>> >> >>        self.bit_size = int(m.group('bits')) if m.group('bits') else<br>
>> >> >> 0<br>
>> >> >><br>
>> >> >> diff --git a/src/compiler/nir/nir_opt_algebraic.py<br>
>> >> >> b/src/compiler/nir/nir_opt_algebraic.py<br>
>> >> >> index 0a95725..952a91a 100644<br>
>> >> >> --- a/src/compiler/nir/nir_opt_algebraic.py<br>
>> >> >> +++ b/src/compiler/nir/nir_opt_algebraic.py<br>
>> >> >> @@ -62,6 +62,11 @@ d = 'd'<br>
>> >> >>  # constructed value should have that bit-size.<br>
>> >> >><br>
>> >> >>  optimizations = [<br>
>> >> >> +<br>
>> >> >> +   (('imul', a, '#b@32(is_power_of_two)'), ('ishl', a, ('find_lsb',<br>
>> >> >> b))),<br>
>> >> >> +   (('udiv', a, '#b@32(is_power_of_two)'), ('ushr', a, ('find_lsb',<br>
>> >> >> b))),<br>
>> >> >> +   (('umod', a, '#b(is_power_of_two)'),    ('iand', a, ('isub', b,<br>
>> >> >> 1))),<br>
>> >> >> +<br>
>> >> >>     (('fneg', ('fneg', a)), a),<br>
>> >> >>     (('ineg', ('ineg', a)), a),<br>
>> >> >>     (('fabs', ('fabs', a)), ('fabs', a)),<br>
>> >> >> diff --git a/src/compiler/nir/nir_search.c<br>
>> >> >> b/src/compiler/nir/nir_search.c<br>
>> >> >> index 2c2fd92..b21fb2c 100644<br>
>> >> >> --- a/src/compiler/nir/nir_search.c<br>
>> >> >> +++ b/src/compiler/nir/nir_search.c<br>
>> >> >> @@ -127,6 +127,9 @@ match_value(const nir_search_value *value,<br>
>> >> >> nir_alu_instr *instr, unsigned src,<br>
>> >> >>               instr->src[src].src.ssa->parent_instr->type !=<br>
>> >> >> nir_instr_type_load_const)<br>
>> >> >>              return false;<br>
>> >> >><br>
>> >> >> +         if (var->cond && !var->cond(instr, src, num_components,<br>
>> >> >> new_swizzle))<br>
>> >> >> +            return false;<br>
>> >> >> +<br>
>> >> >>           if (var->type != nir_type_invalid) {<br>
>> >> >>              if (instr->src[src].src.ssa->parent_instr->type !=<br>
>> >> >> nir_instr_type_alu)<br>
>> >> >>                 return false;<br>
>> >> >> diff --git a/src/compiler/nir/nir_search.h<br>
>> >> >> b/src/compiler/nir/nir_search.h<br>
>> >> >> index a500feb..f55d797 100644<br>
>> >> >> --- a/src/compiler/nir/nir_search.h<br>
>> >> >> +++ b/src/compiler/nir/nir_search.h<br>
>> >> >> @@ -68,6 +68,16 @@ typedef struct {<br>
>> >> >>      * never match anything.<br>
>> >> >>      */<br>
>> >> >>     nir_alu_type type;<br>
>> >> >> +<br>
>> >> >> +   /** Optional condition fxn ptr<br>
>> >> >> +    *<br>
>> >> >> +    * This is only allowed in search expressions, and allows<br>
>> >> >> additional<br>
>> >> >> +    * constraints to be placed on the match.  Typically used for<br>
>> >> >> 'is_constant'<br>
>> >> >> +    * variables to require, for example, power-of-two in order for<br>
>> >> >> the<br>
>> >> >> search<br>
>> >> >> +    * to match.<br>
>> >> >> +    */<br>
>> >> >> +   bool (*cond)(nir_alu_instr *instr, unsigned src,<br>
>> >> >> +                unsigned num_components, const uint8_t *swizzle);<br>
>> >> >>  } nir_search_variable;<br>
>> >> >><br>
>> >> >>  typedef struct {<br>
>> >> >> diff --git a/src/compiler/nir/nir_search_helpers.h<br>
>> >> >> b/src/compiler/nir/nir_search_helpers.h<br>
>> >> >> new file mode 100644<br>
>> >> >> index 0000000..8ed2ca0<br>
>> >> >> --- /dev/null<br>
>> >> >> +++ b/src/compiler/nir/nir_search_helpers.h<br>
>> >> >> @@ -0,0 +1,66 @@<br>
>> >> >> +/*<br>
>> >> >> + * Copyright © 2016 Red Hat<br>
>> >> >> + *<br>
>> >> >> + * Permission is hereby granted, free of charge, to any person<br>
>> >> >> obtaining<br>
>> >> >> 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<br>
>> >> >> next<br>
>> >> >> + * paragraph) shall be included in all copies or substantial<br>
>> >> >> portions<br>
>> >> >> of<br>
>> >> >> 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<br>
>> >> >> 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>
>> >> >> + *    Rob Clark <<a href="mailto:robclark@freedesktop.org">robclark@freedesktop.org</a>><br>
>> >> >> + */<br>
>> >> >> +<br>
>> >> >> +#ifndef _NIR_SEARCH_HELPERS_<br>
>> >> >> +#define _NIR_SEARCH_HELPERS_<br>
>> >> >> +<br>
>> >> >> +#include "nir.h"<br>
>> >> >> +<br>
>> >> >> +static inline bool<br>
>> >> >> +__is_power_of_two(unsigned int x)<br>
>> >> >> +{<br>
>> >> >> +   return ((x != 0) && !(x & (x - 1)));<br>
>> >> >> +}<br>
>> >> >> +<br>
>> >> >> +static inline bool<br>
>> >> >> +is_power_of_two(nir_alu_instr *instr, unsigned src, unsigned<br>
>> >> >> num_components,<br>
>> >> >> +                const uint8_t *swizzle)<br>
>> >> >> +{<br>
>> >> >> +   nir_const_value *val =<br>
>> >> >> nir_src_as_const_value(instr->src[src].src);<br>
>> >> >> +<br>
>> >> >> +   /* only constant src's: */<br>
>> >> >> +   if (!val)<br>
>> >> >> +      return false;<br>
>> >> >> +<br>
>> >> >> +   for (unsigned i = 0; i < num_components; i++) {<br>
>> >> >> +      switch (nir_op_infos[instr->op].input_types[src]) {<br>
>> >> >> +      case nir_type_int:<br>
>> >> >> +         if (!__is_power_of_two(val->i32[swizzle[i]]))<br>
>> >> >> +            return false;<br>
>> >> >> +         break;<br>
>> >> >> +      case nir_type_uint:<br>
>> >> >> +         if (!__is_power_of_two(val->u32[swizzle[i]]))<br>
>> >> >> +            return false;<br>
>> >> ><br>
>> >> ><br>
>> >> > Your implementation of __is_power_of_two takes an unsigned.  There's<br>
>> >> > no<br>
>> >> > benefit to splitting it into two cases and it just creates a false<br>
>> >> > distinction.  If you do, you can probably inline the helper (I don't<br>
>> >> > care<br>
>> >> > much one way or the other on that).<br>
>> >><br>
>> >> hmm, are you sure about negative PoT?  Although possibly that should<br>
>> >> be '__is_power_of_two(ABS(val->i32[..])'?<br>
>> ><br>
>> ><br>
>> > I don't know off-hand whether or not it's correct for negative<br>
>> > power-of-two.<br>
>> > However, I do know that it does exactly the same thing in both cases<br>
>> > regardless of whether or not the first one is correct :-)<br>
>> > --Jason<br>
>><br>
>> so, for the record, __is_power_of_two(ABS(val->i32[..])) seems to be<br>
>> the correct thing to do.  That would let us add a (presumably<br>
>> optional) rule to lower idiv to ushr plus a multiply by the isign of<br>
>> each of the args..<br>
><br>
> Unfortunately, idiv can never be lowered because -1 >> 1 == -1.  Yeah,<br>
> that's annoying.<br>
><br>
> Also, I don't think any of the optimizations you've added here works for<br>
> negative numbers without a sign-flip.  We would need a pair of<br>
> optimizations: one for non-negative powers of two and one for negative.<br>
<br>
</div></div>so pretty sure this isn't an issue, since (udiv, a,<br>
#b(is_power_of_two)) hits the nir_type_uint case in is_power_of_two()<br>
and doesn't recognize -2 (for example) as a PoT..<br>
<br>
possibly we could do a bit better, I think we'd have to split<br>
is_power_of_two() into is_neg_power_of_two() and<br>
is_pos_power_of_two()..<br></blockquote><div><br></div><div>I like that plan<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
BR,<br>
-R<br>
<div class="HOEnZb"><div class="h5"><br>
>> BR,<br>
>> -R<br>
>><br>
>> >><br>
>> >> BR,<br>
>> >> -R<br>
>> >><br>
>> >> > All in all, this seems ok.  The "(some_function)" syntax seems clunky<br>
>> >> > but I<br>
>> >> > can't come up with anything better off-hand.  Let's just go with it<br>
>> >> > for<br>
>> >> > now<br>
>> >> > and we can always change it later.<br>
>> >> ><br>
>> >> > Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
>> >> ><br>
>> >> >><br>
>> >> >> +         break;<br>
>> >> >> +      default:<br>
>> >> >> +         return false;<br>
>> >> >> +      }<br>
>> >> >> +   }<br>
>> >> >> +<br>
>> >> >> +   return true;<br>
>> >> >> +}<br>
>> >> >> +<br>
>> >> >> +#endif /* _NIR_SEARCH_ */<br>
>> >> >> --<br>
>> >> >> 2.5.5<br>
>> >> >><br>
>> >> ><br>
>> ><br>
>> ><br>
</div></div></blockquote></div><br></div></div>