diff options
-rw-r--r-- | src/compiler/nir/nir_opt_algebraic.py | 12 | ||||
-rw-r--r-- | src/compiler/nir/nir_search_helpers.h | 24 |
2 files changed, 36 insertions, 0 deletions
diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py index fa940429281..09eaeaf3f23 100644 --- a/src/compiler/nir/nir_opt_algebraic.py +++ b/src/compiler/nir/nir_opt_algebraic.py @@ -1250,6 +1250,18 @@ late_optimizations = [ (('fmax', ('fadd(is_used_once)', '#c', a), ('fadd(is_used_once)', '#c', b)), ('fadd', c, ('fmax', a, b))), (('bcsel', a, 0, ('b2f32', ('inot', 'b@bool'))), ('b2f32', ('inot', ('ior', a, b)))), + + # Things that look like DPH in the source shader may get expanded to + # something that looks like dot(v1.xyz, v2.xyz) + v1.w by the time it gets + # to NIR. After FFMA is generated, this can look like: + # + # fadd(ffma(v1.z, v2.z, ffma(v1.y, v2.y, fmul(v1.x, v2.x))), v1.w) + # + # Reassociate the last addition into the first multiplication. + (('~fadd', ('ffma(is_used_once)', a, b, ('ffma', c, d, ('fmul', 'e(is_not_const_and_not_fsign)', 'f(is_not_const_and_not_fsign)'))), 'g(is_not_const)'), + ('ffma', a, b, ('ffma', c, d, ('ffma', e, 'f', 'g'))), '!options->intel_vec4'), + (('~fadd', ('ffma(is_used_once)', a, b, ('fmul', 'e(is_not_const_and_not_fsign)', 'f(is_not_const_and_not_fsign)') ), 'g(is_not_const)'), + ('ffma', a, b, ('ffma', e, 'f', 'g') ), '!options->intel_vec4'), ] print(nir_algebraic.AlgebraicPass("nir_opt_algebraic", optimizations).render()) diff --git a/src/compiler/nir/nir_search_helpers.h b/src/compiler/nir/nir_search_helpers.h index 658ed2b1d5b..7c19cd3fdfe 100644 --- a/src/compiler/nir/nir_search_helpers.h +++ b/src/compiler/nir/nir_search_helpers.h @@ -190,6 +190,30 @@ is_not_fmul(nir_alu_instr *instr, unsigned src, } static inline bool +is_fsign(nir_alu_instr *instr, unsigned src, + UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) +{ + nir_alu_instr *src_alu = + nir_src_as_alu_instr(instr->src[src].src); + + if (src_alu == NULL) + return false; + + if (src_alu->op == nir_op_fneg) + src_alu = nir_src_as_alu_instr(src_alu->src[0].src); + + return src_alu->op == nir_op_fsign; +} + +static inline bool +is_not_const_and_not_fsign(nir_alu_instr *instr, unsigned src, + unsigned num_components, const uint8_t *swizzle) +{ + return is_not_const(instr, src, num_components, swizzle) && + !is_fsign(instr, src, num_components, swizzle); +} + +static inline bool is_used_once(nir_alu_instr *instr) { bool zero_if_use = list_empty(&instr->dest.dest.ssa.if_uses); |