Module: Mesa Branch: main Commit: 3e042173e4bb2ba5cdac1b3328d9b8021ba19c07 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=3e042173e4bb2ba5cdac1b3328d9b8021ba19c07
Author: Faith Ekstrand <[email protected]> Date: Fri Dec 8 11:38:37 2023 -0600 nir/lower_doubles: Add lowering for fmin/fmax/fsat Reviewed-by: Georg Lehmann <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26587> --- src/compiler/nir/nir.h | 4 +++- src/compiler/nir/nir_lower_double_ops.c | 37 ++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 3f9f7f8c29e..359909befe6 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -3523,7 +3523,9 @@ typedef enum { nir_lower_dsub = (1 << 9), nir_lower_ddiv = (1 << 10), nir_lower_dsign = (1 << 11), - nir_lower_fp64_full_software = (1 << 12), + nir_lower_dminmax = (1 << 12), + nir_lower_dsat = (1 << 13), + nir_lower_fp64_full_software = (1 << 14), } nir_lower_doubles_options; typedef enum { diff --git a/src/compiler/nir/nir_lower_double_ops.c b/src/compiler/nir/nir_lower_double_ops.c index 07be96dd69b..1c8933de702 100644 --- a/src/compiler/nir/nir_lower_double_ops.c +++ b/src/compiler/nir/nir_lower_double_ops.c @@ -450,6 +450,28 @@ lower_mod(nir_builder *b, nir_def *src0, nir_def *src1) return nir_fsub(b, src0, nir_fmul(b, src1, floor)); } +static nir_def * +lower_minmax(nir_builder *b, nir_op cmp, nir_def *src0, nir_def *src1) +{ + b->exact = true; + nir_def *src1_is_nan = nir_fneu(b, src1, src1); + nir_def *cmp_res = nir_build_alu2(b, cmp, src0, src1); + b->exact = false; + nir_def *take_src0 = nir_ior(b, src1_is_nan, cmp_res); + return nir_bcsel(b, take_src0, src0, src1); +} + +static nir_def * +lower_sat(nir_builder *b, nir_def *src) +{ + b->exact = true; + /* This will get lowered again if nir_lower_dminmax is set */ + nir_def *sat = nir_fclamp(b, src, nir_imm_double(b, 0), + nir_imm_double(b, 1)); + b->exact = false; + return sat; +} + static nir_def * lower_doubles_instr_to_soft(nir_builder *b, nir_alu_instr *instr, const nir_shader *softfp64, @@ -658,6 +680,11 @@ nir_lower_doubles_op_to_options_mask(nir_op opcode) return nir_lower_dsub; case nir_op_fdiv: return nir_lower_ddiv; + case nir_op_fmin: + case nir_op_fmax: + return nir_lower_dminmax; + case nir_op_fsat: + return nir_lower_dsat; default: return 0; } @@ -730,10 +757,14 @@ lower_doubles_instr(nir_builder *b, nir_instr *instr, void *_data) return lower_fract(b, src); case nir_op_fround_even: return lower_round_even(b, src); + case nir_op_fsat: + return lower_sat(b, src); case nir_op_fdiv: case nir_op_fsub: - case nir_op_fmod: { + case nir_op_fmod: + case nir_op_fmin: + case nir_op_fmax: { nir_def *src1 = nir_mov_alu(b, alu->src[1], alu->def.num_components); switch (alu->op) { @@ -743,6 +774,10 @@ lower_doubles_instr(nir_builder *b, nir_instr *instr, void *_data) return nir_fadd(b, src, nir_fneg(b, src1)); case nir_op_fmod: return lower_mod(b, src, src1); + case nir_op_fmin: + return lower_minmax(b, nir_op_flt, src, src1); + case nir_op_fmax: + return lower_minmax(b, nir_op_fge, src, src1); default: unreachable("unhandled opcode"); }
