i965/fs: Track flag register liveness with byte granularity.
authorFrancisco Jerez <currojerez@riseup.net>
Thu, 19 May 2016 04:34:27 +0000 (21:34 -0700)
committerFrancisco Jerez <currojerez@riseup.net>
Sat, 28 May 2016 06:29:04 +0000 (23:29 -0700)
This is required for correctness in presence of multiple 8-wide flag
writes (e.g. 8-wide instructions with a conditional mod set) which
update a different portion of the same 16-bit flag subregister.  Right
now we keep track of flag dataflow with 16-bit granularity and
consider flag writes to have killed any previous definition of the
same subregister even if the write was less than 16 channels wide,
which can cause live flag register updates to be dead code-eliminated
incorrectly.

Additionally this makes sure that we handle 32-wide flag writes and
reads which may span multiple flag subregisters so the current
approach of just setting/testing a single bit from the live set
wouldn't have worked.

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/mesa/drivers/dri/i965/brw_fs_dead_code_eliminate.cpp
src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp

index bd57e09fe0c19650bf9696a1d59091eff452628b..a1d07ff3e8e03f660cf389b8c1a28697cc358e44 100644 (file)
@@ -77,7 +77,7 @@ fs_visitor::dead_code_eliminate()
          }
 
          if (inst->dst.is_null() && inst->writes_flag()) {
-            if (!BITSET_TEST(flag_live, inst->flag_subreg)) {
+            if (!(flag_live[0] & inst->flags_written())) {
                inst->opcode = BRW_OPCODE_NOP;
                progress = true;
             }
@@ -102,9 +102,8 @@ fs_visitor::dead_code_eliminate()
             }
          }
 
-         if (inst->writes_flag() && !inst->predicate) {
-            BITSET_CLEAR(flag_live, inst->flag_subreg);
-         }
+         if (!inst->predicate && inst->exec_size >= 8)
+            flag_live[0] &= ~inst->flags_written();
 
          if (inst->opcode == BRW_OPCODE_NOP) {
             inst->remove(block);
@@ -121,9 +120,7 @@ fs_visitor::dead_code_eliminate()
             }
          }
 
-         if (inst->reads_flag()) {
-            BITSET_SET(flag_live, inst->flag_subreg);
-         }
+         flag_live[0] |= inst->flags_read(devinfo);
       }
    }
 
index 66b70a9144b1a4ace27bd5f03311ff0aabacd297..8bd42298a2381fe6477c6bdbfccd8bfccf31f01f 100644 (file)
@@ -123,19 +123,8 @@ fs_live_variables::setup_def_use()
                reg.reg_offset++;
             }
         }
-         if (inst->reads_flag()) {
-            /* The vertical combination predicates read f0.0 and f0.1. */
-            if (inst->predicate == BRW_PREDICATE_ALIGN1_ANYV ||
-                inst->predicate == BRW_PREDICATE_ALIGN1_ALLV) {
-               assert(inst->flag_subreg == 0);
-               if (!BITSET_TEST(bd->flag_def, 1)) {
-                  BITSET_SET(bd->flag_use, 1);
-               }
-            }
-            if (!BITSET_TEST(bd->flag_def, inst->flag_subreg)) {
-               BITSET_SET(bd->flag_use, inst->flag_subreg);
-            }
-         }
+
+         bd->flag_use[0] |= inst->flags_read(v->devinfo) & ~bd->flag_def[0];
 
          /* Set def[] for this instruction */
          if (inst->dst.file == VGRF) {
@@ -145,11 +134,9 @@ fs_live_variables::setup_def_use()
                reg.reg_offset++;
             }
         }
-         if (inst->writes_flag()) {
-            if (!BITSET_TEST(bd->flag_use, inst->flag_subreg)) {
-               BITSET_SET(bd->flag_def, inst->flag_subreg);
-            }
-         }
+
+         if (!inst->predicate && inst->exec_size >= 8)
+            bd->flag_def[0] |= inst->flags_written() & ~bd->flag_use[0];
 
         ip++;
       }