agx: set lower_fminmax_signed_zero

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Konstantin Seurer <konstantin.seurer@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30075>
This commit is contained in:
Alyssa Rosenzweig 2024-07-08 14:22:10 -04:00 committed by Marge Bot
parent d238d766c6
commit 6ac289dade
2 changed files with 6 additions and 17 deletions

View file

@ -1670,29 +1670,16 @@ static agx_instr *
agx_fminmax_to(agx_builder *b, agx_index dst, agx_index s0, agx_index s1,
nir_alu_instr *alu)
{
/* The hardware gtn/ltn modes are unfortunately incorrect for signed zeros */
assert(!nir_alu_instr_is_signed_zero_preserve(alu) &&
"should've been lowered");
bool fmax = alu->op == nir_op_fmax;
enum agx_fcond fcond = fmax ? AGX_FCOND_GTN : AGX_FCOND_LTN;
enum agx_icond icond = fmax ? AGX_ICOND_SGT : AGX_ICOND_SLT;
/* Calculate min/max with the appropriate hardware instruction */
agx_index tmp = agx_fcmpsel(b, s0, s1, s0, s1, fcond);
/* The hardware ltn/gtn modes implement IEEE 754 NaN rules. Unfortunately,
* they do not respect signed zeros, causing conformance fails. To
* workaround, when both operands are zero, we instead use integer min/max to
* get the appropriate sign on the result. We detect that case by checking
* for float equality of the inputs: signed zero is the only case where the
* floats are equal but the integer values are not, so this works for all
* cases. It's annoying that we need 3 SCIB instructions instead of 1, but
* hopefully apps don't ask for signed zero preserve if they don't need it.
*/
if (nir_is_float_control_signed_zero_preserve(alu->fp_fast_math,
alu->def.bit_size)) {
agx_index iminmax = agx_icmpsel(b, s0, s1, s0, s1, icond);
tmp = agx_fcmpsel(b, s0, s1, iminmax, tmp, AGX_FCOND_EQ);
}
/* Flush denorms, as cmpsel will not. */
return agx_fadd_to(b, dst, tmp, agx_negzero());
}
@ -3306,6 +3293,7 @@ agx_preprocess_nir(nir_shader *nir, const nir_shader *libagx)
NIR_PASS(_, nir, nir_lower_idiv, &idiv_options);
NIR_PASS(_, nir, nir_lower_frexp);
NIR_PASS(_, nir, nir_lower_alu);
NIR_PASS(_, nir, nir_lower_alu_to_scalar, NULL, NULL);
NIR_PASS(_, nir, nir_lower_load_const_to_scalar);
NIR_PASS(_, nir, nir_lower_flrp, 16 | 32 | 64, false);

View file

@ -270,6 +270,7 @@ static const nir_shader_compiler_options agx_nir_options = {
.lower_isign = true,
.lower_fsign = true,
.lower_iabs = true,
.lower_fminmax_signed_zero = true,
.lower_fdph = true,
.lower_ffract = true,
.lower_ldexp = true,