<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Feb 24, 2017 at 3:58 PM, Matt Turner <span dir="ltr"><<a href="mailto:mattst88@gmail.com" target="_blank">mattst88@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 Fri, Feb 24, 2017 at 3:48 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
> The algorithms used by this pass, especially for division, are heavily<br>
> based on the work Ian Romanick did for the similar int64 lowering pass<br>
> in the GLSL compiler.<br>
><br>
> v2: Properly handle vectors<br>
><br>
> v3: Get rid of log2_denom stuff.  Since we're using bcsel, we do all the<br>
>     calculations anyway and this is just extra instructions.<br>
> ---<br>
>  src/compiler/Makefile.sources      |   1 +<br>
>  src/compiler/nir/nir.h             |  11 ++<br>
>  src/compiler/nir/nir_lower_<wbr>int64.c | 261 ++++++++++++++++++++++++++++++<wbr>+++++++<br>
>  3 files changed, 273 insertions(+)<br>
>  create mode 100644 src/compiler/nir/nir_lower_<wbr>int64.c<br>
><br>
> diff --git a/src/compiler/Makefile.<wbr>sources b/src/compiler/Makefile.<wbr>sources<br>
> index 643a018..2455d4e 100644<br>
> --- a/src/compiler/Makefile.<wbr>sources<br>
> +++ b/src/compiler/Makefile.<wbr>sources<br>
> @@ -221,6 +221,7 @@ NIR_FILES = \<br>
>         nir/nir_lower_locals_to_regs.c \<br>
>         nir/nir_lower_idiv.c \<br>
>         nir/nir_lower_indirect_derefs.<wbr>c \<br>
> +       nir/nir_lower_int64.c \<br>
>         nir/nir_lower_io.c \<br>
>         nir/nir_lower_io_to_<wbr>temporaries.c \<br>
>         nir/nir_lower_io_to_scalar.c \<br>
> diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h<br>
> index 5243a9e..1a23e19 100644<br>
> --- a/src/compiler/nir/nir.h<br>
> +++ b/src/compiler/nir/nir.h<br>
> @@ -2540,6 +2540,17 @@ void nir_lower_to_source_mods(nir_<wbr>shader *shader);<br>
>  bool nir_lower_gs_intrinsics(nir_<wbr>shader *shader);<br>
><br>
>  typedef enum {<br>
> +   nir_lower_imul64 = (1 << 0),<br>
> +   nir_lower_isign64 = (1 << 1),<br>
> +   nir_lower_udiv64 = (1 << 2),<br>
> +   nir_lower_idiv64 = (1 << 3),<br>
> +   nir_lower_umod64 = (1 << 4),<br>
> +   nir_lower_imod64 = (1 << 5),<br>
> +} nir_lower_int64_options;<br>
> +<br>
> +bool nir_lower_int64(nir_shader *shader, nir_lower_int64_options options);<br>
> +<br>
> +typedef enum {<br>
>     nir_lower_drcp = (1 << 0),<br>
>     nir_lower_dsqrt = (1 << 1),<br>
>     nir_lower_drsq = (1 << 2),<br>
> diff --git a/src/compiler/nir/nir_lower_<wbr>int64.c b/src/compiler/nir/nir_lower_<wbr>int64.c<br>
> new file mode 100644<br>
> index 0000000..c40305e<br>
> --- /dev/null<br>
> +++ b/src/compiler/nir/nir_lower_<wbr>int64.c<br>
> @@ -0,0 +1,261 @@<br>
> +/*<br>
> + * Copyright © 2016 Intel Corporation<br>
> + *<br>
> + * Permission is hereby granted, free of charge, to any person obtaining a<br>
> + * copy of this software and associated documentation files (the "Software"),<br>
> + * to deal in the Software without restriction, including without limitation<br>
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
> + * and/or sell copies of the Software, and to permit persons to whom the<br>
> + * Software is furnished to do so, subject to the following conditions:<br>
> + *<br>
> + * The above copyright notice and this permission notice (including the next<br>
> + * paragraph) shall be included in all copies or substantial portions of the<br>
> + * Software.<br>
> + *<br>
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL<br>
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
> + * IN THE SOFTWARE.<br>
> + */<br>
> +<br>
> +#include "nir.h"<br>
> +#include "nir_builder.h"<br>
> +<br>
> +static nir_ssa_def *<br>
> +lower_umul64(nir_builder *b, nir_ssa_def *x, nir_ssa_def *y)<br>
> +{<br>
> +   nir_ssa_def *x_lo = nir_unpack_64_2x32_split_x(b, x);<br>
> +   nir_ssa_def *x_hi = nir_unpack_64_2x32_split_y(b, x);<br>
> +   nir_ssa_def *y_lo = nir_unpack_64_2x32_split_x(b, y);<br>
> +   nir_ssa_def *y_hi = nir_unpack_64_2x32_split_y(b, y);<br>
> +<br>
> +   nir_ssa_def *res_lo = nir_imul(b, x_lo, y_lo);<br>
> +   nir_ssa_def *res_hi = nir_iadd(b, nir_umul_high(b, x_lo, y_lo),<br>
> +                         nir_iadd(b, nir_imul(b, x_lo, y_hi),<br>
> +                                     nir_imul(b, x_hi, y_lo)));<br>
> +<br>
> +   return nir_pack_64_2x32_split(b, res_lo, res_hi);<br>
> +}<br>
> +<br>
> +static nir_ssa_def *<br>
> +lower_isign64(nir_builder *b, nir_ssa_def *x)<br>
> +{<br>
> +   nir_ssa_def *x_lo = nir_unpack_64_2x32_split_x(b, x);<br>
> +   nir_ssa_def *x_hi = nir_unpack_64_2x32_split_y(b, x);<br>
> +<br>
> +   nir_ssa_def *is_non_zero = nir_i2b(b, nir_ior(b, x_lo, x_hi));<br>
> +   nir_ssa_def *res_hi = nir_ishr(b, x_hi, nir_imm_int(b, 31));<br>
> +   nir_ssa_def *res_lo = nir_ior(b, res_hi, nir_b2i(b, is_non_zero));<br>
> +<br>
> +   return nir_pack_64_2x32_split(b, res_lo, res_hi);<br>
> +}<br>
> +<br>
> +static void<br>
> +lower_udiv64_mod64(nir_<wbr>builder *b, nir_ssa_def *n, nir_ssa_def *d,<br>
> +                   nir_ssa_def **q, nir_ssa_def **r)<br>
> +{<br>
> +   /* TODO: We should specially handle the case where the denominator is a<br>
> +    * constant.  In that case, we should be able to reduce it to a multiply by<br>
> +    * a constant, some shifts, and an add.<br>
> +    */<br>
> +   nir_ssa_def *n_lo = nir_unpack_64_2x32_split_x(b, n);<br>
> +   nir_ssa_def *n_hi = nir_unpack_64_2x32_split_y(b, n);<br>
> +   nir_ssa_def *d_lo = nir_unpack_64_2x32_split_x(b, d);<br>
> +   nir_ssa_def *d_hi = nir_unpack_64_2x32_split_y(b, d);<br>
> +<br>
> +   nir_const_value v = { .u32 = { 0, 0, 0, 0 } };<br>
> +   nir_ssa_def *q_lo = nir_build_imm(b, n->num_components, 32, v);<br>
> +   nir_ssa_def *q_hi = nir_build_imm(b, n->num_components, 32, v);<br>
> +<br>
> +   nir_ssa_def *n_hi_before_if = n_hi;<br>
> +   nir_ssa_def *q_hi_before_if = q_hi;<br>
> +<br>
> +   /* If the upper 32 bits of denom are non-zero, it is impossible for shifts<br>
> +    * greater than 32 bits to occur.  If the upper 32 bits of the numerator<br>
> +    * are zero, it is impossible for (denom << [63, 32]) <= numer unless<br>
> +    * denom == 0.<br>
> +    */<br>
> +   nir_ssa_def *need_high_div =<br>
> +      nir_iand(b, nir_ieq(b, d_hi, nir_imm_int(b, 0)), nir_uge(b, n_hi, d_lo));<br>
> +   nir_push_if(b, nir_bany(b, need_high_div));<br>
> +   {<br>
> +      /* If we only have one component, then the bany above goes away and<br>
> +       * this is always true within the if statement.<br>
> +       */<br>
> +      if (n->num_components == 1)<br>
> +         need_high_div = nir_imm_int(b, NIR_TRUE);<br>
> +<br>
> +      for (int i = 31; i >= 0; i--) {<br>
> +         /* if ((d.x << i) <= n.y) {<br>
> +         *    n.y -= d.x << i;<br>
> +         *    quot.y |= 1U << i;<br>
> +         * }<br>
<br>
</div></div>Looks like these three lines are missing one space of indentation.<br>
</blockquote></div><br></div><div class="gmail_extra">Gah!  How did tabs get in there!  Good catch.  Fixed locally.<br></div></div>