JIT: defer setting outgoing args size until after optimization (dotnet/coreclr#9683)
authorAndy Ayers <andya@microsoft.com>
Thu, 23 Feb 2017 22:52:10 +0000 (14:52 -0800)
committerGitHub <noreply@github.com>
Thu, 23 Feb 2017 22:52:10 +0000 (14:52 -0800)
commit74ddf00d36b0d50b046ed76f521a57699a12cd8d
tree805e681cfde719afecc7519679299ab84c7c8c63
parent7caa1090b9975e6e44f0ab72382d97633b10f1e0
JIT: defer setting outgoing args size until after optimization (dotnet/coreclr#9683)

For fixed out args ABIs, the jit currently computes the size of the
out arg area during morph, as it encounters calls that must pass arguments
via the stack.

Subsequently, the optimizer may delete calls, either because they are
pure and the results are unused, or because they are conditional and the
guarding predicates are resolved by the optimizer in such a way that
the call is no longer reachable.

In particular if all the calls seen by morph are subsequently removed by
the optimizer, the jit may generate a stack frame that it never uses and
doesn't need. If only some calls are removed then the stack frame may end
up larger than necessary.

One motivating example is the inlining of a shared generic method that
ignores its generic context parameter. The caller typically must invoke a pure
helper to determine the proper argument to pass. Post inline the call's result
is unused, and the helper call is deleted by the optimizer.

This change defers the outgoing arg size computation until fgSimpleLowering,
which runs after optimization. The code in morph now simply records the
needed size for each call in the associated fgArgInfo.

As before, the outgoing arg size computation ignores fast tail calls, since
they can use the caller-supplied scratch area for memory arguments.

The jit may introduce helper calls after optimization which could seemingly
invalidate the out args area size. The presumption here is that these calls
are carefully designed not to use the caller-supplied scratch area. The
current code makes the same assumption.

This change introduces some unanticipated diffs. Optcse estimates the
frame size to decide how aggressive it should be about cses of local
variable references. This size estimate included the out args area, which
appears to be something of an oversight; there are no cse opportunities
in this area and the offsets of the other local variables are not impacted
by the size of this area. With this change the out args area size is seen
as zero during optimization and so the cse strategy for a method may be
different.

Commit migrated from https://github.com/dotnet/coreclr/commit/eaf5835d6a0e914edfdbb6ad1a8af2660e87a08c
src/coreclr/src/jit/compiler.cpp
src/coreclr/src/jit/compiler.h
src/coreclr/src/jit/flowgraph.cpp
src/coreclr/src/jit/lclvars.cpp
src/coreclr/src/jit/morph.cpp
src/coreclr/src/jit/optcse.cpp
src/coreclr/src/jit/utils.h