[llvm-dev] TableGen: spring cleaning, new features for "functional programming"
Nicolai Hähnle via llvm-dev
llvm-dev at lists.llvm.org
Mon Mar 19 07:23:38 PDT 2018
Hi Artem,
On 14.03.2018 01:23, Artem Belevich wrote:
> I want to say huge thank you for your improvements to tablegen.
> While it's still far from perfect, I now have a hope that one day
> I'll be able to *just write* something in tablegen, as opposed to
> constantly struggling to trick tablegen into doing what I need it to do.
And a huge thank you for your quick reviews on what was a *really* long
series of patches!
I agree there's still stuff to be done. I will continue to work on some
writeups of things I've learned, hopefully leading to some better
documentation.
There are also some remaining known quirks, off the top of my head:
1. The weirdness surrounding name resolution, documented in
https://reviews.llvm.org/D44478. Unfortunately, fixing this requires
major surgery in several backends.
2. We could probably flatten the hierarchy of Inits by getting rid of
TypedInits and instead adding an `unset` type and an `any` type.
However, I don't think I'll get to either of those any time soon. If
anybody wants to take a stab at the first one, I've pushed a patch here
which illustrates the idea:
https://cgit.freedesktop.org/~nh/llvm/log/?h=tablegen-name-resolution
which contains the lib/TableGen changes.
Cheers,
Nicolai
>
> Thank you.
>
> --Artem
>
> On Wed, Feb 21, 2018 at 2:48 AM Nicolai Hähnle <nhaehnle at gmail.com
> <mailto:nhaehnle at gmail.com>> wrote:
>
> Hi Artem,
>
> Thank you for your encouraging reply :)
>
> I have now cleaned up the first batch of changes and put them on
> Phabricator here: https://reviews.llvm.org/D43552
>
> I've tried to keep individual changes small, and I've verified with `git
> rebase -x` that the build is good after each change. This first batch
> does not cause any changes in backend's generated files.
>
>
> [snip]> - cleanup type checking> - cleanup variable resolving>
> - cleanup record instantiation> > That can mean whole lot of
> different things. Do you have an > overarching plan how tablegen is
> supposed to do all of the above in a > consistent manner? Just making it
> different may not improve things much.
> Right, and we'll have to see in reviews. But just to give you an
> example, for the last point (cleaning up record instantiation), I ended
> up removing more than 150 lines of code while simultaneously enabling
> simple cases of foreach inside of multiclasses. I think that speaks for
> itself.
>
> When it comes to variable resolving, I propose a simple resolver
> interface, see https://reviews.llvm.org/D43564.
>
> This allows multiple template arguments to be resolved simultaneously,
> which should be a small performance improvements aside from the more
> subjective cleanup of the IMO odd resolveReferences interface. At the
> same time, this allows proper variable hiding when resolving inside
> nested !foreachs.
>
> The type system stuff is more vague, and is mostly about making sure
> that we actually get the right types everywhere. For example, list types
> end up being incorrect all over the place at the moment.
>
>
> > - late generation of anonymous records that appear in expressions
> >
> >
> > That would help, somewhat, though the biggest problem (IMO) with the
> > anonymous records is that when they are instantiated using multiclass
> > template parameters, the inner records are not folded because the
> values
> > are not known yet and they may never be known because instantiated
> > anonymous record has no access to template arguments that may be
> used by
> > its fields. If you moved instantiation of anonymous records to
> the point
> > where the instances of the class/multiclass that uses them are
> > generated, that would help a lot.
>
> That's precisely what I've done, if I understand you correctly.
>
> I've added a VarDefInit class which acts as an uninstantiated anonymous
> record and will "fold" to a DefInit once the template arguments are
> fully resolved to contain no variable references.
>
> Additional benefits of this are that we don't keep partially resolved
> anonymous records in the RecordKeeper, and anonymous records that are
> instantiated with the same template arguments are instantiated only
> once, so there's less computation and memory use.
>
>
> > - cleanup !foreach
> >
> > +1 for having scoped temporary variable. ATM tablegen can use a
> class
> > field for that, but using it in the global scope still needs a record
> > for it. Things also go wrong when one accidentally uses a
> record/field
> > with a known value.
>
> ... and when nesting !foreach with the same iteration variable ;)
>
>
> > - add !foldl
> >
> > - add !isa<type>(...) and make !cast more useful
> >
> >
> > Nice.
> >
> > - add !dag builtin to generate DAG nodes from lists
> >
> >
> > Yes, please! Constructing dags using !foreach and !con() is a pain.
> >
> > - some other minor new built-ins like !size, !le, !lt, !ge, !gt
> > - add a defset mechanism for collecting records which can
> then later be
> > looped over in a foreach statement
> > - make foreach statements in multiclass work
> > - probably more...
> >
> >
> > I'll list few things that I have on my list of tablegen
> annoyances to fix:
> >
> > - !subst() needs some minor tweaks when it's applied to dag from
> > !foreach -- it wants specific types, but I sometimes want to
> replace a
> > dag argument (a record) with another dag.
>
> I haven't touched !subst, but I have a similar issue with !dag.
>
> One of the things I've been thinking about (but haven't actually done)
> is that we should perhaps make the type lattice complete, by making
> UnsetInit typed with a new UnsetType, and adding an AnyType.
>
> I ran into this mostly because it would make sense for !dag(op,
> childnodes, childnodenames) to de facto have the type !dag(any,
> list<any> or unset, list<string> or unset), or perhaps !dag(anyrecord,
> list<any> or unset, list<string> or unset).
>
>
> > - I want some sort of !macro() operator that will never be folded by
> > itself, but will instead literally substitute its value when it's
> used,
> > so it will have access to the multiclass template arguments, class
> > fields, etc. We're currently using anonymous records for similar
> > purposes, but those are instantiated at the wrong time, so it's often
> > impossible to use them as sort of 'subroutines'. Your late generation
> > change you've mentioned above may help, but I'm not sure if
> that's the
> > use pattern you had in mind.
>
> Actually yes, that's one of the things I rely on quite heavily in my
> AMDGPU changes. The AMDGPU backend already uses a pattern to implement
> subroutines that looks like this:
>
> class getWhatever<parameters> {
> type ret = ...;
> }
>
> This tends to work out in many cases because getWhatever<...>.ret is
> substituted early, but there are corner cases when you push it further,
> and I believe those are all fixed with the VarDefInit change I've
> described above. In any case, I'm using "subroutines" very heavily
> :) [0]
>
> The other use pattern I had in mind is that I want to concatenate
> intrinsic type lists that include LLVMMatchType, and so I need to
> generate LLVMMatchType with calculated reference numbers, and that just
> doesn't fly today.
>
>
> > An earlier version of the patches is here if you already want
> to take a
> > look: https://cgit.freedesktop.org/~nh/llvm/log/?h=mimg
> >
> > My plan is to clean those up over the next days and weeks and
> submit
> > them to Phabricator.
> >
> >
> > I'd be happy to help reviewing them.
>
> Much appreciated!
>
>
> > With the exception of !foreach, which doesn't actually seem
> to be used,
> >
> >
> > I do have few outstanding changes for NVPTX where I rely on !foreach,
> > but I think it should not be too hard to adapt them.
>
> That's good to hear :)
>
> Thanks,
> Nicolai
>
> [0]
> http://nhaehnle.blogspot.de/2018/02/tablegen-2-functional-programming.html
>
> --
> Lerne, wie die Welt wirklich ist,
> Aber vergiss niemals, wie sie sein sollte.
>
>
>
> --
> --Artem Belevich
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
More information about the llvm-dev
mailing list