i965/fs: Define methods to calculate the flag subset read or written by an fs_inst.
authorFrancisco Jerez <currojerez@riseup.net>
Thu, 19 May 2016 04:54:35 +0000 (21:54 -0700)
committerFrancisco Jerez <currojerez@riseup.net>
Sat, 28 May 2016 06:29:04 +0000 (23:29 -0700)
v2: Codestyle fixes (Jason).

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

index 98940dae8be1d98a4f58489cc81e5c8303e98ffe..33b3afcfd2dbee2d29705260ad3a956e94b80b61 100644 (file)
@@ -907,19 +907,54 @@ fs_inst::regs_read(int arg) const
    return 0;
 }
 
-bool
-fs_inst::reads_flag() const
+namespace {
+   /* Return the subset of flag registers that an instruction could
+    * potentially read or write based on the execution controls and flag
+    * subregister number of the instruction.
+    */
+   unsigned
+   flag_mask(const fs_inst *inst)
+   {
+      const unsigned start = inst->flag_subreg * 16 + inst->group;
+      const unsigned end = start + inst->exec_size;
+      return ((1 << DIV_ROUND_UP(end, 8)) - 1) & ~((1 << (start / 8)) - 1);
+   }
+}
+
+unsigned
+fs_inst::flags_read(const brw_device_info *devinfo) const
 {
-   return predicate;
+   /* XXX - This doesn't consider explicit uses of the flag register as source
+    *       region.
+    */
+   if (predicate == BRW_PREDICATE_ALIGN1_ANYV ||
+       predicate == BRW_PREDICATE_ALIGN1_ALLV) {
+      /* The vertical predication modes combine corresponding bits from
+       * f0.0 and f1.0 on Gen7+, and f0.0 and f0.1 on older hardware.
+       */
+      const unsigned shift = devinfo->gen >= 7 ? 4 : 2;
+      return flag_mask(this) << shift | flag_mask(this);
+   } else if (predicate) {
+      return flag_mask(this);
+   } else {
+      return 0;
+   }
 }
 
-bool
-fs_inst::writes_flag() const
+unsigned
+fs_inst::flags_written() const
 {
-   return (conditional_mod && (opcode != BRW_OPCODE_SEL &&
-                               opcode != BRW_OPCODE_IF &&
-                               opcode != BRW_OPCODE_WHILE)) ||
-          opcode == FS_OPCODE_MOV_DISPATCH_TO_FLAGS;
+   /* XXX - This doesn't consider explicit uses of the flag register as
+    *       destination region.
+    */
+   if ((conditional_mod && (opcode != BRW_OPCODE_SEL &&
+                            opcode != BRW_OPCODE_IF &&
+                            opcode != BRW_OPCODE_WHILE)) ||
+       opcode == FS_OPCODE_MOV_DISPATCH_TO_FLAGS) {
+      return flag_mask(this);
+   } else {
+      return 0;
+   }
 }
 
 /**
index 13f4e151433f693c0d89e59355c6e38a3ef71b8d..ca4b40a3a1408fa0657aee945baec237cf884c4d 100644 (file)
@@ -276,8 +276,29 @@ public:
    bool has_side_effects() const;
    bool has_source_and_destination_hazard() const;
 
-   bool reads_flag() const;
-   bool writes_flag() const;
+   /**
+    * Return the subset of flag registers read by the instruction as a bitset
+    * with byte granularity.
+    */
+   unsigned flags_read(const brw_device_info *devinfo) const;
+
+   /**
+    * Return the subset of flag registers updated by the instruction (either
+    * partially or fully) as a bitset with byte granularity.
+    */
+   unsigned flags_written() const;
+
+   bool reads_flag() const
+   {
+      /* XXX - Will get rid of this hack shortly. */
+      const brw_device_info devinfo = {};
+      return flags_read(&devinfo);
+   }
+
+   bool writes_flag() const
+   {
+      return flags_written();
+   }
 
    fs_reg dst;
    fs_reg *src;