From 2a7d81759122a22c6616061d02208bc308682830 Mon Sep 17 00:00:00 2001 From: Lorenzo Rossi Date: Tue, 21 Apr 2026 19:11:49 +0200 Subject: [PATCH] nir/opt_algebraic: optimize fadd/fmul with 16-bit source and constant Signed-off-by: Lorenzo Rossi Reviewed-by: Eric R. Smith Reviewed-by: Faith Ekstrand Part-of: --- src/compiler/nir/nir_opt_algebraic.py | 5 +++++ src/compiler/nir/nir_search_helpers.h | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py index 939bc0f79cd..ebcaae2c77e 100644 --- a/src/compiler/nir/nir_opt_algebraic.py +++ b/src/compiler/nir/nir_opt_algebraic.py @@ -1941,6 +1941,11 @@ optimizations.extend([ (('f2u32', ('f2fmp', 'a@32')), ('f2u32', a), 'true', TestStatus.UNSUPPORTED), (('i2f32', ('i2imp', 'a@32')), ('i2f32', a), 'true', TestStatus.UNSUPPORTED), + # f16 -> f2f32 -> fmul32 -> f2fmp when the second operand is a constant + # The optimization only works when the constant can be safely represented with 16 bits + (('f2fmp', ('fmul(is_used_once,contract)', ('f2f32', 'a@16'), '#b(is_representable_as_f16)')), ('fmul', a, ('f2fmp', b)), 'true', TestStatus.UNSUPPORTED), + (('f2fmp', ('fadd(is_used_once,contract)', ('f2f32', 'a@16'), '#b(is_representable_as_f16)')), ('fadd', a, ('f2fmp', b)), 'true', TestStatus.UNSUPPORTED), + (('ffloor', 'a(is_integral)'), a), (('fceil', 'a(is_integral)'), a), (('ftrunc', 'a(is_integral)'), a), diff --git a/src/compiler/nir/nir_search_helpers.h b/src/compiler/nir/nir_search_helpers.h index 328e1936d30..95b4f2b9ba5 100644 --- a/src/compiler/nir/nir_search_helpers.h +++ b/src/compiler/nir/nir_search_helpers.h @@ -30,6 +30,7 @@ #include #include "util/bitscan.h" #include "util/u_math.h" +#include "util/half_float.h" #include "nir.h" #include "nir_range_analysis.h" #include "nir_search.h" @@ -355,6 +356,25 @@ is_neg2x_16_bits(UNUSED const nir_search_state *state, const nir_alu_instr *inst return is_16_bits_with_scale(instr, src, num_components, swizzle, -2); } +/** Is this a float constant that could fit in a half? */ +static inline bool +is_representable_as_f16(UNUSED const nir_search_state *state, + const nir_alu_instr *instr, + unsigned src, unsigned num_components, + const uint8_t *swizzle) +{ + /* only constant srcs: */ + if (!nir_src_is_const(instr->src[src].src)) + return false; + + for (unsigned i = 0; i < num_components; i++) { + double value = nir_src_comp_as_float(instr->src[src].src, swizzle[i]); + if (!_mesa_float_is_half(value)) + return false; + } + return true; +} + static inline bool is_not_const(UNUSED const nir_search_state *state, const nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components,