freedreno/ir3: deal with duplicate phi sources
authorRob Clark <robclark@freedesktop.org>
Mon, 4 Apr 2016 21:38:01 +0000 (17:38 -0400)
committerRob Clark <robclark@freedesktop.org>
Tue, 5 Apr 2016 00:18:18 +0000 (20:18 -0400)
Otherwise we end up with funny things like:

  mov.f32f32 r0.x, r1.y
  mov.f32f32 r0.x, r1.y

(It doesn't happen as much after fixing the problem w/ CP into phi src,
but it can still happen since we aren't too clever about generating phi
sources in the first place.)

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

index 9be5ca34ccd707b8e015abc8177343382ff3d7d4..b56da304f9289e2350ed156b8717262b1e210c5c 100644 (file)
@@ -627,13 +627,28 @@ sched_insert_parallel_copies(struct ir3_block *block)
 {
        list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) {
                if (instr->opc == OPC_META_PHI) {
-                       struct ir3_register *reg;
+                       struct ir3_register *reg, *reg2;
                        foreach_src(reg, instr) {
                                struct ir3_instruction *src = reg->instr;
-                               struct ir3_instruction *mov =
-                                       ir3_MOV(src->block, src, TYPE_U32);
-                               mov->regs[0]->flags |= IR3_REG_PHI_SRC;
-                               mov->regs[0]->instr = instr;
+                               struct ir3_instruction *mov = NULL;
+
+                               /* after CP we could end up w/ duplicate phi srcs: */
+                               foreach_src(reg2, instr) {
+                                       if (reg == reg2)
+                                               break;
+                                       /* reg2 is before reg1 so already an inserted mov: */
+                                       else if (reg2->instr->regs[1]->instr == src) {
+                                               mov = reg2->instr;
+                                               break;
+                                       }
+                               }
+
+                               if (!mov) {
+                                       mov = ir3_MOV(src->block, src, TYPE_U32);
+                                       mov->regs[0]->flags |= IR3_REG_PHI_SRC;
+                                       mov->regs[0]->instr = instr;
+                               }
+
                                reg->instr = mov;
                        }
                }