[Mesa-dev] [PATCH 04/22] nir/spirv: add OpIsFinite and OpIsNormal

Jason Ekstrand jason at jlekstrand.net
Wed Nov 21 21:40:01 UTC 2018


On Tue, Nov 13, 2018 at 9:48 AM Karol Herbst <kherbst at redhat.com> wrote:

> From: Rob Clark <robdclark at gmail.com>
>
> changes by Karol:
> v2: make compatible with 64 bit floats
>     fix isfinite
> v3: use snake_case.
>
> Signed-off-by: Karol Herbst <kherbst at redhat.com>
> ---
>  src/compiler/spirv/vtn_alu.c | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
>
> diff --git a/src/compiler/spirv/vtn_alu.c b/src/compiler/spirv/vtn_alu.c
> index b1492c1501a..ea25d4bcbdc 100644
> --- a/src/compiler/spirv/vtn_alu.c
> +++ b/src/compiler/spirv/vtn_alu.c
> @@ -583,6 +583,38 @@ vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,
>        break;
>     }
>
> +   case SpvOpIsFinite: {
> +      nir_ssa_def *inf = nir_imm_floatN_t(&b->nb, INFINITY,
> src[0]->bit_size);
> +      nir_ssa_def *is_number = nir_feq(&b->nb, src[0], src[0]);
> +      nir_ssa_def *is_not_inf = nir_ine(&b->nb, nir_fabs(&b->nb, src[0]),
> inf);
> +      val->ssa->def = nir_iand(&b->nb, is_number, is_not_inf);
>

What we really want here is FOrdNotEqual.  Unfortunately, I'm not sure
we're handling ordered vs. not correctly in the NIR opcodes but you should
be able to just do return is_not_inf and the abs(x) != INF will return
false if x is NaN assuming that abs handles NaN correctly.

Also, set b->nb.exact = true prior to this sequence to make it build exact
opcodes so that NIR doesn't try to optimize anything away.

Also, I think it'd be nice to have these in builder helpers.  Not a bit
deal but it'd be nice.


> +      break;
> +   }
> +
> +   case SpvOpIsNormal: {
> +      unsigned bit_size = src[0]->bit_size;
> +
> +      uint32_t m;
> +      if (bit_size == 64)
> +         m = 11;
> +      else if (bit_size == 32)
> +         m = 8;
> +      else if (bit_size == 16)
> +         m = 5;
> +      else
> +         assert(!"unknown float type");
> +
> +      nir_ssa_def *shift = nir_imm_int(&b->nb, bit_size - m - 1);
> +      nir_ssa_def *abs = nir_fabs(&b->nb, src[0]);
> +      nir_ssa_def *exp = nir_iadd(&b->nb,
> +                                  nir_ushr(&b->nb, abs, shift),
> +                                  nir_imm_intN_t(&b->nb, -1, bit_size));
> +      val->ssa->def = nir_ult(&b->nb,
> +                              exp,
> +                              nir_imm_intN_t(&b->nb, (1 << m) - 2,
> bit_size));
>

I think you can do this way simpler:

iand(fne(x, 0.0), i2b(iand(x, 0x7f800000)))

assuming 0 is considered normal.


> +      break;
> +   }
> +
>     case SpvOpFUnordEqual:
>     case SpvOpFUnordNotEqual:
>     case SpvOpFUnordLessThan:
> --
> 2.19.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20181121/76817244/attachment.html>


More information about the mesa-dev mailing list