diff options
author | Andy Ayers <andya@microsoft.com> | 2016-06-15 22:53:47 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-06-15 22:53:47 -0700 |
commit | d5a0338ddefc9551f3f573b4950ab046f58d9464 (patch) | |
tree | ad66ff39c9470a184b3a7eebebb49665297be19a /tests | |
parent | 9ec70e119cca0cf317e1d64a3efd2bb9021e6d80 (diff) | |
parent | 1b34b726c3644ca494be54f90bbb190905e52e4e (diff) | |
download | coreclr-d5a0338ddefc9551f3f573b4950ab046f58d9464.tar.gz coreclr-d5a0338ddefc9551f3f573b4950ab046f58d9464.tar.bz2 coreclr-d5a0338ddefc9551f3f573b4950ab046f58d9464.zip |
Merge pull request #5819 from AndyAyersMS/InlineTestsV1
Inliner: simple performance tests
Diffstat (limited to 'tests')
24 files changed, 10804 insertions, 0 deletions
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.cs new file mode 100644 index 0000000000..8271c40a43 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.cs @@ -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 index 0000000000..c8319ca32f --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.csproj @@ -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 index 0000000000..0d1f9284ba --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.cs @@ -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 index 0000000000..e0f78ff254 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.csproj @@ -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 index 0000000000..6c95d482d5 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.cs @@ -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 index 0000000000..60de76c39f --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.csproj @@ -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 index 0000000000..bbd65a4004 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.cs @@ -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 index 0000000000..70b3e29a97 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.csproj @@ -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 index 0000000000..03d59f93d0 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.cs @@ -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 index 0000000000..f5f361032a --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.csproj @@ -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 index 0000000000..f4e45f50db --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.cs @@ -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 index 0000000000..b4cfab2e28 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.csproj @@ -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 index 0000000000..b329122967 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.cs @@ -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 index 0000000000..22268de21f --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.csproj @@ -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 index 0000000000..8718111a72 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.cs @@ -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 index 0000000000..4f5db4c468 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.csproj @@ -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 index 0000000000..b7319086d7 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.cs @@ -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 index 0000000000..8dbc9932e9 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.csproj @@ -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 index 0000000000..db3316ea32 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.cs @@ -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 index 0000000000..68640b81cb --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.csproj @@ -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 index 0000000000..72087077e2 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.cs @@ -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 index 0000000000..cb983a5ecb --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.csproj @@ -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 index 0000000000..249e985496 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.cs @@ -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 index 0000000000..d59541fe8d --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.csproj @@ -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> |