This will be useful for cleaning up phis when unrolling loops. --- src/compiler/nir/nir.h | 1 + src/compiler/nir/nir_opt_remove_phis.c | 94 +++++++++++++++++++--------------- 2 files changed, 53 insertions(+), 42 deletions(-)
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 60aeb8f..0ab3ebc 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -2676,6 +2676,7 @@ void nir_opt_gcm(nir_shader *shader); bool nir_opt_peephole_select(nir_shader *shader); bool nir_opt_remove_phis(nir_shader *shader); +bool nir_opt_remove_phi(nir_phi_instr *phi); bool nir_opt_undef(nir_shader *shader); diff --git a/src/compiler/nir/nir_opt_remove_phis.c b/src/compiler/nir/nir_opt_remove_phis.c index 6d9e0ff..7dea9c7 100644 --- a/src/compiler/nir/nir_opt_remove_phis.c +++ b/src/compiler/nir/nir_opt_remove_phis.c @@ -47,6 +47,57 @@ matching_mov(nir_alu_instr *mov1, nir_ssa_def *ssa) return mov2 && nir_alu_srcs_equal(mov1, mov2, 0, 0); } +bool +nir_opt_remove_phi(nir_phi_instr *phi) +{ + nir_ssa_def *def = NULL; + nir_alu_instr *mov = NULL; + bool srcs_same = true; + + nir_foreach_phi_src(src, phi) { + assert(src->src.is_ssa); + + /* For phi nodes at the beginning of loops, we may encounter some + * sources from backedges that point back to the destination of the + * same phi, i.e. something like: + * + * a = phi(a, b, ...) + * + * We can safely ignore these sources, since if all of the normal + * sources point to the same definition, then that definition must + * still dominate the phi node, and the phi will still always take + * the value of that definition. + */ + if (src->src.ssa == &phi->dest.ssa) + continue; + + if (def == NULL) { + def = src->src.ssa; + mov = get_parent_mov(def); + } else { + if (src->src.ssa != def && !matching_mov(mov, src->src.ssa)) { + srcs_same = false; + break; + } + } + } + + if (!srcs_same) + return false; + + /* We must have found at least one definition, since there must be at + * least one forward edge. + */ + assert(def != NULL); + + + assert(phi->dest.is_ssa); + nir_ssa_def_rewrite_uses(&phi->dest.ssa, nir_src_for_ssa(def)); + nir_instr_remove(&phi->instr); + + return true; +} + /* * This is a pass for removing phi nodes that look like: * a = phi(b, b, b, ...) @@ -74,50 +125,9 @@ remove_phis_block(nir_block *block) nir_phi_instr *phi = nir_instr_as_phi(instr); bool is_lcssa_phi = phi->is_lcssa_phi; - nir_ssa_def *def = NULL; - nir_alu_instr *mov = NULL; - bool srcs_same = true; - - nir_foreach_phi_src(src, phi) { - assert(src->src.is_ssa); - - /* For phi nodes at the beginning of loops, we may encounter some - * sources from backedges that point back to the destination of the - * same phi, i.e. something like: - * - * a = phi(a, b, ...) - * - * We can safely ignore these sources, since if all of the normal - * sources point to the same definition, then that definition must - * still dominate the phi node, and the phi will still always take - * the value of that definition. - */ - if (src->src.ssa == &phi->dest.ssa) - continue; - - if (def == NULL) { - def = src->src.ssa; - mov = get_parent_mov(def); - } else { - if (src->src.ssa != def && !matching_mov(mov, src->src.ssa)) { - srcs_same = false; - break; - } - } - } - - if (!srcs_same) + if (!nir_opt_remove_phi(phi)) continue; - /* We must have found at least one definition, since there must be at - * least one forward edge. - */ - assert(def != NULL); - - assert(phi->dest.is_ssa); - nir_ssa_def_rewrite_uses(&phi->dest.ssa, nir_src_for_ssa(def)); - nir_instr_remove(instr); - if (!is_lcssa_phi) progress = true; } -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev