JIT: change codgen for dup to not lose type information
authorAndy Ayers <andya@microsoft.com>
Sat, 4 Mar 2017 04:01:52 +0000 (20:01 -0800)
committerAndy Ayers <andya@microsoft.com>
Sun, 5 Mar 2017 17:52:57 +0000 (09:52 -0800)
commit4f831dfde67e6e13703a92a4a2cfa530f0a04f11
treef9b28fb8ce4b047e48ad277675c73f0a7054a1cb
parentfda68cd71f6edea31016851e6d862d752f8fd55a
JIT: change codgen for dup to not lose type information

The jit has traditionally optimized most cases of a

   zz; dup; stloc.x

sequence into

   zz; stloc.x; ldloc.x

with a comment noting that this makes the resulting compiler IR
more amenable to CSE. Here zz is any IL operation that pushes
a value on the stack. However if zz's result is a ref type, the
dup'ed value produced by zz may be a subtype of the type of the
local x, so this transformation can lose type information.

In the past the loss of type information hasn't mattered, but now if
zz subsequently is used as the this object in a virtual call, the jit
may attempt devirtualization and ask an ill-posed question to the VM,
claiming the type of the this object is an impossible supertype.

This changes modifies the transformation by introducing a new local temp y
that has the type of zz. The result is now

   zz; stloc.y; ldloc.y; ldloc.y; stloc.x

with the net result that a ldloc.y is left on the stack with the proper
type. As an optimization, if zz is ldloc.z then the expansion is simply

   zz (ldloc.z); ldloc.z; stloc.y

and if zz is a simple "cheap" constant (say ldnull) then the constant
expression is duplicated:

   zz (ldnull); ldnull; stloc.y

This resolves the jit side of dotnet/coreclr#9945. Further work is needed on the VM
side since in unverifiable IL there may be other cases where the jit
can present an impossible type.

Diffs from this were minor and in many cases small improvements.

Commit migrated from https://github.com/dotnet/coreclr/commit/743e5e1660b308cba660565419a972146a6b4191
src/coreclr/src/jit/importer.cpp
src/coreclr/tests/src/jit/opt/Devirtualization/GitHub_9945.cs [new file with mode: 0644]
src/coreclr/tests/src/jit/opt/Devirtualization/GitHub_9945.csproj [new file with mode: 0644]