diff --git a/src/gallium/drivers/r300/compiler/r300_nir.h b/src/gallium/drivers/r300/compiler/r300_nir.h index 951e0a8cdbd..916eb08fd48 100644 --- a/src/gallium/drivers/r300/compiler/r300_nir.h +++ b/src/gallium/drivers/r300/compiler/r300_nir.h @@ -26,6 +26,27 @@ #include "pipe/p_screen.h" #include "compiler/nir/nir.h" +static inline bool +is_ubo_or_input(UNUSED struct hash_table *ht, const nir_alu_instr *instr, + unsigned src, unsigned num_components, + const uint8_t *swizzle) +{ + nir_instr *parent = instr->src[src].src.ssa->parent_instr; + if (parent->type != nir_instr_type_intrinsic) + return false; + + nir_intrinsic_instr *intrinsic = nir_instr_as_intrinsic(parent); + + switch (intrinsic->intrinsic) { + case nir_intrinsic_load_ubo_vec4: + case nir_intrinsic_load_input: + case nir_intrinsic_load_interpolated_input: + return true; + default: + return false; + } +} + char *r300_finalize_nir(struct pipe_screen *pscreen, void *nir); extern bool r300_transform_vs_trig_input(struct nir_shader *shader); diff --git a/src/gallium/drivers/r300/compiler/r300_nir_algebraic.py b/src/gallium/drivers/r300/compiler/r300_nir_algebraic.py index c27dba90ec4..485943e16f2 100644 --- a/src/gallium/drivers/r300/compiler/r300_nir_algebraic.py +++ b/src/gallium/drivers/r300/compiler/r300_nir_algebraic.py @@ -76,6 +76,10 @@ r300_nir_prepare_presubtract = [ (('ffma', -2.0, a, 1.0), ('fneg', ('ffma', ('fneg', a), 2.0, 1.0))), (('ffma', 2.0, a, -1.0), ('fneg', ('ffma', ('fneg', a), 2.0, 1.0))), (('ffma', a, 2.0, -1.0), ('fneg', ('ffma', ('fneg', a), 2.0, 1.0))), + # x * 2 can be usually folded into output modifier for the previous + # instruction, but that only works if x is a temporary. If it is input or + # constant just convert it to add instead. + (('fmul', 'a(is_ubo_or_input)', 2.0), ('fadd', a, a)), ] # Previous prepare_presubtract pass can sometimes produce double fneg patterns.