nv50: fix find_dom_frontier
[mesa.git] / src / gallium / drivers / nv50 / nv50_pc.c
index b9d274414d15e336866706e5c162f474d3f41828..c2f2ab3ef30fe7929fea5cacacc5f7a7c641b8f4 100644 (file)
@@ -20,6 +20,8 @@
  * SOFTWARE.
  */
 
+/* #define NV50PC_DEBUG */
+
 #include "nv50_pc.h"
 #include "nv50_program.h"
 
@@ -202,6 +204,35 @@ nvcg_replace_value(struct nv_pc *pc, struct nv_value *old_val,
    return n;
 }
 
+struct nv_value *
+nvcg_find_constant(struct nv_ref *ref)
+{
+   struct nv_value *src;
+
+   if (!ref)
+      return NULL;
+
+   src = ref->value;
+   while (src->insn && src->insn->opcode == NV_OP_MOV) {
+      assert(!src->insn->src[0]->mod);
+      src = src->insn->src[0]->value;
+   }
+   if ((src->reg.file == NV_FILE_IMM) ||
+       (src->insn && src->insn->opcode == NV_OP_LDA &&
+        src->insn->src[0]->value->reg.file >= NV_FILE_MEM_C(0) &&
+        src->insn->src[0]->value->reg.file <= NV_FILE_MEM_C(15)))
+      return src;
+   return NULL;
+}
+
+struct nv_value *
+nvcg_find_immediate(struct nv_ref *ref)
+{
+   struct nv_value *src = nvcg_find_constant(ref);
+
+   return (src && src->reg.file == NV_FILE_IMM) ? src : NULL;
+}
+
 static void
 nv_pc_free_refs(struct nv_pc *pc)
 {
@@ -218,6 +249,7 @@ edge_name(ubyte type)
    case CFG_EDGE_BACK: return "back";
    case CFG_EDGE_LOOP_ENTER: return "loop";
    case CFG_EDGE_LOOP_LEAVE: return "break";
+   case CFG_EDGE_FAKE: return "fake";
    default:
       return "?";
    }
@@ -245,6 +277,7 @@ nv_pc_pass_in_order(struct nv_basic_block *root, nv_pc_pass_func f, void *priv)
          case CFG_EDGE_BACK:
             continue;
          case CFG_EDGE_FORWARD:
+         case CFG_EDGE_FAKE:
             if (++b->out[j]->priv == b->out[j]->num_in)
                bb[p++] = b->out[j];
             break;
@@ -262,9 +295,11 @@ nv_pc_pass_in_order(struct nv_basic_block *root, nv_pc_pass_func f, void *priv)
 
       f(priv, b);
 
-      if (!p)
-         while (pp > 0)
-            bb[p++] = bbb[--pp];
+      if (!p) {
+         p = pp;
+         for (; pp > 0; --pp)
+            bb[pp - 1] = bbb[pp - 1];
+      }
    }
 }
 
@@ -311,7 +346,7 @@ nv50_emit_program(struct nv_pc *pc)
    uint32_t *code = pc->emit;
    int n;
 
-   debug_printf("emitting program: size = %u\n", pc->bin_size);
+   NV50_DBGMSG("emitting program: size = %u\n", pc->bin_size);
 
    for (n = 0; n < pc->num_blocks; ++n) {
       struct nv_instruction *i;
@@ -336,7 +371,9 @@ nv50_emit_program(struct nv_pc *pc)
    pc->emit = code;
    code[pc->bin_size / 4 - 1] |= 1;
 
+#ifdef NV50PC_DEBUG
    nvcg_show_bincode(pc);
+#endif
 
    return 0;
 }
@@ -354,17 +391,25 @@ nv50_generate_code(struct nv50_translation_info *ti)
    ret = nv50_tgsi_to_nc(pc, ti);
    if (ret)
       goto out;
+#ifdef NV50PC_DEBUG
    nv_print_program(pc->root);
+#endif
 
    /* optimization */
    ret = nv_pc_exec_pass0(pc);
    if (ret)
       goto out;
+#ifdef NV50PC_DEBUG
+   nv_print_program(pc->root);
+#endif
 
    /* register allocation */
    ret = nv_pc_exec_pass1(pc);
    if (ret)
       goto out;
+#ifdef NV50PC_DEBUG
+   nv_print_program(pc->root);
+#endif
 
    /* prepare for emission */
    ret = nv_pc_exec_pass2(pc);
@@ -392,7 +437,7 @@ nv50_generate_code(struct nv50_translation_info *ti)
    ti->p->fixups = pc->fixups;
    ti->p->num_fixups = pc->num_fixups;
 
-   debug_printf("SHADER TRANSLATION - %s\n", ret ? "failure" : "success");
+   NV50_DBGMSG("SHADER TRANSLATION - %s\n", ret ? "failure" : "success");
 
 out:
    nv_pc_free_refs(pc);
@@ -492,7 +537,7 @@ nv_nvi_delete(struct nv_instruction *nvi)
 
    if (nvi == b->phi) {
       if (nvi->opcode != NV_OP_PHI)
-         debug_printf("NOTE: b->phi points to non-PHI instruction\n");
+         NV50_DBGMSG("NOTE: b->phi points to non-PHI instruction\n");
 
       assert(!nvi->prev);
       if (!nvi->next || nvi->next->opcode != NV_OP_PHI)
@@ -574,10 +619,10 @@ nvbb_reachable_by(struct nv_basic_block *bf, struct nv_basic_block *bp,
    if (bp == bt)
       return FALSE;
 
-   if (bp->out[0] && bp->out_kind[0] != CFG_EDGE_BACK &&
+   if (bp->out[0] && !IS_WALL_EDGE(bp->out_kind[0]) &&
        nvbb_reachable_by(bf, bp->out[0], bt))
       return TRUE;
-   if (bp->out[1] && bp->out_kind[1] != CFG_EDGE_BACK &&
+   if (bp->out[1] && !IS_WALL_EDGE(bp->out_kind[1]) &&
        nvbb_reachable_by(bf, bp->out[1], bt))
       return TRUE;
    return FALSE;
@@ -586,6 +631,7 @@ nvbb_reachable_by(struct nv_basic_block *bf, struct nv_basic_block *bp,
 static struct nv_basic_block *
 nvbb_find_dom_frontier(struct nv_basic_block *b, struct nv_basic_block *df)
 {
+   struct nv_basic_block *out;
    int i;
 
    if (!nvbb_dominated_by(df, b)) {
@@ -596,11 +642,11 @@ nvbb_find_dom_frontier(struct nv_basic_block *b, struct nv_basic_block *df)
             return df;
       }
    }
-   for (i = 0; i < 2 && b->out[i]; ++i) {
-      if (b->out_kind[i] == CFG_EDGE_BACK)
+   for (i = 0; i < 2 && df->out[i]; ++i) {
+      if (df->out_kind[i] == CFG_EDGE_BACK)
          continue;
-      if ((df = nvbb_find_dom_frontier(b, b->out[i])))
-         return df;
+      if ((out = nvbb_find_dom_frontier(b, df->out[i])))
+         return out;
    }
    return NULL;
 }