<p dir="ltr"><br>
On Dec 15, 2015 12:30 AM, "Abdiel Janulgue" <<a href="mailto:abdiel.janulgue@linux.intel.com">abdiel.janulgue@linux.intel.com</a>> wrote:<br>
><br>
><br>
><br>
> On 12/10/2015 06:23 AM, Jason Ekstrand wrote:<br>
> > While we're at it, we also add support for the possibility that the<br>
> > indirect is, in fact, a constant.  This shouldn't happen in the common case<br>
> > (if it does, that means NIR failed to constant-fold something), but it's<br>
> > possible so we should handle it.<br>
><br>
> Perhaps this should re-ordered before patch 3?</p>
<p dir="ltr">We could, but it really doesn't matter. No MOV_INDIRECT ever hits the generator pre-BDW prior to patch 15. They get lowered away to pull constant loads.<br>
--Jason</p>
<p dir="ltr">> > ---<br>
> >  src/mesa/drivers/dri/i965/brw_fs.cpp           |  4 ++<br>
> >  src/mesa/drivers/dri/i965/brw_fs_generator.cpp | 51 +++++++++++++++++++-------<br>
> >  2 files changed, 42 insertions(+), 13 deletions(-)<br>
> ><br>
> > diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
> > index 9eaf8d0..a2ec03e 100644<br>
> > --- a/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
> > +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
> > @@ -4424,6 +4424,10 @@ get_lowered_simd_width(const struct brw_device_info *devinfo,<br>
> >     case SHADER_OPCODE_TYPED_SURFACE_WRITE_LOGICAL:<br>
> >        return 8;<br>
> ><br>
> > +   case SHADER_OPCODE_MOV_INDIRECT:<br>
> > +      /* Prior to Broadwell, we only have 8 address subregisters */<br>
> > +      return devinfo->gen < 8 ? 8 : inst->exec_size;<br>
> > +<br>
> >     default:<br>
> >        return inst->exec_size;<br>
> >     }<br>
> > diff --git a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp<br>
> > index d86eee1..7fa6d84 100644<br>
> > --- a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp<br>
> > +++ b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp<br>
> > @@ -351,22 +351,47 @@ fs_generator::generate_mov_indirect(fs_inst *inst,<br>
> ><br>
> >     unsigned imm_byte_offset = <a href="http://reg.nr">reg.nr</a> * REG_SIZE + reg.subnr;<br>
> ><br>
> > -   /* We use VxH indirect addressing, clobbering a0.0 through a0.7. */<br>
> > -   struct brw_reg addr = vec8(brw_address_reg(0));<br>
> > +   if (indirect_byte_offset.file == BRW_IMMEDIATE_VALUE) {<br>
> > +      imm_byte_offset += indirect_byte_offset.ud;<br>
> ><br>
> > -   /* The destination stride of an instruction (in bytes) must be greater<br>
> > -    * than or equal to the size of the rest of the instruction.  Since the<br>
> > -    * address register is of type UW, we can't use a D-type instruction.<br>
> > -    * In order to get around this, re re-type to UW and use a stride.<br>
> > -    */<br>
> > -   indirect_byte_offset =<br>
> > -      retype(spread(indirect_byte_offset, 2), BRW_REGISTER_TYPE_UW);<br>
> > +      <a href="http://reg.nr">reg.nr</a> = imm_byte_offset / REG_SIZE;<br>
> > +      reg.subnr = imm_byte_offset % REG_SIZE;<br>
> > +      brw_MOV(p, dst, reg);<br>
> > +   } else {<br>
> > +      /* Prior to Broadwell, there are only 8 address registers. */<br>
> > +      assert(inst->exec_size == 8 || devinfo->gen >= 8);<br>
> ><br>
> > -   /* Prior to Broadwell, there are only 8 address registers. */<br>
> > -   assert(inst->exec_size == 8 || devinfo->gen >= 8);<br>
> > +      /* We use VxH indirect addressing, clobbering a0.0 through a0.7. */<br>
> > +      struct brw_reg addr = vec8(brw_address_reg(0));<br>
> ><br>
> > -   brw_MOV(p, addr, indirect_byte_offset);<br>
> > -   brw_MOV(p, dst, retype(brw_VxH_indirect(0, imm_byte_offset), dst.type));<br>
> > +      /* The destination stride of an instruction (in bytes) must be greater<br>
> > +       * than or equal to the size of the rest of the instruction.  Since the<br>
> > +       * address register is of type UW, we can't use a D-type instruction.<br>
> > +       * In order to get around this, re re-type to UW and use a stride.<br>
> > +       */<br>
> > +      indirect_byte_offset =<br>
> > +         retype(spread(indirect_byte_offset, 2), BRW_REGISTER_TYPE_UW);<br>
> > +<br>
> > +      if (devinfo->gen < 8) {<br>
> > +         /* Prior to broadwell, we have a restriction that the bottom 5 bits<br>
> > +          * of the base offset and the bottom 5 bits of the indirect must add<br>
> > +          * to less than 32.  In other words, the hardware needs to be able to<br>
> > +          * add the bottom five bits of the two to get the subnumber and add<br>
> > +          * the next 7 bits of each to get the actual register number.  Since<br>
> > +          * the indirect may cause us to cross a register boundary, this makes<br>
> > +          * it almost useless.  We could try and do something clever where we<br>
> > +          * use a actual base offset if base_offset % 32 == 0 but that would<br>
> > +          * mean we were generating different code depending on the base<br>
> > +          * offset.  Instead, for the sake of consistency, we'll just do the<br>
> > +          * add ourselves.<br>
> > +          */<br>
> > +         brw_ADD(p, addr, indirect_byte_offset, brw_imm_uw(imm_byte_offset));<br>
> > +         brw_MOV(p, dst, retype(brw_VxH_indirect(0, 0), dst.type));<br>
> > +      } else {<br>
> > +         brw_MOV(p, addr, indirect_byte_offset);<br>
> > +         brw_MOV(p, dst, retype(brw_VxH_indirect(0, imm_byte_offset), dst.type));<br>
> > +      }<br>
> > +   }<br>
> >  }<br>
> ><br>
> >  void<br>
> ><br>
</p>