diff --git a/tests/src/JIT/opt/Devirtualization/comparable.cs b/tests/src/JIT/opt/Devirtualization/comparable.cs new file mode 100644 index 000000000000..2322395bf2d0 --- /dev/null +++ b/tests/src/JIT/opt/Devirtualization/comparable.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +public sealed class X: IComparable +{ + int ival; + + public X(int i) + { + ival = i; + } + + public int CompareTo(X x) + { + return ival - x.ival; + } + + public bool Equals(X x) + { + return ival == x.ival; + } +} + +public class Y where T : IComparable +{ + public static int C(T x, T y) + { + // IL here is + // ldarga 0 + // ldarg 1 + // constrained ... callvirt ... + // + // The ldarga blocks both caller-arg direct sub and type + // propagation since the jit thinks arg0 might be redefined. + // + // For ref types the ldarga is undone in codegen just before + // the call so we end up with *(&arg0) and we know this is + // arg0. Ideally we'd also understand that this pattern can't + // lead to reassignment, but our view of the callee and what + // it does with address-taken args is quite limited. + // + // Even if we can't propagate the caller's value or type, we + // might be able to retype the generic __Canon for arg0 as the + // more specific type that the caller is using (here, X). + // + // An interesting variant on this would be to derive from X + // (say with XD) and have the caller pass instances of XD + // instead of instances of X. We'd need to make sure we retype + // arg0 as X and not XD. + return x.CompareTo(y); + } +} + +public class Z +{ + public static int Main() + { + // Ideally inlining Y.C would enable the interface call in Y + // to be devirtualized, since we know the exact type of the + // first argument. We can't get this yet. + int result = Y.C(new X(103), new X(3)); + return result; + } +} diff --git a/tests/src/JIT/opt/Devirtualization/comparable.csproj b/tests/src/JIT/opt/Devirtualization/comparable.csproj new file mode 100644 index 000000000000..780cd910cad6 --- /dev/null +++ b/tests/src/JIT/opt/Devirtualization/comparable.csproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + PdbOnly + True + + + + + + + + + + + diff --git a/tests/src/JIT/opt/Devirtualization/contravariance.cs b/tests/src/JIT/opt/Devirtualization/contravariance.cs new file mode 100644 index 000000000000..0594772c9afd --- /dev/null +++ b/tests/src/JIT/opt/Devirtualization/contravariance.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +interface I +{ + T A(); +} + +class X : I where T: class +{ + T I.A() + { + return (T)(object)"X"; + } +} + +class T +{ + static object F(I i) + { + return i.A(); + } + + public static int Main() + { + // Jit should inline F and then devirtualize the call to A. + // (inlining A blocked by runtime lookup) + object j = F(new X()); + if (j is string) + { + return ((string)j)[0] + 12; + } + return -1; + } +} diff --git a/tests/src/JIT/opt/Devirtualization/contravariance.csproj b/tests/src/JIT/opt/Devirtualization/contravariance.csproj new file mode 100644 index 000000000000..287c2009f13d --- /dev/null +++ b/tests/src/JIT/opt/Devirtualization/contravariance.csproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + PdbOnly + True + + + + + + + + + + + diff --git a/tests/src/JIT/opt/Devirtualization/covariance.cs b/tests/src/JIT/opt/Devirtualization/covariance.cs new file mode 100644 index 000000000000..2ed7d2bdd83a --- /dev/null +++ b/tests/src/JIT/opt/Devirtualization/covariance.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +interface I +{ + int A(T t); +} + +class X : I +{ + int c = 0; + int I.A(T t) + { + return ++c; + } +} + +class T +{ + static int F(I i) + { + return i.A("A"); + } + + public static int Main() + { + // Jit should inline F and then devirtualize + // and inline the call to A. + int j = F(new X()); + return j + 99; + } +} diff --git a/tests/src/JIT/opt/Devirtualization/covariance.csproj b/tests/src/JIT/opt/Devirtualization/covariance.csproj new file mode 100644 index 000000000000..b94309945ab7 --- /dev/null +++ b/tests/src/JIT/opt/Devirtualization/covariance.csproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + PdbOnly + True + + + + + + + + + + + diff --git a/tests/src/JIT/opt/Devirtualization/late.cs b/tests/src/JIT/opt/Devirtualization/late.cs new file mode 100644 index 000000000000..3991e7df43b6 --- /dev/null +++ b/tests/src/JIT/opt/Devirtualization/late.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +interface Ix where T : class +{ + T F(); +} + +class Base : Ix +{ + public virtual string F() { return "B"; } +} + +class Derived : Base +{ + public override string F() { return "D"; } +} + +class Bx +{ + public Ix Get() { return new Derived(); } +} + +public class Z +{ + static string X(Base b) + { + return b.F(); + } + + public static int Main() + { + // Would like to be able to late devirtualize the call to F + // here after inlining Get exposes the exact type of the + // object, but since the return type of Get is a (shared) + // interface type, we need the exact context for F to do so + // safely. + // + // Unfortunately we lose track of that context, because when + // we import the call to F, it is not an inline candidate. + string s = new Bx().Get().F(); + return (int) s[0] + 32; + } +} + diff --git a/tests/src/JIT/opt/Devirtualization/late.csproj b/tests/src/JIT/opt/Devirtualization/late.csproj new file mode 100644 index 000000000000..6af10b47f605 --- /dev/null +++ b/tests/src/JIT/opt/Devirtualization/late.csproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + PdbOnly + True + + + + + + + + + + + diff --git a/tests/src/JIT/opt/Devirtualization/simple.cs b/tests/src/JIT/opt/Devirtualization/simple.cs new file mode 100644 index 000000000000..58ecf16b320d --- /dev/null +++ b/tests/src/JIT/opt/Devirtualization/simple.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +// Some simple interface call devirtualization cases + +interface Ix +{ + int F(); +} + +interface Iy +{ + int G(); +} + +public class B : Iy, Ix +{ + public int F() { return 44; } + virtual public int G() { return 55; } +} + +public class Z : B +{ + new public int F() { return 33; } + override public int G() { return 22; } + + static int Fx(Ix x) { return x.F(); } + static int Gy(Iy y) { return y.G(); } + + public static int Main() + { + // B:F Z:G B:F B:G + return Fx(new Z()) + Gy(new Z()) + Fx(new B()) + Gy(new B()) - 65; + } +} + diff --git a/tests/src/JIT/opt/Devirtualization/simple.csproj b/tests/src/JIT/opt/Devirtualization/simple.csproj new file mode 100644 index 000000000000..cb5b5e33e0a4 --- /dev/null +++ b/tests/src/JIT/opt/Devirtualization/simple.csproj @@ -0,0 +1,41 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + + + + False + + + + PdbOnly + True + + + + + + + + + + +