<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Dec 2, 2019 at 2:42 PM Reid Kleckner via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">I like this idea. I'm not sure a warning is the best way to surface it. The first alternative that occurs to be would be the -ftime-trace JSON file, so you can dump out complete info about the most often instantiated templates, how many nodes they contained, and how many of them were dependent.<div><br></div><div>Which brings me to wonder, if clang <a href="https://github.com/llvm/llvm-project/blob/master/clang/include/clang/AST/Expr.h#L183" target="_blank">already tracks</a> whether an Expr is instantiation dependent, why can't it do this optimization itself? I assume there are good reasons. I recall there are some invariants about Decl or Expr pointer identity, but maybe those are handled by <a href="https://github.com/llvm/llvm-project/blob/master/clang/lib/Sema/TreeTransform.h#L140" target="_blank">AlwaysRebuild</a>. Another thing that occurs to me is that some semantic analysis or warnings may not fire if the DeclContext of an Expr is dependent. I wonder what the savings would be if we could enumerate those checks, store them in the template pattern, and run only the checks that matter without re-traversing the entire AST. The last reason I can think of is ADL. I think that would defer name lookup for almost every CallExpr in a template.</div></div></blockquote><div><br>I /think/ ADL still allows calls to be resolved up-front if the parameters aren't dependent. Yeah, here the non-dependent call is resolved and the dependent call is left with an UnresolvedLookupExpr: <a href="https://godbolt.org/z/kgmDHj">https://godbolt.org/z/kgmDHj</a><br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Dec 2, 2019 at 8:01 AM Brian Gesiak <<a href="mailto:modocache@gmail.com" target="_blank">modocache@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I work on a C++ project for which compilation time is a significant<br>
concern. One of my colleagues was able to significantly shorten the<br>
time Clang took to compile our project, by manually outlining<br>
independently-typed code from large template functions.<br>
<br>
This makes intuitive sense to me, because when instantiating a<br>
template function, Clang traverses the body of the function. The<br>
longer the function body, the more nodes in the AST Clang has to<br>
traverse, and the more time it takes. Programmers can read the<br>
function and see that some statements in the function body remain the<br>
same no matter what types the function is instantiated with. By<br>
extracting these statements into a separate, non-template function,<br>
programmers can reduce the amount of nodes Clang must traverse.<br>
<br>
I created a contrived example that demonstrates how splitting up a<br>
long template function can improve compile time. (Beware, the files<br>
are large, I needed something that would take Clang a hefty amount of<br>
time to process.)<br>
<a href="https://gist.github.com/modocache/77b8ac09280c08bd88f84b92ff43a28b" rel="noreferrer" target="_blank">https://gist.github.com/modocache/77b8ac09280c08bd88f84b92ff43a28b</a><br>
<br>
In the example above, 'example.cpp' defines a template function<br>
'foo<T, U, V, W, X, Y, Z>', whose body is ~46k LoC. It then<br>
instantiates 'foo' 10 times, with 10 different combinations of<br>
template type parameters. In total, 'clang -c -O1 example.cpp -Xclang<br>
-disable-llvm-passes -Xclang -emit-llvm' takes ~35 seconds in total to<br>
compile. Each additional instantiation of 'foo' adds an additional ~3<br>
seconds to the total compile time.<br>
<br>
Only the last statement in 'foo' is dependent upon the template type<br>
parameters to 'foo'. 'example-outlined.cpp' moves ~46k LoC of<br>
independently-typed statements out of 'foo' and into a function named<br>
'foo_prologue_outlined', and has 'foo' call 'foo_prologue_outlined'.<br>
'foo_prologue_outlined' is not a template function. The result is<br>
identical program behavior, but a total compile time of just ~5<br>
seconds (~85% faster). Additional instantiations of 'foo' in<br>
'example-outlined.cpp' cost almost no additional compile time.<br>
<br>
Although the functions in our project are not as long, some of them<br>
take significantly longer than 35 seconds to compile. By outlining<br>
independently-typed statements, we've been able to reduce compile time<br>
of some functions, from 300s to 200s (1/3rd faster). So, my colleagues<br>
and I are looking for other functions we can manually outline in order<br>
to reduce the amount of time Clang takes to compile our project. To<br>
this end, it would be handy if Clang could tell us, for example, “hey,<br>
I just instantiated 'bar<int, float, double>', but X% of the<br>
statements in that function did not require transformation,” where<br>
'X%' is some threshold that could be set in the compiler invocation.<br>
For now I'm thinking the option to set this warning threshold could be<br>
called '-Wwasteful-template-threshold=' -- but I'm aware that sounds<br>
awkward, and I'd love suggestions for a better name.<br>
<br>
I think implementing this feature is possible by adding some state to<br>
TreeTransform, or the Clang template instantiators that derive from<br>
that class. But before I send a patch to do so, I'm curious if anyone<br>
has attempted such a thing before, or if anyone has thoughts or<br>
comments on this feature. I'd prefer not to spend time implementing<br>
this diagnostic in Clang if it's predestined to be rejected in code<br>
review, so please let me know what you think!<br>
<br>
(I've cc'ed some contributors who I think have worked in this space<br>
like @rnk, or those who might have better naming suggestions like<br>
@rtrieu.)<br>
<br>
- Brian Gesiak<br>
</blockquote></div>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div></div>