<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Oct 20, 2020 at 10:32 AM Arthur Eubanks via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-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"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Oct 20, 2020 at 7:24 AM David Greene via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-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">Hi all,<br>
<br>
I've run into a sticky situation with CGSSCPassManager.  I have a module<br>
pass that needs to run after all inlining has occurred but *before*<br>
loops have been optimized significantly.  I'm not sure this is possible<br>
with the way CGSCCPassManager is formulated, at least not without<br>
hackery.<br></blockquote><div>Could you explain what your pass does and why it needs to be where it needs to be? </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
My pass has to be a module pass or a CGSCC pass because it has to add<br>
global variables and function declarations.  It does not otherwise modify<br>
global state or the call graph SCC.<br>
<br>
Incidentally WRT my pass, this page about pass requirements seems<br>
ambiguous:<br>
<br>
<a href="http://llvm.org/docs/WritingAnLLVMPass.html" rel="noreferrer" target="_blank">http://llvm.org/docs/WritingAnLLVMPass.html</a><br>
<br>
  To be explicit, FunctionPass subclasses are not allowed to:<br>
<br>
  1. Inspect or modify a Function other than the one currently being processed.<br>
  2. Add or remove Functions from the current Module.<br>
  3. Add or remove global variables from the current Module.<br>
  4. Maintain state across invocations of runOnFunction (including global data).<br>
<br>
#2 is ambiguous to me.  Does "add or remove Functions" mean definitions<br>
only or both definitions and declarations?  It might be helpful to<br>
clarify that in this section of the document.<br></blockquote><div>At least for the NPM, it was designed with potential future concurrency in mind. Modifying the list of functions in a module, even just declarations, could mess with that. <a href="http://llvm.org/docs/WritingAnLLVMPass.html" target="_blank">http://llvm.org/docs/WritingAnLLVMPass.html</a> is more of a legacy PM tutorial. I started on <a href="http://llvm.org/docs/WritingAnLLVMNewPMPass.html" target="_blank">http://llvm.org/docs/WritingAnLLVMNewPMPass.html</a> for the NPM, I can clarify that there.</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
As I understand things, CGSCCPassManager is designed to run things in a<br>
bottom-up manner:<br>
<br>
  // #1<br>
  for scc in scc_list {<br>
    inline callees everywhere<br>
    do other CG passes<br>
    for function in bottom_up(scc) {<br>
      run function passes<br>
    }<br>
  }<br>
<br>
Have I got that right?  I have some questions below about this general<br>
structure that are only tangentially related to my main issue.<br></blockquote><div>The inliner inlines calls within the function, it doesn't look at callers of the current function. A CGSCC pass shouldn't look at anything above the current SCC. As you mentioned below, this is what makes callers see the most optimized version of these functions when deciding to inline or not.</div></div></div></blockquote><div>(may be nit) not quite: see <a href="https://github.com/llvm/llvm-project/blob/master/llvm/lib/Analysis/InlineAdvisor.cpp#L185">"shouldBeDeferred"</a>, where the cost of inlining the current caller into its callers is evaluated.<br></div><div> </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"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
I need to be able to do something like this:<br>
<br>
  // #2<br>
  for scc in scc_list {<br>
    inline callees everywhere<br>
    run my pass<br>
    do other CG passes<br>
    for function in bottom_up(scc) {<br>
      run function passes<br>
    }<br>
  }<br>
<br>
It doesn't seem possible currently because there's no adaptor to run a<br>
module pass inside CGSCCPassManager.  You can run a CGSCCPassManager<br>
inside a ModulePassManager but not the other way around.  It kind of<br>
makes sense because a call graph SCC doesn't necessarily contain all of<br>
the Functions in a Module.  On the other hand, my pass doesn't really<br>
care that it might not see all Functions in the Module in a single<br>
invocation.  It would eventually see them all as CGSCCPassManager<br>
processes additional SCCs.<br>
<br>
I suppose I could make my pass a CGSCC pass but that seems like overkill<br>
for my purposes.  Indeed, I had no need to do this with the Old Pass<br>
Manager as inlining ran in a ModulePassManager, not a CGSCCPassManager.<br></blockquote><div>It doesn't really make sense to run a module pass multiple times because of the number of SCCs/functions. A module pass should just do everything it needs to do once and be done.</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
When I first looked into this I expected the inliner SCC algorithm to<br>
work something like this:<br>
<br>
  // #3<br>
  for scc in scc_list {<br>
    for function in bottom_up(scc) {<br>
      inline callees into function<br>
      run function passes<br>
    }<br>
    do other CG passes<br>
  }<br>
<br>
But it apparently doesn't work that way.  If it did I would be in really<br>
bad shape because there would be no way to run my pass after all<br>
inlining has occurred but before loops have been significantly altered.<br>
It is functionally incorrect for my pass to modify a Function B and have<br>
B inlined into the Function A which my pass also modifies.<br>
<br>
Another option would be to split the current CGSCC pass pipeline in two,<br>
creating one pipeline for things to run before my pass and another for<br>
things to run after my pass.  But upstream is definitely not interested<br>
in my pass so this would be a downstream change and rather burdensome to<br>
maintain.<br>
<br>
Now for the additional questions about CGSCCPassManager mentioned above.<br>
<br>
>From the pseudocode #1 above, it looks like all inlining happens before<br>
any optimization.  This seems sub-optimal to me because transformations<br>
may make Functions good inline candidates when they were not previously.<br>
Is this a know issue with the current setup?  I'm kind of glad it works<br>
like #1 (if indeed it does) because it at least makes my goal<br>
theoretically attainable.  But another part of me really wants it to<br>
work like pseudocode #3 because it seems better for optimization.<br>
<br>
Thanks for all insights and help!<br>
<br>
              -David<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div></div>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div></div>