i965/vec4: Replace dst/src_reg::reg_offset with dst/src_reg::offset expressed in...
authorFrancisco Jerez <currojerez@riseup.net>
Thu, 1 Sep 2016 20:10:36 +0000 (13:10 -0700)
committerFrancisco Jerez <currojerez@riseup.net>
Wed, 14 Sep 2016 21:50:52 +0000 (14:50 -0700)
The dst/src_reg::offset field in byte units introduced in the previous
patch is a more straightforward alternative to an offset
representation split between ::reg_offset and ::subreg_offset fields.
The split representation makes it too easy to forget about one of the
offsets while dealing with the other, which has led to multiple FS
back-end bugs in the past.  To make the matter worse the unit
reg_offset was expressed in was rather inconsistent, for uniforms it
would be expressed in either 4B or 16B units depending on the
back-end, and for most other things it would be expressed in 32B
units.

This encodes reg_offset as a new offset field expressed consistently
in byte units.  Each rvalue reference of reg_offset in existing code
like 'x = r.reg_offset' is rewritten to 'x = r.offset / reg_unit', and
each lvalue reference like 'r.reg_offset = x' is rewritten to
'r.offset = r.offset % reg_unit + x * reg_unit'.

Because the change affects a lot of places and is rather non-trivial
to verify due to the inconsistent value of reg_unit, I've tried to
avoid making any additional changes other than applying the rewrite
rule above in order to keep the patch as simple as possible, sometimes
at the cost of introducing obvious stupidity (e.g. algebraic
expressions that could be simplified given some knowledge of the
context) -- I'll clean those up later on in a second pass.

v2: Fix division by the wrong reg_unit in the UNIFORM case of
    convert_to_hw_regs(). (Iago)

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
src/mesa/drivers/dri/i965/brw_ir_vec4.h
src/mesa/drivers/dri/i965/brw_vec4.cpp
src/mesa/drivers/dri/i965/brw_vec4_cmod_propagation.cpp
src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp
src/mesa/drivers/dri/i965/brw_vec4_live_variables.h
src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp

index 3813bb8d0ea13c1f6eac3addc4ab11349c6659fb..4f49428ef3f82b5f905eae54b26dab1b66646ac9 100644 (file)
@@ -65,7 +65,7 @@ offset(src_reg reg, unsigned delta)
 {
    assert(delta == 0 ||
           (reg.file != ARF && reg.file != FIXED_GRF && reg.file != IMM));
-   reg.reg_offset += delta;
+   reg.offset += delta * (reg.file == UNIFORM ? 16 : REG_SIZE);
    return reg;
 }
 
@@ -134,7 +134,7 @@ offset(dst_reg reg, unsigned delta)
 {
    assert(delta == 0 ||
           (reg.file != ARF && reg.file != FIXED_GRF && reg.file != IMM));
-   reg.reg_offset += delta;
+   reg.offset += delta * (reg.file == UNIFORM ? 16 : REG_SIZE);
    return reg;
 }
 
index d52fdc06eddc7290ec843a78d2eadf955b8bfdcb..de5b5d6c838d4b33bfc2c57e07e9897dfafc917f 100644 (file)
@@ -68,7 +68,7 @@ src_reg::src_reg()
 src_reg::src_reg(struct ::brw_reg reg) :
    backend_reg(reg)
 {
-   this->reg_offset = 0;
+   this->offset = 0;
    this->reladdr = NULL;
 }
 
@@ -125,7 +125,7 @@ dst_reg::dst_reg(enum brw_reg_file file, int nr, brw_reg_type type,
 dst_reg::dst_reg(struct ::brw_reg reg) :
    backend_reg(reg)
 {
-   this->reg_offset = 0;
+   this->offset = 0;
    this->reladdr = NULL;
 }
 
@@ -395,7 +395,7 @@ vec4_visitor::opt_vector_float()
           * sequence.  Combine anything we've accumulated so far.
           */
          if (last_reg != inst->dst.nr ||
-             last_reg_offset != inst->dst.reg_offset ||
+             last_reg_offset != inst->dst.offset / REG_SIZE ||
              last_reg_file != inst->dst.file ||
              (vf > 0 && dest_type != need_type)) {
 
@@ -439,7 +439,7 @@ vec4_visitor::opt_vector_float()
             imm_inst[inst_count++] = inst;
 
             last_reg = inst->dst.nr;
-            last_reg_offset = inst->dst.reg_offset;
+            last_reg_offset = inst->dst.offset / REG_SIZE;
             last_reg_file = inst->dst.file;
             if (vf > 0)
                dest_type = need_type;
@@ -539,8 +539,8 @@ vec4_visitor::split_uniform_registers()
 
         assert(!inst->src[i].reladdr);
 
-         inst->src[i].nr += inst->src[i].reg_offset;
-        inst->src[i].reg_offset = 0;
+         inst->src[i].nr += inst->src[i].offset / 16;
+        inst->src[i].offset %= 16;
       }
    }
 }
@@ -857,7 +857,7 @@ vec4_visitor::move_push_constants_to_pull_constants()
 
         inst->src[i].file = temp.file;
          inst->src[i].nr = temp.nr;
-        inst->src[i].reg_offset = temp.reg_offset;
+        inst->src[i].offset %= 16;
         inst->src[i].reladdr = NULL;
       }
    }
@@ -948,7 +948,7 @@ vec4_visitor::opt_set_dependency_control()
           * on, don't do dependency control across the read.
           */
          for (int i = 0; i < 3; i++) {
-            int reg = inst->src[i].nr + inst->src[i].reg_offset;
+            int reg = inst->src[i].nr + inst->src[i].offset / REG_SIZE;
             if (inst->src[i].file == VGRF) {
                last_grf_write[reg] = NULL;
             } else if (inst->src[i].file == FIXED_GRF) {
@@ -967,7 +967,7 @@ vec4_visitor::opt_set_dependency_control()
          /* Now, see if we can do dependency control for this instruction
           * against a previous one writing to its destination.
           */
-         int reg = inst->dst.nr + inst->dst.reg_offset;
+         int reg = inst->dst.nr + inst->dst.offset / REG_SIZE;
          if (inst->dst.file == VGRF || inst->dst.file == FIXED_GRF) {
             if (last_grf_write[reg] &&
                 !(inst->dst.writemask & grf_channels_written[reg])) {
@@ -1086,7 +1086,7 @@ vec4_visitor::opt_register_coalesce()
       /* Remove no-op MOVs */
       if (inst->dst.file == inst->src[0].file &&
           inst->dst.nr == inst->src[0].nr &&
-          inst->dst.reg_offset == inst->src[0].reg_offset) {
+          inst->dst.offset / REG_SIZE == inst->src[0].offset / REG_SIZE) {
          bool is_nop_mov = true;
 
          for (unsigned c = 0; c < 4; c++) {
@@ -1232,12 +1232,14 @@ vec4_visitor::opt_register_coalesce()
         while (scan_inst != inst) {
            if (scan_inst->dst.file == VGRF &&
                 scan_inst->dst.nr == inst->src[0].nr &&
-               scan_inst->dst.reg_offset == inst->src[0].reg_offset) {
+               scan_inst->dst.offset / REG_SIZE ==
+                 inst->src[0].offset / REG_SIZE) {
                scan_inst->reswizzle(inst->dst.writemask,
                                     inst->src[0].swizzle);
               scan_inst->dst.file = inst->dst.file;
                scan_inst->dst.nr = inst->dst.nr;
-              scan_inst->dst.reg_offset = inst->dst.reg_offset;
+              scan_inst->dst.offset = scan_inst->dst.offset % REG_SIZE +
+                  ROUND_DOWN_TO(inst->dst.offset, REG_SIZE);
                if (inst->saturate &&
                    inst->dst.type != scan_inst->dst.type) {
                   /* If we have reached this point, scan_inst is a non
@@ -1360,17 +1362,17 @@ vec4_visitor::split_virtual_grfs()
 
    foreach_block_and_inst(block, vec4_instruction, inst, cfg) {
       if (inst->dst.file == VGRF && split_grf[inst->dst.nr] &&
-          inst->dst.reg_offset != 0) {
+          inst->dst.offset / REG_SIZE != 0) {
          inst->dst.nr = (new_virtual_grf[inst->dst.nr] +
-                          inst->dst.reg_offset - 1);
-         inst->dst.reg_offset = 0;
+                         inst->dst.offset / REG_SIZE - 1);
+         inst->dst.offset %= REG_SIZE;
       }
       for (int i = 0; i < 3; i++) {
          if (inst->src[i].file == VGRF && split_grf[inst->src[i].nr] &&
-             inst->src[i].reg_offset != 0) {
+             inst->src[i].offset / REG_SIZE != 0) {
             inst->src[i].nr = (new_virtual_grf[inst->src[i].nr] +
-                                inst->src[i].reg_offset - 1);
-            inst->src[i].reg_offset = 0;
+                                inst->src[i].offset / REG_SIZE - 1);
+            inst->src[i].offset %= REG_SIZE;
          }
       }
    }
@@ -1411,7 +1413,7 @@ vec4_visitor::dump_instruction(backend_instruction *be_inst, FILE *file)
 
    switch (inst->dst.file) {
    case VGRF:
-      fprintf(file, "vgrf%d.%d", inst->dst.nr, inst->dst.reg_offset);
+      fprintf(file, "vgrf%d.%d", inst->dst.nr, inst->dst.offset / REG_SIZE);
       break;
    case FIXED_GRF:
       fprintf(file, "g%d", inst->dst.nr);
@@ -1534,10 +1536,10 @@ vec4_visitor::dump_instruction(backend_instruction *be_inst, FILE *file)
       }
 
       /* Don't print .0; and only VGRFs have reg_offsets and sizes */
-      if (inst->src[i].reg_offset != 0 &&
+      if (inst->src[i].offset / REG_SIZE != 0 &&
           inst->src[i].file == VGRF &&
           alloc.sizes[inst->src[i].nr] != 1)
-         fprintf(file, ".%d", inst->src[i].reg_offset);
+         fprintf(file, ".%d", inst->src[i].offset / REG_SIZE);
 
       if (inst->src[i].file != IMM) {
          static const char *chans[4] = {"x", "y", "z", "w"};
@@ -1596,7 +1598,8 @@ vec4_visitor::lower_attributes_to_hw_regs(const int *attribute_map,
         if (inst->src[i].file != ATTR)
            continue;
 
-         int grf = attribute_map[inst->src[i].nr + inst->src[i].reg_offset];
+         int grf = attribute_map[inst->src[i].nr +
+                                 inst->src[i].offset / REG_SIZE];
 
          /* All attributes used in the shader need to have been assigned a
           * hardware register by the caller
@@ -1808,7 +1811,7 @@ vec4_visitor::emit_shader_time_write(int shader_time_subindex, src_reg value)
 
    dst_reg offset = dst;
    dst_reg time = dst;
-   time.reg_offset++;
+   time.offset += REG_SIZE;
 
    offset.type = BRW_REGISTER_TYPE_UD;
    int index = shader_time_index * 3 + shader_time_subindex;
@@ -1831,7 +1834,7 @@ vec4_visitor::convert_to_hw_regs()
          struct brw_reg reg;
          switch (src.file) {
          case VGRF:
-            reg = brw_vec8_grf(src.nr + src.reg_offset, 0);
+            reg = brw_vec8_grf(src.nr + src.offset / REG_SIZE, 0);
             reg.type = src.type;
             reg.swizzle = src.swizzle;
             reg.abs = src.abs;
@@ -1840,8 +1843,8 @@ vec4_visitor::convert_to_hw_regs()
 
          case UNIFORM:
             reg = stride(brw_vec4_grf(prog_data->base.dispatch_grf_start_reg +
-                                      (src.nr + src.reg_offset) / 2,
-                                      ((src.nr + src.reg_offset) % 2) * 4),
+                                      (src.nr + src.offset / 16) / 2,
+                                      ((src.nr + src.offset / 16) % 2) * 4),
                          0, 4, 1);
             reg.type = src.type;
             reg.swizzle = src.swizzle;
@@ -1887,14 +1890,14 @@ vec4_visitor::convert_to_hw_regs()
 
       switch (inst->dst.file) {
       case VGRF:
-         reg = brw_vec8_grf(dst.nr + dst.reg_offset, 0);
+         reg = brw_vec8_grf(dst.nr + dst.offset / REG_SIZE, 0);
          reg.type = dst.type;
          reg.writemask = dst.writemask;
          break;
 
       case MRF:
-         assert(((dst.nr + dst.reg_offset) & ~BRW_MRF_COMPR4) < BRW_MAX_MRF(devinfo->gen));
-         reg = brw_message_reg(dst.nr + dst.reg_offset);
+         assert(((dst.nr + dst.offset / REG_SIZE) & ~BRW_MRF_COMPR4) < BRW_MAX_MRF(devinfo->gen));
+         reg = brw_message_reg(dst.nr + dst.offset / REG_SIZE);
          reg.type = dst.type;
          reg.writemask = dst.writemask;
          break;
index c376bebbe8eed71b373f32ba9b86e9724123be9f..17f9e15c5a2ab8f7e2f3e65dd1b9c9a2148ef785 100644 (file)
@@ -71,7 +71,7 @@ opt_cmod_propagation_local(bblock_t *block)
          if (inst->src[0].in_range(scan_inst->dst,
                                    scan_inst->regs_written)) {
             if ((scan_inst->predicate && scan_inst->opcode != BRW_OPCODE_SEL) ||
-                scan_inst->dst.reg_offset != inst->src[0].reg_offset ||
+                scan_inst->dst.offset / REG_SIZE != inst->src[0].offset / REG_SIZE ||
                 (scan_inst->dst.writemask != WRITEMASK_X &&
                  scan_inst->dst.writemask != WRITEMASK_XYZW) ||
                 (scan_inst->dst.writemask == WRITEMASK_XYZW &&
index cc0e44cc8e13cbc6cef301b608c139acce14d1fc..1f77d229a3337f61274005fce7772726e3103060 100644 (file)
@@ -441,7 +441,7 @@ vec4_visitor::opt_copy_propagation(bool do_constant_prop)
             continue;
 
          const unsigned reg = (alloc.offsets[inst->src[i].nr] +
-                                inst->src[i].reg_offset);
+                               inst->src[i].offset / REG_SIZE);
          const copy_entry &entry = entries[reg];
 
          if (do_constant_prop && try_constant_propagate(devinfo, inst, i, &entry))
@@ -453,7 +453,7 @@ vec4_visitor::opt_copy_propagation(bool do_constant_prop)
       /* Track available source registers. */
       if (inst->dst.file == VGRF) {
         const int reg =
-            alloc.offsets[inst->dst.nr] + inst->dst.reg_offset;
+            alloc.offsets[inst->dst.nr] + inst->dst.offset / REG_SIZE;
 
         /* Update our destination's current channel values.  For a direct copy,
          * the value is the newly propagated source.  Otherwise, we don't know
index 12d281eb24551d49d5d0e96097c12a97ee12afbd..2fbcaa1228a00b7479e9571a6c2e6f0f8b131965 100644 (file)
@@ -83,8 +83,8 @@ var_from_reg(const simple_allocator &alloc, const src_reg &reg,
              unsigned c = 0)
 {
    assert(reg.file == VGRF && reg.nr < alloc.count &&
-          reg.reg_offset < alloc.sizes[reg.nr] && c < 4);
-   return (4 * (alloc.offsets[reg.nr] + reg.reg_offset) +
+          reg.offset / REG_SIZE < alloc.sizes[reg.nr] && c < 4);
+   return (4 * (alloc.offsets[reg.nr] + reg.offset / REG_SIZE) +
            BRW_GET_SWZ(reg.swizzle, c));
 }
 
@@ -93,8 +93,8 @@ var_from_reg(const simple_allocator &alloc, const dst_reg &reg,
              unsigned c = 0)
 {
    assert(reg.file == VGRF && reg.nr < alloc.count &&
-          reg.reg_offset < alloc.sizes[reg.nr] && c < 4);
-   return 4 * (alloc.offsets[reg.nr] + reg.reg_offset) + c;
+          reg.offset / REG_SIZE < alloc.sizes[reg.nr] && c < 4);
+   return 4 * (alloc.offsets[reg.nr] + reg.offset / REG_SIZE) + c;
 }
 
 } /* namespace brw */
index c29411847e53442ae602725dbb1ff0659ca3a6ff..60f87834b9f2313ca356a6cf4f07c05253f019fd 100644 (file)
@@ -715,7 +715,7 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
          assert(const_offset->u32[0] % 4 == 0);
 
          unsigned offset = const_offset->u32[0] + shift * 4;
-         src.reg_offset = offset / 16;
+         src.offset = ROUND_DOWN_TO(offset, 16);
          shift = (offset % 16) / 4;
          src.swizzle += BRW_SWIZZLE4(shift, shift, shift, shift);
 
index afc326612a2812f3ff0b667a356788e6fcdab48a..947bb492bda7f766cf86a58a1cc4eef1b10204ea 100644 (file)
@@ -33,8 +33,8 @@ static void
 assign(unsigned int *reg_hw_locations, backend_reg *reg)
 {
    if (reg->file == VGRF) {
-      reg->nr = reg_hw_locations[reg->nr] + reg->reg_offset;
-      reg->reg_offset = 0;
+      reg->nr = reg_hw_locations[reg->nr] + reg->offset / REG_SIZE;
+      reg->offset %= REG_SIZE;
    }
 }
 
index 22991e911adf4a1096619b22c4faf905cfd0bccd..b5204e889f5bf4fb909fbf15a281e37eae6ba939 100644 (file)
@@ -1481,7 +1481,7 @@ vec4_visitor::emit_scratch_read(bblock_t *block, vec4_instruction *inst,
                                dst_reg temp, src_reg orig_src,
                                int base_offset)
 {
-   int reg_offset = base_offset + orig_src.reg_offset;
+   int reg_offset = base_offset + orig_src.offset / REG_SIZE;
    src_reg index = get_scratch_offset(block, inst, orig_src.reladdr,
                                       reg_offset);
 
@@ -1498,7 +1498,7 @@ void
 vec4_visitor::emit_scratch_write(bblock_t *block, vec4_instruction *inst,
                                  int base_offset)
 {
-   int reg_offset = base_offset + inst->dst.reg_offset;
+   int reg_offset = base_offset + inst->dst.offset / REG_SIZE;
    src_reg index = get_scratch_offset(block, inst, inst->dst.reladdr,
                                       reg_offset);
 
@@ -1523,7 +1523,7 @@ vec4_visitor::emit_scratch_write(bblock_t *block, vec4_instruction *inst,
 
    inst->dst.file = temp.file;
    inst->dst.nr = temp.nr;
-   inst->dst.reg_offset = temp.reg_offset;
+   inst->dst.offset %= REG_SIZE;
    inst->dst.reladdr = NULL;
 }
 
@@ -1553,7 +1553,7 @@ vec4_visitor::emit_resolve_reladdr(int scratch_loc[], bblock_t *block,
       dst_reg temp = dst_reg(this, glsl_type::vec4_type);
       emit_scratch_read(block, inst, temp, src, scratch_loc[src.nr]);
       src.nr = temp.nr;
-      src.reg_offset = temp.reg_offset;
+      src.offset %= REG_SIZE;
       src.reladdr = NULL;
    }
 
@@ -1649,7 +1649,7 @@ vec4_visitor::emit_pull_constant_load(bblock_t *block, vec4_instruction *inst,
                                      dst_reg temp, src_reg orig_src,
                                       int base_offset, src_reg indirect)
 {
-   int reg_offset = base_offset + orig_src.reg_offset;
+   int reg_offset = base_offset + orig_src.offset / 16;
    const unsigned index = prog_data->base.binding_table.pull_constants_start;
 
    src_reg offset;
@@ -1710,7 +1710,7 @@ vec4_visitor::move_uniform_array_access_to_pull_constants()
           inst->src[0].file != UNIFORM)
          continue;
 
-      int uniform_nr = inst->src[0].nr + inst->src[0].reg_offset;
+      int uniform_nr = inst->src[0].nr + inst->src[0].offset / 16;
 
       for (unsigned j = 0; j < DIV_ROUND_UP(inst->src[2].ud, 16); j++)
          pull_constant_loc[uniform_nr + j] = 0;
@@ -1740,7 +1740,7 @@ vec4_visitor::move_uniform_array_access_to_pull_constants()
           inst->src[0].file != UNIFORM)
          continue;
 
-      int uniform_nr = inst->src[0].nr + inst->src[0].reg_offset;
+      int uniform_nr = inst->src[0].nr + inst->src[0].offset / 16;
 
       assert(inst->src[0].swizzle == BRW_SWIZZLE_NOOP);