nvc0: make sure all sources of the BIND op are distinct
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sat, 15 Jan 2011 13:03:05 +0000 (14:03 +0100)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sat, 15 Jan 2011 13:14:50 +0000 (14:14 +0100)
They're supposed to be assigned consecutive registers so they can't
contain the same SSA value more than once.

src/gallium/drivers/nvc0/nvc0_pc.c
src/gallium/drivers/nvc0/nvc0_pc.h
src/gallium/drivers/nvc0/nvc0_pc_optimize.c

index 72483f1..304a191 100644 (file)
@@ -515,6 +515,13 @@ nvc0_insn_insert_after(struct nv_instruction *at, struct nv_instruction *ni)
 }
 
 void
+nvc0_insn_insert_before(struct nv_instruction *at, struct nv_instruction *ni)
+{
+   nvc0_insn_insert_after(at, ni);
+   nvc0_insns_permute(at, ni);
+}
+
+void
 nvc0_insn_delete(struct nv_instruction *nvi)
 {
    struct nv_basic_block *b = nvi->bb;
index 74867f0..969cc68 100644 (file)
@@ -473,6 +473,7 @@ struct nv_pc {
 };
 
 void nvc0_insn_append(struct nv_basic_block *, struct nv_instruction *);
+void nvc0_insn_insert_before(struct nv_instruction *, struct nv_instruction *);
 void nvc0_insn_insert_after(struct nv_instruction *, struct nv_instruction *);
 
 static INLINE struct nv_instruction *
index e4449c2..8dce32b 100644 (file)
@@ -1101,6 +1101,40 @@ nv_pass_cse(struct nv_pass *ctx, struct nv_basic_block *b)
    return 0;
 }
 
+/* Make sure all sources of an NV_OP_BIND are distinct, they need to occupy
+ * neighbouring registers. CSE might have messed this up.
+ */
+static int
+nv_pass_fix_bind(struct nv_pass *ctx, struct nv_basic_block *b)
+{
+   struct nv_value *val;
+   struct nv_instruction *bnd, *nvi, *next;
+   int s, t;
+
+   for (bnd = b->entry; bnd; bnd = next) {
+      next = bnd->next;
+      if (bnd->opcode != NV_OP_BIND)
+         continue;
+      for (s = 0; s < 4 && bnd->src[s]; ++s) {
+         val = bnd->src[s]->value;
+         for (t = s + 1; t < 4 && bnd->src[t]; ++t) {
+            if (bnd->src[t]->value != val)
+               continue;
+            nvi = nv_alloc_instruction(ctx->pc, NV_OP_MOV);
+            nvi->def[0] = new_value_like(ctx->pc, val);
+            nvi->def[0]->insn = nvi;
+            nv_reference(ctx->pc, nvi, 0, val);
+            nvc0_insn_insert_before(bnd, nvi);
+
+            nv_reference(ctx->pc, bnd, t, nvi->def[0]);
+         }
+      }
+   }
+   DESCEND_ARBITRARY(t, nv_pass_fix_bind);
+
+   return 0;
+}
+
 static int
 nv_pc_pass0(struct nv_pc *pc, struct nv_basic_block *root)
 {
@@ -1177,6 +1211,9 @@ nv_pc_pass0(struct nv_pc *pc, struct nv_basic_block *root)
    if (ret)
       return ret;
 
+   pc->pass_seq++;
+   ret = nv_pass_fix_bind(&pass, root);
+
    return ret;
 }