[Mesa-dev] [PATCH 10/25] i965/fs: Generalize regions_overlap() from copy propagation to handle non-VGRF files.

Francisco Jerez currojerez at riseup.net
Sat May 28 02:05:51 UTC 2016


This will be useful in several places.  The only externally visible
difference (other than non-VGRF files being supported now) is that the
region sizes are now passed in byte units instead of in GRF units
because the loss of precision would have become a problem in the SIMD
lowering pass.
---
 .../drivers/dri/i965/brw_fs_copy_propagation.cpp   | 16 +++------
 src/mesa/drivers/dri/i965/brw_ir_fs.h              | 38 ++++++++++++++++++++++
 2 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp b/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp
index 38103af..d88d62b 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp
@@ -757,14 +757,6 @@ can_propagate_from(fs_inst *inst)
            !inst->is_partial_write());
 }
 
-inline bool
-regions_overlap(const fs_reg &r, unsigned n, const fs_reg &s, unsigned m)
-{
-   return r.file == s.file && r.nr == s.nr &&
-      !(r.reg_offset + n <= s.reg_offset ||
-        s.reg_offset + m <= r.reg_offset);
-}
-
 /* Walks a basic block and does copy propagation on it using the acp
  * list.
  */
@@ -791,8 +783,8 @@ fs_visitor::opt_copy_propagate_local(void *copy_prop_ctx, bblock_t *block,
       /* kill the destination from the ACP */
       if (inst->dst.file == VGRF) {
          foreach_in_list_safe(acp_entry, entry, &acp[inst->dst.nr % ACP_HASH_SIZE]) {
-            if (regions_overlap(entry->dst, entry->regs_written,
-                                inst->dst, inst->regs_written))
+            if (regions_overlap(entry->dst, entry->regs_written * REG_SIZE,
+                                inst->dst, inst->regs_written * REG_SIZE))
                entry->remove();
          }
 
@@ -804,8 +796,8 @@ fs_visitor::opt_copy_propagate_local(void *copy_prop_ctx, bblock_t *block,
                /* Make sure we kill the entry if this instruction overwrites
                 * _any_ of the registers that it reads
                 */
-               if (regions_overlap(entry->src, entry->regs_read,
-                                   inst->dst, inst->regs_written))
+               if (regions_overlap(entry->src, entry->regs_read * REG_SIZE,
+                                   inst->dst, inst->regs_written * REG_SIZE))
                   entry->remove();
             }
 	 }
diff --git a/src/mesa/drivers/dri/i965/brw_ir_fs.h b/src/mesa/drivers/dri/i965/brw_ir_fs.h
index cc1561d..73c6327 100644
--- a/src/mesa/drivers/dri/i965/brw_ir_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_ir_fs.h
@@ -172,6 +172,44 @@ component(fs_reg reg, unsigned idx)
 }
 
 /**
+ * Return an integer identifying the discrete address space a register is
+ * contained in.  A register is by definition fully contained in the single
+ * reg_space it belongs to, so two registers with different reg_space ids are
+ * guaranteed not to overlap.  Most register files are a single reg_space of
+ * its own, only the VGRF file is composed of multiple discrete address
+ * spaces, one for each VGRF allocation.
+ */
+static inline uint32_t
+reg_space(const fs_reg &r)
+{
+   return r.file << 16 | (r.file == VGRF ? r.nr : 0);
+}
+
+/**
+ * Return the base offset in bytes of a register relative to the start of its
+ * reg_space().
+ */
+static inline unsigned
+reg_offset(const fs_reg &r)
+{
+   return ((r.file == VGRF || r.file == IMM ? 0 : r.nr) + r.reg_offset) *
+          (r.file == UNIFORM ? 4 : REG_SIZE) + r.subreg_offset;
+}
+
+/**
+ * Return whether the register region starting at \p r and spanning \p dr
+ * bytes could potentially overlap the register region starting at \p s and
+ * spanning \p ds bytes.
+ */
+static inline bool
+regions_overlap(const fs_reg &r, unsigned dr, const fs_reg &s, unsigned ds)
+{
+   return reg_space(r) == reg_space(s) &&
+          !(reg_offset(r) + dr <= reg_offset(s) ||
+            reg_offset(s) + ds <= reg_offset(r));
+}
+
+/**
  * 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.
-- 
2.7.3



More information about the mesa-dev mailing list