summaryrefslogtreecommitdiffstats
path: root/src/compiler/nir
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2019-07-12 11:01:40 -0500
committerJuan A. Suarez Romero <[email protected]>2019-07-17 08:17:29 +0000
commitb43e2d5a1212d35c8b7554d2e4d12425a29fe42a (patch)
tree645c9d0ef8dd681f6193cdb0e9e7954dff22241c /src/compiler/nir
parentcffebf6f57d4dca7df742c808d4759a1da73cc33 (diff)
nir/regs_to_ssa: Handle regs in phi sources properly
Sources of phi instructions act as if they occur at the very end of the predecessor block not the block in which the phi lives. In order to handle them correctly, we have to skip phi sources on the normal instruction walk and handle them as a separate walk over the successor phis. While registers in phi instructions is a bit of an oddity it can happen when we temporarily go out-of-SSA for control-flow manipulations. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111075 Cc: [email protected] Reviewed-by: Caio Marcelo de Oliveira Filho <[email protected]> (cherry picked from commit 6fb685fe4b762c8030f86895707516e2481e9ece)
Diffstat (limited to 'src/compiler/nir')
-rw-r--r--src/compiler/nir/nir_lower_regs_to_ssa.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/src/compiler/nir/nir_lower_regs_to_ssa.c b/src/compiler/nir/nir_lower_regs_to_ssa.c
index 0db11ff1d1c..76ed1287379 100644
--- a/src/compiler/nir/nir_lower_regs_to_ssa.c
+++ b/src/compiler/nir/nir_lower_regs_to_ssa.c
@@ -251,9 +251,17 @@ nir_lower_regs_to_ssa_impl(nir_function_impl *impl)
nir_foreach_block(block, impl) {
nir_foreach_instr(instr, block) {
- if (instr->type == nir_instr_type_alu) {
+ switch (instr->type) {
+ case nir_instr_type_alu:
rewrite_alu_instr(nir_instr_as_alu(instr), &state);
- } else {
+ break;
+
+ case nir_instr_type_phi:
+ /* We rewrite sources as a separate pass */
+ nir_foreach_dest(instr, rewrite_dest, &state);
+ break;
+
+ default:
nir_foreach_src(instr, rewrite_src, &state);
nir_foreach_dest(instr, rewrite_dest, &state);
}
@@ -262,6 +270,28 @@ nir_lower_regs_to_ssa_impl(nir_function_impl *impl)
nir_if *following_if = nir_block_get_following_if(block);
if (following_if)
rewrite_if_condition(following_if, &state);
+
+ /* Handle phi sources that source from this block. We have to do this
+ * as a separate pass because the phi builder assumes that uses and
+ * defs are processed in an order that respects dominance. When we have
+ * loops, a phi source may be a back-edge so we have to handle it as if
+ * it were one of the last instructions in the predecessor block.
+ */
+ for (unsigned i = 0; i < ARRAY_SIZE(block->successors); i++) {
+ if (block->successors[i] == NULL)
+ continue;
+
+ nir_foreach_instr(instr, block->successors[i]) {
+ if (instr->type != nir_instr_type_phi)
+ break;
+
+ nir_phi_instr *phi = nir_instr_as_phi(instr);
+ nir_foreach_phi_src(phi_src, phi) {
+ if (phi_src->pred == block)
+ rewrite_src(&phi_src->src, &state);
+ }
+ }
+ }
}
nir_phi_builder_finish(phi_build);