<p dir="ltr"><br>
On Oct 3, 2014 11:06 PM, "Connor Abbott" <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>> wrote:<br>
><br>
> On Fri, Oct 3, 2014 at 10:03 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
> > Previously, we were allowing the register allocation code to do the<br>
> > computation for us in ra_set_finalize.  However, the runtime for this<br>
> > computation is O(c^4 * g) where c is the number of classes and g is the<br>
> > number of GRF registers.  However, these q-values are directly computable<br>
> > based on the way we lay out our register classes so there is no need for<br>
> > the aweful runtime algorithm.<br>
> ><br>
> > We were doing ok until commit 7210583eb where we bumped the number of<br>
> > register classes from 11 to 16.  While startup times don't normally matter,<br>
> > this caused piglit to take 4 times as long to run on Bay Trail.  This patch<br>
> > should make generating the ra_set much faster and melt the piglit run<br>
> > times.<br>
><br>
> Did you check that you get the same q-values that we calculated<br>
> previously? Bugs in this code are subtle and might not cause obvious<br>
> problems.</p>
<p dir="ltr">I've double and tripple-checked my calculations but no, I haven't actually done that test.  Should be easy enough to hack up though so I'll try it some time next week.<br>
--Jason</p>
<p dir="ltr">><br>
> ><br>
> > Signed-off-by: Jason Ekstrand <<a href="mailto:jason.ekstrand@intel.com">jason.ekstrand@intel.com</a>><br>
> > ---<br>
> >  src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp | 52 ++++++++++++++++++++++-<br>
> >  1 file changed, 50 insertions(+), 2 deletions(-)<br>
> ><br>
> > diff --git a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp<br>
> > index fd34941..15fa0f0 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>
> > @@ -152,6 +152,13 @@ brw_alloc_reg_set(struct intel_screen *screen, int reg_width)<br>
> >     int *classes = ralloc_array(screen, int, class_count);<br>
> >     int aligned_pairs_class = -1;<br>
> ><br>
> > +   /* Allocate space for q values.  We allocate class_count + 1 because we<br>
> > +    * want to leave room for the aligned pairs class if we have it. */<br>
> > +   unsigned int **q_values = ralloc_array(screen, unsigned int *,<br>
> > +                                          class_count + 1);<br>
> > +   for (int i = 0; i < class_count + 1; ++i)<br>
> > +      q_values[i] = ralloc_array(q_values, unsigned int, class_count + 1);<br>
> > +<br>
> >     /* Now, add the registers to their classes, and add the conflicts<br>
> >      * between them and the base GRF registers (and also each other).<br>
> >      */<br>
> > @@ -162,8 +169,41 @@ brw_alloc_reg_set(struct intel_screen *screen, int reg_width)<br>
> >        int class_reg_count;<br>
> >        if (devinfo->gen <= 5 && reg_width == 2) {<br>
> >           class_reg_count = (base_reg_count - (class_sizes[i] - 1)) / 2;<br>
> > +<br>
> > +         /* See comment below.  The only difference here is that we are<br>
> > +          * dealing with pairs of registers instead of single registers.<br>
> > +          * Registers of odd sizes simply get rounded up. */<br>
> > +         for (int j = 0; j < class_count; j++)<br>
> > +            q_values[i][j] = (class_sizes[i] + 1) / 2 +<br>
> > +                             (class_sizes[j] + 1) / 2 - 1;<br>
> >        } else {<br>
> >           class_reg_count = base_reg_count - (class_sizes[i] - 1);<br>
> > +<br>
> > +         /* From register_allocate.c:<br>
> > +          *<br>
> > +          * q(B,C) (indexed by C, B is this register class) in<br>
> > +          * Runeson/Nyström paper.  This is "how many registers of B could<br>
> > +          * the worst choice register from C conflict with".<br>
> > +          *<br>
> > +          * If we just let the register allocation algorithm compute these<br>
> > +          * values, is extremely expensive.  However, since all of our<br>
> > +          * registers are laid out, we can very easily compute them<br>
> > +          * ourselves.  View the register from C as fixed starting at GRF n<br>
> > +          * somwhere in the middle, and the register from B as sliding back<br>
> > +          * and forth.  Then the first register to conflict from B is the<br>
> > +          * one starting at n - class_size[B] + 1 and the last register to<br>
> > +          * conflict will start at n + class_size[B] - 1.  Therefore, the<br>
> > +          * number of conflicts from B is class_size[B] + class_size[C] - 1.<br>
> > +          *<br>
> > +          *   +-+-+-+-+-+-+     +-+-+-+-+-+-+<br>
> > +          * B | | | | | |n| --> | | | | | | |<br>
> > +          *   +-+-+-+-+-+-+     +-+-+-+-+-+-+<br>
> > +          *             +-+-+-+-+-+<br>
> > +          * C           |n| | | | |<br>
> > +          *             +-+-+-+-+-+<br>
> > +          */<br>
> > +         for (int j = 0; j < class_count; j++)<br>
> > +            q_values[i][j] = class_sizes[i] + class_sizes[j] - 1;<br>
> >        }<br>
> >        classes[i] = ra_alloc_reg_class(regs);<br>
> ><br>
> > @@ -208,7 +248,7 @@ brw_alloc_reg_set(struct intel_screen *screen, int reg_width)<br>
> >     /* Add a special class for aligned pairs, which we'll put delta_x/y<br>
> >      * in on gen5 so that we can do PLN.<br>
> >      */<br>
> > -   if (devinfo->has_pln && devinfo->gen < 6) {<br>
> > +   if (devinfo->has_pln && reg_width == 1 && devinfo->gen < 6) {<br>
> >        aligned_pairs_class = ra_alloc_reg_class(regs);<br>
> ><br>
> >        for (int i = 0; i < pairs_reg_count; i++) {<br>
> > @@ -216,9 +256,17 @@ brw_alloc_reg_set(struct intel_screen *screen, int reg_width)<br>
> >             ra_class_add_reg(regs, aligned_pairs_class, pairs_base_reg + i);<br>
> >          }<br>
> >        }<br>
> > +<br>
> > +      for (int i = 0; i < class_count; i++) {<br>
> > +         q_values[class_count][i] = (class_sizes[i] + 1) / 2;<br>
> > +         q_values[i][class_count] = class_sizes[i] + 1;<br>
> > +      }<br>
> > +      q_values[class_count][class_count] = 1;<br>
> >     }<br>
> ><br>
> > -   ra_set_finalize(regs, NULL);<br>
> > +   ra_set_finalize(regs, q_values);<br>
> > +<br>
> > +   ralloc_free(q_values);<br>
> ><br>
> >     screen->wm_reg_sets[index].regs = regs;<br>
> >     for (unsigned i = 0; i < ARRAY_SIZE(screen->wm_reg_sets[index].classes); i++)<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></p>