<p dir="ltr"><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>> 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>> 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 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 sets<br>
> >> >> the cond fxn ptr to 'is_const') or just get rid of it entirely?  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">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">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">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 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 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 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 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 EVENT<br>
> >> >> SHALL<br>
> >> >> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 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 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 = 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 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 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..</p>
<p dir="ltr">Unfortunately, idiv can never be lowered because -1 >> 1 == -1.  Yeah, that's annoying.</p>
<p dir="ltr">Also, I don't think any of the optimizations you've added here works for negative numbers without a sign-flip.  We would need a pair of optimizations: one for non-negative powers of two and one for negative.</p>
<p dir="ltr">> 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 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>
</p>