i965/vec4: Simplify reswizzle() using the swizzle utils.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fs_sel_peephole.cpp
index db0be1911cc439905406398580f21a97d7695a36..740ba67bb9453e05a27ec9c4aeb382e3b7011537 100644 (file)
@@ -41,9 +41,9 @@
  * Scans forwards from an IF counting consecutive MOV instructions in the
  * "then" and "else" blocks of the if statement.
  *
- * A pointer to the fs_inst* for IF is passed as the <if_inst> argument. The
- * function stores pointers to the MOV instructions in the <then_mov> and
- * <else_mov> arrays.
+ * A pointer to the bblock_t following the IF is passed as the <then_block>
+ * argument. The function stores pointers to the MOV instructions in the
+ * <then_mov> and <else_mov> arrays.
  *
  * \return the minimum number of MOVs found in the two branches or zero if
  *         an error occurred.
  */
 static int
 count_movs_from_if(fs_inst *then_mov[MAX_MOVS], fs_inst *else_mov[MAX_MOVS],
-                   fs_inst *if_inst, fs_inst *else_inst)
+                   bblock_t *then_block, bblock_t *else_block)
 {
-   fs_inst *m = if_inst;
-
-   assert(m->opcode == BRW_OPCODE_IF);
-   m = (fs_inst *) m->next;
-
    int then_movs = 0;
-   while (then_movs < MAX_MOVS && m->opcode == BRW_OPCODE_MOV) {
-      then_mov[then_movs] = m;
-      m = (fs_inst *) m->next;
+   foreach_inst_in_block(fs_inst, inst, then_block) {
+      if (then_movs == MAX_MOVS || inst->opcode != BRW_OPCODE_MOV)
+         break;
+
+      then_mov[then_movs] = inst;
       then_movs++;
    }
 
-   m = (fs_inst *) else_inst->next;
-
    int else_movs = 0;
-   while (else_movs < MAX_MOVS && m->opcode == BRW_OPCODE_MOV) {
-      else_mov[else_movs] = m;
-      m = (fs_inst *) m->next;
+   foreach_inst_in_block(fs_inst, inst, else_block) {
+      if (else_movs == MAX_MOVS || inst->opcode != BRW_OPCODE_MOV)
+         break;
+
+      else_mov[else_movs] = inst;
       else_movs++;
    }
 
@@ -127,28 +124,31 @@ fs_visitor::opt_peephole_sel()
 {
    bool progress = false;
 
-   cfg_t cfg(&instructions);
-
-   for (int b = 0; b < cfg.num_blocks; b++) {
-      bblock_t *block = cfg.blocks[b];
-
+   foreach_block (block, cfg) {
       /* IF instructions, by definition, can only be found at the ends of
        * basic blocks.
        */
-      fs_inst *if_inst = (fs_inst *) block->end;
+      fs_inst *if_inst = (fs_inst *)block->end();
       if (if_inst->opcode != BRW_OPCODE_IF)
          continue;
 
-      if (!block->else_inst)
-         continue;
-
-      fs_inst *else_inst = (fs_inst *) block->else_inst;
-      assert(else_inst->opcode == BRW_OPCODE_ELSE);
-
       fs_inst *else_mov[MAX_MOVS] = { NULL };
       fs_inst *then_mov[MAX_MOVS] = { NULL };
 
-      int movs = count_movs_from_if(then_mov, else_mov, if_inst, else_inst);
+      bblock_t *then_block = block->next();
+      bblock_t *else_block = NULL;
+      foreach_list_typed(bblock_link, child, link, &block->children) {
+         if (child->block != then_block) {
+            if (child->block->prev()->end()->opcode == BRW_OPCODE_ELSE) {
+               else_block = child->block;
+            }
+            break;
+         }
+      }
+      if (else_block == NULL)
+         continue;
+
+      int movs = count_movs_from_if(then_mov, else_mov, then_block, else_block);
 
       if (movs == 0)
          continue;
@@ -156,6 +156,18 @@ fs_visitor::opt_peephole_sel()
       fs_inst *sel_inst[MAX_MOVS] = { NULL };
       fs_inst *mov_imm_inst[MAX_MOVS] = { NULL };
 
+      enum brw_predicate predicate;
+      bool predicate_inverse;
+      if (brw->gen == 6 && if_inst->conditional_mod) {
+         /* For Sandybridge with IF with embedded comparison */
+         predicate = BRW_PREDICATE_NORMAL;
+         predicate_inverse = false;
+      } else {
+         /* Separate CMP and IF instructions */
+         predicate = if_inst->predicate;
+         predicate_inverse = if_inst->predicate_inverse;
+      }
+
       /* Generate SEL instructions for pairs of MOVs to a common destination. */
       for (int i = 0; i < movs; i++) {
          if (!then_mov[i] || !else_mov[i])
@@ -164,7 +176,9 @@ fs_visitor::opt_peephole_sel()
          /* Check that the MOVs are the right form. */
          if (!then_mov[i]->dst.equals(else_mov[i]->dst) ||
              then_mov[i]->is_partial_write() ||
-             else_mov[i]->is_partial_write()) {
+             else_mov[i]->is_partial_write() ||
+             then_mov[i]->conditional_mod != BRW_CONDITIONAL_NONE ||
+             else_mov[i]->conditional_mod != BRW_CONDITIONAL_NONE) {
             movs = i;
             break;
          }
@@ -175,30 +189,23 @@ fs_visitor::opt_peephole_sel()
             break;
          }
 
-         if (!then_mov[i]->src[0].equals(else_mov[i]->src[0])) {
+         if (then_mov[i]->src[0].equals(else_mov[i]->src[0])) {
+            sel_inst[i] = MOV(then_mov[i]->dst, then_mov[i]->src[0]);
+         } else {
             /* Only the last source register can be a constant, so if the MOV
              * in the "then" clause uses a constant, we need to put it in a
              * temporary.
              */
             fs_reg src0(then_mov[i]->src[0]);
             if (src0.file == IMM) {
-               src0 = fs_reg(this, glsl_type::float_type);
+               src0 = vgrf(glsl_type::float_type);
                src0.type = then_mov[i]->src[0].type;
                mov_imm_inst[i] = MOV(src0, then_mov[i]->src[0]);
             }
 
             sel_inst[i] = SEL(then_mov[i]->dst, src0, else_mov[i]->src[0]);
-
-            if (brw->gen == 6 && if_inst->conditional_mod) {
-               /* For Sandybridge with IF with embedded comparison */
-               sel_inst[i]->predicate = BRW_PREDICATE_NORMAL;
-            } else {
-               /* Separate CMP and IF instructions */
-               sel_inst[i]->predicate = if_inst->predicate;
-               sel_inst[i]->predicate_inverse = if_inst->predicate_inverse;
-            }
-         } else {
-            sel_inst[i] = MOV(then_mov[i]->dst, then_mov[i]->src[0]);
+            sel_inst[i]->predicate = predicate;
+            sel_inst[i]->predicate_inverse = predicate_inverse;
          }
       }
 
@@ -209,16 +216,16 @@ fs_visitor::opt_peephole_sel()
       if (brw->gen == 6 && if_inst->conditional_mod) {
          fs_inst *cmp_inst = CMP(reg_null_d, if_inst->src[0], if_inst->src[1],
                                  if_inst->conditional_mod);
-         if_inst->insert_before(cmp_inst);
+         if_inst->insert_before(block, cmp_inst);
       }
 
       for (int i = 0; i < movs; i++) {
          if (mov_imm_inst[i])
-            if_inst->insert_before(mov_imm_inst[i]);
-         if_inst->insert_before(sel_inst[i]);
+            if_inst->insert_before(block, mov_imm_inst[i]);
+         if_inst->insert_before(block, sel_inst[i]);
 
-         then_mov[i]->remove();
-         else_mov[i]->remove();
+         then_mov[i]->remove(then_block);
+         else_mov[i]->remove(else_block);
       }
 
       progress = true;