i965/fs: Expose arbitrary pull constant load sizes to the IR.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_vec4_dead_code_eliminate.cpp
index 70d2af5e911ac2acdfdc3a1746f70dc551e5d307..65f9f3889883904c51900d3f4945b02666bf517e 100644 (file)
 
 using namespace brw;
 
-static bool
-can_do_writemask(const struct brw_context *brw,
-                 const vec4_instruction *inst)
-{
-   switch (inst->opcode) {
-   case SHADER_OPCODE_GEN4_SCRATCH_READ:
-   case VS_OPCODE_PULL_CONSTANT_LOAD:
-   case VS_OPCODE_PULL_CONSTANT_LOAD_GEN7:
-   case VS_OPCODE_SET_SIMD4X2_HEADER_GEN9:
-      return false;
-   default:
-      /* The MATH instruction on Gen6 only executes in align1 mode, which does
-       * not support writemasking.
-       */
-      if (brw->gen == 6 && inst->is_math())
-         return false;
-
-      if (inst->is_tex())
-         return false;
-
-      return true;
-   }
-}
-
 bool
 vec4_visitor::dead_code_eliminate()
 {
@@ -68,29 +44,36 @@ vec4_visitor::dead_code_eliminate()
    calculate_live_intervals();
 
    int num_vars = live_intervals->num_vars;
-   BITSET_WORD *live = ralloc_array(NULL, BITSET_WORD, BITSET_WORDS(num_vars));
-   BITSET_WORD *flag_live = ralloc_array(NULL, BITSET_WORD, 1);
+   BITSET_WORD *live = rzalloc_array(NULL, BITSET_WORD, BITSET_WORDS(num_vars));
+   BITSET_WORD *flag_live = rzalloc_array(NULL, BITSET_WORD, 1);
 
-   foreach_block(block, cfg) {
+   foreach_block_reverse_safe(block, cfg) {
       memcpy(live, live_intervals->block_data[block->num].liveout,
              sizeof(BITSET_WORD) * BITSET_WORDS(num_vars));
       memcpy(flag_live, live_intervals->block_data[block->num].flag_liveout,
              sizeof(BITSET_WORD));
 
-      foreach_inst_in_block_reverse(vec4_instruction, inst, block) {
-         if (inst->dst.file == GRF && !inst->has_side_effects()) {
+      foreach_inst_in_block_reverse_safe(vec4_instruction, inst, block) {
+         if ((inst->dst.file == VGRF && !inst->has_side_effects()) ||
+             (inst->dst.is_null() && inst->writes_flag())){
             bool result_live[4] = { false };
 
-            for (unsigned i = 0; i < inst->regs_written; i++) {
-               for (int c = 0; c < 4; c++)
-                  result_live[c] |= BITSET_TEST(
-                     live, var_from_reg(alloc, offset(inst->dst, i), c));
+            if (inst->dst.file == VGRF) {
+               for (unsigned i = 0; i < regs_written(inst); i++) {
+                  for (int c = 0; c < 4; c++)
+                     result_live[c] |= BITSET_TEST(live,
+                        var_from_reg(alloc,
+                                     byte_offset(inst->dst, i * REG_SIZE), c));
+               }
+            } else {
+               for (unsigned c = 0; c < 4; c++)
+                  result_live[c] = BITSET_TEST(flag_live, c);
             }
 
             /* If the instruction can't do writemasking, then it's all or
              * nothing.
              */
-            if (!can_do_writemask(brw, inst)) {
+            if (!inst->can_do_writemask(devinfo)) {
                bool result = result_live[0] | result_live[1] |
                              result_live[2] | result_live[3];
                result_live[0] = result;
@@ -109,7 +92,7 @@ vec4_visitor::dead_code_eliminate()
                         inst->dst = dst_reg(retype(brw_null_reg(), inst->dst.type));
                      } else {
                         inst->opcode = BRW_OPCODE_NOP;
-                        continue;
+                        break;
                      }
                   }
                }
@@ -117,41 +100,57 @@ vec4_visitor::dead_code_eliminate()
          }
 
          if (inst->dst.is_null() && inst->writes_flag()) {
-            if (!BITSET_TEST(flag_live, 0)) {
+            bool combined_live = false;
+            for (unsigned c = 0; c < 4; c++)
+               combined_live |= BITSET_TEST(flag_live, c);
+
+            if (!combined_live) {
                inst->opcode = BRW_OPCODE_NOP;
                progress = true;
-               continue;
             }
          }
 
-         if (inst->dst.file == GRF && !inst->predicate) {
-            for (unsigned i = 0; i < inst->regs_written; i++) {
+         if (inst->dst.file == VGRF && !inst->predicate) {
+            for (unsigned i = 0; i < regs_written(inst); i++) {
                for (int c = 0; c < 4; c++) {
                   if (inst->dst.writemask & (1 << c)) {
-                     BITSET_CLEAR(live, var_from_reg(alloc,
-                                                     offset(inst->dst, i), c));
+                     BITSET_CLEAR(live,
+                                  var_from_reg(alloc,
+                                               byte_offset(inst->dst,
+                                                           i * REG_SIZE),
+                                               c));
                   }
                }
             }
          }
 
-         if (inst->writes_flag()) {
-            BITSET_CLEAR(flag_live, 0);
+         if (inst->writes_flag() && !inst->predicate) {
+            for (unsigned c = 0; c < 4; c++)
+               BITSET_CLEAR(flag_live, c);
+         }
+
+         if (inst->opcode == BRW_OPCODE_NOP) {
+            inst->remove(block);
+            continue;
          }
 
          for (int i = 0; i < 3; i++) {
-            if (inst->src[i].file == GRF) {
-               for (unsigned j = 0; j < inst->regs_read(i); j++) {
+            if (inst->src[i].file == VGRF) {
+               for (unsigned j = 0; j < regs_read(inst, i); j++) {
                   for (int c = 0; c < 4; c++) {
                      BITSET_SET(live, var_from_reg(alloc,
-                                                   offset(inst->src[i], j), c));
+                                                   byte_offset(inst->src[i],
+                                                               j * REG_SIZE),
+                                                   c));
                   }
                }
             }
          }
 
-         if (inst->reads_flag()) {
-            BITSET_SET(flag_live, 0);
+         for (unsigned c = 0; c < 4; c++) {
+            if (inst->reads_flag(c)) {
+               BITSET_SET(flag_live, c);
+            }
          }
       }
    }
@@ -159,15 +158,8 @@ vec4_visitor::dead_code_eliminate()
    ralloc_free(live);
    ralloc_free(flag_live);
 
-   if (progress) {
-      foreach_block_and_inst_safe(block, backend_instruction, inst, cfg) {
-         if (inst->opcode == BRW_OPCODE_NOP) {
-            inst->remove(block);
-         }
-      }
-
+   if (progress)
       invalidate_live_intervals();
-   }
 
    return progress;
 }