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