<p dir="ltr"><br>
On Sep 20, 2014 2:52 PM, "Connor Abbott" <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>> wrote:<br>
><br>
> On Sat, Sep 20, 2014 at 4:56 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
> ><br>
> ><br>
> > On Sat, Sep 20, 2014 at 12:44 PM, Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>> wrote:<br>
> >><br>
> >> On Sat, Sep 20, 2014 at 1:23 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
> >> wrote:<br>
> >> > ---<br>
> >> >  src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp | 24<br>
> >> > ++++++++++++++++++++++-<br>
> >> >  src/mesa/drivers/dri/i965/intel_screen.h          |  5 +++++<br>
> >> >  2 files changed, 28 insertions(+), 1 deletion(-)<br>
> >> ><br>
> >> > diff --git a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp<br>
> >> > b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp<br>
> >> > index b42f1e5..41e8855 100644<br>
> >> > --- a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp<br>
> >> > +++ b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp<br>
> >> > @@ -116,8 +116,10 @@ brw_alloc_reg_set(struct intel_screen *screen, int<br>
> >> > reg_width)<br>
> >> >     /* Compute the total number of registers across all classes. */<br>
> >> >     int ra_reg_count = 0;<br>
> >> >     for (int i = 0; i < class_count; i++) {<br>
> >> > +      screen->wm_reg_sets[index].class_first_reg[i] = ra_reg_count;<br>
> >> >        ra_reg_count += base_reg_count - (class_sizes[i] - 1);<br>
> >> >     }<br>
> >> > +   screen->wm_reg_sets[index].class_first_reg[class_count] =<br>
> >> > ra_reg_count;<br>
> >> ><br>
> >> >     uint8_t *ra_reg_to_grf = ralloc_array(screen, uint8_t,<br>
> >> > ra_reg_count);<br>
> >> >     struct ra_regs *regs = ra_alloc_reg_set(screen, ra_reg_count);<br>
> >> > @@ -469,9 +471,29 @@ fs_visitor::assign_regs(bool allow_spilling)<br>
> >> >     }<br>
> >> ><br>
> >> >     setup_payload_interference(g, payload_node_count,<br>
> >> > first_payload_node);<br>
> >> > -   if (brw->gen >= 7)<br>
> >> > +   if (brw->gen >= 7) {<br>
> >> >        setup_mrf_hack_interference(g, first_mrf_hack_node);<br>
> >> ><br>
> >> > +      foreach_in_list(fs_inst, inst, &instructions) {<br>
> >> > +         /* When we do send-from-GRF for FB writes, we need to ensure<br>
> >> > that<br>
> >> > +          * the last write instruction sends from a high register.<br>
> >> > This is<br>
> >> > +          * because the vertex fetcher wants to start filling the low<br>
> >> > +          * payload registers while the pixel data port is still<br>
> >> > working on<br>
> >> > +          * writing out the memory.  If we don't do this, we get<br>
> >> > rendering<br>
> >> > +          * artifacts.<br>
> >> > +          *<br>
> >> > +          * We could just do "something high".  Instead, we just pick<br>
> >> > the<br>
> >> > +          * highest register that works.<br>
> >> > +          */<br>
> >> > +         if (inst->opcode == FS_OPCODE_FB_WRITE && inst->eot) {<br>
> >> > +            int size = virtual_grf_sizes[inst->src[0].reg];<br>
> >> > +            int reg = screen->wm_reg_sets[rsi].class_first_reg[size] -<br>
> >> > 1;<br>
> >> > +            ra_set_node_reg(g, inst->src[0].reg, reg);<br>
> >> > +            break;<br>
> >> > +         }<br>
> >> > +      }<br>
> >> > +   }<br>
> >> > +<br>
> >> >     if (dispatch_width > 8) {<br>
> >> >        /* In 16-wide dispatch we have an issue where a compressed<br>
> >> >         * instruction is actually two instructions executed<br>
> >> > simultaneiously.<br>
> >> > diff --git a/src/mesa/drivers/dri/i965/intel_screen.h<br>
> >> > b/src/mesa/drivers/dri/i965/intel_screen.h<br>
> >> > index 945f6f5..8bc6abd 100644<br>
> >> > --- a/src/mesa/drivers/dri/i965/intel_screen.h<br>
> >> > +++ b/src/mesa/drivers/dri/i965/intel_screen.h<br>
> >> > @@ -90,6 +90,11 @@ struct intel_screen<br>
> >> >        int classes[16];<br>
> >> ><br>
> >> >        /**<br>
> >> > +       * Array of the first ra reg in eahch ra class.<br>
> >><br>
> >> Typo.<br>
> ><br>
> ><br>
> > Thanks<br>
> ><br>
> >><br>
> >><br>
> >> > +       */<br>
> >> > +      int class_first_reg[17];<br>
> >> > +<br>
> >> > +      /**<br>
> >> >         * Mapping for register-allocated objects in *regs to the first<br>
> >> >         * GRF for that object.<br>
> >> >         */<br>
> >> > --<br>
> >> > 2.1.0<br>
> >> ><br>
> >> > _______________________________________________<br>
> >> > mesa-dev mailing list<br>
> >> > <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> >> > <a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
> >><br>
> >> I think it would be less confusing if instead of introducing a<br>
> >> "class_first_reg" array you added a class_last_reg array and then did<br>
> >> class_last_reg[size - 1] - iiuc, you're relying on the fact that the<br>
> >> first reg of one class minus one is the last reg of the previous<br>
> >> class, which isn't obvious and it takes a while to realize what's<br>
> >> going on.<br>
> ><br>
> ><br>
> > That's fair.  I can change that easily enough.  It doesn't really matter<br>
> > that much.  I just kind of liked the fact that  last_reg[n] - last_reg[n-1]<br>
> > == class_size.  But it doesn't matter and what you suggested would be far<br>
> > more obvious.<br>
> ><br>
> >><br>
> >> BTW, just so you know, I don't think it's generally a good idea to set<br>
> >> more than one node to be pre-allocated to the same register, since<br>
> >> things will blow up if those nodes interfere. It's probably OK here<br>
> >> since I can't think of a way that an input register preallocated to<br>
> >> the highest register would interfere with the input to the fb write,<br>
> ><br>
> ><br>
> > Yes, I'm aware of the problem.  However, the only things we preallocate are<br>
> > payload registers which only ever go at the beginning and the final FB write<br>
> > which goes at the end.  As long as we don't start preallocating more things,<br>
> > I think we'll be fine.  Also, isn't there some cap on how many payload<br>
> > registers we can have?  If so then that already solves our problem.<br>
><br>
> Yeah, that's what I meant. I'm not sure if the varying payload<br>
> registers can fill up the entire register space (and hence one gets<br>
> allocated to the same register as the fb write load_payload<br>
> destination), but I guess it doesn't matter too much.<br>
><br>
> ><br>
> >><br>
> >> but in the future we'll probably want to think about how to handle<br>
> >> this in a more sophisticated way. This is sort of on a tangent, but<br>
> >> with SSA register allocation we should probably allocate load_payload<br>
> >> destinations before anything else and then treat load_payload as a<br>
> >> series of writes to preallocated registers, since spilling the result<br>
> >> of a load_payload seems like a silly thing to do and then we don't<br>
> >> have to deal with allocating a contiguous set of registers which<br>
> ><br>
> ><br>
> > If only that were true...  The problem is that we will *always* have the<br>
> > problem of contiguous registers.  Once we add fp64 to the mix, we will have<br>
> > registers of size 1 and 2 in SIMD8 and registers of size 1 (Unsigned single<br>
> > words), 2 (dwords, floats, etc) and 4 (doubles) in SIMD16.  Sure, we can<br>
> > probably preallocate payload registers, but we'll never get away from<br>
> > handling multiple sizes.<br>
><br>
> True, there's still that problem. And don't forget that we want to be<br>
> able to allocate scalar/uniform registers, so now you have registers<br>
> of size 1, 8, and 16... </p>
<p dir="ltr">Yeah. I think right now we always do those with pulls so its not a problem yet.  We may want to do that in the future though.</p>
<p dir="ltr">> I think Periera's puzzle-solving allocator<br>
> (<a href="http://compilers.cs.ucla.edu/fernando/publications/papers/PhdDiss.pdf">http://compilers.cs.ucla.edu/fernando/publications/papers/PhdDiss.pdf</a>)<br>
> handles the case where the register classes are aligned, so if we make<br>
> SIMD16 registers aligned like we currently do it might work. It's<br>
> definitely a difficult problem though, and it'll take a lot of work to<br>
> solve.</p>
<p dir="ltr">Thanks for the link. I'll give it a look.<br>
--Jason<br>
><br>
> ><br>
> >><br>
> >> breaks some nice properties of SSA register allocation. Then, we could<br>
> >> have a simple heuristic to allocate the source of an fb write as high<br>
> >> as possible, or just allocate all load_payload instructions as high as<br>
> >> possible.<br>
> ><br>
> ><br>
> > I've actually been thinking about the register allocation problem quite a<br>
> > bit lately.  One of the things I've got on my todo list is to do some<br>
> > research and figure out if we can be doing it better.  There may be a better<br>
> > way to handle the multiple sizes problem than we're doing currently.<br>
> > Unfortunately, I can't really say much now because I haven't dug into it<br>
> > very far yet.<br>
</p>