From e14f85366ebbc57f45d2561e0d3f0804f8adb549 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Fri, 28 Oct 2022 16:27:17 -0700 Subject: [PATCH] nir/lower_int64: Fix float16 to int64 conversions. Currently float16 to int64 conversions don't work correctly, because the "div" variable has an infinite value, since 2^32 isn't representable as a 16-bit float, which causes the result of of rem(x, div) to be NaN for all inputs, leading to an incorrect result. Since no values of magnitude greater than 2^32 are representable as a float16 we don't actually need to do the fdiv/frem operations, the conversion is equivalent to f2u32 with the result padded to 64 bits. Rework: * Jordan: Handle f16 in if/else rather than conditional Fixes: 936c58c8fcc ("nir: Extend nir_lower_int64() to support i2f/f2i lowering") Reviewed-by: Jordan Justen Reviewed-by: Lionel Landwerlin Part-of: --- src/compiler/nir/nir_lower_int64.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/compiler/nir/nir_lower_int64.c b/src/compiler/nir/nir_lower_int64.c index 005343fa4d5..e73e3fab1f6 100644 --- a/src/compiler/nir/nir_lower_int64.c +++ b/src/compiler/nir/nir_lower_int64.c @@ -813,10 +813,15 @@ lower_f2(nir_builder *b, nir_ssa_def *x, bool dst_is_signed) if (dst_is_signed) x = nir_fabs(b, x); - nir_ssa_def *div = nir_imm_floatN_t(b, 1ULL << 32, x->bit_size); - nir_ssa_def *res_hi = nir_f2u32(b, nir_fdiv(b, x, div)); - nir_ssa_def *res_lo = nir_f2u32(b, nir_frem(b, x, div)); - nir_ssa_def *res = nir_pack_64_2x32_split(b, res_lo, res_hi); + nir_ssa_def *res; + if (x->bit_size < 32) { + res = nir_pack_64_2x32_split(b, nir_f2u32(b, x), nir_imm_int(b, 0)); + } else { + nir_ssa_def *div = nir_imm_floatN_t(b, 1ULL << 32, x->bit_size); + nir_ssa_def *res_hi = nir_f2u32(b, nir_fdiv(b, x, div)); + nir_ssa_def *res_lo = nir_f2u32(b, nir_frem(b, x, div)); + res = nir_pack_64_2x32_split(b, res_lo, res_hi); + } if (dst_is_signed) res = nir_bcsel(b, nir_flt(b, x_sign, nir_imm_floatN_t(b, 0, x->bit_size)),