freedreno/ir3: insert extra move into phi
authorRob Clark <robclark@freedesktop.org>
Tue, 5 Apr 2016 17:45:34 +0000 (13:45 -0400)
committerRob Clark <robclark@freedesktop.org>
Tue, 5 Apr 2016 19:04:43 +0000 (15:04 -0400)
We had an implicit assumption that the phi src was assigned in it's
source (pred) block leading into the phi.  But this is not true with
NIR, so we can't just ignore the source block specified in the
nir_phi_src.  Insert an extra mov in the source block.  If it is not
required the CP pass will take it back out again.

Fixes:

  ./tests/spec/glsl-1.10/execution/vs-call-in-nested-loop.shader_test
  ./tests/spec/glsl-1.10/execution/vs-inner-loop-modifies-outer-loop-var.shader_test

and probably others.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c

index 3f14412998cf39b2ae6a611eeaccfb0faaf6f0bb..245b61f31e5854db0cb38f62a1317a4f8109568c 100644 (file)
@@ -1661,6 +1661,16 @@ resolve_phis(struct ir3_compile *ctx, struct ir3_block *block)
 
                foreach_list_typed(nir_phi_src, nsrc, node, &nphi->srcs) {
                        struct ir3_instruction *src = get_src(ctx, &nsrc->src)[0];
+
+                       /* NOTE: src might not be in the same block as it comes from
+                        * according to the phi.. but in the end the backend assumes
+                        * it will be able to assign the same register to each (which
+                        * only works if it is assigned in the src block), so insert
+                        * an extra mov to make sure the phi src is assigned in the
+                        * block it comes from:
+                        */
+                       src = ir3_MOV(get_block(ctx, nsrc->pred), src, TYPE_U32);
+
                        ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = src;
                }
        }