diff options
author | Jason Ekstrand <[email protected]> | 2015-03-23 14:55:20 -0700 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2015-04-01 12:51:04 -0700 |
commit | 7f344721b1a94a6166b53f959ff6b159af3b5f9a (patch) | |
tree | 7d76ffd620f73a8c8eea6aeea186e28be8668c76 /src | |
parent | a8c8b3b8720bb7ce8ac1cb94815ed36d8c881f66 (diff) |
nir/peephole_ffma: Be less agressive about fusing multiply-adds
shader-db results for fragment shaders on Haswell:
total instructions in shared programs: 4395688 -> 4389623 (-0.14%)
instructions in affected programs: 355876 -> 349811 (-1.70%)
helped: 1455
HURT: 14
GAINED: 5
LOST: 0
Reviewed-by: Matt Turner <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/glsl/nir/nir_opt_peephole_ffma.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/glsl/nir/nir_opt_peephole_ffma.c b/src/glsl/nir/nir_opt_peephole_ffma.c index 1ba4ac2b195..bf4dbe16b9e 100644 --- a/src/glsl/nir/nir_opt_peephole_ffma.c +++ b/src/glsl/nir/nir_opt_peephole_ffma.c @@ -38,6 +38,41 @@ struct peephole_ffma_state { bool progress; }; +static inline bool +are_all_uses_fadd(nir_ssa_def *def) +{ + if (def->if_uses->entries > 0) + return false; + + struct set_entry *use_iter; + set_foreach(def->uses, use_iter) { + nir_instr *use_instr = (nir_instr *)use_iter->key; + + if (use_instr->type != nir_instr_type_alu) + return false; + + nir_alu_instr *use_alu = nir_instr_as_alu(use_instr); + switch (use_alu->op) { + case nir_op_fadd: + break; /* This one's ok */ + + case nir_op_imov: + case nir_op_fmov: + case nir_op_fneg: + case nir_op_fabs: + assert(use_alu->dest.dest.is_ssa); + if (!are_all_uses_fadd(&use_alu->dest.dest.ssa)) + return false; + break; + + default: + return false; + } + } + + return true; +} + static nir_alu_instr * get_mul_for_src(nir_alu_src *src, uint8_t swizzle[4], bool *negate, bool *abs) { @@ -66,6 +101,12 @@ get_mul_for_src(nir_alu_src *src, uint8_t swizzle[4], bool *negate, bool *abs) break; case nir_op_fmul: + /* Only absorbe a fmul into a ffma if the fmul is is only used in fadd + * operations. This prevents us from being too agressive with our + * fusing which can actually lead to more instructions. + */ + if (!are_all_uses_fadd(&alu->dest.dest.ssa)) + return NULL; break; default: |