X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fnir%2Fnir_opt_remove_phis.c;h=db58c618f6bd2070fecea18055dd47d9bb6144eb;hb=60dae98456830a6a1d0b28e22555e9faec948a32;hp=ee92fbefacb7322ff928ab64a8f455111c40b08b;hpb=144cbf89879103c45f79b7c5b923ebad63f08c55;p=mesa.git diff --git a/src/compiler/nir/nir_opt_remove_phis.c b/src/compiler/nir/nir_opt_remove_phis.c index ee92fbefacb..db58c618f6b 100644 --- a/src/compiler/nir/nir_opt_remove_phis.c +++ b/src/compiler/nir/nir_opt_remove_phis.c @@ -26,6 +26,7 @@ */ #include "nir.h" +#include "nir_builder.h" static nir_alu_instr * get_parent_mov(nir_ssa_def *ssa) @@ -34,7 +35,7 @@ get_parent_mov(nir_ssa_def *ssa) return NULL; nir_alu_instr *alu = nir_instr_as_alu(ssa->parent_instr); - return (alu->op == nir_op_imov || alu->op == nir_op_fmov) ? alu : NULL; + return (alu->op == nir_op_mov) ? alu : NULL; } static bool @@ -51,7 +52,7 @@ matching_mov(nir_alu_instr *mov1, nir_ssa_def *ssa) * This is a pass for removing phi nodes that look like: * a = phi(b, b, b, ...) * - * Note that we can't ignore undef sources here, or else we may create a + * Note that we can't always ignore undef sources here, or else we may create a * situation where the definition of b isn't dominated by its uses. We're * allowed to do this since the definition of b must dominate all of the * phi node's predecessors, which means it must dominate the phi node as well @@ -63,7 +64,7 @@ matching_mov(nir_alu_instr *mov1, nir_ssa_def *ssa) */ static bool -remove_phis_block(nir_block *block) +remove_phis_block(nir_block *block, nir_builder *b) { bool progress = false; @@ -97,6 +98,9 @@ remove_phis_block(nir_block *block) if (def == NULL) { def = src->src.ssa; mov = get_parent_mov(def); + } else if (src->src.ssa->parent_instr->type == nir_instr_type_ssa_undef && + nir_block_dominates(def->parent_instr->block, src->pred)) { + /* Ignore this undef source. */ } else { if (src->src.ssa != def && !matching_mov(mov, src->src.ssa)) { srcs_same = false; @@ -108,10 +112,24 @@ remove_phis_block(nir_block *block) if (!srcs_same) continue; - /* We must have found at least one definition, since there must be at - * least one forward edge. - */ - assert(def != NULL); + if (!def) { + /* In this case, the phi had no sources. So turn it into an undef. */ + + b->cursor = nir_after_phis(block); + def = nir_ssa_undef(b, phi->dest.ssa.num_components, + phi->dest.ssa.bit_size); + } else if (mov) { + /* If the sources were all movs from the same source with the same + * swizzle, then we can't just pick a random move because it may not + * dominate the phi node. Instead, we need to emit our own move after + * the phi which uses the shared source, and rewrite uses of the phi + * to use the move instead. This is ok, because while the movs may + * not all dominate the phi node, their shared source does. + */ + + b->cursor = nir_after_phis(block); + def = nir_mov_alu(b, mov->src[0], def->num_components); + } assert(phi->dest.is_ssa); nir_ssa_def_rewrite_uses(&phi->dest.ssa, nir_src_for_ssa(def)); @@ -123,18 +141,32 @@ remove_phis_block(nir_block *block) return progress; } +bool +nir_opt_remove_phis_block(nir_block *block) +{ + nir_builder b; + nir_builder_init(&b, nir_cf_node_get_function(&block->cf_node)); + return remove_phis_block(block, &b); +} + static bool -remove_phis_impl(nir_function_impl *impl) +nir_opt_remove_phis_impl(nir_function_impl *impl) { bool progress = false; + nir_builder bld; + nir_builder_init(&bld, impl); + + nir_metadata_require(impl, nir_metadata_dominance); nir_foreach_block(block, impl) { - progress |= remove_phis_block(block); + progress |= remove_phis_block(block, &bld); } if (progress) { nir_metadata_preserve(impl, nir_metadata_block_index | nir_metadata_dominance); + } else { + nir_metadata_preserve(impl, nir_metadata_all); } return progress; @@ -147,7 +179,7 @@ nir_opt_remove_phis(nir_shader *shader) nir_foreach_function(function, shader) if (function->impl) - progress = remove_phis_impl(function->impl) || progress; + progress = nir_opt_remove_phis_impl(function->impl) || progress; return progress; }