i965/fs: Take into account trailing padding in regs_written() and regs_read().
authorFrancisco Jerez <currojerez@riseup.net>
Wed, 7 Sep 2016 21:33:55 +0000 (14:33 -0700)
committerFrancisco Jerez <currojerez@riseup.net>
Wed, 14 Sep 2016 21:50:54 +0000 (14:50 -0700)
This fixes regs_written() and regs_read() to return a more accurate
value when the padding left between components due to a stride value
greater than one causes the region bounds given by size_written or
size_read to overflow into the next register.  This could become a
problem in optimization passes that keep track of dataflow using
fixed-size arrays with register granularity, because the overflow
register (not actually accessed by the region) may not have been
allocated at all which could lead to undefined memory access.

An alternative to this would be to subtract the trailing padding
already during the calculation of fs_inst::size_read and
::size_written, but that would break code that currently assumes that
::size_read and _written are whole multiples of the component size,
and would be hard to maintain looking forward because size_written is
assigned from a bunch of different places.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
src/mesa/drivers/dri/i965/brw_ir_fs.h

index 4ac9baabc1ee264725c58cdb769c0babe2ede0c3..0be67b7b2f9bad2c480686b67608a681b83ad883 100644 (file)
@@ -191,6 +191,20 @@ reg_offset(const fs_reg &r)
           (r.file == ARF || r.file == FIXED_GRF ? r.subnr : 0);
 }
 
+/**
+ * Return the amount of padding in bytes left unused between individual
+ * components of register \p r due to a (horizontal) stride value greater than
+ * one, or zero if components are tightly packed in the register file.
+ */
+static inline unsigned
+reg_padding(const fs_reg &r)
+{
+   const unsigned stride = ((r.file != ARF && r.file != FIXED_GRF) ? r.stride :
+                            r.hstride == 0 ? 0 :
+                            1 << (r.hstride - 1));
+   return (MAX2(1, stride) - 1) * type_sz(r.type);
+}
+
 /**
  * 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
@@ -423,7 +437,9 @@ regs_written(const fs_inst *inst)
 {
    /* XXX - Take into account register-misaligned offsets correctly. */
    assert(inst->dst.file != UNIFORM && inst->dst.file != IMM);
-   return DIV_ROUND_UP(inst->size_written, REG_SIZE);
+   return DIV_ROUND_UP(inst->size_written -
+                       MIN2(inst->size_written, reg_padding(inst->dst)),
+                       REG_SIZE);
 }
 
 /**
@@ -438,7 +454,9 @@ regs_read(const fs_inst *inst, unsigned i)
    /* XXX - Take into account register-misaligned offsets correctly. */
    const unsigned reg_size =
       inst->src[i].file == UNIFORM || inst->src[i].file == IMM ? 4 : REG_SIZE;
-   return DIV_ROUND_UP(inst->size_read(i), reg_size);
+   return DIV_ROUND_UP(inst->size_read(i) -
+                       MIN2(inst->size_read(i), reg_padding(inst->src[i])),
+                       reg_size);
 }
 
 #endif