The current dumping format consists of 1 row of information per function. This
will become unweildy to write patterns for when I add additional state to
FunctionInfo.
Instead, this commit converts the dumping format of the caller analysis into a
multi line yaml format. This yaml format looks as follows:
---
calleeName: closure1
hasCaller: false
minPartialAppliedArgs: 1
partialAppliers:
- partial_apply_one_arg
- partial_apply_two_args1
fullAppliers:
...
This can easily expand over time as we expand the queries that caller analysis
can answer.
As an additional advantage, there are definitely yaml parsers that can handle
multiple yaml documents in sequence in a stream. This means that by running via
sil-opt the caller-analysis-printer pass, one now will get a yaml description of
the caller analysis state, perfect and ready for analysis.
This consists of 3 parts:
1) Extend CallerAnalysis to also provide information if a function is partially applied
2) A new DeadArgSignatureOpt pass, similar to FunctionSignatureOpts, which just specializes for dead arguments of partially applied functions.
3) Let CapturePropagation eliminate such partial_apply instructions and replace them with a thin_to_thick conversion of the specialized functions.
This optimzation improves benchmarks where static struct or class functions are passed as a closure (e.g. -20% for SortStrings).
Such functions have a additional metatype parameter. We used to create a partial_apply in this case, which allocates a context, etc.
But this is not necessary as the metatype parameter is not used in most cases.
rdar://problem/27513085
We really only need the analysis to tell whether a function has caller
inside the module or not. We do not need to know the callsites.
Remove them for now to make the analysis more memory efficient.
Add a note to indicate it can be extended.
Address the comments from 0acc0a8464
I still have not made up my mind how to handle deleted functions.
CallerAnalysis is not hooked up to anything yet.
The analysis can tell all the callsites which calls a function in the module.
The analysis is computed and kept up-to-date lazily.
At the core of it, it keeps a list of functions that need to be recomputed for
the Caller/Callee relation to be precise and on every query, the analysis makes
sure to recompute them and clear the list before any query.
This is NFC right now. I am going to wire it up to function signature analysis
eventually.