The current inlining strategy doesn't support inlining coroutines
when there are multiple end_apply or abort_apply instructions in
the caller, so refuse to inline such cases. Also, handle the case
where there are no yield instructions in the callee, which can
happen if e.g. the callee calls a no-return function.
I also simplified the code somewhat by removing the vestiges of the
code that tried to unify control flow with switches.
As an unrelated fix, suppress function signature optimization for
coroutines for now.
To do so this commit does a few different things:
1. I changed SILOptFunctionBuilder to notify the pass manager's logging
functionality when new functions are added to the module and to notify analyses
as well. NOTE: This on purpose does not put the new function on the pass manager
worklist since we do not want to by mistake introduce a large amount of
re-optimizations. Such a thing should be explicit.
2. I eliminated SILModuleTransform::notifyAddFunction. This just performed the
operations from 1. Now that SILOptFunctionBuilder performs this operation for
us, it is not needed.
3. I changed SILFunctionTransform::notifyAddFunction to just add the function to
the passmanager worklist. It does not need to notify the pass manager's logging
or analyses that a new function was added to the module since
SILOptFunctionBuilder now performs that operation. Given its reduced
functionality, I changed the name to addFunctionToPassManagerWorklist(...). The
name is a little long/verbose, but this is a feature since one should think
before getting the pass manager to rerun transforms on a function. Also, giving
it a longer name calls out the operation in the code visually, giving this
operation more prominance when reading code. NOTE: I did the rename using
Xcode's refactoring functionality!
rdar://42301529
I am going to add the code in a bit that does the notifications. I tried to pass
down the builder instead of the pass manager. I also tried not to change the
formatting.
rdar://42301529
This commit does not modify those APIs or their usage. It just:
1. Moves the APIs onto SILFunctionBuilder and makes SILFunctionBuilder a friend
of SILModule.
2. Hides the APIs on SILModule so all users need to use SILFunctionBuilder to
create/destroy functions.
I am doing this in order to allow for adding/removing function notifications to
be enforced via the type system in the SILOptimizer. In the process of finishing
off CallerAnalysis for FSO, I discovered that we were not doing this everywhere
we need to. After considering various other options such as:
1. Verifying after all passes that the notifications were sent correctly and
asserting. Turned out to be expensive.
2. Putting a callback in SILModule. This would add an unnecessary virtual call.
I realized that by using a builder we can:
1. Enforce that users of SILFunctionBuilder can only construct composed function
builders by making the composed function builder's friends of
SILFunctionBuilder (notice I did not use the word subclass, I am talking
about a pure composition).
2. Refactor a huge amount of code in SILOpt/SILGen that involve function
creation onto a SILGenFunctionBuilder/SILOptFunctionBuilder struct. Many of
the SILFunction creation code in question are straight up copies of each
other with small variations. A builder would be a great way to simplify that
code.
3. Reduce the size of SILModule.cpp by 25% from ~30k -> ~23k making the whole
file easier to read.
NOTE: In this commit, I do not hide the constructor of SILFunctionBuilder since
I have not created the derived builder structs yet. Once I have created those in
a subsequent commit, I will hide that constructor.
rdar://42301529
The new function with an optimized signature _shouldn't_ have a non-trivial
classSubclassScope, even if the original function did, since the original
function (that becomes the thunk) is the symbol that serves that role.
Also part of rdar://problem/40738913
The "subclass scope" is meant to represent a connection to a vtable (and how
public something needs to be), for things that end up in class
vtables. Specializations and thunks are mostly internal implementation details
and do not end up there, so subclass scope is not applicable to them. This stops
the thunks and specializations being incorrectly public.
(Note, there are some thunks that _are_ public facing: if a function has its
signature optimized, the original entry point becomes a thunk, and this entry
point is what ends up in vtables etc., so needs to remain around, which means
keeping the same hacks for `private` members of an `open` class.)
Fixes rdar://problem/40738913.
Signature optimization is slightly different to (most) other thunks, in that
it's taking an existing function and turning that into a thunk, rather than
creating a thunk that calls an existing function. These symbols can be public,
etc. and so need to be handled a bit different to other types of thunks.