nv50: fix potential null deref in insn modifer optimization pass
[profile/ivi/mesa.git] / src / gallium / drivers / nv50 / nv50_pc_optimize.c
index 921ed15..4271731 100644 (file)
@@ -20,8 +20,6 @@
  * SOFTWARE.
  */
 
-/* #define NV50PC_DEBUG */
-
 #include "nv50_pc.h"
 
 #define DESCEND_ARBITRARY(j, f)                                 \
@@ -116,7 +114,7 @@ nvi_isnop(struct nv_instruction *nvi)
       return FALSE;
 
    if (nvi->src[0]->value->join->reg.id < 0) {
-      NV50_DBGMSG("nvi_isnop: orphaned value detected\n");
+      NV50_DBGMSG(PROG_IR, "nvi_isnop: orphaned value detected\n");
       return TRUE;
    }
 
@@ -145,8 +143,9 @@ nv_pc_pass_pre_emission(void *priv, struct nv_basic_block *b)
    int j;
    uint size, n32 = 0;
 
+   /* find first non-empty block emitted before b */
    for (j = pc->num_blocks - 1; j >= 0 && !pc->bb_list[j]->bin_size; --j);
-   if (j >= 0) {
+   for (; j >= 0; --j) {
       in = pc->bb_list[j];
 
       /* check for no-op branches (BRA $PC+8) */
@@ -160,6 +159,9 @@ nv_pc_pass_pre_emission(void *priv, struct nv_basic_block *b)
          nv_nvi_delete(in->exit);
       }
       b->bin_pos = in->bin_pos + in->bin_size;
+
+      if (in->bin_size) /* no more no-op branches to b */
+         break;
    }
 
    pc->bb_list[pc->num_blocks++] = b;
@@ -197,7 +199,7 @@ nv_pc_pass_pre_emission(void *priv, struct nv_basic_block *b)
    }
 
    if (!b->entry) {
-      NV50_DBGMSG("block %p is now empty\n", b);
+      NV50_DBGMSG(PROG_IR, "block %p is now empty\n", b);
    } else
    if (!b->exit->is_long) {
       assert(n32);
@@ -236,7 +238,7 @@ nv_pc_exec_pass2(struct nv_pc *pc)
 {
    int i, ret;
 
-   NV50_DBGMSG("preparing %u blocks for emission\n", pc->num_blocks);
+   NV50_DBGMSG(PROG_IR, "preparing %u blocks for emission\n", pc->num_blocks);
 
    pc->num_blocks = 0; /* will reorder bb_list */
 
@@ -299,7 +301,7 @@ check_swap_src_0_1(struct nv_instruction *nvi)
    }
 
    if (nvi->opcode == NV_OP_SET && nvi->src[0] != src0)
-      nvi->set_cond = cc_swapped[nvi->set_cond];
+      nvi->set_cond = (nvi->set_cond & ~7) | cc_swapped[nvi->set_cond & 7];
 }
 
 static int
@@ -452,7 +454,7 @@ nv_pass_lower_mods(struct nv_pass *ctx, struct nv_basic_block *b)
       if (nvi->opcode == NV_OP_SAT) {
          mi = nvi->src[0]->value->insn;
 
-         if (mi->opcode != NV_OP_ADD || mi->opcode != NV_OP_MAD)
+         if (mi->opcode != NV_OP_ADD && mi->opcode != NV_OP_MAD)
             continue;
          if (mi->flags_def || mi->def[0]->refc > 1)
             continue;
@@ -460,6 +462,10 @@ nv_pass_lower_mods(struct nv_pass *ctx, struct nv_basic_block *b)
          mi->saturate = 1;
          mi->def[0] = nvi->def[0];
          mi->def[0]->insn = mi;
+         if (nvi->flags_def) {
+            mi->flags_def = nvi->flags_def;
+            mi->flags_def->insn = mi;
+         }
          nv_nvi_delete(nvi);
       }
    }
@@ -962,7 +968,8 @@ nv_pass_flatten(struct nv_pass *ctx, struct nv_basic_block *b)
 
    if (bb_is_if_else_endif(b)) {
 
-      NV50_DBGMSG("pass_flatten: IF/ELSE/ENDIF construct at BB:%i\n", b->id);
+      NV50_DBGMSG(PROG_IR,
+                  "pass_flatten: IF/ELSE/ENDIF construct at BB:%i\n", b->id);
 
       for (n0 = 0, nvi = b->out[0]->entry; nvi; nvi = nvi->next, ++n0)
          if (!nv50_nvi_can_predicate(nvi))
@@ -971,7 +978,7 @@ nv_pass_flatten(struct nv_pass *ctx, struct nv_basic_block *b)
          for (n1 = 0, nvi = b->out[1]->entry; nvi; nvi = nvi->next, ++n1)
             if (!nv50_nvi_can_predicate(nvi))
                break;
-#ifdef NV50PC_DEBUG
+#if NV50_DEBUG & NV50_DEBUG_PROG_IR
          if (nvi) {
             debug_printf("cannot predicate: "); nv_print_instruction(nvi);
          }