i965/fs: Clean up remaining uses of fs_inst::reads_flag and ::writes_flag.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_ir_fs.h
index 7e977e9e727a8a5f7cb53a337b4106000f6c4f63..cae41a02b8c36f67886724cb8aa89ef3bdd1e17f 100644 (file)
@@ -36,12 +36,7 @@ public:
    void init();
 
    fs_reg();
-   explicit fs_reg(float f);
-   explicit fs_reg(int32_t i);
-   explicit fs_reg(uint32_t u);
-   explicit fs_reg(uint8_t vf[4]);
-   explicit fs_reg(uint8_t vf0, uint8_t vf1, uint8_t vf2, uint8_t vf3);
-   fs_reg(struct brw_reg reg);
+   fs_reg(struct ::brw_reg reg);
    fs_reg(enum brw_reg_file file, int nr);
    fs_reg(enum brw_reg_file file, int nr, enum brw_reg_type type);
 
@@ -63,8 +58,6 @@ public:
     */
    int subreg_offset;
 
-   fs_reg *reladdr;
-
    /** Register region horizontal stride */
    uint8_t stride;
 };
@@ -92,18 +85,30 @@ byte_offset(fs_reg reg, unsigned delta)
       break;
    case VGRF:
    case ATTR:
-      reg.reg_offset += delta / 32;
+   case UNIFORM: {
+      const unsigned reg_size = (reg.file == UNIFORM ? 4 : REG_SIZE);
+      const unsigned suboffset = reg.subreg_offset + delta;
+      reg.reg_offset += suboffset / reg_size;
+      reg.subreg_offset = suboffset % reg_size;
       break;
-   case MRF:
-      reg.nr += delta / 32;
+   }
+   case MRF: {
+      const unsigned suboffset = reg.subreg_offset + delta;
+      reg.nr += suboffset / REG_SIZE;
+      reg.subreg_offset = suboffset % REG_SIZE;
       break;
+   }
    case ARF:
-   case FIXED_GRF:
+   case FIXED_GRF: {
+      const unsigned suboffset = reg.subnr + delta;
+      reg.nr += suboffset / REG_SIZE;
+      reg.subnr = suboffset % REG_SIZE;
+      break;
+   }
    case IMM:
-   case UNIFORM:
+   default:
       assert(delta == 0);
    }
-   reg.subreg_offset += delta % 32;
    return reg;
 }
 
@@ -129,20 +134,51 @@ horiz_offset(fs_reg reg, unsigned delta)
    return reg;
 }
 
+/**
+ * Get the scalar channel of \p reg given by \p idx and replicate it to all
+ * channels of the result.
+ */
 static inline fs_reg
 component(fs_reg reg, unsigned idx)
 {
-   assert(reg.subreg_offset == 0);
-   reg.subreg_offset = idx * type_sz(reg.type);
+   reg = horiz_offset(reg, idx);
    reg.stride = 0;
    return reg;
 }
 
+/**
+ * Return whether the given register region is n-periodic, i.e. whether the
+ * original region remains invariant after shifting it by \p n scalar
+ * channels.
+ */
+static inline bool
+is_periodic(const fs_reg &reg, unsigned n)
+{
+   if (reg.file == BAD_FILE || reg.is_null()) {
+      return true;
+
+   } else if (reg.file == IMM) {
+      const unsigned period = (reg.type == BRW_REGISTER_TYPE_UV ||
+                               reg.type == BRW_REGISTER_TYPE_V ? 8 :
+                               reg.type == BRW_REGISTER_TYPE_VF ? 4 :
+                               1);
+      return n % period == 0;
+
+   } else if (reg.file == ARF || reg.file == FIXED_GRF) {
+      const unsigned period = (reg.hstride == 0 && reg.vstride == 0 ? 1 :
+                               reg.vstride == 0 ? 1 << reg.width :
+                               ~0);
+      return n % period == 0;
+
+   } else {
+      return reg.stride == 0;
+   }
+}
+
 static inline bool
 is_uniform(const fs_reg &reg)
 {
-   return (reg.stride == 0 || reg.is_null()) &&
-          (!reg.reladdr || is_uniform(*reg.reladdr));
+   return is_periodic(reg, 1);
 }
 
 /**
@@ -173,6 +209,34 @@ half(fs_reg reg, unsigned idx)
    return reg;
 }
 
+/**
+ * Reinterpret each channel of register \p reg as a vector of values of the
+ * given smaller type and take the i-th subcomponent from each.
+ */
+static inline fs_reg
+subscript(fs_reg reg, brw_reg_type type, unsigned i)
+{
+   assert((i + 1) * type_sz(type) <= type_sz(reg.type));
+
+   if (reg.file == ARF || reg.file == FIXED_GRF) {
+      /* The stride is encoded inconsistently for fixed GRF and ARF registers
+       * as the log2 of the actual vertical and horizontal strides.
+       */
+      const int delta = _mesa_logbase2(type_sz(reg.type)) -
+                        _mesa_logbase2(type_sz(type));
+      reg.hstride += (reg.hstride ? delta : 0);
+      reg.vstride += (reg.vstride ? delta : 0);
+
+   } else if (reg.file == IMM) {
+      assert(reg.type == type);
+
+   } else {
+      reg.stride *= type_sz(reg.type) / type_sz(type);
+   }
+
+   return byte_offset(retype(reg, type), i * type_sz(type));
+}
+
 static const fs_reg reg_undef;
 
 class fs_inst : public backend_instruction {
@@ -210,9 +274,19 @@ public:
    bool can_do_source_mods(const struct brw_device_info *devinfo);
    bool can_change_types() const;
    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;
 
    fs_reg dst;
    fs_reg *src;
@@ -226,21 +300,19 @@ public:
     */
    uint8_t exec_size;
 
+   /**
+    * Channel group from the hardware execution and predication mask that
+    * should be applied to the instruction.  The subset of channel enable
+    * signals (calculated from the EU control flow and predication state)
+    * given by [group, group + exec_size) will be used to mask GRF writes and
+    * any other side effects of the instruction.
+    */
+   uint8_t group;
+
    bool eot:1;
-   bool force_sechalf:1;
    bool pi_noperspective:1;   /**< Pixel interpolator noperspective flag */
 };
 
-/**
- * Set second-half quarter control on \p inst.
- */
-static inline fs_inst *
-set_sechalf(fs_inst *inst)
-{
-   inst->force_sechalf = true;
-   return inst;
-}
-
 /**
  * Make the execution of \p inst dependent on the evaluation of a possibly
  * inverted predicate.