nir/opcodes: use util_max_num/util_min_num for fmin/fmax constant folding.

Hopefully, this is easier to read.

The SPIR-V behavior has also since been clarified to require associativity.

Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39137>
This commit is contained in:
Georg Lehmann 2026-01-03 10:34:10 +01:00 committed by Marge Bot
parent 026d4cd200
commit 9c6d294111

View file

@ -956,25 +956,10 @@ opcode("fdph_replicated", 0, tfloat, [3, 4], [tfloat, tfloat], False, "",
"src0.x * src1.x + src0.y * src1.y + src0.z * src1.z + src1.w")
# The C fmin/fmax functions have implementation-defined behaviour for signed
# zeroes. However, SPIR-V requires:
#
# fmin(-0, +0) = -0
# fmax(+0, -0) = +0
#
# The NIR opcodes match SPIR-V. Furthermore, the NIR opcodes are commutative, so
# we must also ensure:
#
# fmin(+0, -0) = -0
# fmax(-0, +0) = +0
#
# To implement the constant folding, when the sources are equal, we use the
# min/max of the bit patterns which will order the signed zeroes while
# preserving all other values.
for op, macro in [("fmin", "MIN2"), ("fmax", "MAX2")]:
binop(op, tfloat, _2src_commutative + associative,
"bit_size == 64 ? " +
f"(src0 == src1 ? uid({macro}((int64_t)dui(src0), (int64_t)dui(src1))) : {op}(src0, src1)) :"
f"(src0 == src1 ? uif({macro}((int32_t)fui(src0), (int32_t)fui(src1))) : {op}f(src0, src1))")
# zeroes. However, SPIR-V requires IEEE 754-2019 minimumNumber/maximumNumber:
# -0 compares less than +0.
binop("fmin", tfloat, _2src_commutative + associative, ("util_min_num(src0, src1)"))
binop("fmax", tfloat, _2src_commutative + associative, ("util_max_num(src0, src1)"))
binop("imin", tint, _2src_commutative + associative, "MIN2(src0, src1)")
binop("umin", tuint, _2src_commutative + associative, "MIN2(src0, src1)")