diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index 19620c2c401..c2ad1c805d1 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -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); diff --git a/src/asahi/compiler/agx_compile.h b/src/asahi/compiler/agx_compile.h index 1fd7c25695f..cba23f505fd 100644 --- a/src/asahi/compiler/agx_compile.h +++ b/src/asahi/compiler/agx_compile.h @@ -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,