<p dir="ltr"><br>
On Dec 17, 2015 9:10 AM, "Francisco Jerez" <<a href="mailto:currojerez@riseup.net">currojerez@riseup.net</a>> wrote:<br>
><br>
> Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> writes:<br>
><br>
> > On Dec 14, 2015 6:24 AM, "Francisco Jerez" <<a href="mailto:currojerez@riseup.net">currojerez@riseup.net</a>> wrote:<br>
> >><br>
> >> Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> writes:<br>
> >><br>
> >> > On Dec 11, 2015 5:44 AM, "Francisco Jerez" <<a href="mailto:currojerez@riseup.net">currojerez@riseup.net</a>><br>
> > wrote:<br>
> >> >><br>
> >> >> Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> writes:<br>
> >> >><br>
> >> >> > On Dec 10, 2015 6:58 AM, "Francisco Jerez" <<a href="mailto:currojerez@riseup.net">currojerez@riseup.net</a>><br>
> >> > wrote:<br>
> >> >> >><br>
> >> >> >> Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> writes:<br>
> >> >> >><br>
> >> >> >> > We aren't using it anymore.<br>
> >> >> >><br>
> >> >> >> It seems useful to me to be able to represent indirect access as<br>
> > part<br>
> >> > of<br>
> >> >> >> any instruction source or destination register.<br>
> >> >> >><br>
> >> >> >> The following:<br>
> >> >> >><br>
> >> >> >> | mov_indirect g0, g1, a0<br>
> >> >> >> | foo g2, g0<br>
> >> >> >><br>
> >> >> >> and the converse case with indirect destination offset (which you<br>
> > don't<br>
> >> >> >> seem to represent currently) can be implemented by the hardware more<br>
> >> >> >> efficiently using a single instruction in certain cases.  The<br>
> > current<br>
> >> > IR<br>
> >> >> >> is able to represent what the hardware can do, but supporting the<br>
> >> >> >> MOV_INDIRECT instruction only would force us to keep the indirection<br>
> >> >> >> separate from the instruction that uses it, so it seems like a less<br>
> >> >> >> expressive representation to me than the current approach, unless<br>
> >> > you're<br>
> >> >> >> willing to add _INDIRECT variants of most hardware opcodes.<br>
> >> >> ><br>
> >> >> > Yes and, mostly, no.  Yes, you can put an indirect on almost anything<br>
> >> > but<br>
> >> >> > it has substantial restrictions:<br>
> >> >> ><br>
> >> >> Yes, I'm aware of the restrictions of indirect addressing on Gen<br>
> >> >> hardware.  The fact that reladdr can represent addressing modes which<br>
> >> >> aren't directly implemented in the hardware doesn't invalidate the<br>
> >> >> abstraction, nor implies that optimization and translation passes must<br>
> >> >> be made aware of such restrictions.  It just means that our abstraction<br>
> >> >> is a superset of the hardware indirect addressing scheme, which is fine<br>
> >> >> given a lowering pass to convert indirect addressing into a legal form.<br>
> >> >><br>
> >> >> Your proposal instead goes the opposite direction and replaces the<br>
> >> >> preexisting abstraction with a new abstraction which can only represent<br>
> >> >> a tiny subset of the functionality of hardware instructions, which I<br>
> >> >> don't think is acceptable for a low-level IR.<br>
> >> >><br>
> >> >> > 1) Destination indirects must be uniform (I'm only 95% sure this is<br>
> > the<br>
> >> >> > case)<br>
> >> >> ><br>
> >> >> > 2) We only have 8 address subregisters on HSW and prior and 16 on BDW<br>
> >> > which<br>
> >> >> > means:<br>
> >> >> ><br>
> >> >><br>
> >> >> That's the kind of thing that SIMD lowering would be able to take care<br>
> >> >> of easily.<br>
> >> ><br>
> >> > Yes, and we use it for MOV_INDIRECT.<br>
> >> ><br>
> >> Right, and there's no reason why it couldn't be used for reladdr in the<br>
> >> same way to handle the above restrictions.<br>
> >><br>
> >> >> >     a) All indirects must be uniform OR<br>
> >> >> ><br>
> >> >> >     b) We must be on Broadwell, have only two indirects, and split<br>
> > the<br>
> >> >> > instruction OR<br>
> >> >> ><br>
> >> >> >     c) We can only have one indirect (and still split the<br>
> > instruction on<br>
> >> >> > HSW)<br>
> >> >> ><br>
> >> >> > So, yes, "everthing can be uniform", but not in real life.<br>
> >> >><br>
> >> >> > The reladdr abstraction, while maybe ok for a high-level IR, doesn't<br>
> >> >> > accurately represent the hardware at all because it can't represent<br>
> >> >> > any of the restrictions without piles of helper functions and checks.<br>
> >> >><br>
> >> >> The reladdr abstraction can represent the full flexibility of the<br>
> >> >> hardware, while MOV_INDIRECT cannot, that makes reladdr a more accurate<br>
> >> >> low-level representation of the program.  For that reason I'd argue the<br>
> >> >> exact opposite: MOV_INDIRECT would be a great abstraction and a welcome<br>
> >> >> simplification for a high-level IR (e.g. NIR), in which nothing is lost<br>
> >> >> by sacrificing the expressiveness of individual instructions in favour<br>
> >> >> of instruction composition, because the back-end can always combine<br>
> >> >> multiple high-level instructions into a single low-level instruction<br>
> >> >> where the hardware ISA allows, as long as the low-level IR is able to<br>
> >> >> represent the full functionality of hardware instructions (IOW the<br>
> >> >> mapping between low-level IR instructions and hardware instructions is<br>
> >> >> surjective), which is further from being the case after this series.<br>
> >> ><br>
> >> > Flexibility and expressiveness isn't always a good thing.<br>
> >><br>
> >> Expressiveness is a good thing as long as it's required to represent the<br>
> >> capabilities of the hardware.<br>
> ><br>
> > As long as it's required to represent those capabilities that we care<br>
> > about, yes.  However, the hardware can do many things that either aren't<br>
> > useful for us or take so much effort for the little benefit you gain, that<br>
> > it's not worth it.  I'm arguing that saving a single MOV in the few places<br>
> > that we do in directs isn't worth the complexity.<br>
> ><br>
> >> > Yes, reladdr is more "expressive", but it's not getting used because<br>
> >> > that expressiveness makes it a pain.<br>
> >><br>
> >> AFAIK nobody has bothered to implement it completely down to the<br>
> >> back-end generator so it's not a wonder that it's not extensively used.<br>
> >> I'd like to see some evidence that it would actually be a pain<br>
> >> (e.g. some proof of concept implementation) before we give up and commit<br>
> >> to an inherently more limited model.  If you already have such a proof<br>
> >> of concept, please share it.  If you don't and are fully convinced that<br>
> >> it will be a pain I suggest you hold up this series for a while and let<br>
> >> me write the proof of concept -- Doing something with the expectation<br>
> >> that it's going to be a pain is the best way to make sure it actually<br>
> >> becomes a pain.  Worst-case scenario you're right and it does become a<br>
> >> pain, at which point I come back and review this series.  Best-case<br>
> >> scenario you're wrong and we don't give up useful functionality of the<br>
> >> IR based on an expectation.<br>
> ><br>
> > Do I have a proof-of-concept in code, no.  However, I've run through it in<br>
> > my head and I have a pretty good idea what it would look like.<br>
><br>
> Ah, that's what I guessed.  I don't think that your previous claim that<br>
> supporting indirect addressing based on the current reladdr approach<br>
> would require rewriting optimization passes to be recursive demonstrates<br>
> a particularly clear notion of what it could look like.</p>
<p dir="ltr">That's fair.  I'm sorry if that want particularly well communicated.  I don't always make a distinction between things in just throwing out there avg things I've given substantial thought.</p>
<p dir="ltr">In the case of uniforms, I've been thinking about and poking at how to best do it for a while.  Thinking about relative addressing has been part of that.  Initially, I did try to use reladdr but I realized fairly quickly that it was going to turn into a mess, so I went towards a different solution.</p>
<p dir="ltr">> > You are free to go off and do it if you don't believe me, but I don't<br>
> > really want to hold things up while you do.  If you go off and<br>
> > demonstrate that reladdr really is better, its not that hard to<br>
> > revert.<br>
> ><br>
> Whether it will be hard to revert or not depends on how much of the code<br>
> added in the meantime assumes that reladdr is no longer a thing, and you<br>
> cannot give any guarantees about that.  I don't have any obligation to<br>
> spend time substantiating or refuting your assumption, and I wont if<br>
> your plan is to make things unnecessarily difficult for me in the<br>
> meantime.</p>
<p dir="ltr">You've seen how big this patch is. Almost all of the current code assumes reladdr isn't a thing.  Other than these patches, I doubt we'll add that much more.  That said, Ken had already used MOV_INDIRECT to do indirect inputs for tess and maybe geometry.<br>
--Jason</p>
<p dir="ltr">> > One other side-note: One of the substantial advantages to this series is<br>
> > the removal of the uniform size arrays.  If you do decide to make a<br>
> > different prototype, please make that a major design point.  When we get<br>
> > uniforms in from SPIR-V they may come in std140 packed and with just an<br>
> > offset and maybe range.  The size arrays are implicitly tied to variables.<br>
> > I want them gone.<br>
> ><br>
> >> > You could say it is getting used, but it's current use is just an<br>
> >> > intermediate to something less expressive than MOV_INDIRECT.  In that<br>
> >> > sense, we are expressing *more* with MOV_INDIRECT than we were before<br>
> >> > since we are also expressing in directing on registers and not just<br>
> >> > pull constants.<br>
> >> ><br>
> >> Yes, but MOV_INDIRECT is a dead end in the long-term, and the same<br>
> >> functionality you implement here could have been implemented based on<br>
> >> the preexisting model.<br>
> >><br>
> >> > Also, while reladdr is "expressive", it doesn't actually represent the<br>
> >> > hardware.  If we wanted that, we would expose the address register file<br>
> >> > (which I did consider doing).  However, that comes with it's own set of<br>
> >> > issues.<br>
> >> ><br>
> >> It represents the hardware more accurately than MOV_INDIRECT in the<br>
> >> following sense: It allows us to represent a wide subset of the indirect<br>
> >> addressing capabilities of the hardware down to the generator, on any<br>
> >> instruction, source or destination we can possibly address indirectly.<br>
> >> MOV_INDIRECT on the other hand allows us to represent a MOV instruction<br>
> >> with indirectly-addressed source *only*.<br>
> >><br>
> >> >> > The MOV_INDIRECT instruction, on the other hand, is something we can<br>
> >> >> > always do because it falls in the "one indirect" case above.  The<br>
> >> >> > reladdr abstraction also suffers from the recursive reladdr problem<br>
> >> >> > which MOV_INDIRECT neatly side-steps by design.<br>
> >> >><br>
> >> >> I don't think the reladdr "problem" requires any fundamentally more<br>
> >> >> difficult logic in optimization passes than what you need in order to<br>
> >> >> handle MOV_INDIRECT instructions reasonably.<br>
> >> ><br>
> >> > No, it just requires rewriting them because iterating over sources just<br>
> >> > became recursive.<br>
> >> ><br>
> >> That's quite an overstatement, most optimization passes only need to<br>
> >> care about the top-level register of a source or destination, because<br>
> >> wherever a reladdr is present it's not statically determined so you're<br>
> >> unlikely to be able to optimize through it anyway regardless of whether<br>
> >> you recurse or not.  Cases where you actually want to iterate over each<br>
> >> register used by an instruction are a minority and don't require<br>
> >> fundamentally changing the optimization pass, the iteration can be<br>
> >> factored out as in the straightforward for_each_use() helper I<br>
> >> originally implemented to solve a different problem but which happens to<br>
> >> handle arbitrarily-nested reladdr as one would expect.<br>
> >><br>
> >> >> > We can't even use reladdr past initial NIR -> FS stage because none<br>
> > of<br>
> >> >> > the optimization passes know what to do with it (and no, I don't want<br>
> >> >> > to add reladdr support to any of them).<br>
> >> >> ><br>
> >> >> > Yes, removing reladdr makes the IR "less expressive", but we're not<br>
> >> > really<br>
> >> >> > using that expressiveness nor is reladdr the abstraction we want.<br>
> > If we<br>
> >> >> > want to start taking more advantage of relative addressing in the<br>
> >> > future,<br>
> >> >> > we can come up with a better abstraction then.<br>
> >> >> ><br>
> >> >> > --Jason<br>
> >> >> ><br>
> >> >> >> > ---<br>
> >> >> >> >  src/mesa/drivers/dri/i965/brw_fs.cpp  | 7 +------<br>
> >> >> >> >  src/mesa/drivers/dri/i965/brw_ir_fs.h | 5 +----<br>
> >> >> >> >  2 files changed, 2 insertions(+), 10 deletions(-)<br>
> >> >> >> ><br>
> >> >> >> > diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
> >> >> > b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
> >> >> >> > index 7cc03c5..786c5fb 100644<br>
> >> >> >> > --- a/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
> >> >> >> > +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
> >> >> >> > @@ -433,7 +433,6 @@ fs_reg::fs_reg(struct ::brw_reg reg) :<br>
> >> >> >> >  {<br>
> >> >> >> >     this->reg_offset = 0;<br>
> >> >> >> >     this->subreg_offset = 0;<br>
> >> >> >> > -   this->reladdr = NULL;<br>
> >> >> >> >     this->stride = 1;<br>
> >> >> >> >     if (this->file == IMM &&<br>
> >> >> >> >         (this->type != BRW_REGISTER_TYPE_V &&<br>
> >> >> >> > @@ -448,7 +447,6 @@ fs_reg::equals(const fs_reg &r) const<br>
> >> >> >> >  {<br>
> >> >> >> >     return (this->backend_reg::equals(r) &&<br>
> >> >> >> >             subreg_offset == r.subreg_offset &&<br>
> >> >> >> > -           !reladdr && !r.reladdr &&<br>
> >> >> >> >             stride == r.stride);<br>
> >> >> >> >  }<br>
> >> >> >> ><br>
> >> >> >> > @@ -4716,9 +4714,7 @@<br>
> >> > fs_visitor::dump_instruction(backend_instruction<br>
> >> >> > *be_inst, FILE *file)<br>
> >> >> >> >           break;<br>
> >> >> >> >        case UNIFORM:<br>
> >> >> >> >           fprintf(file, "u%d", inst->src[i].nr +<br>
> >> >> > inst->src[i].reg_offset);<br>
> >> >> >> > -         if (inst->src[i].reladdr) {<br>
> >> >> >> > -            fprintf(file, "+reladdr");<br>
> >> >> >> > -         } else if (inst->src[i].subreg_offset) {<br>
> >> >> >> > +         if (inst->src[i].subreg_offset) {<br>
> >> >> >> >              fprintf(file, "+%d.%d", inst->src[i].reg_offset,<br>
> >> >> >> >                      inst->src[i].subreg_offset);<br>
> >> >> >> >           }<br>
> >> >> >> > @@ -4829,7 +4825,6 @@<br>
> >> >> > fs_visitor::get_instruction_generating_reg(fs_inst *start,<br>
> >> >> >> >  {<br>
> >> >> >> >     if (end == start ||<br>
> >> >> >> >         end->is_partial_write() ||<br>
> >> >> >> > -       reg.reladdr ||<br>
> >> >> >> >         !reg.equals(end->dst)) {<br>
> >> >> >> >        return NULL;<br>
> >> >> >> >     } else {<br>
> >> >> >> > diff --git a/src/mesa/drivers/dri/i965/brw_ir_fs.h<br>
> >> >> > b/src/mesa/drivers/dri/i965/brw_ir_fs.h<br>
> >> >> >> > index c3eec2e..e4f20f4 100644<br>
> >> >> >> > --- a/src/mesa/drivers/dri/i965/brw_ir_fs.h<br>
> >> >> >> > +++ b/src/mesa/drivers/dri/i965/brw_ir_fs.h<br>
> >> >> >> > @@ -58,8 +58,6 @@ public:<br>
> >> >> >> >      */<br>
> >> >> >> >     int subreg_offset;<br>
> >> >> >> ><br>
> >> >> >> > -   fs_reg *reladdr;<br>
> >> >> >> > -<br>
> >> >> >> >     /** Register region horizontal stride */<br>
> >> >> >> >     uint8_t stride;<br>
> >> >> >> >  };<br>
> >> >> >> > @@ -136,8 +134,7 @@ component(fs_reg reg, unsigned idx)<br>
> >> >> >> >  static inline bool<br>
> >> >> >> >  is_uniform(const fs_reg &reg)<br>
> >> >> >> >  {<br>
> >> >> >> > -   return (reg.stride == 0 || reg.is_null()) &&<br>
> >> >> >> > -          (!reg.reladdr || is_uniform(*reg.reladdr));<br>
> >> >> >> > +   return (reg.stride == 0 || reg.is_null());<br>
> >> >> >> >  }<br>
> >> >> >> ><br>
> >> >> >> >  /**<br>
> >> >> >> > --<br>
> >> >> >> > 2.5.0.400.gff86faf<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>
</p>