I thought `reverse(silFn)` would do a post-order walk, but I was wrong.
This patch cuts the number of iterations to propagate coldness from
3-4 down to 2 in a few of the simple regression test cases. At least on
macOS (as the stdlib can vary per platform).
The old analysis pass doesn't take into account profile data, nor does
it consider post-dominance. It primarily dealt with _fastPath/_slowPath.
A block that is dominated by a cold block is itself cold. That's true
whether it's forwards or backwards dominance.
We can also consider a call to any `Never` returning function as a
cold-exit, though the block(s) leading up to that call may be executed
frequently because of concurrency. For now, I'm ignoring the concurrency
case and assuming it's cold. To make use of this "no return" prediction,
use the `-enable-noreturn-prediction` flag, which is currently off by
default.
With the advent of dynamic_function_ref the actual callee of such a ref
my vary. Optimizations should not assume to know the content of a
function referenced by dynamic_function_ref. Introduce
getReferencedFunctionOrNull which will return null for such function
refs. And getInitialReferencedFunction to return the referenced
function.
Use as appropriate.
rdar://50959798
LLVM r355981 changed various intrinsic functions, including expect,
to require immediate arguments. Swift's _branchHint function has an
expected value that is passed in as an argument, so that it cannot
use LLVM's expect intrinsic. The good news is that _branchHint is only
ever used with immediate arguments, so we can just move the intrinsic
into _fastPath and _slowPath and use those instead of _branchHint.
As was noted in the documentation, the _fastPath and _slowPath names are
confusing but we have passed the point where we can simply rename them.
We could add new names but would still need to keep the old ones around
for binary compatibility, and it is not clear that it is worth the
trouble. I have removed that note from the documentation.
The client of this interface naturally expects to get back the
incoming phi value. Ignoring dominance and SIL ownership, the incoming
phi value and the block argument should be substitutable.
This method was actually returning the incoming operand for
checked_cast and switch_enum terminators, which is deeply misleading
and has been the source of bugs.
If the client wants to peek though casts, and enums, it should do so
explicitly. getSingleTerminatorOperand[s]() will do just that.
We were giving special handling to ApplyInst when we were attempting to use
getMemoryBehavior(). This commit changes the special handling to work on all
full apply sites instead of just AI. Additionally, we look through partial
applies and thin to thick functions.
I also added a dumper called BasicInstructionPropertyDumper that just dumps the
results of SILInstruction::get{Memory,Releasing}Behavior() for all instructions
in order to verify this behavior.
This is something that we have wanted for a long time and will enable us to
remove some hacks from the compiler (i.e. how we determine in the ARC optimizer
that we have "fatalError" like function) and also express new things like
"noarc".
(libraries now)
It has been generally agreed that we need to do this reorg, and now
seems like the perfect time. Some major pass reorganization is in the
works.
This does not have to be the final word on the matter. The consensus
among those working on the code is that it's much better than what we
had and a better starting point for future bike shedding.
Note that the previous organization was designed to allow separate
analysis and optimization libraries. It turns out this is an
artificial distinction and not an important goal.