This is an archive of the discontinued LLVM Phabricator instance.

[NewPM][CGSCC] Handle newly added functions in updateCGAndAnalysisManagerForPass
ClosedPublic

Authored by aeubanks on Sep 16 2020, 2:35 PM.

Details

Summary

This seems to fit the CGSCC updates model better than calling
addNewFunctionInto{Ref,}SCC() on newly created/outlined functions.
Now addNewFunctionInto{Ref,}SCC() are no longer necessary.

However, this doesn't work on newly outlined functions that aren't
referenced by the original function. e.g. if a() was outlined into b()
and c(), but c() is only referenced by b() and not by a(), this will
trigger an assert.

This also fixes an issue I was seeing with newly created functions not
having passes run on them.

Ran check-llvm with expensive checks.

Diff Detail

Event Timeline

aeubanks created this revision.Sep 16 2020, 2:35 PM
Herald added a project: Restricted Project. · View Herald TranscriptSep 16 2020, 2:35 PM
aeubanks requested review of this revision.Sep 16 2020, 2:35 PM

The general comment (I mentioned this offline too), is that this is much closer to the direction I'd see the changes going. By this, I mean, the APIs removed here seemed unnecessary, and inlining their functionality at the callsite made more sense.
This seems the right approach for coroutines and outlining. I'm not clear for inlining at this point, Im working to understand the flow better there.

llvm/lib/Analysis/CGSCCPassManager.cpp
518

Remove braces.

519

I'm not clear how adding this call impacts the Inliner.

aeubanks updated this revision to Diff 293198.Sep 21 2020, 9:31 AM

rebase
remove braces

aeubanks marked an inline comment as done.Sep 21 2020, 9:35 AM
aeubanks added inline comments.
llvm/lib/Analysis/CGSCCPassManager.cpp
519

It shouldn't affect the inliner. For a given inline, the inliner will remove an edge, and potentially add new call/ref edges (corresponding to any call/ref edges in the inlined function). All of those will already have nodes since they were further down the call graph.

This would only affect completely new functions being created (or potentially new calls to functions up the call graph, which would be a bug, not sure if that's caught by asserts or not).

asbirlea accepted this revision.Sep 21 2020, 12:18 PM
asbirlea added inline comments.
llvm/lib/Analysis/CGSCCPassManager.cpp
519

Thank you for the clarification.

This revision is now accepted and ready to land.Sep 21 2020, 12:18 PM
lxfind added a subscriber: lxfind.Nov 14 2020, 8:59 AM

@aeubanks, I was wondering if you are familiar with this but it seems that the SCC update after CoroSplit couldn't handle the case when there is recursion in the original coroutine, that is, the newly generated functions by CoroSplit will contain cycles (foo calling foo.resume which then calls foo). Do you have suggestions/thoughts on how to fix it?
For example, test like this will fail assertions:

; RUN: opt < %s --enable-new-pm --enable-coroutines -O3 -S
; Function Attrs: argmemonly nounwind readonly
declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #0

; Function Attrs: nounwind
declare i8* @llvm.coro.begin(token, i8* writeonly) #1

; Function Attrs: nounwind
declare token @llvm.coro.save(i8*) #1

; Function Attrs: nounwind
declare i8 @llvm.coro.suspend(token, i1) #1

define dso_local void @foo() align 2 personality i8* undef {
entry:
  %__promise = alloca i32, align 8
  %0 = bitcast i32* %__promise to i8*
  %1 = call token @llvm.coro.id(i32 16, i8* %0, i8* null, i8* null)
  %2 = call i8* @llvm.coro.begin(token %1, i8* null)
  br i1 undef, label %if.then154, label %init.suspend

init.suspend:                                     ; preds = %entry
  %save = call token @llvm.coro.save(i8* null)
  %3 = call i8 @llvm.coro.suspend(token %save, i1 false)
  %cond = icmp eq i8 %3, 0
  br i1 %cond, label %if.then154, label %invoke.cont163

if.then154:                                       ; preds = %init.suspend, %entry
  call void @foo()
  br label %invoke.cont163

invoke.cont163:                                   ; preds = %if.then154, %init.suspend
  ret void
}

attributes #0 = { argmemonly nounwind readonly }
attributes #1 = { nounwind }
llvm/lib/Transforms/Coroutines/CoroSplit.cpp
1491

Seems like the comments wasn't updated.

Yes I'm aware of the issue and https://reviews.llvm.org/D88714 is an attempt to fix that. I was going to ask exactly what sorts of transformations coroutines does. I'll make a post in llvm-dev.

Yes I'm aware of the issue and https://reviews.llvm.org/D88714 is an attempt to fix that. I was going to ask exactly what sorts of transformations coroutines does. I'll make a post in llvm-dev.

Cool. Thanks!
Besides the problem caused by recursion, I also filed https://bugs.llvm.org/show_bug.cgi?id=48176 the other day which seems to be related too.

Yes I'm aware of the issue and https://reviews.llvm.org/D88714 is an attempt to fix that. I was going to ask exactly what sorts of transformations coroutines does. I'll make a post in llvm-dev.

I just double checked, D88714 is going to fix https://bugs.llvm.org/show_bug.cgi?id=48176 but not the issue I mentioned above.
In the case of recursion, it will form cycles in the newly added functions, which the current SCC update cannot handle. The assertion will fail here:
https://github.com/llvm/llvm-project/blob/master/llvm/lib/Analysis/CGSCCPassManager.cpp#L409