Inliner: simple performance tests
authorAndy Ayers <andya@microsoft.com>
Fri, 10 Jun 2016 21:58:11 +0000 (14:58 -0700)
committerAndy Ayers <andya@microsoft.com>
Wed, 15 Jun 2016 22:24:17 +0000 (15:24 -0700)
Tests that demonstrate that constant arguments passed to callees can
lead to inlining performance wins. All numeric types are tested, as
well as strings.

Tests are generally written as positive/negative pairs with calls to
the same inlinee. This exposes the call site sensitivity. Performance
of the positive test should be better than the negative test.

The overall benchmarking approach used here is something that we might
consider adopting for other small-scale codegen performance tests.

24 files changed:
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.csproj [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.csproj [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.csproj [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.csproj [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.csproj [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.csproj [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.csproj [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.csproj [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.csproj [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.csproj [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.csproj [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.cs [new file with mode: 0644]
tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.csproj [new file with mode: 0644]

diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.cs
new file mode 100644 (file)
index 0000000..8271c40
--- /dev/null
@@ -0,0 +1,930 @@
+// 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 Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsByte
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Bytes feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static byte Five = 5;
+    static byte Ten = 10;
+
+    static byte Id(byte x)
+    {
+        return x;
+    }
+
+    static byte F00(byte x)
+    {
+        return (byte) (x * x);
+    }
+
+    static bool Bench00p()
+    {
+        byte t = 10;
+        byte f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n()
+    {
+        byte t = Ten;
+        byte f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p1()
+    {
+        byte t = Id(10);
+        byte f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n1()
+    {
+        byte t = Id(Ten);
+        byte f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p2()
+    {
+        byte t = Id(10);
+        byte f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00n2()
+    {
+        byte t = Id(Ten);
+        byte f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00p3()
+    {
+        byte t = 10;
+        byte f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00n3()
+    {
+        byte t = Ten;
+        byte f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00p4()
+    {
+        byte t = 5;
+        byte f = F00((byte)(2 * t));
+        return (f == 100);
+    }
+
+    static bool Bench00n4()
+    {
+        byte t = Five;
+        byte f = F00((byte)(2 * t));
+        return (f == 100);
+    }
+
+    static byte F01(byte x)
+    {
+        return (byte)(1000 / x);
+    }
+
+    static bool Bench01p()
+    {
+        byte t = 10;
+        byte f = F01(t);
+        return (f == 100);
+    }
+
+    static bool Bench01n()
+    {
+        byte t = Ten;
+        byte f = F01(t);
+        return (f == 100);
+    }
+
+    static byte F02(byte x)
+    {
+        return (byte) (20 * (x / 2));
+    }
+
+    static bool Bench02p()
+    {
+        byte t = 10;
+        byte f = F02(t);
+        return (f == 100);
+    }
+
+    static bool Bench02n()
+    {
+        byte t = Ten;
+        byte f = F02(t);
+        return (f == 100);
+    }
+
+    static byte F03(byte x)
+    {
+        return (byte)(91 + 1009 % x);
+    }
+
+    static bool Bench03p()
+    {
+        byte t = 10;
+        byte f = F03(t);
+        return (f == 100);
+    }
+
+    static bool Bench03n()
+    {
+        byte t = Ten;
+        byte f = F03(t);
+        return (f == 100);
+    }
+
+    static byte F04(byte x)
+    {
+        return (byte)(50 * (x % 4));
+    }
+
+    static bool Bench04p()
+    {
+        byte t = 10;
+        byte f = F04(t);
+        return (f == 100);
+    }
+
+    static bool Bench04n()
+    {
+        byte t = Ten;
+        byte f = F04(t);
+        return (f == 100);
+    }
+
+    static byte F05(byte x)
+    {
+        return (byte)((1 << x) - 924);
+    }
+
+    static bool Bench05p()
+    {
+        byte t = 10;
+        byte f = F05(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n()
+    {
+        byte t = Ten;
+        byte f = F05(t);
+        return (f == 100);
+    }
+
+    static byte F051(byte x)
+    {
+        return (byte)(102400 >> x);
+    }
+
+    static bool Bench05p1()
+    {
+        byte t = 10;
+        byte f = F051(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n1()
+    {
+        byte t = Ten;
+        byte f = F051(t);
+        return (f == 100);
+    }
+
+    static byte F06(byte x)
+    {
+        return (byte)(-x + 110);
+    }
+
+    static bool Bench06p()
+    {
+        byte t = 10;
+        byte f = F06(t);
+        return (f == 100);
+    }
+
+    static bool Bench06n()
+    {
+        byte t = Ten;
+        byte f = F06(t);
+        return (f == 100);
+    }
+
+    static byte F07(byte x)
+    {
+        return (byte)(~x + 111);
+    }
+
+    static bool Bench07p()
+    {
+        byte t = 10;
+        byte f = F07(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n()
+    {
+        byte t = Ten;
+        byte f = F07(t);
+        return (f == 100);
+    }
+
+    static byte F071(byte x)
+    {
+        return (byte)((x ^ -1) + 111);
+    }
+
+    static bool Bench07p1()
+    {
+        byte t = 10;
+        byte f = F071(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n1()
+    {
+        byte t = Ten;
+        byte f = F071(t);
+        return (f == 100);
+    }
+
+    static byte F08(byte x)
+    {
+        return (byte)((x & 0x7) + 98);
+    }
+
+    static bool Bench08p()
+    {
+        byte t = 10;
+        byte f = F08(t);
+        return (f == 100);
+    }
+
+    static bool Bench08n()
+    {
+        byte t = Ten;
+        byte f = F08(t);
+        return (f == 100);
+    }
+
+    static byte F09(byte x)
+    {
+        return (byte)((x | 0x7) + 85);
+    }
+
+    static bool Bench09p()
+    {
+        byte t = 10;
+        byte f = F09(t);
+        return (f == 100);
+    }
+
+    static bool Bench09n()
+    {
+        byte t = Ten;
+        byte f = F09(t);
+        return (f == 100);
+    }
+
+    // Bytes feeding comparisons.
+    //
+    // Inlining in Bench1xp should enable branch optimization
+    // Inlining in Bench1xn will not enable branch optimization
+
+    static byte F10(byte x)
+    {
+        return x == 10 ? (byte) 100 : (byte) 0;
+    }
+
+    static bool Bench10p()
+    {
+        byte t = 10;
+        byte f = F10(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n()
+    {
+        byte t = Ten;
+        byte f = F10(t);
+        return (f == 100);
+    }
+
+    static byte F101(byte x)
+    {
+        return x != 10 ? (byte) 0 : (byte) 100;
+    }
+
+    static bool Bench10p1()
+    {
+        byte t = 10;
+        byte f = F101(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n1()
+    {
+        byte t = Ten;
+        byte f = F101(t);
+        return (f == 100);
+    }
+
+    static byte F102(byte x)
+    {
+        return x >= 10 ? (byte) 100 : (byte) 0;
+    }
+
+    static bool Bench10p2()
+    {
+        byte t = 10;
+        byte f = F102(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n2()
+    {
+        byte t = Ten;
+        byte f = F102(t);
+        return (f == 100);
+    }
+
+    static byte F103(byte x)
+    {
+        return x <= 10 ? (byte) 100 : (byte) 0;
+    }
+
+    static bool Bench10p3()
+    {
+        byte t = 10;
+        byte f = F103(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n3()
+    {
+        byte t = Ten;
+        byte f = F102(t);
+        return (f == 100);
+    }
+
+    static byte F11(byte x)
+    {
+        if (x == 10)
+        {
+            return 100;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    static bool Bench11p()
+    {
+        byte t = 10;
+        byte f = F11(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n()
+    {
+        byte t = Ten;
+        byte f = F11(t);
+        return (f == 100);
+    }
+
+    static byte F111(byte x)
+    {
+        if (x != 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p1()
+    {
+        byte t = 10;
+        byte f = F111(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n1()
+    {
+        byte t = Ten;
+        byte f = F111(t);
+        return (f == 100);
+    }
+
+    static byte F112(byte x)
+    {
+        if (x > 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p2()
+    {
+        byte t = 10;
+        byte f = F112(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n2()
+    {
+        byte t = Ten;
+        byte f = F112(t);
+        return (f == 100);
+    }
+    static byte F113(byte x)
+    {
+        if (x < 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p3()
+    {
+        byte t = 10;
+        byte f = F113(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n3()
+    {
+        byte t = Ten;
+        byte f = F113(t);
+        return (f == 100);
+    }
+
+    // Ununsed (or effectively unused) parameters
+    //
+    // Simple callee analysis may overstate inline benefit
+
+    static byte F20(byte x)
+    {
+        return 100;
+    }
+
+    static bool Bench20p()
+    {
+        byte t = 10;
+        byte f = F20(t);
+        return (f == 100);
+    }
+
+    static bool Bench20p1()
+    {
+        byte t = Ten;
+        byte f = F20(t);
+        return (f == 100);
+    }
+
+    static byte F21(byte x)
+    {
+        return (byte)(-x + 100 + x);
+    }
+
+    static bool Bench21p()
+    {
+        byte t = 10;
+        byte f = F21(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n()
+    {
+        byte t = Ten;
+        byte f = F21(t);
+        return (f == 100);
+    }
+
+    static byte F211(byte x)
+    {
+        return (byte)(x - x + 100);
+    }
+
+    static bool Bench21p1()
+    {
+        byte t = 10;
+        byte f = F211(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n1()
+    {
+        byte t = Ten;
+        byte f = F211(t);
+        return (f == 100);
+    }
+
+    static byte F22(byte x)
+    {
+        if (x > 0)
+        {
+            return 100;
+        }
+
+        return 100;
+    }
+
+    static bool Bench22p()
+    {
+        byte t = 10;
+        byte f = F22(t);
+        return (f == 100);
+    }
+
+    static bool Bench22p1()
+    {
+        byte t = Ten;
+        byte f = F22(t);
+        return (f == 100);
+    }
+
+    static byte F23(byte x)
+    {
+        if (x > 0)
+        {
+            return (byte)(90 + x);
+        }
+
+        return 100;
+    }
+
+    static bool Bench23p()
+    {
+        byte t = 10;
+        byte f = F23(t);
+        return (f == 100);
+    }
+
+    static bool Bench23n()
+    {
+        byte t = Ten;
+        byte f = F23(t);
+        return (f == 100);
+    }
+
+    // Multiple parameters
+
+    static byte F30(byte x, byte y)
+    {
+        return (byte)(y * y);
+    }
+
+    static bool Bench30p()
+    {
+        byte t = 10;
+        byte f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n()
+    {
+        byte t = Ten;
+        byte f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p1()
+    {
+        byte s = Ten;
+        byte t = 10;
+        byte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n1()
+    {
+        byte s = 10;
+        byte t = Ten;
+        byte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p2()
+    {
+        byte s = 10;
+        byte t = 10;
+        byte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n2()
+    {
+        byte s = Ten;
+        byte t = Ten;
+        byte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p3()
+    {
+        byte s = 10;
+        byte t = s;
+        byte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n3()
+    {
+        byte s = Ten;
+        byte t = s;
+        byte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static byte F31(byte x, byte y, byte z)
+    {
+        return (byte)(z * z);
+    }
+
+    static bool Bench31p()
+    {
+        byte t = 10;
+        byte f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n()
+    {
+        byte t = Ten;
+        byte f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p1()
+    {
+        byte r = Ten;
+        byte s = Ten;
+        byte t = 10;
+        byte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n1()
+    {
+        byte r = 10;
+        byte s = 10;
+        byte t = Ten;
+        byte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p2()
+    {
+        byte r = 10;
+        byte s = 10;
+        byte t = 10;
+        byte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n2()
+    {
+        byte r = Ten;
+        byte s = Ten;
+        byte t = Ten;
+        byte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p3()
+    {
+        byte r = 10;
+        byte s = r;
+        byte t = s;
+        byte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n3()
+    {
+        byte r = Ten;
+        byte s = r;
+        byte t = s;
+        byte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    // Two args, both used
+
+    static byte F40(byte x, byte y)
+    {
+        return (byte)(x * x + y * y - 100);
+    }
+
+    static bool Bench40p()
+    {
+        byte t = 10;
+        byte f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40n()
+    {
+        byte t = Ten;
+        byte f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p1()
+    {
+        byte s = Ten;
+        byte t = 10;
+        byte f = F40(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p2()
+    {
+        byte s = 10;
+        byte t = Ten;
+        byte f = F40(s, t);
+        return (f == 100);
+    }
+
+    static byte F41(byte x, byte y)
+    {
+        return (byte)(x * y);
+    }
+
+    static bool Bench41p()
+    {
+        byte t = 10;
+        byte f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41n()
+    {
+        byte t = Ten;
+        byte f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p1()
+    {
+        byte s = 10;
+        byte t = Ten;
+        byte f = F41(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p2()
+    {
+        byte s = Ten;
+        byte t = 10;
+        byte f = F41(s, t);
+        return (f == 100);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench00p1", "Bench00n1",
+        "Bench00p2", "Bench00n2",
+        "Bench00p3", "Bench00n3",
+        "Bench00p4", "Bench00n4",
+        "Bench01p",  "Bench01n",
+        "Bench02p",  "Bench02n",
+        "Bench03p",  "Bench03n",
+        "Bench04p",  "Bench04n",
+        "Bench05p",  "Bench05n",
+        "Bench05p1", "Bench05n1",
+        "Bench06p",  "Bench06n",
+        "Bench07p",  "Bench07n",
+        "Bench07p1", "Bench07n1",
+        "Bench08p",  "Bench08n",
+        "Bench09p",  "Bench09n",
+        "Bench10p",  "Bench10n",
+        "Bench10p1", "Bench10n1",
+        "Bench10p2", "Bench10n2",
+        "Bench10p3", "Bench10n3",
+        "Bench11p",  "Bench11n",
+        "Bench11p1", "Bench11n1",
+        "Bench11p2", "Bench11n2",
+        "Bench11p3", "Bench11n3",
+        "Bench20p",  "Bench20p1",
+        "Bench21p",  "Bench21n",
+        "Bench21p1", "Bench21n1",
+        "Bench22p",  "Bench22p1",
+        "Bench23p",  "Bench23n",
+        "Bench30p",  "Bench30n",
+        "Bench30p1", "Bench30n1",
+        "Bench30p2", "Bench30n2",
+        "Bench30p3", "Bench30n3",
+        "Bench31p",  "Bench31n",
+        "Bench31p1", "Bench31n1",
+        "Bench31p2", "Bench31n2",
+        "Bench31p3", "Bench31n3",
+        "Bench40p",  "Bench40n",
+        "Bench40p1", "Bench40p2",
+        "Bench41p",  "Bench41n",
+        "Bench41p1", "Bench41p2"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsByte).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.csproj
new file mode 100644 (file)
index 0000000..c8319ca
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsByte.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.cs
new file mode 100644 (file)
index 0000000..0d1f928
--- /dev/null
@@ -0,0 +1,930 @@
+// 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 Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsChar
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Chars feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static char Five = (char) 5;
+    static char Ten = (char) 10;
+
+    static char Id(char x)
+    {
+        return x;
+    }
+
+    static char F00(char x)
+    {
+        return (char) (x * x);
+    }
+
+    static bool Bench00p()
+    {
+        char t = (char) 10;
+        char f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n()
+    {
+        char t = Ten;
+        char f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p1()
+    {
+        char t = Id((char)10);
+        char f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n1()
+    {
+        char t = Id(Ten);
+        char f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p2()
+    {
+        char t = Id((char)10);
+        char f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00n2()
+    {
+        char t = Id(Ten);
+        char f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00p3()
+    {
+        char t = (char) 10;
+        char f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00n3()
+    {
+        char t = Ten;
+        char f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00p4()
+    {
+        char t = (char) 5;
+        char f = F00((char)(2 * t));
+        return (f == 100);
+    }
+
+    static bool Bench00n4()
+    {
+        char t = Five;
+        char f = F00((char)(2 * t));
+        return (f == 100);
+    }
+
+    static char F01(char x)
+    {
+        return (char)(1000 / x);
+    }
+
+    static bool Bench01p()
+    {
+        char t = (char) 10;
+        char f = F01(t);
+        return (f == 100);
+    }
+
+    static bool Bench01n()
+    {
+        char t = Ten;
+        char f = F01(t);
+        return (f == 100);
+    }
+
+    static char F02(char x)
+    {
+        return (char) (20 * (x / 2));
+    }
+
+    static bool Bench02p()
+    {
+        char t = (char) 10;
+        char f = F02(t);
+        return (f == 100);
+    }
+
+    static bool Bench02n()
+    {
+        char t = Ten;
+        char f = F02(t);
+        return (f == 100);
+    }
+
+    static char F03(char x)
+    {
+        return (char)(91 + 1009 % x);
+    }
+
+    static bool Bench03p()
+    {
+        char t = (char) 10;
+        char f = F03(t);
+        return (f == 100);
+    }
+
+    static bool Bench03n()
+    {
+        char t = Ten;
+        char f = F03(t);
+        return (f == 100);
+    }
+
+    static char F04(char x)
+    {
+        return (char)(50 * (x % 4));
+    }
+
+    static bool Bench04p()
+    {
+        char t = (char) 10;
+        char f = F04(t);
+        return (f == 100);
+    }
+
+    static bool Bench04n()
+    {
+        char t = Ten;
+        char f = F04(t);
+        return (f == 100);
+    }
+
+    static char F05(char x)
+    {
+        return (char)((1 << x) - 924);
+    }
+
+    static bool Bench05p()
+    {
+        char t = (char) 10;
+        char f = F05(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n()
+    {
+        char t = Ten;
+        char f = F05(t);
+        return (f == 100);
+    }
+
+    static char F051(char x)
+    {
+        return (char)(102400 >> x);
+    }
+
+    static bool Bench05p1()
+    {
+        char t = (char) 10;
+        char f = F051(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n1()
+    {
+        char t = Ten;
+        char f = F051(t);
+        return (f == 100);
+    }
+
+    static char F06(char x)
+    {
+        return (char)(-x + 110);
+    }
+
+    static bool Bench06p()
+    {
+        char t = (char) 10;
+        char f = F06(t);
+        return (f == 100);
+    }
+
+    static bool Bench06n()
+    {
+        char t = Ten;
+        char f = F06(t);
+        return (f == 100);
+    }
+
+    static char F07(char x)
+    {
+        return (char)(~x + 111);
+    }
+
+    static bool Bench07p()
+    {
+        char t = (char) 10;
+        char f = F07(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n()
+    {
+        char t = Ten;
+        char f = F07(t);
+        return (f == 100);
+    }
+
+    static char F071(char x)
+    {
+        return (char)((x ^ -1) + 111);
+    }
+
+    static bool Bench07p1()
+    {
+        char t = (char) 10;
+        char f = F071(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n1()
+    {
+        char t = Ten;
+        char f = F071(t);
+        return (f == 100);
+    }
+
+    static char F08(char x)
+    {
+        return (char)((x & 0x7) + 98);
+    }
+
+    static bool Bench08p()
+    {
+        char t = (char) 10;
+        char f = F08(t);
+        return (f == 100);
+    }
+
+    static bool Bench08n()
+    {
+        char t = Ten;
+        char f = F08(t);
+        return (f == 100);
+    }
+
+    static char F09(char x)
+    {
+        return (char)((x | 0x7) + 85);
+    }
+
+    static bool Bench09p()
+    {
+        char t = (char) 10;
+        char f = F09(t);
+        return (f == 100);
+    }
+
+    static bool Bench09n()
+    {
+        char t = Ten;
+        char f = F09(t);
+        return (f == 100);
+    }
+
+    // Chars feeding comparisons.
+    //
+    // Inlining in Bench1xp should enable branch optimization
+    // Inlining in Bench1xn will not enable branch optimization
+
+    static char F10(char x)
+    {
+        return x == 10 ? (char) 100 : (char) 0;
+    }
+
+    static bool Bench10p()
+    {
+        char t = (char) 10;
+        char f = F10(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n()
+    {
+        char t = Ten;
+        char f = F10(t);
+        return (f == 100);
+    }
+
+    static char F101(char x)
+    {
+        return x != 10 ? (char) 0 : (char) 100;
+    }
+
+    static bool Bench10p1()
+    {
+        char t = (char) 10;
+        char f = F101(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n1()
+    {
+        char t = Ten;
+        char f = F101(t);
+        return (f == 100);
+    }
+
+    static char F102(char x)
+    {
+        return x >= 10 ? (char) 100 : (char) 0;
+    }
+
+    static bool Bench10p2()
+    {
+        char t = (char) 10;
+        char f = F102(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n2()
+    {
+        char t = Ten;
+        char f = F102(t);
+        return (f == 100);
+    }
+
+    static char F103(char x)
+    {
+        return x <= 10 ? (char) 100 : (char) 0;
+    }
+
+    static bool Bench10p3()
+    {
+        char t = (char) 10;
+        char f = F103(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n3()
+    {
+        char t = Ten;
+        char f = F102(t);
+        return (f == 100);
+    }
+
+    static char F11(char x)
+    {
+        if (x == 10)
+        {
+            return (char) 100;
+        }
+        else
+        {
+            return (char) 0;
+        }
+    }
+
+    static bool Bench11p()
+    {
+        char t = (char) 10;
+        char f = F11(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n()
+    {
+        char t = Ten;
+        char f = F11(t);
+        return (f == 100);
+    }
+
+    static char F111(char x)
+    {
+        if (x != 10)
+        {
+            return (char) 0;
+        }
+        else
+        {
+            return (char) 100;
+        }
+    }
+
+    static bool Bench11p1()
+    {
+        char t = (char) 10;
+        char f = F111(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n1()
+    {
+        char t = Ten;
+        char f = F111(t);
+        return (f == 100);
+    }
+
+    static char F112(char x)
+    {
+        if (x > 10)
+        {
+            return (char) 0;
+        }
+        else
+        {
+            return (char) 100;
+        }
+    }
+
+    static bool Bench11p2()
+    {
+        char t = (char) 10;
+        char f = F112(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n2()
+    {
+        char t = Ten;
+        char f = F112(t);
+        return (f == 100);
+    }
+    static char F113(char x)
+    {
+        if (x < 10)
+        {
+            return (char) 0;
+        }
+        else
+        {
+            return (char) 100;
+        }
+    }
+
+    static bool Bench11p3()
+    {
+        char t = (char) 10;
+        char f = F113(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n3()
+    {
+        char t = Ten;
+        char f = F113(t);
+        return (f == 100);
+    }
+
+    // Ununsed (or effectively unused) parameters
+    //
+    // Simple callee analysis may overstate inline benefit
+
+    static char F20(char x)
+    {
+        return (char) 100;
+    }
+
+    static bool Bench20p()
+    {
+        char t = (char) 10;
+        char f = F20(t);
+        return (f == 100);
+    }
+
+    static bool Bench20p1()
+    {
+        char t = Ten;
+        char f = F20(t);
+        return (f == 100);
+    }
+
+    static char F21(char x)
+    {
+        return (char)(-x + 100 + x);
+    }
+
+    static bool Bench21p()
+    {
+        char t = (char) 10;
+        char f = F21(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n()
+    {
+        char t = Ten;
+        char f = F21(t);
+        return (f == 100);
+    }
+
+    static char F211(char x)
+    {
+        return (char)(x - x + 100);
+    }
+
+    static bool Bench21p1()
+    {
+        char t = (char) 10;
+        char f = F211(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n1()
+    {
+        char t = Ten;
+        char f = F211(t);
+        return (f == 100);
+    }
+
+    static char F22(char x)
+    {
+        if (x > 0)
+        {
+            return (char) 100;
+        }
+
+        return (char) 100;
+    }
+
+    static bool Bench22p()
+    {
+        char t = (char) 10;
+        char f = F22(t);
+        return (f == 100);
+    }
+
+    static bool Bench22p1()
+    {
+        char t = Ten;
+        char f = F22(t);
+        return (f == 100);
+    }
+
+    static char F23(char x)
+    {
+        if (x > 0)
+        {
+            return (char)(90 + x);
+        }
+
+        return (char) 100;
+    }
+
+    static bool Bench23p()
+    {
+        char t = (char) 10;
+        char f = F23(t);
+        return (f == 100);
+    }
+
+    static bool Bench23n()
+    {
+        char t = Ten;
+        char f = F23(t);
+        return (f == 100);
+    }
+
+    // Multiple parameters
+
+    static char F30(char x, char y)
+    {
+        return (char)(y * y);
+    }
+
+    static bool Bench30p()
+    {
+        char t = (char) 10;
+        char f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n()
+    {
+        char t = Ten;
+        char f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p1()
+    {
+        char s = Ten;
+        char t = (char) 10;
+        char f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n1()
+    {
+        char s = (char) 10;
+        char t = Ten;
+        char f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p2()
+    {
+        char s = (char) 10;
+        char t = (char) 10;
+        char f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n2()
+    {
+        char s = Ten;
+        char t = Ten;
+        char f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p3()
+    {
+        char s = (char) 10;
+        char t = s;
+        char f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n3()
+    {
+        char s = Ten;
+        char t = s;
+        char f = F30(s, t);
+        return (f == 100);
+    }
+
+    static char F31(char x, char y, char z)
+    {
+        return (char)(z * z);
+    }
+
+    static bool Bench31p()
+    {
+        char t = (char) 10;
+        char f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n()
+    {
+        char t = Ten;
+        char f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p1()
+    {
+        char r = Ten;
+        char s = Ten;
+        char t = (char) 10;
+        char f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n1()
+    {
+        char r = (char) 10;
+        char s = (char) 10;
+        char t = Ten;
+        char f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p2()
+    {
+        char r = (char) 10;
+        char s = (char) 10;
+        char t = (char) 10;
+        char f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n2()
+    {
+        char r = Ten;
+        char s = Ten;
+        char t = Ten;
+        char f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p3()
+    {
+        char r = (char) 10;
+        char s = r;
+        char t = s;
+        char f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n3()
+    {
+        char r = Ten;
+        char s = r;
+        char t = s;
+        char f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    // Two args, both used
+
+    static char F40(char x, char y)
+    {
+        return (char)(x * x + y * y - 100);
+    }
+
+    static bool Bench40p()
+    {
+        char t = (char) 10;
+        char f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40n()
+    {
+        char t = Ten;
+        char f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p1()
+    {
+        char s = Ten;
+        char t = (char) 10;
+        char f = F40(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p2()
+    {
+        char s = (char) 10;
+        char t = Ten;
+        char f = F40(s, t);
+        return (f == 100);
+    }
+
+    static char F41(char x, char y)
+    {
+        return (char)(x * y);
+    }
+
+    static bool Bench41p()
+    {
+        char t = (char) 10;
+        char f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41n()
+    {
+        char t = Ten;
+        char f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p1()
+    {
+        char s = (char) 10;
+        char t = Ten;
+        char f = F41(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p2()
+    {
+        char s = Ten;
+        char t = (char) 10;
+        char f = F41(s, t);
+        return (f == 100);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench00p1", "Bench00n1",
+        "Bench00p2", "Bench00n2",
+        "Bench00p3", "Bench00n3",
+        "Bench00p4", "Bench00n4",
+        "Bench01p",  "Bench01n",
+        "Bench02p",  "Bench02n",
+        "Bench03p",  "Bench03n",
+        "Bench04p",  "Bench04n",
+        "Bench05p",  "Bench05n",
+        "Bench05p1", "Bench05n1",
+        "Bench06p",  "Bench06n",
+        "Bench07p",  "Bench07n",
+        "Bench07p1", "Bench07n1",
+        "Bench08p",  "Bench08n",
+        "Bench09p",  "Bench09n",
+        "Bench10p",  "Bench10n",
+        "Bench10p1", "Bench10n1",
+        "Bench10p2", "Bench10n2",
+        "Bench10p3", "Bench10n3",
+        "Bench11p",  "Bench11n",
+        "Bench11p1", "Bench11n1",
+        "Bench11p2", "Bench11n2",
+        "Bench11p3", "Bench11n3",
+        "Bench20p",  "Bench20p1",
+        "Bench21p",  "Bench21n",
+        "Bench21p1", "Bench21n1",
+        "Bench22p",  "Bench22p1",
+        "Bench23p",  "Bench23n",
+        "Bench30p",  "Bench30n",
+        "Bench30p1", "Bench30n1",
+        "Bench30p2", "Bench30n2",
+        "Bench30p3", "Bench30n3",
+        "Bench31p",  "Bench31n",
+        "Bench31p1", "Bench31n1",
+        "Bench31p2", "Bench31n2",
+        "Bench31p3", "Bench31n3",
+        "Bench40p",  "Bench40n",
+        "Bench40p1", "Bench40p2",
+        "Bench41p",  "Bench41n",
+        "Bench41p1", "Bench41p2"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsChar).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.csproj
new file mode 100644 (file)
index 0000000..e0f78ff
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsChar.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.cs
new file mode 100644 (file)
index 0000000..6c95d48
--- /dev/null
@@ -0,0 +1,810 @@
+// 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 Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsDouble
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Doubles feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static double Five = 5;
+    static double Ten = 10;
+
+    static double Id(double x)
+    {
+        return x;
+    }
+
+    static double F00(double x)
+    {
+        return x * x;
+    }
+
+    static bool Bench00p()
+    {
+        double t = 10;
+        double f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n()
+    {
+        double t = Ten;
+        double f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p1()
+    {
+        double t = Id(10);
+        double f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n1()
+    {
+        double t = Id(Ten);
+        double f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p2()
+    {
+        double t = Id(10);
+        double f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00n2()
+    {
+        double t = Id(Ten);
+        double f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00p3()
+    {
+        double t = 10;
+        double f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00n3()
+    {
+        double t = Ten;
+        double f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00p4()
+    {
+        double t = 5;
+        double f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static bool Bench00n4()
+    {
+        double t = Five;
+        double f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static double F01(double x)
+    {
+        return 1000 / x;
+    }
+
+    static bool Bench01p()
+    {
+        double t = 10;
+        double f = F01(t);
+        return (f == 100);
+    }
+
+    static bool Bench01n()
+    {
+        double t = Ten;
+        double f = F01(t);
+        return (f == 100);
+    }
+
+    static double F02(double x)
+    {
+        return 20 * (x / 2);
+    }
+
+    static bool Bench02p()
+    {
+        double t = 10;
+        double f = F02(t);
+        return (f == 100);
+    }
+
+    static bool Bench02n()
+    {
+        double t = Ten;
+        double f = F02(t);
+        return (f == 100);
+    }
+
+    static double F03(double x)
+    {
+        return 91 + 1009 % x;
+    }
+
+    static bool Bench03p()
+    {
+        double t = 10;
+        double f = F03(t);
+        return (f == 100);
+    }
+
+    static bool Bench03n()
+    {
+        double t = Ten;
+        double f = F03(t);
+        return (f == 100);
+    }
+
+    static double F04(double x)
+    {
+        return 50 * (x % 4);
+    }
+
+    static bool Bench04p()
+    {
+        double t = 10;
+        double f = F04(t);
+        return (f == 100);
+    }
+
+    static bool Bench04n()
+    {
+        double t = Ten;
+        double f = F04(t);
+        return (f == 100);
+    }
+
+    static double F06(double x)
+    {
+        return -x + 110;
+    }
+
+    static bool Bench06p()
+    {
+        double t = 10;
+        double f = F06(t);
+        return (f == 100);
+    }
+
+    static bool Bench06n()
+    {
+        double t = Ten;
+        double f = F06(t);
+        return (f == 100);
+    }
+
+    // Doubles feeding comparisons.
+    //
+    // Inlining in Bench1xp should enable branch optimization
+    // Inlining in Bench1xn will not enable branch optimization
+
+    static double F10(double x)
+    {
+        return x == 10 ? 100 : 0;
+    }
+
+    static bool Bench10p()
+    {
+        double t = 10;
+        double f = F10(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n()
+    {
+        double t = Ten;
+        double f = F10(t);
+        return (f == 100);
+    }
+
+    static double F101(double x)
+    {
+        return x != 10 ? 0 : 100;
+    }
+
+    static bool Bench10p1()
+    {
+        double t = 10;
+        double f = F101(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n1()
+    {
+        double t = Ten;
+        double f = F101(t);
+        return (f == 100);
+    }
+
+    static double F102(double x)
+    {
+        return x >= 10 ? 100 : 0;
+    }
+
+    static bool Bench10p2()
+    {
+        double t = 10;
+        double f = F102(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n2()
+    {
+        double t = Ten;
+        double f = F102(t);
+        return (f == 100);
+    }
+
+    static double F103(double x)
+    {
+        return x <= 10 ? 100 : 0;
+    }
+
+    static bool Bench10p3()
+    {
+        double t = 10;
+        double f = F103(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n3()
+    {
+        double t = Ten;
+        double f = F102(t);
+        return (f == 100);
+    }
+
+    static double F11(double x)
+    {
+        if (x == 10)
+        {
+            return 100;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    static bool Bench11p()
+    {
+        double t = 10;
+        double f = F11(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n()
+    {
+        double t = Ten;
+        double f = F11(t);
+        return (f == 100);
+    }
+
+    static double F111(double x)
+    {
+        if (x != 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p1()
+    {
+        double t = 10;
+        double f = F111(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n1()
+    {
+        double t = Ten;
+        double f = F111(t);
+        return (f == 100);
+    }
+
+    static double F112(double x)
+    {
+        if (x > 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p2()
+    {
+        double t = 10;
+        double f = F112(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n2()
+    {
+        double t = Ten;
+        double f = F112(t);
+        return (f == 100);
+    }
+    static double F113(double x)
+    {
+        if (x < 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p3()
+    {
+        double t = 10;
+        double f = F113(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n3()
+    {
+        double t = Ten;
+        double f = F113(t);
+        return (f == 100);
+    }
+
+    // Ununsed (or effectively unused) parameters
+    //
+    // Simple callee analysis may overstate inline benefit
+
+    static double F20(double x)
+    {
+        return 100;
+    }
+
+    static bool Bench20p()
+    {
+        double t = 10;
+        double f = F20(t);
+        return (f == 100);
+    }
+
+    static bool Bench20p1()
+    {
+        double t = Ten;
+        double f = F20(t);
+        return (f == 100);
+    }
+
+    static double F21(double x)
+    {
+        return -x + 100 + x;
+    }
+
+    static bool Bench21p()
+    {
+        double t = 10;
+        double f = F21(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n()
+    {
+        double t = Ten;
+        double f = F21(t);
+        return (f == 100);
+    }
+
+    static double F211(double x)
+    {
+        return x - x + 100;
+    }
+
+    static bool Bench21p1()
+    {
+        double t = 10;
+        double f = F211(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n1()
+    {
+        double t = Ten;
+        double f = F211(t);
+        return (f == 100);
+    }
+
+    static double F22(double x)
+    {
+        if (x > 0)
+        {
+            return 100;
+        }
+
+        return 100;
+    }
+
+    static bool Bench22p()
+    {
+        double t = 10;
+        double f = F22(t);
+        return (f == 100);
+    }
+
+    static bool Bench22p1()
+    {
+        double t = Ten;
+        double f = F22(t);
+        return (f == 100);
+    }
+
+    static double F23(double x)
+    {
+        if (x > 0)
+        {
+            return 90 + x;
+        }
+
+        return 100;
+    }
+
+    static bool Bench23p()
+    {
+        double t = 10;
+        double f = F23(t);
+        return (f == 100);
+    }
+
+    static bool Bench23n()
+    {
+        double t = Ten;
+        double f = F23(t);
+        return (f == 100);
+    }
+
+    // Multiple parameters
+
+    static double F30(double x, double y)
+    {
+        return y * y;
+    }
+
+    static bool Bench30p()
+    {
+        double t = 10;
+        double f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n()
+    {
+        double t = Ten;
+        double f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p1()
+    {
+        double s = Ten;
+        double t = 10;
+        double f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n1()
+    {
+        double s = 10;
+        double t = Ten;
+        double f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p2()
+    {
+        double s = 10;
+        double t = 10;
+        double f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n2()
+    {
+        double s = Ten;
+        double t = Ten;
+        double f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p3()
+    {
+        double s = 10;
+        double t = s;
+        double f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n3()
+    {
+        double s = Ten;
+        double t = s;
+        double f = F30(s, t);
+        return (f == 100);
+    }
+
+    static double F31(double x, double y, double z)
+    {
+        return z * z;
+    }
+
+    static bool Bench31p()
+    {
+        double t = 10;
+        double f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n()
+    {
+        double t = Ten;
+        double f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p1()
+    {
+        double r = Ten;
+        double s = Ten;
+        double t = 10;
+        double f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n1()
+    {
+        double r = 10;
+        double s = 10;
+        double t = Ten;
+        double f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p2()
+    {
+        double r = 10;
+        double s = 10;
+        double t = 10;
+        double f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n2()
+    {
+        double r = Ten;
+        double s = Ten;
+        double t = Ten;
+        double f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p3()
+    {
+        double r = 10;
+        double s = r;
+        double t = s;
+        double f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n3()
+    {
+        double r = Ten;
+        double s = r;
+        double t = s;
+        double f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    // Two args, both used
+
+    static double F40(double x, double y)
+    {
+        return x * x + y * y - 100;
+    }
+
+    static bool Bench40p()
+    {
+        double t = 10;
+        double f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40n()
+    {
+        double t = Ten;
+        double f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p1()
+    {
+        double s = Ten;
+        double t = 10;
+        double f = F40(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p2()
+    {
+        double s = 10;
+        double t = Ten;
+        double f = F40(s, t);
+        return (f == 100);
+    }
+
+    static double F41(double x, double y)
+    {
+        return x * y;
+    }
+
+    static bool Bench41p()
+    {
+        double t = 10;
+        double f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41n()
+    {
+        double t = Ten;
+        double f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p1()
+    {
+        double s = 10;
+        double t = Ten;
+        double f = F41(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p2()
+    {
+        double s = Ten;
+        double t = 10;
+        double f = F41(s, t);
+        return (f == 100);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench00p1", "Bench00n1",
+        "Bench00p2", "Bench00n2",
+        "Bench00p3", "Bench00n3",
+        "Bench00p4", "Bench00n4",
+        "Bench01p",  "Bench01n",
+        "Bench02p",  "Bench02n",
+        "Bench03p",  "Bench03n",
+        "Bench04p",  "Bench04n",
+        "Bench06p",  "Bench06n",
+        "Bench10p",  "Bench10n",
+        "Bench10p1", "Bench10n1",
+        "Bench10p2", "Bench10n2",
+        "Bench10p3", "Bench10n3",
+        "Bench11p",  "Bench11n",
+        "Bench11p1", "Bench11n1",
+        "Bench11p2", "Bench11n2",
+        "Bench11p3", "Bench11n3",
+        "Bench20p",  "Bench20p1",
+        "Bench21p",  "Bench21n",
+        "Bench21p1", "Bench21n1",
+        "Bench22p",  "Bench22p1",
+        "Bench23p",  "Bench23n",
+        "Bench30p",  "Bench30n",
+        "Bench30p1", "Bench30n1",
+        "Bench30p2", "Bench30n2",
+        "Bench30p3", "Bench30n3",
+        "Bench31p",  "Bench31n",
+        "Bench31p1", "Bench31n1",
+        "Bench31p2", "Bench31n2",
+        "Bench31p3", "Bench31n3",
+        "Bench40p",  "Bench40n",
+        "Bench40p1", "Bench40p2",
+        "Bench41p",  "Bench41n",
+        "Bench41p1", "Bench41p2"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsDouble).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.csproj
new file mode 100644 (file)
index 0000000..60de76c
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsDouble.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.cs
new file mode 100644 (file)
index 0000000..bbd65a4
--- /dev/null
@@ -0,0 +1,810 @@
+// 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 Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsFloat
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Floats feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static float Five = 5;
+    static float Ten = 10;
+
+    static float Id(float x)
+    {
+        return x;
+    }
+
+    static float F00(float x)
+    {
+        return x * x;
+    }
+
+    static bool Bench00p()
+    {
+        float t = 10;
+        float f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n()
+    {
+        float t = Ten;
+        float f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p1()
+    {
+        float t = Id(10);
+        float f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n1()
+    {
+        float t = Id(Ten);
+        float f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p2()
+    {
+        float t = Id(10);
+        float f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00n2()
+    {
+        float t = Id(Ten);
+        float f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00p3()
+    {
+        float t = 10;
+        float f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00n3()
+    {
+        float t = Ten;
+        float f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00p4()
+    {
+        float t = 5;
+        float f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static bool Bench00n4()
+    {
+        float t = Five;
+        float f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static float F01(float x)
+    {
+        return 1000 / x;
+    }
+
+    static bool Bench01p()
+    {
+        float t = 10;
+        float f = F01(t);
+        return (f == 100);
+    }
+
+    static bool Bench01n()
+    {
+        float t = Ten;
+        float f = F01(t);
+        return (f == 100);
+    }
+
+    static float F02(float x)
+    {
+        return 20 * (x / 2);
+    }
+
+    static bool Bench02p()
+    {
+        float t = 10;
+        float f = F02(t);
+        return (f == 100);
+    }
+
+    static bool Bench02n()
+    {
+        float t = Ten;
+        float f = F02(t);
+        return (f == 100);
+    }
+
+    static float F03(float x)
+    {
+        return 91 + 1009 % x;
+    }
+
+    static bool Bench03p()
+    {
+        float t = 10;
+        float f = F03(t);
+        return (f == 100);
+    }
+
+    static bool Bench03n()
+    {
+        float t = Ten;
+        float f = F03(t);
+        return (f == 100);
+    }
+
+    static float F04(float x)
+    {
+        return 50 * (x % 4);
+    }
+
+    static bool Bench04p()
+    {
+        float t = 10;
+        float f = F04(t);
+        return (f == 100);
+    }
+
+    static bool Bench04n()
+    {
+        float t = Ten;
+        float f = F04(t);
+        return (f == 100);
+    }
+
+    static float F06(float x)
+    {
+        return -x + 110;
+    }
+
+    static bool Bench06p()
+    {
+        float t = 10;
+        float f = F06(t);
+        return (f == 100);
+    }
+
+    static bool Bench06n()
+    {
+        float t = Ten;
+        float f = F06(t);
+        return (f == 100);
+    }
+
+    // Floats feeding comparisons.
+    //
+    // Inlining in Bench1xp should enable branch optimization
+    // Inlining in Bench1xn will not enable branch optimization
+
+    static float F10(float x)
+    {
+        return x == 10 ? 100 : 0;
+    }
+
+    static bool Bench10p()
+    {
+        float t = 10;
+        float f = F10(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n()
+    {
+        float t = Ten;
+        float f = F10(t);
+        return (f == 100);
+    }
+
+    static float F101(float x)
+    {
+        return x != 10 ? 0 : 100;
+    }
+
+    static bool Bench10p1()
+    {
+        float t = 10;
+        float f = F101(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n1()
+    {
+        float t = Ten;
+        float f = F101(t);
+        return (f == 100);
+    }
+
+    static float F102(float x)
+    {
+        return x >= 10 ? 100 : 0;
+    }
+
+    static bool Bench10p2()
+    {
+        float t = 10;
+        float f = F102(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n2()
+    {
+        float t = Ten;
+        float f = F102(t);
+        return (f == 100);
+    }
+
+    static float F103(float x)
+    {
+        return x <= 10 ? 100 : 0;
+    }
+
+    static bool Bench10p3()
+    {
+        float t = 10;
+        float f = F103(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n3()
+    {
+        float t = Ten;
+        float f = F102(t);
+        return (f == 100);
+    }
+
+    static float F11(float x)
+    {
+        if (x == 10)
+        {
+            return 100;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    static bool Bench11p()
+    {
+        float t = 10;
+        float f = F11(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n()
+    {
+        float t = Ten;
+        float f = F11(t);
+        return (f == 100);
+    }
+
+    static float F111(float x)
+    {
+        if (x != 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p1()
+    {
+        float t = 10;
+        float f = F111(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n1()
+    {
+        float t = Ten;
+        float f = F111(t);
+        return (f == 100);
+    }
+
+    static float F112(float x)
+    {
+        if (x > 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p2()
+    {
+        float t = 10;
+        float f = F112(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n2()
+    {
+        float t = Ten;
+        float f = F112(t);
+        return (f == 100);
+    }
+    static float F113(float x)
+    {
+        if (x < 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p3()
+    {
+        float t = 10;
+        float f = F113(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n3()
+    {
+        float t = Ten;
+        float f = F113(t);
+        return (f == 100);
+    }
+
+    // Ununsed (or effectively unused) parameters
+    //
+    // Simple callee analysis may overstate inline benefit
+
+    static float F20(float x)
+    {
+        return 100;
+    }
+
+    static bool Bench20p()
+    {
+        float t = 10;
+        float f = F20(t);
+        return (f == 100);
+    }
+
+    static bool Bench20p1()
+    {
+        float t = Ten;
+        float f = F20(t);
+        return (f == 100);
+    }
+
+    static float F21(float x)
+    {
+        return -x + 100 + x;
+    }
+
+    static bool Bench21p()
+    {
+        float t = 10;
+        float f = F21(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n()
+    {
+        float t = Ten;
+        float f = F21(t);
+        return (f == 100);
+    }
+
+    static float F211(float x)
+    {
+        return x - x + 100;
+    }
+
+    static bool Bench21p1()
+    {
+        float t = 10;
+        float f = F211(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n1()
+    {
+        float t = Ten;
+        float f = F211(t);
+        return (f == 100);
+    }
+
+    static float F22(float x)
+    {
+        if (x > 0)
+        {
+            return 100;
+        }
+
+        return 100;
+    }
+
+    static bool Bench22p()
+    {
+        float t = 10;
+        float f = F22(t);
+        return (f == 100);
+    }
+
+    static bool Bench22p1()
+    {
+        float t = Ten;
+        float f = F22(t);
+        return (f == 100);
+    }
+
+    static float F23(float x)
+    {
+        if (x > 0)
+        {
+            return 90 + x;
+        }
+
+        return 100;
+    }
+
+    static bool Bench23p()
+    {
+        float t = 10;
+        float f = F23(t);
+        return (f == 100);
+    }
+
+    static bool Bench23n()
+    {
+        float t = Ten;
+        float f = F23(t);
+        return (f == 100);
+    }
+
+    // Multiple parameters
+
+    static float F30(float x, float y)
+    {
+        return y * y;
+    }
+
+    static bool Bench30p()
+    {
+        float t = 10;
+        float f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n()
+    {
+        float t = Ten;
+        float f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p1()
+    {
+        float s = Ten;
+        float t = 10;
+        float f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n1()
+    {
+        float s = 10;
+        float t = Ten;
+        float f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p2()
+    {
+        float s = 10;
+        float t = 10;
+        float f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n2()
+    {
+        float s = Ten;
+        float t = Ten;
+        float f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p3()
+    {
+        float s = 10;
+        float t = s;
+        float f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n3()
+    {
+        float s = Ten;
+        float t = s;
+        float f = F30(s, t);
+        return (f == 100);
+    }
+
+    static float F31(float x, float y, float z)
+    {
+        return z * z;
+    }
+
+    static bool Bench31p()
+    {
+        float t = 10;
+        float f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n()
+    {
+        float t = Ten;
+        float f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p1()
+    {
+        float r = Ten;
+        float s = Ten;
+        float t = 10;
+        float f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n1()
+    {
+        float r = 10;
+        float s = 10;
+        float t = Ten;
+        float f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p2()
+    {
+        float r = 10;
+        float s = 10;
+        float t = 10;
+        float f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n2()
+    {
+        float r = Ten;
+        float s = Ten;
+        float t = Ten;
+        float f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p3()
+    {
+        float r = 10;
+        float s = r;
+        float t = s;
+        float f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n3()
+    {
+        float r = Ten;
+        float s = r;
+        float t = s;
+        float f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    // Two args, both used
+
+    static float F40(float x, float y)
+    {
+        return x * x + y * y - 100;
+    }
+
+    static bool Bench40p()
+    {
+        float t = 10;
+        float f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40n()
+    {
+        float t = Ten;
+        float f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p1()
+    {
+        float s = Ten;
+        float t = 10;
+        float f = F40(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p2()
+    {
+        float s = 10;
+        float t = Ten;
+        float f = F40(s, t);
+        return (f == 100);
+    }
+
+    static float F41(float x, float y)
+    {
+        return x * y;
+    }
+
+    static bool Bench41p()
+    {
+        float t = 10;
+        float f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41n()
+    {
+        float t = Ten;
+        float f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p1()
+    {
+        float s = 10;
+        float t = Ten;
+        float f = F41(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p2()
+    {
+        float s = Ten;
+        float t = 10;
+        float f = F41(s, t);
+        return (f == 100);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench00p1", "Bench00n1",
+        "Bench00p2", "Bench00n2",
+        "Bench00p3", "Bench00n3",
+        "Bench00p4", "Bench00n4",
+        "Bench01p",  "Bench01n",
+        "Bench02p",  "Bench02n",
+        "Bench03p",  "Bench03n",
+        "Bench04p",  "Bench04n",
+        "Bench06p",  "Bench06n",
+        "Bench10p",  "Bench10n",
+        "Bench10p1", "Bench10n1",
+        "Bench10p2", "Bench10n2",
+        "Bench10p3", "Bench10n3",
+        "Bench11p",  "Bench11n",
+        "Bench11p1", "Bench11n1",
+        "Bench11p2", "Bench11n2",
+        "Bench11p3", "Bench11n3",
+        "Bench20p",  "Bench20p1",
+        "Bench21p",  "Bench21n",
+        "Bench21p1", "Bench21n1",
+        "Bench22p",  "Bench22p1",
+        "Bench23p",  "Bench23n",
+        "Bench30p",  "Bench30n",
+        "Bench30p1", "Bench30n1",
+        "Bench30p2", "Bench30n2",
+        "Bench30p3", "Bench30n3",
+        "Bench31p",  "Bench31n",
+        "Bench31p1", "Bench31n1",
+        "Bench31p2", "Bench31n2",
+        "Bench31p3", "Bench31n3",
+        "Bench40p",  "Bench40n",
+        "Bench40p1", "Bench40p2",
+        "Bench41p",  "Bench41n",
+        "Bench41p1", "Bench41p2"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsFloat).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.csproj
new file mode 100644 (file)
index 0000000..70b3e29
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsFloat.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.cs
new file mode 100644 (file)
index 0000000..03d59f9
--- /dev/null
@@ -0,0 +1,930 @@
+// 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 Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsInt
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Ints feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static int Five = 5;
+    static int Ten = 10;
+
+    static int Id(int x)
+    {
+        return x;
+    }
+
+    static int F00(int x)
+    {
+        return x * x;
+    }
+
+    static bool Bench00p()
+    {
+        int t = 10;
+        int f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n()
+    {
+        int t = Ten;
+        int f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p1()
+    {
+        int t = Id(10);
+        int f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n1()
+    {
+        int t = Id(Ten);
+        int f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p2()
+    {
+        int t = Id(10);
+        int f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00n2()
+    {
+        int t = Id(Ten);
+        int f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00p3()
+    {
+        int t = 10;
+        int f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00n3()
+    {
+        int t = Ten;
+        int f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00p4()
+    {
+        int t = 5;
+        int f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static bool Bench00n4()
+    {
+        int t = Five;
+        int f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static int F01(int x)
+    {
+        return 1000 / x;
+    }
+
+    static bool Bench01p()
+    {
+        int t = 10;
+        int f = F01(t);
+        return (f == 100);
+    }
+
+    static bool Bench01n()
+    {
+        int t = Ten;
+        int f = F01(t);
+        return (f == 100);
+    }
+
+    static int F02(int x)
+    {
+        return 20 * (x / 2);
+    }
+
+    static bool Bench02p()
+    {
+        int t = 10;
+        int f = F02(t);
+        return (f == 100);
+    }
+
+    static bool Bench02n()
+    {
+        int t = Ten;
+        int f = F02(t);
+        return (f == 100);
+    }
+
+    static int F03(int x)
+    {
+        return 91 + 1009 % x;
+    }
+
+    static bool Bench03p()
+    {
+        int t = 10;
+        int f = F03(t);
+        return (f == 100);
+    }
+
+    static bool Bench03n()
+    {
+        int t = Ten;
+        int f = F03(t);
+        return (f == 100);
+    }
+
+    static int F04(int x)
+    {
+        return 50 * (x % 4);
+    }
+
+    static bool Bench04p()
+    {
+        int t = 10;
+        int f = F04(t);
+        return (f == 100);
+    }
+
+    static bool Bench04n()
+    {
+        int t = Ten;
+        int f = F04(t);
+        return (f == 100);
+    }
+
+    static int F05(int x)
+    {
+        return (1 << x) - 924;
+    }
+
+    static bool Bench05p()
+    {
+        int t = 10;
+        int f = F05(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n()
+    {
+        int t = Ten;
+        int f = F05(t);
+        return (f == 100);
+    }
+
+    static int F051(int x)
+    {
+        return (102400 >> x);
+    }
+
+    static bool Bench05p1()
+    {
+        int t = 10;
+        int f = F051(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n1()
+    {
+        int t = Ten;
+        int f = F051(t);
+        return (f == 100);
+    }
+
+    static int F06(int x)
+    {
+        return -x + 110;
+    }
+
+    static bool Bench06p()
+    {
+        int t = 10;
+        int f = F06(t);
+        return (f == 100);
+    }
+
+    static bool Bench06n()
+    {
+        int t = Ten;
+        int f = F06(t);
+        return (f == 100);
+    }
+
+    static int F07(int x)
+    {
+        return ~x + 111;
+    }
+
+    static bool Bench07p()
+    {
+        int t = 10;
+        int f = F07(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n()
+    {
+        int t = Ten;
+        int f = F07(t);
+        return (f == 100);
+    }
+
+    static int F071(int x)
+    {
+        return (x ^ -1) + 111;
+    }
+
+    static bool Bench07p1()
+    {
+        int t = 10;
+        int f = F071(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n1()
+    {
+        int t = Ten;
+        int f = F071(t);
+        return (f == 100);
+    }
+
+    static int F08(int x)
+    {
+        return (x & 0x7) + 98;
+    }
+
+    static bool Bench08p()
+    {
+        int t = 10;
+        int f = F08(t);
+        return (f == 100);
+    }
+
+    static bool Bench08n()
+    {
+        int t = Ten;
+        int f = F08(t);
+        return (f == 100);
+    }
+
+    static int F09(int x)
+    {
+        return (x | 0x7) + 85;
+    }
+
+    static bool Bench09p()
+    {
+        int t = 10;
+        int f = F09(t);
+        return (f == 100);
+    }
+
+    static bool Bench09n()
+    {
+        int t = Ten;
+        int f = F09(t);
+        return (f == 100);
+    }
+
+    // Ints feeding comparisons.
+    //
+    // Inlining in Bench1xp should enable branch optimization
+    // Inlining in Bench1xn will not enable branch optimization
+
+    static int F10(int x)
+    {
+        return x == 10 ? 100 : 0;
+    }
+
+    static bool Bench10p()
+    {
+        int t = 10;
+        int f = F10(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n()
+    {
+        int t = Ten;
+        int f = F10(t);
+        return (f == 100);
+    }
+
+    static int F101(int x)
+    {
+        return x != 10 ? 0 : 100;
+    }
+
+    static bool Bench10p1()
+    {
+        int t = 10;
+        int f = F101(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n1()
+    {
+        int t = Ten;
+        int f = F101(t);
+        return (f == 100);
+    }
+
+    static int F102(int x)
+    {
+        return x >= 10 ? 100 : 0;
+    }
+
+    static bool Bench10p2()
+    {
+        int t = 10;
+        int f = F102(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n2()
+    {
+        int t = Ten;
+        int f = F102(t);
+        return (f == 100);
+    }
+
+    static int F103(int x)
+    {
+        return x <= 10 ? 100 : 0;
+    }
+
+    static bool Bench10p3()
+    {
+        int t = 10;
+        int f = F103(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n3()
+    {
+        int t = Ten;
+        int f = F102(t);
+        return (f == 100);
+    }
+
+    static int F11(int x)
+    {
+        if (x == 10)
+        {
+            return 100;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    static bool Bench11p()
+    {
+        int t = 10;
+        int f = F11(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n()
+    {
+        int t = Ten;
+        int f = F11(t);
+        return (f == 100);
+    }
+
+    static int F111(int x)
+    {
+        if (x != 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p1()
+    {
+        int t = 10;
+        int f = F111(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n1()
+    {
+        int t = Ten;
+        int f = F111(t);
+        return (f == 100);
+    }
+
+    static int F112(int x)
+    {
+        if (x > 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p2()
+    {
+        int t = 10;
+        int f = F112(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n2()
+    {
+        int t = Ten;
+        int f = F112(t);
+        return (f == 100);
+    }
+    static int F113(int x)
+    {
+        if (x < 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p3()
+    {
+        int t = 10;
+        int f = F113(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n3()
+    {
+        int t = Ten;
+        int f = F113(t);
+        return (f == 100);
+    }
+
+    // Ununsed (or effectively unused) parameters
+    //
+    // Simple callee analysis may overstate inline benefit
+
+    static int F20(int x)
+    {
+        return 100;
+    }
+
+    static bool Bench20p()
+    {
+        int t = 10;
+        int f = F20(t);
+        return (f == 100);
+    }
+
+    static bool Bench20p1()
+    {
+        int t = Ten;
+        int f = F20(t);
+        return (f == 100);
+    }
+
+    static int F21(int x)
+    {
+        return -x + 100 + x;
+    }
+
+    static bool Bench21p()
+    {
+        int t = 10;
+        int f = F21(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n()
+    {
+        int t = Ten;
+        int f = F21(t);
+        return (f == 100);
+    }
+
+    static int F211(int x)
+    {
+        return x - x + 100;
+    }
+
+    static bool Bench21p1()
+    {
+        int t = 10;
+        int f = F211(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n1()
+    {
+        int t = Ten;
+        int f = F211(t);
+        return (f == 100);
+    }
+
+    static int F22(int x)
+    {
+        if (x > 0)
+        {
+            return 100;
+        }
+
+        return 100;
+    }
+
+    static bool Bench22p()
+    {
+        int t = 10;
+        int f = F22(t);
+        return (f == 100);
+    }
+
+    static bool Bench22p1()
+    {
+        int t = Ten;
+        int f = F22(t);
+        return (f == 100);
+    }
+
+    static int F23(int x)
+    {
+        if (x > 0)
+        {
+            return 90 + x;
+        }
+
+        return 100;
+    }
+
+    static bool Bench23p()
+    {
+        int t = 10;
+        int f = F23(t);
+        return (f == 100);
+    }
+
+    static bool Bench23n()
+    {
+        int t = Ten;
+        int f = F23(t);
+        return (f == 100);
+    }
+
+    // Multiple parameters
+
+    static int F30(int x, int y)
+    {
+        return y * y;
+    }
+
+    static bool Bench30p()
+    {
+        int t = 10;
+        int f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n()
+    {
+        int t = Ten;
+        int f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p1()
+    {
+        int s = Ten;
+        int t = 10;
+        int f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n1()
+    {
+        int s = 10;
+        int t = Ten;
+        int f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p2()
+    {
+        int s = 10;
+        int t = 10;
+        int f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n2()
+    {
+        int s = Ten;
+        int t = Ten;
+        int f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p3()
+    {
+        int s = 10;
+        int t = s;
+        int f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n3()
+    {
+        int s = Ten;
+        int t = s;
+        int f = F30(s, t);
+        return (f == 100);
+    }
+
+    static int F31(int x, int y, int z)
+    {
+        return z * z;
+    }
+
+    static bool Bench31p()
+    {
+        int t = 10;
+        int f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n()
+    {
+        int t = Ten;
+        int f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p1()
+    {
+        int r = Ten;
+        int s = Ten;
+        int t = 10;
+        int f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n1()
+    {
+        int r = 10;
+        int s = 10;
+        int t = Ten;
+        int f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p2()
+    {
+        int r = 10;
+        int s = 10;
+        int t = 10;
+        int f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n2()
+    {
+        int r = Ten;
+        int s = Ten;
+        int t = Ten;
+        int f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p3()
+    {
+        int r = 10;
+        int s = r;
+        int t = s;
+        int f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n3()
+    {
+        int r = Ten;
+        int s = r;
+        int t = s;
+        int f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    // Two args, both used
+
+    static int F40(int x, int y)
+    {
+        return x * x + y * y - 100;
+    }
+
+    static bool Bench40p()
+    {
+        int t = 10;
+        int f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40n()
+    {
+        int t = Ten;
+        int f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p1()
+    {
+        int s = Ten;
+        int t = 10;
+        int f = F40(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p2()
+    {
+        int s = 10;
+        int t = Ten;
+        int f = F40(s, t);
+        return (f == 100);
+    }
+
+    static int F41(int x, int y)
+    {
+        return x * y;
+    }
+
+    static bool Bench41p()
+    {
+        int t = 10;
+        int f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41n()
+    {
+        int t = Ten;
+        int f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p1()
+    {
+        int s = 10;
+        int t = Ten;
+        int f = F41(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p2()
+    {
+        int s = Ten;
+        int t = 10;
+        int f = F41(s, t);
+        return (f == 100);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench00p1", "Bench00n1",
+        "Bench00p2", "Bench00n2",
+        "Bench00p3", "Bench00n3",
+        "Bench00p4", "Bench00n4",
+        "Bench01p",  "Bench01n",
+        "Bench02p",  "Bench02n",
+        "Bench03p",  "Bench03n",
+        "Bench04p",  "Bench04n",
+        "Bench05p",  "Bench05n",
+        "Bench05p1", "Bench05n1",
+        "Bench06p",  "Bench06n",
+        "Bench07p",  "Bench07n",
+        "Bench07p1", "Bench07n1",
+        "Bench08p",  "Bench08n",
+        "Bench09p",  "Bench09n",
+        "Bench10p",  "Bench10n",
+        "Bench10p1", "Bench10n1",
+        "Bench10p2", "Bench10n2",
+        "Bench10p3", "Bench10n3",
+        "Bench11p",  "Bench11n",
+        "Bench11p1", "Bench11n1",
+        "Bench11p2", "Bench11n2",
+        "Bench11p3", "Bench11n3",
+        "Bench20p",  "Bench20p1",
+        "Bench21p",  "Bench21n",
+        "Bench21p1", "Bench21n1",
+        "Bench22p",  "Bench22p1",
+        "Bench23p",  "Bench23n",
+        "Bench30p",  "Bench30n",
+        "Bench30p1", "Bench30n1",
+        "Bench30p2", "Bench30n2",
+        "Bench30p3", "Bench30n3",
+        "Bench31p",  "Bench31n",
+        "Bench31p1", "Bench31n1",
+        "Bench31p2", "Bench31n2",
+        "Bench31p3", "Bench31n3",
+        "Bench40p",  "Bench40n",
+        "Bench40p1", "Bench40p2",
+        "Bench41p",  "Bench41n",
+        "Bench41p1", "Bench41p2"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsInt).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.csproj
new file mode 100644 (file)
index 0000000..f5f3610
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsInt.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.cs
new file mode 100644 (file)
index 0000000..f4e45f5
--- /dev/null
@@ -0,0 +1,930 @@
+// 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 Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsLong
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Longs feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static long Five = 5;
+    static long Ten = 10;
+
+    static long Id(long x)
+    {
+        return x;
+    }
+
+    static long F00(long x)
+    {
+        return x * x;
+    }
+
+    static bool Bench00p()
+    {
+        long t = 10;
+        long f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n()
+    {
+        long t = Ten;
+        long f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p1()
+    {
+        long t = Id(10);
+        long f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n1()
+    {
+        long t = Id(Ten);
+        long f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p2()
+    {
+        long t = Id(10);
+        long f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00n2()
+    {
+        long t = Id(Ten);
+        long f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00p3()
+    {
+        long t = 10;
+        long f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00n3()
+    {
+        long t = Ten;
+        long f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00p4()
+    {
+        long t = 5;
+        long f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static bool Bench00n4()
+    {
+        long t = Five;
+        long f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static long F01(long x)
+    {
+        return 1000 / x;
+    }
+
+    static bool Bench01p()
+    {
+        long t = 10;
+        long f = F01(t);
+        return (f == 100);
+    }
+
+    static bool Bench01n()
+    {
+        long t = Ten;
+        long f = F01(t);
+        return (f == 100);
+    }
+
+    static long F02(long x)
+    {
+        return 20 * (x / 2);
+    }
+
+    static bool Bench02p()
+    {
+        long t = 10;
+        long f = F02(t);
+        return (f == 100);
+    }
+
+    static bool Bench02n()
+    {
+        long t = Ten;
+        long f = F02(t);
+        return (f == 100);
+    }
+
+    static long F03(long x)
+    {
+        return 91 + 1009 % x;
+    }
+
+    static bool Bench03p()
+    {
+        long t = 10;
+        long f = F03(t);
+        return (f == 100);
+    }
+
+    static bool Bench03n()
+    {
+        long t = Ten;
+        long f = F03(t);
+        return (f == 100);
+    }
+
+    static long F04(long x)
+    {
+        return 50 * (x % 4);
+    }
+
+    static bool Bench04p()
+    {
+        long t = 10;
+        long f = F04(t);
+        return (f == 100);
+    }
+
+    static bool Bench04n()
+    {
+        long t = Ten;
+        long f = F04(t);
+        return (f == 100);
+    }
+
+    static long F05(long x)
+    {
+        return (1 << (int) x) - 924;
+    }
+
+    static bool Bench05p()
+    {
+        long t = 10;
+        long f = F05(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n()
+    {
+        long t = Ten;
+        long f = F05(t);
+        return (f == 100);
+    }
+
+    static long F051(long x)
+    {
+        return (102400 >> (int) x);
+    }
+
+    static bool Bench05p1()
+    {
+        long t = 10;
+        long f = F051(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n1()
+    {
+        long t = Ten;
+        long f = F051(t);
+        return (f == 100);
+    }
+
+    static long F06(long x)
+    {
+        return -x + 110;
+    }
+
+    static bool Bench06p()
+    {
+        long t = 10;
+        long f = F06(t);
+        return (f == 100);
+    }
+
+    static bool Bench06n()
+    {
+        long t = Ten;
+        long f = F06(t);
+        return (f == 100);
+    }
+
+    static long F07(long x)
+    {
+        return ~x + 111;
+    }
+
+    static bool Bench07p()
+    {
+        long t = 10;
+        long f = F07(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n()
+    {
+        long t = Ten;
+        long f = F07(t);
+        return (f == 100);
+    }
+
+    static long F071(long x)
+    {
+        return (x ^ -1) + 111;
+    }
+
+    static bool Bench07p1()
+    {
+        long t = 10;
+        long f = F071(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n1()
+    {
+        long t = Ten;
+        long f = F071(t);
+        return (f == 100);
+    }
+
+    static long F08(long x)
+    {
+        return (x & 0x7) + 98;
+    }
+
+    static bool Bench08p()
+    {
+        long t = 10;
+        long f = F08(t);
+        return (f == 100);
+    }
+
+    static bool Bench08n()
+    {
+        long t = Ten;
+        long f = F08(t);
+        return (f == 100);
+    }
+
+    static long F09(long x)
+    {
+        return (x | 0x7) + 85;
+    }
+
+    static bool Bench09p()
+    {
+        long t = 10;
+        long f = F09(t);
+        return (f == 100);
+    }
+
+    static bool Bench09n()
+    {
+        long t = Ten;
+        long f = F09(t);
+        return (f == 100);
+    }
+
+    // Longs feeding comparisons.
+    //
+    // Inlining in Bench1xp should enable branch optimization
+    // Inlining in Bench1xn will not enable branch optimization
+
+    static long F10(long x)
+    {
+        return x == 10 ? 100 : 0;
+    }
+
+    static bool Bench10p()
+    {
+        long t = 10;
+        long f = F10(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n()
+    {
+        long t = Ten;
+        long f = F10(t);
+        return (f == 100);
+    }
+
+    static long F101(long x)
+    {
+        return x != 10 ? 0 : 100;
+    }
+
+    static bool Bench10p1()
+    {
+        long t = 10;
+        long f = F101(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n1()
+    {
+        long t = Ten;
+        long f = F101(t);
+        return (f == 100);
+    }
+
+    static long F102(long x)
+    {
+        return x >= 10 ? 100 : 0;
+    }
+
+    static bool Bench10p2()
+    {
+        long t = 10;
+        long f = F102(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n2()
+    {
+        long t = Ten;
+        long f = F102(t);
+        return (f == 100);
+    }
+
+    static long F103(long x)
+    {
+        return x <= 10 ? 100 : 0;
+    }
+
+    static bool Bench10p3()
+    {
+        long t = 10;
+        long f = F103(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n3()
+    {
+        long t = Ten;
+        long f = F102(t);
+        return (f == 100);
+    }
+
+    static long F11(long x)
+    {
+        if (x == 10)
+        {
+            return 100;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    static bool Bench11p()
+    {
+        long t = 10;
+        long f = F11(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n()
+    {
+        long t = Ten;
+        long f = F11(t);
+        return (f == 100);
+    }
+
+    static long F111(long x)
+    {
+        if (x != 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p1()
+    {
+        long t = 10;
+        long f = F111(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n1()
+    {
+        long t = Ten;
+        long f = F111(t);
+        return (f == 100);
+    }
+
+    static long F112(long x)
+    {
+        if (x > 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p2()
+    {
+        long t = 10;
+        long f = F112(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n2()
+    {
+        long t = Ten;
+        long f = F112(t);
+        return (f == 100);
+    }
+    static long F113(long x)
+    {
+        if (x < 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p3()
+    {
+        long t = 10;
+        long f = F113(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n3()
+    {
+        long t = Ten;
+        long f = F113(t);
+        return (f == 100);
+    }
+
+    // Ununsed (or effectively unused) parameters
+    //
+    // Simple callee analysis may overstate inline benefit
+
+    static long F20(long x)
+    {
+        return 100;
+    }
+
+    static bool Bench20p()
+    {
+        long t = 10;
+        long f = F20(t);
+        return (f == 100);
+    }
+
+    static bool Bench20p1()
+    {
+        long t = Ten;
+        long f = F20(t);
+        return (f == 100);
+    }
+
+    static long F21(long x)
+    {
+        return -x + 100 + x;
+    }
+
+    static bool Bench21p()
+    {
+        long t = 10;
+        long f = F21(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n()
+    {
+        long t = Ten;
+        long f = F21(t);
+        return (f == 100);
+    }
+
+    static long F211(long x)
+    {
+        return x - x + 100;
+    }
+
+    static bool Bench21p1()
+    {
+        long t = 10;
+        long f = F211(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n1()
+    {
+        long t = Ten;
+        long f = F211(t);
+        return (f == 100);
+    }
+
+    static long F22(long x)
+    {
+        if (x > 0)
+        {
+            return 100;
+        }
+
+        return 100;
+    }
+
+    static bool Bench22p()
+    {
+        long t = 10;
+        long f = F22(t);
+        return (f == 100);
+    }
+
+    static bool Bench22p1()
+    {
+        long t = Ten;
+        long f = F22(t);
+        return (f == 100);
+    }
+
+    static long F23(long x)
+    {
+        if (x > 0)
+        {
+            return 90 + x;
+        }
+
+        return 100;
+    }
+
+    static bool Bench23p()
+    {
+        long t = 10;
+        long f = F23(t);
+        return (f == 100);
+    }
+
+    static bool Bench23n()
+    {
+        long t = Ten;
+        long f = F23(t);
+        return (f == 100);
+    }
+
+    // Multiple parameters
+
+    static long F30(long x, long y)
+    {
+        return y * y;
+    }
+
+    static bool Bench30p()
+    {
+        long t = 10;
+        long f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n()
+    {
+        long t = Ten;
+        long f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p1()
+    {
+        long s = Ten;
+        long t = 10;
+        long f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n1()
+    {
+        long s = 10;
+        long t = Ten;
+        long f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p2()
+    {
+        long s = 10;
+        long t = 10;
+        long f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n2()
+    {
+        long s = Ten;
+        long t = Ten;
+        long f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p3()
+    {
+        long s = 10;
+        long t = s;
+        long f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n3()
+    {
+        long s = Ten;
+        long t = s;
+        long f = F30(s, t);
+        return (f == 100);
+    }
+
+    static long F31(long x, long y, long z)
+    {
+        return z * z;
+    }
+
+    static bool Bench31p()
+    {
+        long t = 10;
+        long f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n()
+    {
+        long t = Ten;
+        long f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p1()
+    {
+        long r = Ten;
+        long s = Ten;
+        long t = 10;
+        long f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n1()
+    {
+        long r = 10;
+        long s = 10;
+        long t = Ten;
+        long f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p2()
+    {
+        long r = 10;
+        long s = 10;
+        long t = 10;
+        long f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n2()
+    {
+        long r = Ten;
+        long s = Ten;
+        long t = Ten;
+        long f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p3()
+    {
+        long r = 10;
+        long s = r;
+        long t = s;
+        long f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n3()
+    {
+        long r = Ten;
+        long s = r;
+        long t = s;
+        long f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    // Two args, both used
+
+    static long F40(long x, long y)
+    {
+        return x * x + y * y - 100;
+    }
+
+    static bool Bench40p()
+    {
+        long t = 10;
+        long f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40n()
+    {
+        long t = Ten;
+        long f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p1()
+    {
+        long s = Ten;
+        long t = 10;
+        long f = F40(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p2()
+    {
+        long s = 10;
+        long t = Ten;
+        long f = F40(s, t);
+        return (f == 100);
+    }
+
+    static long F41(long x, long y)
+    {
+        return x * y;
+    }
+
+    static bool Bench41p()
+    {
+        long t = 10;
+        long f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41n()
+    {
+        long t = Ten;
+        long f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p1()
+    {
+        long s = 10;
+        long t = Ten;
+        long f = F41(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p2()
+    {
+        long s = Ten;
+        long t = 10;
+        long f = F41(s, t);
+        return (f == 100);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench00p1", "Bench00n1",
+        "Bench00p2", "Bench00n2",
+        "Bench00p3", "Bench00n3",
+        "Bench00p4", "Bench00n4",
+        "Bench01p",  "Bench01n",
+        "Bench02p",  "Bench02n",
+        "Bench03p",  "Bench03n",
+        "Bench04p",  "Bench04n",
+        "Bench05p",  "Bench05n",
+        "Bench05p1", "Bench05n1",
+        "Bench06p",  "Bench06n",
+        "Bench07p",  "Bench07n",
+        "Bench07p1", "Bench07n1",
+        "Bench08p",  "Bench08n",
+        "Bench09p",  "Bench09n",
+        "Bench10p",  "Bench10n",
+        "Bench10p1", "Bench10n1",
+        "Bench10p2", "Bench10n2",
+        "Bench10p3", "Bench10n3",
+        "Bench11p",  "Bench11n",
+        "Bench11p1", "Bench11n1",
+        "Bench11p2", "Bench11n2",
+        "Bench11p3", "Bench11n3",
+        "Bench20p",  "Bench20p1",
+        "Bench21p",  "Bench21n",
+        "Bench21p1", "Bench21n1",
+        "Bench22p",  "Bench22p1",
+        "Bench23p",  "Bench23n",
+        "Bench30p",  "Bench30n",
+        "Bench30p1", "Bench30n1",
+        "Bench30p2", "Bench30n2",
+        "Bench30p3", "Bench30n3",
+        "Bench31p",  "Bench31n",
+        "Bench31p1", "Bench31n1",
+        "Bench31p2", "Bench31n2",
+        "Bench31p3", "Bench31n3",
+        "Bench40p",  "Bench40n",
+        "Bench40p1", "Bench40p2",
+        "Bench41p",  "Bench41n",
+        "Bench41p1", "Bench41p2"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsLong).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.csproj
new file mode 100644 (file)
index 0000000..b4cfab2
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsLong.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.cs
new file mode 100644 (file)
index 0000000..b329122
--- /dev/null
@@ -0,0 +1,930 @@
+// 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 Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsSByte
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Sbytes feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static sbyte Five = 5;
+    static sbyte Ten = 10;
+
+    static sbyte Id(sbyte x)
+    {
+        return x;
+    }
+
+    static sbyte F00(sbyte x)
+    {
+        return (sbyte) (x * x);
+    }
+
+    static bool Bench00p()
+    {
+        sbyte t = 10;
+        sbyte f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n()
+    {
+        sbyte t = Ten;
+        sbyte f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p1()
+    {
+        sbyte t = Id(10);
+        sbyte f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n1()
+    {
+        sbyte t = Id(Ten);
+        sbyte f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p2()
+    {
+        sbyte t = Id(10);
+        sbyte f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00n2()
+    {
+        sbyte t = Id(Ten);
+        sbyte f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00p3()
+    {
+        sbyte t = 10;
+        sbyte f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00n3()
+    {
+        sbyte t = Ten;
+        sbyte f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00p4()
+    {
+        sbyte t = 5;
+        sbyte f = F00((sbyte)(2 * t));
+        return (f == 100);
+    }
+
+    static bool Bench00n4()
+    {
+        sbyte t = Five;
+        sbyte f = F00((sbyte)(2 * t));
+        return (f == 100);
+    }
+
+    static sbyte F01(sbyte x)
+    {
+        return (sbyte)(1000 / x);
+    }
+
+    static bool Bench01p()
+    {
+        sbyte t = 10;
+        sbyte f = F01(t);
+        return (f == 100);
+    }
+
+    static bool Bench01n()
+    {
+        sbyte t = Ten;
+        sbyte f = F01(t);
+        return (f == 100);
+    }
+
+    static sbyte F02(sbyte x)
+    {
+        return (sbyte) (20 * (x / 2));
+    }
+
+    static bool Bench02p()
+    {
+        sbyte t = 10;
+        sbyte f = F02(t);
+        return (f == 100);
+    }
+
+    static bool Bench02n()
+    {
+        sbyte t = Ten;
+        sbyte f = F02(t);
+        return (f == 100);
+    }
+
+    static sbyte F03(sbyte x)
+    {
+        return (sbyte)(91 + 1009 % x);
+    }
+
+    static bool Bench03p()
+    {
+        sbyte t = 10;
+        sbyte f = F03(t);
+        return (f == 100);
+    }
+
+    static bool Bench03n()
+    {
+        sbyte t = Ten;
+        sbyte f = F03(t);
+        return (f == 100);
+    }
+
+    static sbyte F04(sbyte x)
+    {
+        return (sbyte)(50 * (x % 4));
+    }
+
+    static bool Bench04p()
+    {
+        sbyte t = 10;
+        sbyte f = F04(t);
+        return (f == 100);
+    }
+
+    static bool Bench04n()
+    {
+        sbyte t = Ten;
+        sbyte f = F04(t);
+        return (f == 100);
+    }
+
+    static sbyte F05(sbyte x)
+    {
+        return (sbyte)((1 << x) - 924);
+    }
+
+    static bool Bench05p()
+    {
+        sbyte t = 10;
+        sbyte f = F05(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n()
+    {
+        sbyte t = Ten;
+        sbyte f = F05(t);
+        return (f == 100);
+    }
+
+    static sbyte F051(sbyte x)
+    {
+        return (sbyte)(102400 >> x);
+    }
+
+    static bool Bench05p1()
+    {
+        sbyte t = 10;
+        sbyte f = F051(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n1()
+    {
+        sbyte t = Ten;
+        sbyte f = F051(t);
+        return (f == 100);
+    }
+
+    static sbyte F06(sbyte x)
+    {
+        return (sbyte)(-x + 110);
+    }
+
+    static bool Bench06p()
+    {
+        sbyte t = 10;
+        sbyte f = F06(t);
+        return (f == 100);
+    }
+
+    static bool Bench06n()
+    {
+        sbyte t = Ten;
+        sbyte f = F06(t);
+        return (f == 100);
+    }
+
+    static sbyte F07(sbyte x)
+    {
+        return (sbyte)(~x + 111);
+    }
+
+    static bool Bench07p()
+    {
+        sbyte t = 10;
+        sbyte f = F07(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n()
+    {
+        sbyte t = Ten;
+        sbyte f = F07(t);
+        return (f == 100);
+    }
+
+    static sbyte F071(sbyte x)
+    {
+        return (sbyte)((x ^ -1) + 111);
+    }
+
+    static bool Bench07p1()
+    {
+        sbyte t = 10;
+        sbyte f = F071(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n1()
+    {
+        sbyte t = Ten;
+        sbyte f = F071(t);
+        return (f == 100);
+    }
+
+    static sbyte F08(sbyte x)
+    {
+        return (sbyte)((x & 0x7) + 98);
+    }
+
+    static bool Bench08p()
+    {
+        sbyte t = 10;
+        sbyte f = F08(t);
+        return (f == 100);
+    }
+
+    static bool Bench08n()
+    {
+        sbyte t = Ten;
+        sbyte f = F08(t);
+        return (f == 100);
+    }
+
+    static sbyte F09(sbyte x)
+    {
+        return (sbyte)((x | 0x7) + 85);
+    }
+
+    static bool Bench09p()
+    {
+        sbyte t = 10;
+        sbyte f = F09(t);
+        return (f == 100);
+    }
+
+    static bool Bench09n()
+    {
+        sbyte t = Ten;
+        sbyte f = F09(t);
+        return (f == 100);
+    }
+
+    // Sbytes feeding comparisons.
+    //
+    // Inlining in Bench1xp should enable branch optimization
+    // Inlining in Bench1xn will not enable branch optimization
+
+    static sbyte F10(sbyte x)
+    {
+        return x == 10 ? (sbyte) 100 : (sbyte) 0;
+    }
+
+    static bool Bench10p()
+    {
+        sbyte t = 10;
+        sbyte f = F10(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n()
+    {
+        sbyte t = Ten;
+        sbyte f = F10(t);
+        return (f == 100);
+    }
+
+    static sbyte F101(sbyte x)
+    {
+        return x != 10 ? (sbyte) 0 : (sbyte) 100;
+    }
+
+    static bool Bench10p1()
+    {
+        sbyte t = 10;
+        sbyte f = F101(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n1()
+    {
+        sbyte t = Ten;
+        sbyte f = F101(t);
+        return (f == 100);
+    }
+
+    static sbyte F102(sbyte x)
+    {
+        return x >= 10 ? (sbyte) 100 : (sbyte) 0;
+    }
+
+    static bool Bench10p2()
+    {
+        sbyte t = 10;
+        sbyte f = F102(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n2()
+    {
+        sbyte t = Ten;
+        sbyte f = F102(t);
+        return (f == 100);
+    }
+
+    static sbyte F103(sbyte x)
+    {
+        return x <= 10 ? (sbyte) 100 : (sbyte) 0;
+    }
+
+    static bool Bench10p3()
+    {
+        sbyte t = 10;
+        sbyte f = F103(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n3()
+    {
+        sbyte t = Ten;
+        sbyte f = F102(t);
+        return (f == 100);
+    }
+
+    static sbyte F11(sbyte x)
+    {
+        if (x == 10)
+        {
+            return 100;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    static bool Bench11p()
+    {
+        sbyte t = 10;
+        sbyte f = F11(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n()
+    {
+        sbyte t = Ten;
+        sbyte f = F11(t);
+        return (f == 100);
+    }
+
+    static sbyte F111(sbyte x)
+    {
+        if (x != 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p1()
+    {
+        sbyte t = 10;
+        sbyte f = F111(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n1()
+    {
+        sbyte t = Ten;
+        sbyte f = F111(t);
+        return (f == 100);
+    }
+
+    static sbyte F112(sbyte x)
+    {
+        if (x > 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p2()
+    {
+        sbyte t = 10;
+        sbyte f = F112(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n2()
+    {
+        sbyte t = Ten;
+        sbyte f = F112(t);
+        return (f == 100);
+    }
+    static sbyte F113(sbyte x)
+    {
+        if (x < 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p3()
+    {
+        sbyte t = 10;
+        sbyte f = F113(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n3()
+    {
+        sbyte t = Ten;
+        sbyte f = F113(t);
+        return (f == 100);
+    }
+
+    // Ununsed (or effectively unused) parameters
+    //
+    // Simple callee analysis may overstate inline benefit
+
+    static sbyte F20(sbyte x)
+    {
+        return 100;
+    }
+
+    static bool Bench20p()
+    {
+        sbyte t = 10;
+        sbyte f = F20(t);
+        return (f == 100);
+    }
+
+    static bool Bench20p1()
+    {
+        sbyte t = Ten;
+        sbyte f = F20(t);
+        return (f == 100);
+    }
+
+    static sbyte F21(sbyte x)
+    {
+        return (sbyte)(-x + 100 + x);
+    }
+
+    static bool Bench21p()
+    {
+        sbyte t = 10;
+        sbyte f = F21(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n()
+    {
+        sbyte t = Ten;
+        sbyte f = F21(t);
+        return (f == 100);
+    }
+
+    static sbyte F211(sbyte x)
+    {
+        return (sbyte)(x - x + 100);
+    }
+
+    static bool Bench21p1()
+    {
+        sbyte t = 10;
+        sbyte f = F211(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n1()
+    {
+        sbyte t = Ten;
+        sbyte f = F211(t);
+        return (f == 100);
+    }
+
+    static sbyte F22(sbyte x)
+    {
+        if (x > 0)
+        {
+            return 100;
+        }
+
+        return 100;
+    }
+
+    static bool Bench22p()
+    {
+        sbyte t = 10;
+        sbyte f = F22(t);
+        return (f == 100);
+    }
+
+    static bool Bench22p1()
+    {
+        sbyte t = Ten;
+        sbyte f = F22(t);
+        return (f == 100);
+    }
+
+    static sbyte F23(sbyte x)
+    {
+        if (x > 0)
+        {
+            return (sbyte)(90 + x);
+        }
+
+        return 100;
+    }
+
+    static bool Bench23p()
+    {
+        sbyte t = 10;
+        sbyte f = F23(t);
+        return (f == 100);
+    }
+
+    static bool Bench23n()
+    {
+        sbyte t = Ten;
+        sbyte f = F23(t);
+        return (f == 100);
+    }
+
+    // Multiple parameters
+
+    static sbyte F30(sbyte x, sbyte y)
+    {
+        return (sbyte)(y * y);
+    }
+
+    static bool Bench30p()
+    {
+        sbyte t = 10;
+        sbyte f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n()
+    {
+        sbyte t = Ten;
+        sbyte f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p1()
+    {
+        sbyte s = Ten;
+        sbyte t = 10;
+        sbyte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n1()
+    {
+        sbyte s = 10;
+        sbyte t = Ten;
+        sbyte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p2()
+    {
+        sbyte s = 10;
+        sbyte t = 10;
+        sbyte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n2()
+    {
+        sbyte s = Ten;
+        sbyte t = Ten;
+        sbyte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p3()
+    {
+        sbyte s = 10;
+        sbyte t = s;
+        sbyte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n3()
+    {
+        sbyte s = Ten;
+        sbyte t = s;
+        sbyte f = F30(s, t);
+        return (f == 100);
+    }
+
+    static sbyte F31(sbyte x, sbyte y, sbyte z)
+    {
+        return (sbyte)(z * z);
+    }
+
+    static bool Bench31p()
+    {
+        sbyte t = 10;
+        sbyte f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n()
+    {
+        sbyte t = Ten;
+        sbyte f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p1()
+    {
+        sbyte r = Ten;
+        sbyte s = Ten;
+        sbyte t = 10;
+        sbyte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n1()
+    {
+        sbyte r = 10;
+        sbyte s = 10;
+        sbyte t = Ten;
+        sbyte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p2()
+    {
+        sbyte r = 10;
+        sbyte s = 10;
+        sbyte t = 10;
+        sbyte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n2()
+    {
+        sbyte r = Ten;
+        sbyte s = Ten;
+        sbyte t = Ten;
+        sbyte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p3()
+    {
+        sbyte r = 10;
+        sbyte s = r;
+        sbyte t = s;
+        sbyte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n3()
+    {
+        sbyte r = Ten;
+        sbyte s = r;
+        sbyte t = s;
+        sbyte f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    // Two args, both used
+
+    static sbyte F40(sbyte x, sbyte y)
+    {
+        return (sbyte)(x * x + y * y - 100);
+    }
+
+    static bool Bench40p()
+    {
+        sbyte t = 10;
+        sbyte f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40n()
+    {
+        sbyte t = Ten;
+        sbyte f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p1()
+    {
+        sbyte s = Ten;
+        sbyte t = 10;
+        sbyte f = F40(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p2()
+    {
+        sbyte s = 10;
+        sbyte t = Ten;
+        sbyte f = F40(s, t);
+        return (f == 100);
+    }
+
+    static sbyte F41(sbyte x, sbyte y)
+    {
+        return (sbyte)(x * y);
+    }
+
+    static bool Bench41p()
+    {
+        sbyte t = 10;
+        sbyte f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41n()
+    {
+        sbyte t = Ten;
+        sbyte f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p1()
+    {
+        sbyte s = 10;
+        sbyte t = Ten;
+        sbyte f = F41(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p2()
+    {
+        sbyte s = Ten;
+        sbyte t = 10;
+        sbyte f = F41(s, t);
+        return (f == 100);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench00p1", "Bench00n1",
+        "Bench00p2", "Bench00n2",
+        "Bench00p3", "Bench00n3",
+        "Bench00p4", "Bench00n4",
+        "Bench01p",  "Bench01n",
+        "Bench02p",  "Bench02n",
+        "Bench03p",  "Bench03n",
+        "Bench04p",  "Bench04n",
+        "Bench05p",  "Bench05n",
+        "Bench05p1", "Bench05n1",
+        "Bench06p",  "Bench06n",
+        "Bench07p",  "Bench07n",
+        "Bench07p1", "Bench07n1",
+        "Bench08p",  "Bench08n",
+        "Bench09p",  "Bench09n",
+        "Bench10p",  "Bench10n",
+        "Bench10p1", "Bench10n1",
+        "Bench10p2", "Bench10n2",
+        "Bench10p3", "Bench10n3",
+        "Bench11p",  "Bench11n",
+        "Bench11p1", "Bench11n1",
+        "Bench11p2", "Bench11n2",
+        "Bench11p3", "Bench11n3",
+        "Bench20p",  "Bench20p1",
+        "Bench21p",  "Bench21n",
+        "Bench21p1", "Bench21n1",
+        "Bench22p",  "Bench22p1",
+        "Bench23p",  "Bench23n",
+        "Bench30p",  "Bench30n",
+        "Bench30p1", "Bench30n1",
+        "Bench30p2", "Bench30n2",
+        "Bench30p3", "Bench30n3",
+        "Bench31p",  "Bench31n",
+        "Bench31p1", "Bench31n1",
+        "Bench31p2", "Bench31n2",
+        "Bench31p3", "Bench31n3",
+        "Bench40p",  "Bench40n",
+        "Bench40p1", "Bench40p2",
+        "Bench41p",  "Bench41n",
+        "Bench41p1", "Bench41p2"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsSByte).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.csproj
new file mode 100644 (file)
index 0000000..22268de
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsSByte.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.cs
new file mode 100644 (file)
index 0000000..8718111
--- /dev/null
@@ -0,0 +1,930 @@
+// 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 Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsShort
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Shorts feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static short Five = 5;
+    static short Ten = 10;
+
+    static short Id(short x)
+    {
+        return x;
+    }
+
+    static short F00(short x)
+    {
+        return (short) (x * x);
+    }
+
+    static bool Bench00p()
+    {
+        short t = 10;
+        short f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n()
+    {
+        short t = Ten;
+        short f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p1()
+    {
+        short t = Id(10);
+        short f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n1()
+    {
+        short t = Id(Ten);
+        short f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p2()
+    {
+        short t = Id(10);
+        short f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00n2()
+    {
+        short t = Id(Ten);
+        short f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00p3()
+    {
+        short t = 10;
+        short f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00n3()
+    {
+        short t = Ten;
+        short f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00p4()
+    {
+        short t = 5;
+        short f = F00((short)(2 * t));
+        return (f == 100);
+    }
+
+    static bool Bench00n4()
+    {
+        short t = Five;
+        short f = F00((short)(2 * t));
+        return (f == 100);
+    }
+
+    static short F01(short x)
+    {
+        return (short)(1000 / x);
+    }
+
+    static bool Bench01p()
+    {
+        short t = 10;
+        short f = F01(t);
+        return (f == 100);
+    }
+
+    static bool Bench01n()
+    {
+        short t = Ten;
+        short f = F01(t);
+        return (f == 100);
+    }
+
+    static short F02(short x)
+    {
+        return (short) (20 * (x / 2));
+    }
+
+    static bool Bench02p()
+    {
+        short t = 10;
+        short f = F02(t);
+        return (f == 100);
+    }
+
+    static bool Bench02n()
+    {
+        short t = Ten;
+        short f = F02(t);
+        return (f == 100);
+    }
+
+    static short F03(short x)
+    {
+        return (short)(91 + 1009 % x);
+    }
+
+    static bool Bench03p()
+    {
+        short t = 10;
+        short f = F03(t);
+        return (f == 100);
+    }
+
+    static bool Bench03n()
+    {
+        short t = Ten;
+        short f = F03(t);
+        return (f == 100);
+    }
+
+    static short F04(short x)
+    {
+        return (short)(50 * (x % 4));
+    }
+
+    static bool Bench04p()
+    {
+        short t = 10;
+        short f = F04(t);
+        return (f == 100);
+    }
+
+    static bool Bench04n()
+    {
+        short t = Ten;
+        short f = F04(t);
+        return (f == 100);
+    }
+
+    static short F05(short x)
+    {
+        return (short)((1 << x) - 924);
+    }
+
+    static bool Bench05p()
+    {
+        short t = 10;
+        short f = F05(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n()
+    {
+        short t = Ten;
+        short f = F05(t);
+        return (f == 100);
+    }
+
+    static short F051(short x)
+    {
+        return (short)(102400 >> x);
+    }
+
+    static bool Bench05p1()
+    {
+        short t = 10;
+        short f = F051(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n1()
+    {
+        short t = Ten;
+        short f = F051(t);
+        return (f == 100);
+    }
+
+    static short F06(short x)
+    {
+        return (short)(-x + 110);
+    }
+
+    static bool Bench06p()
+    {
+        short t = 10;
+        short f = F06(t);
+        return (f == 100);
+    }
+
+    static bool Bench06n()
+    {
+        short t = Ten;
+        short f = F06(t);
+        return (f == 100);
+    }
+
+    static short F07(short x)
+    {
+        return (short)(~x + 111);
+    }
+
+    static bool Bench07p()
+    {
+        short t = 10;
+        short f = F07(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n()
+    {
+        short t = Ten;
+        short f = F07(t);
+        return (f == 100);
+    }
+
+    static short F071(short x)
+    {
+        return (short)((x ^ -1) + 111);
+    }
+
+    static bool Bench07p1()
+    {
+        short t = 10;
+        short f = F071(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n1()
+    {
+        short t = Ten;
+        short f = F071(t);
+        return (f == 100);
+    }
+
+    static short F08(short x)
+    {
+        return (short)((x & 0x7) + 98);
+    }
+
+    static bool Bench08p()
+    {
+        short t = 10;
+        short f = F08(t);
+        return (f == 100);
+    }
+
+    static bool Bench08n()
+    {
+        short t = Ten;
+        short f = F08(t);
+        return (f == 100);
+    }
+
+    static short F09(short x)
+    {
+        return (short)((x | 0x7) + 85);
+    }
+
+    static bool Bench09p()
+    {
+        short t = 10;
+        short f = F09(t);
+        return (f == 100);
+    }
+
+    static bool Bench09n()
+    {
+        short t = Ten;
+        short f = F09(t);
+        return (f == 100);
+    }
+
+    // Shorts feeding comparisons.
+    //
+    // Inlining in Bench1xp should enable branch optimization
+    // Inlining in Bench1xn will not enable branch optimization
+
+    static short F10(short x)
+    {
+        return x == 10 ? (short) 100 : (short) 0;
+    }
+
+    static bool Bench10p()
+    {
+        short t = 10;
+        short f = F10(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n()
+    {
+        short t = Ten;
+        short f = F10(t);
+        return (f == 100);
+    }
+
+    static short F101(short x)
+    {
+        return x != 10 ? (short) 0 : (short) 100;
+    }
+
+    static bool Bench10p1()
+    {
+        short t = 10;
+        short f = F101(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n1()
+    {
+        short t = Ten;
+        short f = F101(t);
+        return (f == 100);
+    }
+
+    static short F102(short x)
+    {
+        return x >= 10 ? (short) 100 : (short) 0;
+    }
+
+    static bool Bench10p2()
+    {
+        short t = 10;
+        short f = F102(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n2()
+    {
+        short t = Ten;
+        short f = F102(t);
+        return (f == 100);
+    }
+
+    static short F103(short x)
+    {
+        return x <= 10 ? (short) 100 : (short) 0;
+    }
+
+    static bool Bench10p3()
+    {
+        short t = 10;
+        short f = F103(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n3()
+    {
+        short t = Ten;
+        short f = F102(t);
+        return (f == 100);
+    }
+
+    static short F11(short x)
+    {
+        if (x == 10)
+        {
+            return 100;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    static bool Bench11p()
+    {
+        short t = 10;
+        short f = F11(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n()
+    {
+        short t = Ten;
+        short f = F11(t);
+        return (f == 100);
+    }
+
+    static short F111(short x)
+    {
+        if (x != 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p1()
+    {
+        short t = 10;
+        short f = F111(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n1()
+    {
+        short t = Ten;
+        short f = F111(t);
+        return (f == 100);
+    }
+
+    static short F112(short x)
+    {
+        if (x > 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p2()
+    {
+        short t = 10;
+        short f = F112(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n2()
+    {
+        short t = Ten;
+        short f = F112(t);
+        return (f == 100);
+    }
+    static short F113(short x)
+    {
+        if (x < 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p3()
+    {
+        short t = 10;
+        short f = F113(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n3()
+    {
+        short t = Ten;
+        short f = F113(t);
+        return (f == 100);
+    }
+
+    // Ununsed (or effectively unused) parameters
+    //
+    // Simple callee analysis may overstate inline benefit
+
+    static short F20(short x)
+    {
+        return 100;
+    }
+
+    static bool Bench20p()
+    {
+        short t = 10;
+        short f = F20(t);
+        return (f == 100);
+    }
+
+    static bool Bench20p1()
+    {
+        short t = Ten;
+        short f = F20(t);
+        return (f == 100);
+    }
+
+    static short F21(short x)
+    {
+        return (short)(-x + 100 + x);
+    }
+
+    static bool Bench21p()
+    {
+        short t = 10;
+        short f = F21(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n()
+    {
+        short t = Ten;
+        short f = F21(t);
+        return (f == 100);
+    }
+
+    static short F211(short x)
+    {
+        return (short)(x - x + 100);
+    }
+
+    static bool Bench21p1()
+    {
+        short t = 10;
+        short f = F211(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n1()
+    {
+        short t = Ten;
+        short f = F211(t);
+        return (f == 100);
+    }
+
+    static short F22(short x)
+    {
+        if (x > 0)
+        {
+            return 100;
+        }
+
+        return 100;
+    }
+
+    static bool Bench22p()
+    {
+        short t = 10;
+        short f = F22(t);
+        return (f == 100);
+    }
+
+    static bool Bench22p1()
+    {
+        short t = Ten;
+        short f = F22(t);
+        return (f == 100);
+    }
+
+    static short F23(short x)
+    {
+        if (x > 0)
+        {
+            return (short)(90 + x);
+        }
+
+        return 100;
+    }
+
+    static bool Bench23p()
+    {
+        short t = 10;
+        short f = F23(t);
+        return (f == 100);
+    }
+
+    static bool Bench23n()
+    {
+        short t = Ten;
+        short f = F23(t);
+        return (f == 100);
+    }
+
+    // Multiple parameters
+
+    static short F30(short x, short y)
+    {
+        return (short)(y * y);
+    }
+
+    static bool Bench30p()
+    {
+        short t = 10;
+        short f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n()
+    {
+        short t = Ten;
+        short f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p1()
+    {
+        short s = Ten;
+        short t = 10;
+        short f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n1()
+    {
+        short s = 10;
+        short t = Ten;
+        short f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p2()
+    {
+        short s = 10;
+        short t = 10;
+        short f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n2()
+    {
+        short s = Ten;
+        short t = Ten;
+        short f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p3()
+    {
+        short s = 10;
+        short t = s;
+        short f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n3()
+    {
+        short s = Ten;
+        short t = s;
+        short f = F30(s, t);
+        return (f == 100);
+    }
+
+    static short F31(short x, short y, short z)
+    {
+        return (short)(z * z);
+    }
+
+    static bool Bench31p()
+    {
+        short t = 10;
+        short f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n()
+    {
+        short t = Ten;
+        short f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p1()
+    {
+        short r = Ten;
+        short s = Ten;
+        short t = 10;
+        short f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n1()
+    {
+        short r = 10;
+        short s = 10;
+        short t = Ten;
+        short f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p2()
+    {
+        short r = 10;
+        short s = 10;
+        short t = 10;
+        short f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n2()
+    {
+        short r = Ten;
+        short s = Ten;
+        short t = Ten;
+        short f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p3()
+    {
+        short r = 10;
+        short s = r;
+        short t = s;
+        short f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n3()
+    {
+        short r = Ten;
+        short s = r;
+        short t = s;
+        short f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    // Two args, both used
+
+    static short F40(short x, short y)
+    {
+        return (short)(x * x + y * y - 100);
+    }
+
+    static bool Bench40p()
+    {
+        short t = 10;
+        short f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40n()
+    {
+        short t = Ten;
+        short f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p1()
+    {
+        short s = Ten;
+        short t = 10;
+        short f = F40(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p2()
+    {
+        short s = 10;
+        short t = Ten;
+        short f = F40(s, t);
+        return (f == 100);
+    }
+
+    static short F41(short x, short y)
+    {
+        return (short)(x * y);
+    }
+
+    static bool Bench41p()
+    {
+        short t = 10;
+        short f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41n()
+    {
+        short t = Ten;
+        short f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p1()
+    {
+        short s = 10;
+        short t = Ten;
+        short f = F41(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p2()
+    {
+        short s = Ten;
+        short t = 10;
+        short f = F41(s, t);
+        return (f == 100);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench00p1", "Bench00n1",
+        "Bench00p2", "Bench00n2",
+        "Bench00p3", "Bench00n3",
+        "Bench00p4", "Bench00n4",
+        "Bench01p",  "Bench01n",
+        "Bench02p",  "Bench02n",
+        "Bench03p",  "Bench03n",
+        "Bench04p",  "Bench04n",
+        "Bench05p",  "Bench05n",
+        "Bench05p1", "Bench05n1",
+        "Bench06p",  "Bench06n",
+        "Bench07p",  "Bench07n",
+        "Bench07p1", "Bench07n1",
+        "Bench08p",  "Bench08n",
+        "Bench09p",  "Bench09n",
+        "Bench10p",  "Bench10n",
+        "Bench10p1", "Bench10n1",
+        "Bench10p2", "Bench10n2",
+        "Bench10p3", "Bench10n3",
+        "Bench11p",  "Bench11n",
+        "Bench11p1", "Bench11n1",
+        "Bench11p2", "Bench11n2",
+        "Bench11p3", "Bench11n3",
+        "Bench20p",  "Bench20p1",
+        "Bench21p",  "Bench21n",
+        "Bench21p1", "Bench21n1",
+        "Bench22p",  "Bench22p1",
+        "Bench23p",  "Bench23n",
+        "Bench30p",  "Bench30n",
+        "Bench30p1", "Bench30n1",
+        "Bench30p2", "Bench30n2",
+        "Bench30p3", "Bench30n3",
+        "Bench31p",  "Bench31n",
+        "Bench31p1", "Bench31n1",
+        "Bench31p2", "Bench31n2",
+        "Bench31p3", "Bench31n3",
+        "Bench40p",  "Bench40n",
+        "Bench40p1", "Bench40p2",
+        "Bench41p",  "Bench41n",
+        "Bench41p1", "Bench41p2"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsShort).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.csproj
new file mode 100644 (file)
index 0000000..4f5db4c
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsShort.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.cs
new file mode 100644 (file)
index 0000000..b731908
--- /dev/null
@@ -0,0 +1,330 @@
+// 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.
+
+// Strings are the only ref class where there is built-in support for
+// constant objects.
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsString
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Ints feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static string Ten = "Ten";
+    static string Five = "Five";
+
+    static string Id(string x)
+    {
+        return x;
+    }
+
+    static char F00(string x)
+    {
+        return x[0];
+    }
+
+    static bool Bench00p()
+    {
+        string t = "Ten";
+        char f = F00(t);
+        return (f == 'T');
+    }
+
+    static bool Bench00n()
+    {
+        string t = Ten;
+        char f = F00(t);
+        return (f == 'T');
+    }
+
+    static int F01(string x)
+    {
+        return x.Length;
+    }
+
+    static bool Bench01p()
+    {
+        string t = "Ten";
+        int f = F01(t);
+        return (f == 3);
+    }
+
+    static bool Bench01n()
+    {
+        string t = Ten;
+        int f = F01(t);
+        return (f == 3);
+    }
+
+    static bool Bench01p1()
+    {
+        return "Ten".Length == 3;
+    }
+
+    static bool Bench01n1()
+    {
+        return Ten.Length == 3;
+    }
+
+    static bool Bench02p()
+    {
+        return "Ten".Equals("Ten", StringComparison.Ordinal);
+    }
+
+    static bool Bench02n()
+    {
+        return "Ten".Equals(Ten, StringComparison.Ordinal);
+    }
+
+    static bool Bench02n1()
+    {
+        return Ten.Equals("Ten", StringComparison.Ordinal);
+    }
+
+    static bool Bench02n2()
+    {
+        return Ten.Equals(Ten, StringComparison.Ordinal);
+    }
+
+    static bool Bench03p()
+    {
+        return "Ten" == "Ten";
+    }
+
+    static bool Bench03n()
+    {
+        return "Ten" == Ten;
+    }
+
+    static bool Bench03n1()
+    {
+        return Ten == "Ten";
+    }
+
+    static bool Bench03n2()
+    {
+        return Ten == Ten;
+    }
+
+    static bool Bench04p()
+    {
+        return "Ten" != "Five";
+    }
+
+    static bool Bench04n()
+    {
+        return "Ten" != Five;
+    }
+
+    static bool Bench04n1()
+    {
+        return Ten != "Five";
+    }
+
+    static bool Bench04n2()
+    {
+        return Ten != Five;
+    }
+
+    static bool Bench05p()
+    {
+        string t = "Ten";
+        return (t == t);
+    }
+
+    static bool Bench05n()
+    {
+        string t = Ten;
+        return (t == t);
+    }
+
+    static bool Bench06p()
+    {
+        return "Ten" != null;
+    }
+
+    static bool Bench06n()
+    {
+        return Ten != null;
+    }
+
+    static bool Bench07p()
+    {
+        return !"Ten".Equals(null);
+    }
+
+    static bool Bench07n()
+    {
+        return !Ten.Equals(null);
+    }
+
+    static bool Bench08p()
+    {
+        return !"Ten".Equals("Five", StringComparison.Ordinal);
+    }
+
+    static bool Bench08n()
+    {
+        return !"Ten".Equals(Five, StringComparison.Ordinal);
+    }
+
+    static bool Bench08n1()
+    {
+        return !Ten.Equals("Five", StringComparison.Ordinal);
+    }
+
+    static bool Bench08n2()
+    {
+        return !Ten.Equals(Five, StringComparison.Ordinal);
+    }
+
+    static bool Bench09p()
+    {
+        return string.Equals("Ten", "Ten");
+    }
+
+    static bool Bench09n()
+    {
+        return string.Equals("Ten", Ten);
+    }
+
+    static bool Bench09n1()
+    {
+        return string.Equals(Ten, "Ten");
+    }
+
+    static bool Bench09n2()
+    {
+        return string.Equals(Ten, Ten);
+    }
+
+    static bool Bench10p()
+    {
+        return !string.Equals("Five", "Ten");
+    }
+
+    static bool Bench10n()
+    {
+        return !string.Equals(Five, "Ten");
+    }
+
+    static bool Bench10n1()
+    {
+        return !string.Equals("Five", Ten);
+    }
+
+    static bool Bench10n2()
+    {
+        return !string.Equals(Five, Ten);
+    }
+
+    static bool Bench11p()
+    {
+        return !string.Equals("Five", null);
+    }
+
+    static bool Bench11n()
+    {
+        return !string.Equals(Five, null);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench01p",  "Bench01n",
+        "Bench01p1", "Bench01n1",
+        "Bench02p",  "Bench02n",
+        "Bench02n1", "Bench02n2",
+        "Bench03p",  "Bench03n",
+        "Bench03n1", "Bench03n2",
+        "Bench04p",  "Bench04n",
+        "Bench04n1", "Bench04n2",
+        "Bench05p",  "Bench05n",
+        "Bench06p",  "Bench06n",
+        "Bench07p",  "Bench07n",
+        "Bench08p",  "Bench08n",
+        "Bench08n1", "Bench08n2",
+        "Bench09p",  "Bench09n",
+        "Bench09n1", "Bench09n2",
+        "Bench10p",  "Bench10n",
+        "Bench10n1", "Bench10n2",
+        "Bench11p",  "Bench11n"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsString).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.csproj
new file mode 100644 (file)
index 0000000..8dbc993
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsString.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.cs
new file mode 100644 (file)
index 0000000..db3316e
--- /dev/null
@@ -0,0 +1,890 @@
+// 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 Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsUInt
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Ints feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static uint Five = 5;
+    static uint Ten = 10;
+
+    static uint Id(uint x)
+    {
+        return x;
+    }
+
+    static uint F00(uint x)
+    {
+        return x * x;
+    }
+
+    static bool Bench00p()
+    {
+        uint t = 10;
+        uint f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n()
+    {
+        uint t = Ten;
+        uint f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p1()
+    {
+        uint t = Id(10);
+        uint f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n1()
+    {
+        uint t = Id(Ten);
+        uint f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p2()
+    {
+        uint t = Id(10);
+        uint f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00n2()
+    {
+        uint t = Id(Ten);
+        uint f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00p3()
+    {
+        uint t = 10;
+        uint f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00n3()
+    {
+        uint t = Ten;
+        uint f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00p4()
+    {
+        uint t = 5;
+        uint f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static bool Bench00n4()
+    {
+        uint t = Five;
+        uint f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static uint F01(uint x)
+    {
+        return 1000 / x;
+    }
+
+    static bool Bench01p()
+    {
+        uint t = 10;
+        uint f = F01(t);
+        return (f == 100);
+    }
+
+    static bool Bench01n()
+    {
+        uint t = Ten;
+        uint f = F01(t);
+        return (f == 100);
+    }
+
+    static uint F02(uint x)
+    {
+        return 20 * (x / 2);
+    }
+
+    static bool Bench02p()
+    {
+        uint t = 10;
+        uint f = F02(t);
+        return (f == 100);
+    }
+
+    static bool Bench02n()
+    {
+        uint t = Ten;
+        uint f = F02(t);
+        return (f == 100);
+    }
+
+    static uint F03(uint x)
+    {
+        return 91 + 1009 % x;
+    }
+
+    static bool Bench03p()
+    {
+        uint t = 10;
+        uint f = F03(t);
+        return (f == 100);
+    }
+
+    static bool Bench03n()
+    {
+        uint t = Ten;
+        uint f = F03(t);
+        return (f == 100);
+    }
+
+    static uint F04(uint x)
+    {
+        return 50 * (x % 4);
+    }
+
+    static bool Bench04p()
+    {
+        uint t = 10;
+        uint f = F04(t);
+        return (f == 100);
+    }
+
+    static bool Bench04n()
+    {
+        uint t = Ten;
+        uint f = F04(t);
+        return (f == 100);
+    }
+
+    static uint F06(uint x)
+    {
+        return 110 - x;
+    }
+
+    static bool Bench06p()
+    {
+        uint t = 10;
+        uint f = F06(t);
+        return (f == 100);
+    }
+
+    static bool Bench06n()
+    {
+        uint t = Ten;
+        uint f = F06(t);
+        return (f == 100);
+    }
+
+    static uint F07(uint x)
+    {
+        return ~x + 111;
+    }
+
+    static bool Bench07p()
+    {
+        uint t = 10;
+        uint f = F07(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n()
+    {
+        uint t = Ten;
+        uint f = F07(t);
+        return (f == 100);
+    }
+
+    static uint F071(uint x)
+    {
+        return (x ^ 0xFFFFFFFF) + 111;
+    }
+
+    static bool Bench07p1()
+    {
+        uint t = 10;
+        uint f = F071(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n1()
+    {
+        uint t = Ten;
+        uint f = F071(t);
+        return (f == 100);
+    }
+
+    static uint F08(uint x)
+    {
+        return (x & 0x7) + 98;
+    }
+
+    static bool Bench08p()
+    {
+        uint t = 10;
+        uint f = F08(t);
+        return (f == 100);
+    }
+
+    static bool Bench08n()
+    {
+        uint t = Ten;
+        uint f = F08(t);
+        return (f == 100);
+    }
+
+    static uint F09(uint x)
+    {
+        return (x | 0x7) + 85;
+    }
+
+    static bool Bench09p()
+    {
+        uint t = 10;
+        uint f = F09(t);
+        return (f == 100);
+    }
+
+    static bool Bench09n()
+    {
+        uint t = Ten;
+        uint f = F09(t);
+        return (f == 100);
+    }
+
+    // Uints feeding comparisons.
+    //
+    // Inlining in Bench1xp should enable branch optimization
+    // Inlining in Bench1xn will not enable branch optimization
+
+    static uint F10(uint x)
+    {
+        return x == 10 ? 100u : 0u;
+    }
+
+    static bool Bench10p()
+    {
+        uint t = 10;
+        uint f = F10(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n()
+    {
+        uint t = Ten;
+        uint f = F10(t);
+        return (f == 100);
+    }
+
+    static uint F101(uint x)
+    {
+        return x != 10 ? 0u : 100u;
+    }
+
+    static bool Bench10p1()
+    {
+        uint t = 10;
+        uint f = F101(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n1()
+    {
+        uint t = Ten;
+        uint f = F101(t);
+        return (f == 100);
+    }
+
+    static uint F102(uint x)
+    {
+        return x >= 10 ? 100u : 0u;
+    }
+
+    static bool Bench10p2()
+    {
+        uint t = 10;
+        uint f = F102(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n2()
+    {
+        uint t = Ten;
+        uint f = F102(t);
+        return (f == 100);
+    }
+
+    static uint F103(uint x)
+    {
+        return x <= 10 ? 100u : 0u;
+    }
+
+    static bool Bench10p3()
+    {
+        uint t = 10;
+        uint f = F103(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n3()
+    {
+        uint t = Ten;
+        uint f = F102(t);
+        return (f == 100);
+    }
+
+    static uint F11(uint x)
+    {
+        if (x == 10)
+        {
+            return 100;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    static bool Bench11p()
+    {
+        uint t = 10;
+        uint f = F11(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n()
+    {
+        uint t = Ten;
+        uint f = F11(t);
+        return (f == 100);
+    }
+
+    static uint F111(uint x)
+    {
+        if (x != 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p1()
+    {
+        uint t = 10;
+        uint f = F111(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n1()
+    {
+        uint t = Ten;
+        uint f = F111(t);
+        return (f == 100);
+    }
+
+    static uint F112(uint x)
+    {
+        if (x > 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p2()
+    {
+        uint t = 10;
+        uint f = F112(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n2()
+    {
+        uint t = Ten;
+        uint f = F112(t);
+        return (f == 100);
+    }
+    static uint F113(uint x)
+    {
+        if (x < 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p3()
+    {
+        uint t = 10;
+        uint f = F113(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n3()
+    {
+        uint t = Ten;
+        uint f = F113(t);
+        return (f == 100);
+    }
+
+    // Ununsed (or effectively unused) parameters
+    //
+    // Simple callee analysis may overstate inline benefit
+
+    static uint F20(uint x)
+    {
+        return 100;
+    }
+
+    static bool Bench20p()
+    {
+        uint t = 10;
+        uint f = F20(t);
+        return (f == 100);
+    }
+
+    static bool Bench20p1()
+    {
+        uint t = Ten;
+        uint f = F20(t);
+        return (f == 100);
+    }
+
+    static uint F21(uint x)
+    {
+        return (uint) -x + 100 + x;
+    }
+
+    static bool Bench21p()
+    {
+        uint t = 10;
+        uint f = F21(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n()
+    {
+        uint t = Ten;
+        uint f = F21(t);
+        return (f == 100);
+    }
+
+    static uint F211(uint x)
+    {
+        return x - x + 100;
+    }
+
+    static bool Bench21p1()
+    {
+        uint t = 10;
+        uint f = F211(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n1()
+    {
+        uint t = Ten;
+        uint f = F211(t);
+        return (f == 100);
+    }
+
+    static uint F22(uint x)
+    {
+        if (x > 0)
+        {
+            return 100;
+        }
+
+        return 100;
+    }
+
+    static bool Bench22p()
+    {
+        uint t = 10;
+        uint f = F22(t);
+        return (f == 100);
+    }
+
+    static bool Bench22p1()
+    {
+        uint t = Ten;
+        uint f = F22(t);
+        return (f == 100);
+    }
+
+    static uint F23(uint x)
+    {
+        if (x > 0)
+        {
+            return 90 + x;
+        }
+
+        return 100;
+    }
+
+    static bool Bench23p()
+    {
+        uint t = 10;
+        uint f = F23(t);
+        return (f == 100);
+    }
+
+    static bool Bench23n()
+    {
+        uint t = Ten;
+        uint f = F23(t);
+        return (f == 100);
+    }
+
+    // Multiple parameters
+
+    static uint F30(uint x, uint y)
+    {
+        return y * y;
+    }
+
+    static bool Bench30p()
+    {
+        uint t = 10;
+        uint f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n()
+    {
+        uint t = Ten;
+        uint f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p1()
+    {
+        uint s = Ten;
+        uint t = 10;
+        uint f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n1()
+    {
+        uint s = 10;
+        uint t = Ten;
+        uint f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p2()
+    {
+        uint s = 10;
+        uint t = 10;
+        uint f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n2()
+    {
+        uint s = Ten;
+        uint t = Ten;
+        uint f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p3()
+    {
+        uint s = 10;
+        uint t = s;
+        uint f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n3()
+    {
+        uint s = Ten;
+        uint t = s;
+        uint f = F30(s, t);
+        return (f == 100);
+    }
+
+    static uint F31(uint x, uint y, uint z)
+    {
+        return z * z;
+    }
+
+    static bool Bench31p()
+    {
+        uint t = 10;
+        uint f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n()
+    {
+        uint t = Ten;
+        uint f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p1()
+    {
+        uint r = Ten;
+        uint s = Ten;
+        uint t = 10;
+        uint f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n1()
+    {
+        uint r = 10;
+        uint s = 10;
+        uint t = Ten;
+        uint f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p2()
+    {
+        uint r = 10;
+        uint s = 10;
+        uint t = 10;
+        uint f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n2()
+    {
+        uint r = Ten;
+        uint s = Ten;
+        uint t = Ten;
+        uint f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p3()
+    {
+        uint r = 10;
+        uint s = r;
+        uint t = s;
+        uint f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n3()
+    {
+        uint r = Ten;
+        uint s = r;
+        uint t = s;
+        uint f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    // Two args, both used
+
+    static uint F40(uint x, uint y)
+    {
+        return x * x + y * y - 100;
+    }
+
+    static bool Bench40p()
+    {
+        uint t = 10;
+        uint f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40n()
+    {
+        uint t = Ten;
+        uint f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p1()
+    {
+        uint s = Ten;
+        uint t = 10;
+        uint f = F40(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p2()
+    {
+        uint s = 10;
+        uint t = Ten;
+        uint f = F40(s, t);
+        return (f == 100);
+    }
+
+    static uint F41(uint x, uint y)
+    {
+        return x * y;
+    }
+
+    static bool Bench41p()
+    {
+        uint t = 10;
+        uint f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41n()
+    {
+        uint t = Ten;
+        uint f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p1()
+    {
+        uint s = 10;
+        uint t = Ten;
+        uint f = F41(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p2()
+    {
+        uint s = Ten;
+        uint t = 10;
+        uint f = F41(s, t);
+        return (f == 100);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench00p1", "Bench00n1",
+        "Bench00p2", "Bench00n2",
+        "Bench00p3", "Bench00n3",
+        "Bench00p4", "Bench00n4",
+        "Bench01p",  "Bench01n",
+        "Bench02p",  "Bench02n",
+        "Bench03p",  "Bench03n",
+        "Bench04p",  "Bench04n",
+        "Bench06p",  "Bench06n",
+        "Bench07p",  "Bench07n",
+        "Bench07p1", "Bench07n1",
+        "Bench08p",  "Bench08n",
+        "Bench09p",  "Bench09n",
+        "Bench10p",  "Bench10n",
+        "Bench10p1", "Bench10n1",
+        "Bench10p2", "Bench10n2",
+        "Bench10p3", "Bench10n3",
+        "Bench11p",  "Bench11n",
+        "Bench11p1", "Bench11n1",
+        "Bench11p2", "Bench11n2",
+        "Bench11p3", "Bench11n3",
+        "Bench20p",  "Bench20p1",
+        "Bench21p",  "Bench21n",
+        "Bench21p1", "Bench21n1",
+        "Bench22p",  "Bench22p1",
+        "Bench23p",  "Bench23n",
+        "Bench30p",  "Bench30n",
+        "Bench30p1", "Bench30n1",
+        "Bench30p2", "Bench30n2",
+        "Bench30p3", "Bench30n3",
+        "Bench31p",  "Bench31n",
+        "Bench31p1", "Bench31n1",
+        "Bench31p2", "Bench31n2",
+        "Bench31p3", "Bench31n3",
+        "Bench40p",  "Bench40n",
+        "Bench40p1", "Bench40p2",
+        "Bench41p",  "Bench41n",
+        "Bench41p1", "Bench41p2"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsUInt).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.csproj
new file mode 100644 (file)
index 0000000..68640b8
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsUInt.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.cs
new file mode 100644 (file)
index 0000000..7208707
--- /dev/null
@@ -0,0 +1,890 @@
+// 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 Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsULong
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Ints feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static ulong Five = 5;
+    static ulong Ten = 10;
+
+    static ulong Id(ulong x)
+    {
+        return x;
+    }
+
+    static ulong F00(ulong x)
+    {
+        return x * x;
+    }
+
+    static bool Bench00p()
+    {
+        ulong t = 10;
+        ulong f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n()
+    {
+        ulong t = Ten;
+        ulong f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p1()
+    {
+        ulong t = Id(10);
+        ulong f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n1()
+    {
+        ulong t = Id(Ten);
+        ulong f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p2()
+    {
+        ulong t = Id(10);
+        ulong f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00n2()
+    {
+        ulong t = Id(Ten);
+        ulong f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00p3()
+    {
+        ulong t = 10;
+        ulong f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00n3()
+    {
+        ulong t = Ten;
+        ulong f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00p4()
+    {
+        ulong t = 5;
+        ulong f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static bool Bench00n4()
+    {
+        ulong t = Five;
+        ulong f = F00(2 * t);
+        return (f == 100);
+    }
+
+    static ulong F01(ulong x)
+    {
+        return 1000 / x;
+    }
+
+    static bool Bench01p()
+    {
+        ulong t = 10;
+        ulong f = F01(t);
+        return (f == 100);
+    }
+
+    static bool Bench01n()
+    {
+        ulong t = Ten;
+        ulong f = F01(t);
+        return (f == 100);
+    }
+
+    static ulong F02(ulong x)
+    {
+        return 20 * (x / 2);
+    }
+
+    static bool Bench02p()
+    {
+        ulong t = 10;
+        ulong f = F02(t);
+        return (f == 100);
+    }
+
+    static bool Bench02n()
+    {
+        ulong t = Ten;
+        ulong f = F02(t);
+        return (f == 100);
+    }
+
+    static ulong F03(ulong x)
+    {
+        return 91 + 1009 % x;
+    }
+
+    static bool Bench03p()
+    {
+        ulong t = 10;
+        ulong f = F03(t);
+        return (f == 100);
+    }
+
+    static bool Bench03n()
+    {
+        ulong t = Ten;
+        ulong f = F03(t);
+        return (f == 100);
+    }
+
+    static ulong F04(ulong x)
+    {
+        return 50 * (x % 4);
+    }
+
+    static bool Bench04p()
+    {
+        ulong t = 10;
+        ulong f = F04(t);
+        return (f == 100);
+    }
+
+    static bool Bench04n()
+    {
+        ulong t = Ten;
+        ulong f = F04(t);
+        return (f == 100);
+    }
+
+    static ulong F06(ulong x)
+    {
+        return 110 - x;
+    }
+
+    static bool Bench06p()
+    {
+        ulong t = 10;
+        ulong f = F06(t);
+        return (f == 100);
+    }
+
+    static bool Bench06n()
+    {
+        ulong t = Ten;
+        ulong f = F06(t);
+        return (f == 100);
+    }
+
+    static ulong F07(ulong x)
+    {
+        return ~x + 111;
+    }
+
+    static bool Bench07p()
+    {
+        ulong t = 10;
+        ulong f = F07(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n()
+    {
+        ulong t = Ten;
+        ulong f = F07(t);
+        return (f == 100);
+    }
+
+    static ulong F071(ulong x)
+    {
+        return (x ^ 0xFFFFFFFFFFFFFFFF) + 111;
+    }
+
+    static bool Bench07p1()
+    {
+        ulong t = 10;
+        ulong f = F071(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n1()
+    {
+        ulong t = Ten;
+        ulong f = F071(t);
+        return (f == 100);
+    }
+
+    static ulong F08(ulong x)
+    {
+        return (x & 0x7) + 98;
+    }
+
+    static bool Bench08p()
+    {
+        ulong t = 10;
+        ulong f = F08(t);
+        return (f == 100);
+    }
+
+    static bool Bench08n()
+    {
+        ulong t = Ten;
+        ulong f = F08(t);
+        return (f == 100);
+    }
+
+    static ulong F09(ulong x)
+    {
+        return (x | 0x7) + 85;
+    }
+
+    static bool Bench09p()
+    {
+        ulong t = 10;
+        ulong f = F09(t);
+        return (f == 100);
+    }
+
+    static bool Bench09n()
+    {
+        ulong t = Ten;
+        ulong f = F09(t);
+        return (f == 100);
+    }
+
+    // Ulongs feeding comparisons.
+    //
+    // Inlining in Bench1xp should enable branch optimization
+    // Inlining in Bench1xn will not enable branch optimization
+
+    static ulong F10(ulong x)
+    {
+        return x == 10 ? 100u : 0u;
+    }
+
+    static bool Bench10p()
+    {
+        ulong t = 10;
+        ulong f = F10(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n()
+    {
+        ulong t = Ten;
+        ulong f = F10(t);
+        return (f == 100);
+    }
+
+    static ulong F101(ulong x)
+    {
+        return x != 10 ? 0u : 100u;
+    }
+
+    static bool Bench10p1()
+    {
+        ulong t = 10;
+        ulong f = F101(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n1()
+    {
+        ulong t = Ten;
+        ulong f = F101(t);
+        return (f == 100);
+    }
+
+    static ulong F102(ulong x)
+    {
+        return x >= 10 ? 100u : 0u;
+    }
+
+    static bool Bench10p2()
+    {
+        ulong t = 10;
+        ulong f = F102(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n2()
+    {
+        ulong t = Ten;
+        ulong f = F102(t);
+        return (f == 100);
+    }
+
+    static ulong F103(ulong x)
+    {
+        return x <= 10 ? 100u : 0u;
+    }
+
+    static bool Bench10p3()
+    {
+        ulong t = 10;
+        ulong f = F103(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n3()
+    {
+        ulong t = Ten;
+        ulong f = F102(t);
+        return (f == 100);
+    }
+
+    static ulong F11(ulong x)
+    {
+        if (x == 10)
+        {
+            return 100;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    static bool Bench11p()
+    {
+        ulong t = 10;
+        ulong f = F11(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n()
+    {
+        ulong t = Ten;
+        ulong f = F11(t);
+        return (f == 100);
+    }
+
+    static ulong F111(ulong x)
+    {
+        if (x != 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p1()
+    {
+        ulong t = 10;
+        ulong f = F111(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n1()
+    {
+        ulong t = Ten;
+        ulong f = F111(t);
+        return (f == 100);
+    }
+
+    static ulong F112(ulong x)
+    {
+        if (x > 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p2()
+    {
+        ulong t = 10;
+        ulong f = F112(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n2()
+    {
+        ulong t = Ten;
+        ulong f = F112(t);
+        return (f == 100);
+    }
+    static ulong F113(ulong x)
+    {
+        if (x < 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p3()
+    {
+        ulong t = 10;
+        ulong f = F113(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n3()
+    {
+        ulong t = Ten;
+        ulong f = F113(t);
+        return (f == 100);
+    }
+
+    // Ununsed (or effectively unused) parameters
+    //
+    // Simple callee analysis may overstate inline benefit
+
+    static ulong F20(ulong x)
+    {
+        return 100;
+    }
+
+    static bool Bench20p()
+    {
+        ulong t = 10;
+        ulong f = F20(t);
+        return (f == 100);
+    }
+
+    static bool Bench20p1()
+    {
+        ulong t = Ten;
+        ulong f = F20(t);
+        return (f == 100);
+    }
+
+    static ulong F21(ulong x)
+    {
+        return x + 100 - x;
+    }
+
+    static bool Bench21p()
+    {
+        ulong t = 10;
+        ulong f = F21(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n()
+    {
+        ulong t = Ten;
+        ulong f = F21(t);
+        return (f == 100);
+    }
+
+    static ulong F211(ulong x)
+    {
+        return x - x + 100;
+    }
+
+    static bool Bench21p1()
+    {
+        ulong t = 10;
+        ulong f = F211(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n1()
+    {
+        ulong t = Ten;
+        ulong f = F211(t);
+        return (f == 100);
+    }
+
+    static ulong F22(ulong x)
+    {
+        if (x > 0)
+        {
+            return 100;
+        }
+
+        return 100;
+    }
+
+    static bool Bench22p()
+    {
+        ulong t = 10;
+        ulong f = F22(t);
+        return (f == 100);
+    }
+
+    static bool Bench22p1()
+    {
+        ulong t = Ten;
+        ulong f = F22(t);
+        return (f == 100);
+    }
+
+    static ulong F23(ulong x)
+    {
+        if (x > 0)
+        {
+            return 90 + x;
+        }
+
+        return 100;
+    }
+
+    static bool Bench23p()
+    {
+        ulong t = 10;
+        ulong f = F23(t);
+        return (f == 100);
+    }
+
+    static bool Bench23n()
+    {
+        ulong t = Ten;
+        ulong f = F23(t);
+        return (f == 100);
+    }
+
+    // Multiple parameters
+
+    static ulong F30(ulong x, ulong y)
+    {
+        return y * y;
+    }
+
+    static bool Bench30p()
+    {
+        ulong t = 10;
+        ulong f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n()
+    {
+        ulong t = Ten;
+        ulong f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p1()
+    {
+        ulong s = Ten;
+        ulong t = 10;
+        ulong f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n1()
+    {
+        ulong s = 10;
+        ulong t = Ten;
+        ulong f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p2()
+    {
+        ulong s = 10;
+        ulong t = 10;
+        ulong f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n2()
+    {
+        ulong s = Ten;
+        ulong t = Ten;
+        ulong f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p3()
+    {
+        ulong s = 10;
+        ulong t = s;
+        ulong f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n3()
+    {
+        ulong s = Ten;
+        ulong t = s;
+        ulong f = F30(s, t);
+        return (f == 100);
+    }
+
+    static ulong F31(ulong x, ulong y, ulong z)
+    {
+        return z * z;
+    }
+
+    static bool Bench31p()
+    {
+        ulong t = 10;
+        ulong f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n()
+    {
+        ulong t = Ten;
+        ulong f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p1()
+    {
+        ulong r = Ten;
+        ulong s = Ten;
+        ulong t = 10;
+        ulong f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n1()
+    {
+        ulong r = 10;
+        ulong s = 10;
+        ulong t = Ten;
+        ulong f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p2()
+    {
+        ulong r = 10;
+        ulong s = 10;
+        ulong t = 10;
+        ulong f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n2()
+    {
+        ulong r = Ten;
+        ulong s = Ten;
+        ulong t = Ten;
+        ulong f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p3()
+    {
+        ulong r = 10;
+        ulong s = r;
+        ulong t = s;
+        ulong f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n3()
+    {
+        ulong r = Ten;
+        ulong s = r;
+        ulong t = s;
+        ulong f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    // Two args, both used
+
+    static ulong F40(ulong x, ulong y)
+    {
+        return x * x + y * y - 100;
+    }
+
+    static bool Bench40p()
+    {
+        ulong t = 10;
+        ulong f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40n()
+    {
+        ulong t = Ten;
+        ulong f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p1()
+    {
+        ulong s = Ten;
+        ulong t = 10;
+        ulong f = F40(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p2()
+    {
+        ulong s = 10;
+        ulong t = Ten;
+        ulong f = F40(s, t);
+        return (f == 100);
+    }
+
+    static ulong F41(ulong x, ulong y)
+    {
+        return x * y;
+    }
+
+    static bool Bench41p()
+    {
+        ulong t = 10;
+        ulong f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41n()
+    {
+        ulong t = Ten;
+        ulong f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p1()
+    {
+        ulong s = 10;
+        ulong t = Ten;
+        ulong f = F41(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p2()
+    {
+        ulong s = Ten;
+        ulong t = 10;
+        ulong f = F41(s, t);
+        return (f == 100);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench00p1", "Bench00n1",
+        "Bench00p2", "Bench00n2",
+        "Bench00p3", "Bench00n3",
+        "Bench00p4", "Bench00n4",
+        "Bench01p",  "Bench01n",
+        "Bench02p",  "Bench02n",
+        "Bench03p",  "Bench03n",
+        "Bench04p",  "Bench04n",
+        "Bench06p",  "Bench06n",
+        "Bench07p",  "Bench07n",
+        "Bench07p1", "Bench07n1",
+        "Bench08p",  "Bench08n",
+        "Bench09p",  "Bench09n",
+        "Bench10p",  "Bench10n",
+        "Bench10p1", "Bench10n1",
+        "Bench10p2", "Bench10n2",
+        "Bench10p3", "Bench10n3",
+        "Bench11p",  "Bench11n",
+        "Bench11p1", "Bench11n1",
+        "Bench11p2", "Bench11n2",
+        "Bench11p3", "Bench11n3",
+        "Bench20p",  "Bench20p1",
+        "Bench21p",  "Bench21n",
+        "Bench21p1", "Bench21n1",
+        "Bench22p",  "Bench22p1",
+        "Bench23p",  "Bench23n",
+        "Bench30p",  "Bench30n",
+        "Bench30p1", "Bench30n1",
+        "Bench30p2", "Bench30n2",
+        "Bench30p3", "Bench30n3",
+        "Bench31p",  "Bench31n",
+        "Bench31p1", "Bench31n1",
+        "Bench31p2", "Bench31n2",
+        "Bench31p3", "Bench31n3",
+        "Bench40p",  "Bench40n",
+        "Bench40p1", "Bench40p2",
+        "Bench41p",  "Bench41n",
+        "Bench41p1", "Bench41p2"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsULong).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.csproj
new file mode 100644 (file)
index 0000000..cb983a5
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsULong.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.cs
new file mode 100644 (file)
index 0000000..249e985
--- /dev/null
@@ -0,0 +1,930 @@
+// 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 Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class ConstantArgsUShort
+{
+
+#if DEBUG
+    public const int Iterations = 1;
+#else
+    public const int Iterations = 100000;
+#endif
+
+    // Ushorts feeding math operations.
+    //
+    // Inlining in Bench0xp should enable constant folding
+    // Inlining in Bench0xn will not enable constant folding
+
+    static ushort Five = 5;
+    static ushort Ten = 10;
+
+    static ushort Id(ushort x)
+    {
+        return x;
+    }
+
+    static ushort F00(ushort x)
+    {
+        return (ushort) (x * x);
+    }
+
+    static bool Bench00p()
+    {
+        ushort t = 10;
+        ushort f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n()
+    {
+        ushort t = Ten;
+        ushort f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p1()
+    {
+        ushort t = Id(10);
+        ushort f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00n1()
+    {
+        ushort t = Id(Ten);
+        ushort f = F00(t);
+        return (f == 100);
+    }
+
+    static bool Bench00p2()
+    {
+        ushort t = Id(10);
+        ushort f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00n2()
+    {
+        ushort t = Id(Ten);
+        ushort f = F00(Id(t));
+        return (f == 100);
+    }
+
+    static bool Bench00p3()
+    {
+        ushort t = 10;
+        ushort f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00n3()
+    {
+        ushort t = Ten;
+        ushort f = F00(Id(Id(t)));
+        return (f == 100);
+    }
+
+    static bool Bench00p4()
+    {
+        ushort t = 5;
+        ushort f = F00((ushort)(2 * t));
+        return (f == 100);
+    }
+
+    static bool Bench00n4()
+    {
+        ushort t = Five;
+        ushort f = F00((ushort)(2 * t));
+        return (f == 100);
+    }
+
+    static ushort F01(ushort x)
+    {
+        return (ushort)(1000 / x);
+    }
+
+    static bool Bench01p()
+    {
+        ushort t = 10;
+        ushort f = F01(t);
+        return (f == 100);
+    }
+
+    static bool Bench01n()
+    {
+        ushort t = Ten;
+        ushort f = F01(t);
+        return (f == 100);
+    }
+
+    static ushort F02(ushort x)
+    {
+        return (ushort) (20 * (x / 2));
+    }
+
+    static bool Bench02p()
+    {
+        ushort t = 10;
+        ushort f = F02(t);
+        return (f == 100);
+    }
+
+    static bool Bench02n()
+    {
+        ushort t = Ten;
+        ushort f = F02(t);
+        return (f == 100);
+    }
+
+    static ushort F03(ushort x)
+    {
+        return (ushort)(91 + 1009 % x);
+    }
+
+    static bool Bench03p()
+    {
+        ushort t = 10;
+        ushort f = F03(t);
+        return (f == 100);
+    }
+
+    static bool Bench03n()
+    {
+        ushort t = Ten;
+        ushort f = F03(t);
+        return (f == 100);
+    }
+
+    static ushort F04(ushort x)
+    {
+        return (ushort)(50 * (x % 4));
+    }
+
+    static bool Bench04p()
+    {
+        ushort t = 10;
+        ushort f = F04(t);
+        return (f == 100);
+    }
+
+    static bool Bench04n()
+    {
+        ushort t = Ten;
+        ushort f = F04(t);
+        return (f == 100);
+    }
+
+    static ushort F05(ushort x)
+    {
+        return (ushort)((1 << x) - 924);
+    }
+
+    static bool Bench05p()
+    {
+        ushort t = 10;
+        ushort f = F05(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n()
+    {
+        ushort t = Ten;
+        ushort f = F05(t);
+        return (f == 100);
+    }
+
+    static ushort F051(ushort x)
+    {
+        return (ushort)(102400 >> x);
+    }
+
+    static bool Bench05p1()
+    {
+        ushort t = 10;
+        ushort f = F051(t);
+        return (f == 100);
+    }
+
+    static bool Bench05n1()
+    {
+        ushort t = Ten;
+        ushort f = F051(t);
+        return (f == 100);
+    }
+
+    static ushort F06(ushort x)
+    {
+        return (ushort)(-x + 110);
+    }
+
+    static bool Bench06p()
+    {
+        ushort t = 10;
+        ushort f = F06(t);
+        return (f == 100);
+    }
+
+    static bool Bench06n()
+    {
+        ushort t = Ten;
+        ushort f = F06(t);
+        return (f == 100);
+    }
+
+    static ushort F07(ushort x)
+    {
+        return (ushort)(~x + 111);
+    }
+
+    static bool Bench07p()
+    {
+        ushort t = 10;
+        ushort f = F07(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n()
+    {
+        ushort t = Ten;
+        ushort f = F07(t);
+        return (f == 100);
+    }
+
+    static ushort F071(ushort x)
+    {
+        return (ushort)((x ^ -1) + 111);
+    }
+
+    static bool Bench07p1()
+    {
+        ushort t = 10;
+        ushort f = F071(t);
+        return (f == 100);
+    }
+
+    static bool Bench07n1()
+    {
+        ushort t = Ten;
+        ushort f = F071(t);
+        return (f == 100);
+    }
+
+    static ushort F08(ushort x)
+    {
+        return (ushort)((x & 0x7) + 98);
+    }
+
+    static bool Bench08p()
+    {
+        ushort t = 10;
+        ushort f = F08(t);
+        return (f == 100);
+    }
+
+    static bool Bench08n()
+    {
+        ushort t = Ten;
+        ushort f = F08(t);
+        return (f == 100);
+    }
+
+    static ushort F09(ushort x)
+    {
+        return (ushort)((x | 0x7) + 85);
+    }
+
+    static bool Bench09p()
+    {
+        ushort t = 10;
+        ushort f = F09(t);
+        return (f == 100);
+    }
+
+    static bool Bench09n()
+    {
+        ushort t = Ten;
+        ushort f = F09(t);
+        return (f == 100);
+    }
+
+    // Ushorts feeding comparisons.
+    //
+    // Inlining in Bench1xp should enable branch optimization
+    // Inlining in Bench1xn will not enable branch optimization
+
+    static ushort F10(ushort x)
+    {
+        return x == 10 ? (ushort) 100 : (ushort) 0;
+    }
+
+    static bool Bench10p()
+    {
+        ushort t = 10;
+        ushort f = F10(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n()
+    {
+        ushort t = Ten;
+        ushort f = F10(t);
+        return (f == 100);
+    }
+
+    static ushort F101(ushort x)
+    {
+        return x != 10 ? (ushort) 0 : (ushort) 100;
+    }
+
+    static bool Bench10p1()
+    {
+        ushort t = 10;
+        ushort f = F101(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n1()
+    {
+        ushort t = Ten;
+        ushort f = F101(t);
+        return (f == 100);
+    }
+
+    static ushort F102(ushort x)
+    {
+        return x >= 10 ? (ushort) 100 : (ushort) 0;
+    }
+
+    static bool Bench10p2()
+    {
+        ushort t = 10;
+        ushort f = F102(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n2()
+    {
+        ushort t = Ten;
+        ushort f = F102(t);
+        return (f == 100);
+    }
+
+    static ushort F103(ushort x)
+    {
+        return x <= 10 ? (ushort) 100 : (ushort) 0;
+    }
+
+    static bool Bench10p3()
+    {
+        ushort t = 10;
+        ushort f = F103(t);
+        return (f == 100);
+    }
+
+    static bool Bench10n3()
+    {
+        ushort t = Ten;
+        ushort f = F102(t);
+        return (f == 100);
+    }
+
+    static ushort F11(ushort x)
+    {
+        if (x == 10)
+        {
+            return 100;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    static bool Bench11p()
+    {
+        ushort t = 10;
+        ushort f = F11(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n()
+    {
+        ushort t = Ten;
+        ushort f = F11(t);
+        return (f == 100);
+    }
+
+    static ushort F111(ushort x)
+    {
+        if (x != 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p1()
+    {
+        ushort t = 10;
+        ushort f = F111(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n1()
+    {
+        ushort t = Ten;
+        ushort f = F111(t);
+        return (f == 100);
+    }
+
+    static ushort F112(ushort x)
+    {
+        if (x > 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p2()
+    {
+        ushort t = 10;
+        ushort f = F112(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n2()
+    {
+        ushort t = Ten;
+        ushort f = F112(t);
+        return (f == 100);
+    }
+    static ushort F113(ushort x)
+    {
+        if (x < 10)
+        {
+            return 0;
+        }
+        else
+        {
+            return 100;
+        }
+    }
+
+    static bool Bench11p3()
+    {
+        ushort t = 10;
+        ushort f = F113(t);
+        return (f == 100);
+    }
+
+    static bool Bench11n3()
+    {
+        ushort t = Ten;
+        ushort f = F113(t);
+        return (f == 100);
+    }
+
+    // Ununsed (or effectively unused) parameters
+    //
+    // Simple callee analysis may overstate inline benefit
+
+    static ushort F20(ushort x)
+    {
+        return 100;
+    }
+
+    static bool Bench20p()
+    {
+        ushort t = 10;
+        ushort f = F20(t);
+        return (f == 100);
+    }
+
+    static bool Bench20p1()
+    {
+        ushort t = Ten;
+        ushort f = F20(t);
+        return (f == 100);
+    }
+
+    static ushort F21(ushort x)
+    {
+        return (ushort)(-x + 100 + x);
+    }
+
+    static bool Bench21p()
+    {
+        ushort t = 10;
+        ushort f = F21(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n()
+    {
+        ushort t = Ten;
+        ushort f = F21(t);
+        return (f == 100);
+    }
+
+    static ushort F211(ushort x)
+    {
+        return (ushort)(x - x + 100);
+    }
+
+    static bool Bench21p1()
+    {
+        ushort t = 10;
+        ushort f = F211(t);
+        return (f == 100);
+    }
+
+    static bool Bench21n1()
+    {
+        ushort t = Ten;
+        ushort f = F211(t);
+        return (f == 100);
+    }
+
+    static ushort F22(ushort x)
+    {
+        if (x > 0)
+        {
+            return 100;
+        }
+
+        return 100;
+    }
+
+    static bool Bench22p()
+    {
+        ushort t = 10;
+        ushort f = F22(t);
+        return (f == 100);
+    }
+
+    static bool Bench22p1()
+    {
+        ushort t = Ten;
+        ushort f = F22(t);
+        return (f == 100);
+    }
+
+    static ushort F23(ushort x)
+    {
+        if (x > 0)
+        {
+            return (ushort)(90 + x);
+        }
+
+        return 100;
+    }
+
+    static bool Bench23p()
+    {
+        ushort t = 10;
+        ushort f = F23(t);
+        return (f == 100);
+    }
+
+    static bool Bench23n()
+    {
+        ushort t = Ten;
+        ushort f = F23(t);
+        return (f == 100);
+    }
+
+    // Multiple parameters
+
+    static ushort F30(ushort x, ushort y)
+    {
+        return (ushort)(y * y);
+    }
+
+    static bool Bench30p()
+    {
+        ushort t = 10;
+        ushort f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n()
+    {
+        ushort t = Ten;
+        ushort f = F30(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p1()
+    {
+        ushort s = Ten;
+        ushort t = 10;
+        ushort f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n1()
+    {
+        ushort s = 10;
+        ushort t = Ten;
+        ushort f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p2()
+    {
+        ushort s = 10;
+        ushort t = 10;
+        ushort f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n2()
+    {
+        ushort s = Ten;
+        ushort t = Ten;
+        ushort f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30p3()
+    {
+        ushort s = 10;
+        ushort t = s;
+        ushort f = F30(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench30n3()
+    {
+        ushort s = Ten;
+        ushort t = s;
+        ushort f = F30(s, t);
+        return (f == 100);
+    }
+
+    static ushort F31(ushort x, ushort y, ushort z)
+    {
+        return (ushort)(z * z);
+    }
+
+    static bool Bench31p()
+    {
+        ushort t = 10;
+        ushort f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n()
+    {
+        ushort t = Ten;
+        ushort f = F31(t, t, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p1()
+    {
+        ushort r = Ten;
+        ushort s = Ten;
+        ushort t = 10;
+        ushort f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n1()
+    {
+        ushort r = 10;
+        ushort s = 10;
+        ushort t = Ten;
+        ushort f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p2()
+    {
+        ushort r = 10;
+        ushort s = 10;
+        ushort t = 10;
+        ushort f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n2()
+    {
+        ushort r = Ten;
+        ushort s = Ten;
+        ushort t = Ten;
+        ushort f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31p3()
+    {
+        ushort r = 10;
+        ushort s = r;
+        ushort t = s;
+        ushort f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    static bool Bench31n3()
+    {
+        ushort r = Ten;
+        ushort s = r;
+        ushort t = s;
+        ushort f = F31(r, s, t);
+        return (f == 100);
+    }
+
+    // Two args, both used
+
+    static ushort F40(ushort x, ushort y)
+    {
+        return (ushort)(x * x + y * y - 100);
+    }
+
+    static bool Bench40p()
+    {
+        ushort t = 10;
+        ushort f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40n()
+    {
+        ushort t = Ten;
+        ushort f = F40(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p1()
+    {
+        ushort s = Ten;
+        ushort t = 10;
+        ushort f = F40(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench40p2()
+    {
+        ushort s = 10;
+        ushort t = Ten;
+        ushort f = F40(s, t);
+        return (f == 100);
+    }
+
+    static ushort F41(ushort x, ushort y)
+    {
+        return (ushort)(x * y);
+    }
+
+    static bool Bench41p()
+    {
+        ushort t = 10;
+        ushort f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41n()
+    {
+        ushort t = Ten;
+        ushort f = F41(t, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p1()
+    {
+        ushort s = 10;
+        ushort t = Ten;
+        ushort f = F41(s, t);
+        return (f == 100);
+    }
+
+    static bool Bench41p2()
+    {
+        ushort s = Ten;
+        ushort t = 10;
+        ushort f = F41(s, t);
+        return (f == 100);
+    }
+
+    private static IEnumerable<object[]> MakeArgs(params string[] args)
+    {
+        return args.Select(arg => new object[] { arg });
+    }
+
+    public static IEnumerable<object[]> TestFuncs = MakeArgs(
+        "Bench00p",  "Bench00n",
+        "Bench00p1", "Bench00n1",
+        "Bench00p2", "Bench00n2",
+        "Bench00p3", "Bench00n3",
+        "Bench00p4", "Bench00n4",
+        "Bench01p",  "Bench01n",
+        "Bench02p",  "Bench02n",
+        "Bench03p",  "Bench03n",
+        "Bench04p",  "Bench04n",
+        "Bench05p",  "Bench05n",
+        "Bench05p1", "Bench05n1",
+        "Bench06p",  "Bench06n",
+        "Bench07p",  "Bench07n",
+        "Bench07p1", "Bench07n1",
+        "Bench08p",  "Bench08n",
+        "Bench09p",  "Bench09n",
+        "Bench10p",  "Bench10n",
+        "Bench10p1", "Bench10n1",
+        "Bench10p2", "Bench10n2",
+        "Bench10p3", "Bench10n3",
+        "Bench11p",  "Bench11n",
+        "Bench11p1", "Bench11n1",
+        "Bench11p2", "Bench11n2",
+        "Bench11p3", "Bench11n3",
+        "Bench20p",  "Bench20p1",
+        "Bench21p",  "Bench21n",
+        "Bench21p1", "Bench21n1",
+        "Bench22p",  "Bench22p1",
+        "Bench23p",  "Bench23n",
+        "Bench30p",  "Bench30n",
+        "Bench30p1", "Bench30n1",
+        "Bench30p2", "Bench30n2",
+        "Bench30p3", "Bench30n3",
+        "Bench31p",  "Bench31n",
+        "Bench31p1", "Bench31n1",
+        "Bench31p2", "Bench31n2",
+        "Bench31p3", "Bench31n3",
+        "Bench40p",  "Bench40n",
+        "Bench40p1", "Bench40p2",
+        "Bench41p",  "Bench41n",
+        "Bench41p1", "Bench41p2"
+    );
+
+    static Func<bool> LookupFunc(object o)
+    {
+        TypeInfo t = typeof(ConstantArgsUShort).GetTypeInfo();
+        MethodInfo m = t.GetDeclaredMethod((string) o);
+        return m.CreateDelegate(typeof(Func<bool>)) as Func<bool>;
+    }
+
+    [Benchmark]
+    [MemberData(nameof(TestFuncs))]
+    public static void Test(object funcName)
+    {
+        Func<bool> f = LookupFunc(funcName);
+        foreach (var iteration in Benchmark.Iterations)
+        {
+            using (iteration.StartMeasurement())
+            {
+                for (int i = 0; i < Iterations; i++)
+                {
+                    f();
+                }
+            }
+        }
+    }
+
+    static bool TestBase(Func<bool> f)
+    {
+        bool result = true;
+        for (int i = 0; i < Iterations; i++)
+        {
+            result &= f();
+        }
+        return result;
+    }
+
+    public static int Main()
+    {
+        bool result = true;
+
+        foreach(object[] o in TestFuncs)
+        {
+            string funcName = (string) o[0];
+            Func<bool> func = LookupFunc(funcName);
+            bool thisResult = TestBase(func);
+            if (!thisResult)
+            {
+                Console.WriteLine("{0} failed", funcName);
+            }
+            result &= thisResult;
+        }
+
+        return (result ? 100 : -1);
+    }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.csproj
new file mode 100644 (file)
index 0000000..d59541f
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)benchmark\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ConstantArgsUShort.cs" />
+  </ItemGroup>
+  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark\project.lock.json</ProjectLockJson>
+  </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>