summaryrefslogtreecommitdiff
path: root/tests/src/JIT/Performance
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
commit4b4aad7217d3292650e77eec2cf4c198ea9c3b4b (patch)
tree98110734c91668dfdbb126fcc0e15ddbd93738ca /tests/src/JIT/Performance
parentfa45f57ed55137c75ac870356a1b8f76c84b229c (diff)
downloadcoreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.gz
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.bz2
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.zip
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'tests/src/JIT/Performance')
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.cs163
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/BenchMk2/BenchMk2.cs66
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/BenchMk2/BenchMk2.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/BenchMrk/BenchMrk.cs66
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/BenchMrk/BenchMrk.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Bisect/Bisect.cs163
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Bisect/Bisect.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/DMath/DMath.cs113
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/DMath/DMath.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/FFT/FFT.cs153
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/FFT/FFT.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/InProd/InProd.cs134
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/InProd/InProd.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/InvMt/InvMt.cs137
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/InvMt/InvMt.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/LLoops/LLoops.cs650
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/LLoops/LLoops.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Lorenz/Lorenz.cs134
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Lorenz/Lorenz.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/MatInv4/MatInv4.cs495
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/MatInv4/MatInv4.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/NewtE/NewtE.cs135
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/NewtE/NewtE.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/NewtR/NewtR.cs131
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/NewtR/NewtR.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Regula/Regula.cs193
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Regula/Regula.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Romber/Romber.cs169
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Romber/Romber.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Secant/Secant.cs142
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Secant/Secant.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Simpsn/Simpsn.cs93
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Simpsn/Simpsn.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/SqMtx/SqMtx.cs103
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/SqMtx/SqMtx.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Trap/Trap.cs96
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Trap/Trap.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Whetsto/Whetsto.cs242
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchF/Whetsto/Whetsto.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/8Queens/8Queens.cs100
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/8Queens/8Queens.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Ackermann/Ackermann.cs67
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Ackermann/Ackermann.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/AddArray/AddArray.cs91
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/AddArray/AddArray.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/AddArray2/AddArray2.cs131
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/AddArray2/AddArray2.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Array1/Array1.cs154
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Array1/Array1.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Array2/Array2.cs100
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Array2/Array2.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/BenchE/BenchE.cs117
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/BenchE/BenchE.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort/BubbleSort.cs87
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort/BubbleSort.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort2/BubbleSort2.cs90
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort2/BubbleSort2.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/CSieve/CSieve.cs82
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/CSieve/CSieve.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Fib/Fib.cs63
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Fib/Fib.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/HeapSort/HeapSort.cs121
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/HeapSort/HeapSort.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/IniArray/IniArray.cs60
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/IniArray/IniArray.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/LogicArray/LogicArray.cs97
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/LogicArray/LogicArray.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Midpoint/Midpoint.cs104
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Midpoint/Midpoint.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/MulMatrix/MulMatrix.cs140
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/MulMatrix/MulMatrix.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/NDhrystone/NDhrystone.cs286
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/NDhrystone/NDhrystone.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Permutate/Permutate.cs116
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Permutate/Permutate.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Pi/Pi.cs86
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Pi/Pi.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Puzzle/Puzzle.cs393
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/Puzzle/Puzzle.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/QuickSort/QuickSort.cs116
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/QuickSort/QuickSort.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/TreeInsert/TreeInsert.cs138
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/TreeInsert/TreeInsert.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/TreeSort/TreeSort.cs151
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/TreeSort/TreeSort.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/XposMatrix/XposMatrix.cs90
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchI/XposMatrix/XposMatrix.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/LICENSE.TXT18
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/README.TXT37
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp.cs151
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csproj44
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csharp-2.cs220
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csharp.cs184
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs156
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.cs114
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.cs126
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Burgers/Burgers.cs339
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Burgers/Burgers.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/ByteMark.cs1546
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/Bytemark.csproj59
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/Huffman.cs570
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/StringSort.cs348
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/assign_jagged.cs551
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/assign_rect.cs545
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/bitops.cs279
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/assignjagged.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/assignrect.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/bitfield.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/emfclass.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/emfstruct.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/four.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/huff.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/idea.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/lu.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/nnetjagged.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/nnetrect.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/numsortjagged.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/numsortrect.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/commands/stringsort.dat2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/emfloat.cs1577
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/emfloatclass.cs1566
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/fourier.cs230
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/idea.cs451
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/ludecomp.cs340
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/neural-dat.cs231
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/neural.cs883
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/neuraljagged.cs882
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/nnet.dat210
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/numericsort.cs539
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Bytemark/utility.cs103
-rw-r--r--tests/src/JIT/Performance/CodeQuality/FractalPerf/FractalPerf.cs177
-rw-r--r--tests/src/JIT/Performance/CodeQuality/FractalPerf/FractalPerf.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.cs930
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.cs930
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.cs810
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.cs810
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.cs930
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.cs930
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.cs930
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.cs930
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.cs330
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.cs890
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.cs890
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.cs930
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.cs75
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.csproj45
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Linq/Linq.cs595
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Linq/Linq.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AbsDouble.cs48
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AcosDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AsinDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/Atan2Double.cs48
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AtanDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CeilingDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CosDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CoshDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/ExpDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/FloorDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/Log10Double.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/LogDouble.cs48
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/PowDouble.cs48
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/RoundDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SinDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SinhDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SqrtDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/TanDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/TanhDouble.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Functions.cs158
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Functions.csproj67
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/MathTests.cs29
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Math/Functions/Single/AbsSingle.cs47
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Roslyn/CscBench.cs196
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Roslyn/CscBench.csproj44
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/Abstractions.cs138
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.cs256
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.csproj52
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/Interfaces.cs145
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ScalarDouble.cs158
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ScalarFloat.cs132
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorDouble.cs212
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorDoubleStrict.cs215
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorFloat.cs214
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorFloatStrict.cs191
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorHelpers.cs38
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Camera.cs25
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Color.cs143
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ISect.cs16
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Light.cs13
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ObjectPool.cs68
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Plane.cs25
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ProducerConsumerCollectionBase.cs107
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Ray.cs13
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/RayTracer.csproj58
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/RayTracerBench.cs144
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Raytracer.cs196
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Scene.cs24
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/SceneObject.cs14
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Sphere.cs38
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Surface.cs26
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Surfaces.cs44
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Vector.cs77
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SciMark/CommandLine.cs106
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SciMark/Constants.cs51
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SciMark/FFT.cs222
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SciMark/LU.cs271
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SciMark/MonteCarlo.cs72
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SciMark/Random.cs305
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SciMark/SOR.cs56
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SciMark/SciMark.csproj53
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SciMark/SparseCompRow.cs59
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SciMark/Stopwatch.cs112
-rw-r--r--tests/src/JIT/Performance/CodeQuality/SciMark/kernel.cs450
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.cs201
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Serialization/Serialize.cs188
-rw-r--r--tests/src/JIT/Performance/CodeQuality/Serialization/Serialize.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/V8/Crypto/Crypto.cs2111
-rw-r--r--tests/src/JIT/Performance/CodeQuality/V8/Crypto/Crypto.csproj43
-rw-r--r--tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.cs1068
-rw-r--r--tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.csproj44
-rw-r--r--tests/src/JIT/Performance/CodeQuality/V8/Richards/Richards.cs757
-rw-r--r--tests/src/JIT/Performance/CodeQuality/V8/Richards/Richards.csproj43
-rw-r--r--tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.cmd63
-rw-r--r--tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.cs1155
-rw-r--r--tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.csproj42
-rw-r--r--tests/src/JIT/Performance/RunBenchmarks/benchmarks.xml812
-rw-r--r--tests/src/JIT/Performance/RunBenchmarks/build.cmd28
-rw-r--r--tests/src/JIT/Performance/RunBenchmarks/coreclr_benchmarks.xml728
246 files changed, 46139 insertions, 0 deletions
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.cs
new file mode 100644
index 0000000000..427ec9269e
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.cs
@@ -0,0 +1,163 @@
+// 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.
+//
+// The Adams-Moulton Predictor Corrector Method adapted from Conte and de Boor
+// original source: adams_d.c
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Diagnostics;
+#if XUNIT_PERF
+using Xunit;
+using Microsoft.Xunit.Performance;
+#endif // XUNIT_PERF
+
+#if XUNIT_PERF
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+#endif // XUNIT_PERF
+
+public static class Adams
+{
+#if DEBUG
+ public static int Iterations = 1;
+#else
+ public static int Iterations = 200000;
+#endif // DEBUG
+
+ static double g_xn, g_yn, g_dn, g_en;
+ const double g_xn_base = 0.09999999E+01;
+ const double g_yn_base = 0.71828180E+00;
+ const double g_dn_base = 0.21287372E-08;
+ const double g_en_base = 0.74505806E-08;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void Bench()
+ {
+ double[] f = new double[5];
+ double xn, yn, dn, en, yxn, h, fnp, ynp, y0, x0, nz;
+ int i, k, n, nstep;
+
+#if VERBOSE
+ Console.WriteLine(" ADAMS-MOULTON METHOD ");
+#endif // VERBOSE
+
+ n = 4;
+ h = 1.0 / 32.0;
+ nstep = 32;
+ y0 = 0.0;
+ x0 = 0.0;
+ xn = 0.0;
+ yn = 0.0;
+ dn = 0.0;
+ en = 0.0;
+ nz = 0;
+
+ f[1] = x0 + y0;
+#if VERBOSE
+ Console.WriteLine("{0}, {1}, {2}, {3}, {4}", nz, x0, y0, dn, en);
+#endif // VERBOSE
+ xn = x0;
+ for (i = 2; i <= 4; i++)
+ {
+ k = i - 1;
+ xn = xn + h;
+ yn = Soln(xn);
+ f[i] = xn + yn;
+#if VERBOSE
+ Console.WriteLine("{0}, {1}, {2}, {3}, {4}", k, xn, yn, dn, en);
+#endif // VERBOSE
+ }
+
+ for (k = 4; k <= nstep; k++)
+ {
+ ynp = yn + (h / 24) * (55 * f[n] - 59 * f[n - 1] + 37 * f[n - 2] - 9 * f[n - 3]);
+ xn = xn + h;
+ fnp = xn + ynp;
+ yn = yn + (h / 24) * (9 * fnp + 19 * f[n] - 5 * f[n - 1] + f[n - 2]);
+ dn = (yn - ynp) / 14;
+ f[n - 3] = f[n - 2];
+ f[n - 2] = f[n - 1];
+ f[n - 1] = f[n];
+ f[n] = xn + yn;
+ yxn = Soln(xn);
+ en = yn - yxn;
+#if VERBOSE
+ Console.WriteLine("{0}, {1}, {2}, {3}, {4}", k, xn, yn, dn, en);
+#endif // VERBOSE
+ }
+
+ // Escape calculated values:
+ g_xn = xn;
+ g_yn = yn;
+ g_dn = dn;
+ g_en = en;
+ }
+
+ private static double Soln(double x)
+ {
+ return (System.Math.Exp(x) - 1.0 - (x));
+ }
+
+ [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
+ private static void TestBench()
+ {
+ for (int l = 1; l <= Iterations; l++)
+ {
+ Bench();
+ }
+ }
+
+#if XUNIT_PERF
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ TestBench();
+ }
+ }
+ }
+#endif // XUNIT_PERF
+
+ [MethodImpl(MethodImplOptions.NoOptimization)]
+ public static int Main(string[] argv)
+ {
+ if (argv.Length > 0)
+ {
+ Iterations = Int32.Parse(argv[0]);
+ }
+
+ Stopwatch sw = Stopwatch.StartNew();
+ TestBench();
+ sw.Stop();
+
+ bool result = true;
+ // Note: we can't check xn or yn better because of the precision
+ // with which original results are given
+ result &= System.Math.Abs(g_xn_base - g_xn) <= 1.5e-7;
+ result &= System.Math.Abs(g_yn_base - g_yn) <= 1.5e-7;
+ result &= System.Math.Abs(g_dn) <= 2.5e-9;
+ // Actual error is much bigger than base error;
+ // this is likely due to the fact that the original program was written in Fortran
+ // and was running on a mainframe with a non-IEEE floating point arithmetic
+ // (it's still beyond the published precision of yn)
+ result &= System.Math.Abs(g_en) <= 5.5e-8;
+ Console.WriteLine(result ? "Passed" : "Failed");
+
+ Console.WriteLine(" BASE.....P1 1/4 (ADAMS-MOULTON), XN = {0}", g_xn_base);
+ Console.WriteLine(" VERIFY...P1 1/4 (ADAMS-MOULTON), XN = {0}\n", g_xn);
+ Console.WriteLine(" BASE.....P1 2/4 (ADAMS-MOULTON), YN = {0}", g_yn_base);
+ Console.WriteLine(" VERIFY...P1 2/4 (ADAMS-MOULTON), YN = {0}\n", g_yn);
+ Console.WriteLine(" BASE.....P1 3/4 (ADAMS-MOULTON), DN = {0}", g_dn_base);
+ Console.WriteLine(" VERIFY...P1 3/4 (ADAMS-MOULTON), DN = {0}\n", g_dn);
+ Console.WriteLine(" BASE.....P1 4/4 (ADAMS-MOULTON), EN = {0}", g_en_base);
+ Console.WriteLine(" VERIFY...P1 4/4 (ADAMS-MOULTON), EN = {0}\n", g_en);
+
+ Console.WriteLine("Test iterations: {0}; Total time: {1} sec", Iterations, sw.Elapsed.TotalSeconds);
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.csproj
new file mode 100644
index 0000000000..580bd54343
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Adams/Adams.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Adams.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/BenchF/BenchMk2/BenchMk2.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMk2/BenchMk2.cs
new file mode 100644
index 0000000000..970164405b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMk2/BenchMk2.cs
@@ -0,0 +1,66 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class BenchMk2
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 4000000;
+#endif
+
+ private static int s_i, s_n;
+ private static double s_p, s_a, s_x, s_f, s_e;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ s_p = Math.Acos(-1.0);
+ s_a = 0.0;
+ s_n = Iterations;
+ s_f = s_p / s_n;
+ for (s_i = 1; s_i <= s_n; ++s_i)
+ {
+ s_f = s_p / s_n;
+ s_x = s_f * s_i;
+ s_e = Math.Abs(Math.Log(Math.Exp(s_x)) / s_x) - Math.Sqrt((Math.Sin(s_x) * Math.Sin(s_x)) + Math.Cos(s_x) * Math.Cos(s_x));
+ s_a = s_a + Math.Abs(s_e);
+ }
+
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMk2/BenchMk2.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMk2/BenchMk2.csproj
new file mode 100644
index 0000000000..a8c38ad663
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMk2/BenchMk2.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BenchMk2.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/BenchF/BenchMrk/BenchMrk.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMrk/BenchMrk.cs
new file mode 100644
index 0000000000..27a5fe617c
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMrk/BenchMrk.cs
@@ -0,0 +1,66 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class BenchMrk
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 4000000;
+#endif
+
+ private static int s_i, s_n;
+ private static float s_p, s_a, s_x, s_f, s_e;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ s_p = (float)Math.Acos(-1.0);
+ s_a = 0.0F;
+ s_n = Iterations;
+ s_f = s_p / s_n;
+ for (s_i = 1; s_i <= s_n; ++s_i)
+ {
+ s_f = s_p / s_n;
+ s_x = s_f * s_i;
+ s_e = (float)(Math.Abs(Math.Log(Math.Exp(s_x)) / s_x) - Math.Sqrt((Math.Sin(s_x) * Math.Sin(s_x)) + Math.Cos(s_x) * Math.Cos(s_x)));
+ s_a = s_a + Math.Abs(s_e);
+ }
+
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMrk/BenchMrk.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMrk/BenchMrk.csproj
new file mode 100644
index 0000000000..a2acd3bea8
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/BenchMrk/BenchMrk.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BenchMrk.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/BenchF/Bisect/Bisect.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Bisect/Bisect.cs
new file mode 100644
index 0000000000..1c27003567
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Bisect/Bisect.cs
@@ -0,0 +1,163 @@
+// 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.
+//
+// The Bisect algorithm adapted from Conte and de Boor
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Bisect
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 400000;
+#endif
+
+ public static volatile object VolatileObject;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void Escape(object obj)
+ {
+ VolatileObject = obj;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ int idbg, iflag;
+ double a, b, error, p1, xi;
+
+ iflag = 0;
+ error = 0.0;
+ xi = 0.0;
+ idbg = 0;
+ for (int i = 1; i <= Iterations; i++)
+ {
+ for (int j = 1; j <= 10; j++)
+ {
+ a = 1.0;
+ b = 2.0;
+ p1 = 0.000001;
+ Inner(ref a, ref b, ref p1, out iflag);
+ if (iflag > 1)
+ {
+ goto L999;
+ }
+
+ xi = (a + b) / 2.0;
+ if (a > b)
+ {
+ error = (a - b) / 2.0;
+ }
+ else
+ {
+ error = (b - a) / 2.0;
+ }
+
+ if (idbg != 0)
+ {
+ System.Console.WriteLine(" the root is {0:E} plus/minus {1:E}\n", xi, error);
+ }
+ }
+ }
+ L999:
+ {
+ }
+
+ // Escape iflag, error, xi so that they appear live
+ Escape(iflag);
+ Escape(error);
+ Escape(xi);
+
+ return true;
+ }
+
+ private static double FF(double x)
+ {
+ return ((-1.0 - (x * (1.0 - (x * x)))));
+ }
+
+ private static void Inner(ref double a, ref double b, ref double xtol, out int iflag)
+ {
+ double fa, error;
+ double xm, fm;
+
+ iflag = 0;
+ fa = FF(a);
+ /* check for sign change */
+ if (((fa) * FF(b)) < 0.0)
+ {
+ goto L5;
+ }
+
+ iflag = 2;
+ goto L99;
+
+ L5:
+ {
+ error = System.Math.Abs(b - a);
+ }
+ L6:
+ error = error / 2.0;
+ /* check for sufficiently small interval */
+ if (error < xtol)
+ {
+ goto L99;
+ }
+ xm = (a + b) / 2.0;
+ /* check for unreasonable error requirement */
+ if (xm + error == xm)
+ {
+ goto L20;
+ }
+
+ fm = FF(xm);
+ /* change to new interval */
+ if (fa * fm < 0.0)
+ {
+ goto L9;
+ }
+ a = xm;
+ fa = fm;
+ goto L6;
+ L9:
+ b = xm;
+ goto L6;
+ L20:
+ iflag = 1;
+ L99:
+ {
+ }
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Bisect/Bisect.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/Bisect/Bisect.csproj
new file mode 100644
index 0000000000..210f6f1940
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Bisect/Bisect.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Bisect.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/BenchF/DMath/DMath.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/DMath/DMath.cs
new file mode 100644
index 0000000000..a2c3a385cd
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/DMath/DMath.cs
@@ -0,0 +1,113 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class DMath
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 100000;
+#endif
+
+ private const double Deg2Rad = 57.29577951;
+ private static volatile object s_volatileObject;
+
+ private static void Escape(object obj)
+ {
+ s_volatileObject = obj;
+ }
+
+ private static double Fact(double n)
+ {
+ double res;
+ res = 1.0;
+ while (n > 0.0)
+ {
+ res *= n;
+ n -= 1.0;
+ }
+
+ return res;
+ }
+
+ private static double Power(double n, double p)
+ {
+ double res;
+ res = 1.0;
+ while (p > 0.0)
+ {
+ res *= n;
+ p -= 1.0;
+ }
+
+ return res;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench(int loop)
+ {
+ double[] sines = new double[91];
+ double angle, radians, sine, worksine, temp, k;
+ double diff;
+
+ for (int iter = 1; iter <= loop; iter++)
+ {
+ for (angle = 0.0; angle <= 90.0; angle += 1.0)
+ {
+ radians = angle / Deg2Rad;
+ k = 0.0;
+ worksine = 0.0;
+ do
+ {
+ sine = worksine;
+ temp = (2.0 * k) + 1.0;
+ worksine += (Power(-1.0, k) / Fact(temp)) * Power(radians, temp);
+ k += 1.0;
+ diff = Math.Abs(sine - worksine);
+ } while (diff > 1E-8);
+
+ sines[(int)angle] = worksine;
+ }
+ }
+
+ // Escape sines array so that its elements appear live-out
+ Escape(sines);
+
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench(Iterations);
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench(Iterations);
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/DMath/DMath.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/DMath/DMath.csproj
new file mode 100644
index 0000000000..6ca1184365
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/DMath/DMath.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="DMath.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/BenchF/FFT/FFT.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/FFT/FFT.cs
new file mode 100644
index 0000000000..3e853273fb
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/FFT/FFT.cs
@@ -0,0 +1,153 @@
+// 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.
+//
+// FFT benchmark adapted from a Fortran routine from the book
+// Digital Signal Analysis, Samuel Stearns, Hayden Book Co.
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class FFT
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 300000;
+#endif
+
+ private static readonly int s_points = 16;
+ public static volatile object VolatileObject;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void Escape(object obj)
+ {
+ VolatileObject = obj;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ double[] fr = new double[17];
+ double[] fi = new double[17];
+
+ int i;
+ double t;
+
+ for (int iter = 1; iter <= Iterations; iter++)
+ {
+ for (i = 1; i <= s_points; ++i)
+ {
+ t = ((double)0.375) * ((double)(i - 1));
+ fr[i] = System.Math.Exp(-t) * System.Math.Sin(t);
+ fi[i] = 0.0;
+ }
+ FastFourierT(fr, fi, s_points);
+ }
+
+ // Escape the results to live-out.
+ Escape(fr);
+ Escape(fi);
+
+ return true;
+ }
+
+ private static void FastFourierT(double[] fr, double[] fi, int n)
+ {
+ int i, j, l, m;
+ int istep, mr, nn;
+ double a, el, tr, ti, wr, wi;
+
+ mr = 0;
+ nn = n - 1;
+ m = 1;
+
+ do
+ {
+ l = n;
+ for (l = l / 2; ((mr + l) > nn); l = l / 2)
+ {
+ }
+ // l <= n/2
+ // mr <= (mr % l) + l ==> mr <= (l - 1) + l = 2l - 1
+ // ==> mr <= n - 1
+ mr = (mr % l) + l;
+
+ if (mr > m)
+ {
+ // Accessing upto m + 1 ==> nn + 1 ==> n - 1 + 1 ==> n
+ tr = fr[m + 1];
+ // Accessing upto mr + 1 ==> n - 1 + 1 ==> n
+ fr[m + 1] = fr[mr + 1];
+ fr[mr + 1] = tr;
+ ti = fi[m + 1];
+ fi[m + 1] = fi[mr + 1];
+ fi[mr + 1] = ti;
+ }
+ ++m;
+ } while (m <= nn);
+
+ for (l = 1; l < n; l = istep)
+ {
+ istep = 2 * l;
+
+ el = ((double)l);
+ m = 1;
+ do
+ {
+ a = ((double)3.1415926535) * (((double)(1 - m)) / el);
+ wr = System.Math.Cos(a);
+ wi = System.Math.Sin(a);
+ i = m;
+ do
+ {
+ // l can have a maximum value of 2^x where 2^x < n and 2^(x+1) = n, since n is even
+ // ==> istep <= 2^(x+1) ==> i can only take the value of m and m <= l
+ // Therefore, j <= l + l
+ // or j <= 2^x + 2^x = 2^(x+1) = n
+ // i.e. j <= n
+ j = i + l;
+
+ // Accessing upto j <= n, i <= n
+ tr = wr * fr[j] - wi * fi[j];
+ ti = wr * fi[j] + wi * fr[j];
+ fr[j] = fr[i] - tr;
+ fi[j] = fi[i] - ti;
+ fr[i] = fr[i] + tr;
+ fi[i] = fi[i] + ti;
+ i += istep;
+ } while (i <= n);
+ ++m;
+ } while (m <= l);
+ }
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/FFT/FFT.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/FFT/FFT.csproj
new file mode 100644
index 0000000000..bfb377fe62
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/FFT/FFT.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="FFT.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/BenchF/InProd/InProd.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/InProd/InProd.cs
new file mode 100644
index 0000000000..ff54ea7acd
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/InProd/InProd.cs
@@ -0,0 +1,134 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class InProd
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 70;
+#endif
+
+ private const int RowSize = 10 * Iterations;
+
+ private static int s_seed;
+
+ private static T[][] AllocArray<T>(int n1, int n2)
+ {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i)
+ {
+ a[i] = new T[n2];
+ }
+ return a;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ double[][] rma = AllocArray<double>(RowSize, RowSize);
+ double[][] rmb = AllocArray<double>(RowSize, RowSize);
+ double[][] rmr = AllocArray<double>(RowSize, RowSize);
+
+ double sum;
+
+ Inner(rma, rmb, rmr);
+
+ for (int i = 1; i < RowSize; i++)
+ {
+ for (int j = 1; j < RowSize; j++)
+ {
+ sum = 0;
+ for (int k = 1; k < RowSize; k++)
+ {
+ sum = sum + rma[i][k] * rmb[k][j];
+ }
+ if (rmr[i][j] != sum)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private static void InitRand()
+ {
+ s_seed = 7774755;
+ }
+
+ private static int Rand()
+ {
+ s_seed = (s_seed * 77 + 13218009) % 3687091;
+ return s_seed;
+ }
+
+ private static void InitMatrix(double[][] m)
+ {
+ for (int i = 1; i < RowSize; i++)
+ {
+ for (int j = 1; j < RowSize; j++)
+ {
+ m[i][j] = (Rand() % 120 - 60) / 3;
+ }
+ }
+ }
+
+ private static void InnerProduct(out double result, double[][] a, double[][] b, int row, int col)
+ {
+ result = 0.0;
+ for (int i = 1; i < RowSize; i++)
+ {
+ result = result + a[row][i] * b[i][col];
+ }
+ }
+
+ private static void Inner(double[][] rma, double[][] rmb, double[][] rmr)
+ {
+ InitRand();
+ InitMatrix(rma);
+ InitMatrix(rmb);
+ for (int i = 1; i < RowSize; i++)
+ {
+ for (int j = 1; j < RowSize; j++)
+ {
+ InnerProduct(out rmr[i][j], rma, rmb, i, j);
+ }
+ }
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/InProd/InProd.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/InProd/InProd.csproj
new file mode 100644
index 0000000000..416c1b9662
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/InProd/InProd.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="InProd.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/BenchF/InvMt/InvMt.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/InvMt/InvMt.cs
new file mode 100644
index 0000000000..a5f387b7f5
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/InvMt/InvMt.cs
@@ -0,0 +1,137 @@
+// 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.
+//
+// Solution of linear algebraic equations and matrix inversion.
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class InvMt
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 80;
+#endif
+
+ private const int MatSize = Iterations;
+
+ private static T[][] AllocArray<T>(int n1, int n2)
+ {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i)
+ {
+ a[i] = new T[n2];
+ }
+ return a;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ double[][] t = AllocArray<double>(MatSize + 1, (MatSize + 1) * 2);
+
+ double det, detinv, ber, p;
+ int n, i, j;
+
+ n = MatSize;
+ for (i = 1; i <= n; i++)
+ {
+ for (j = 1; j <= n; j++)
+ {
+ if (i == j)
+ {
+ t[i][j] = 2.0001;
+ t[i][n + 1 + j] = 1.0;
+ }
+ else
+ {
+ t[i][j] = 1.0001;
+ t[i][n + 1 + j] = 0.0;
+ }
+ }
+ t[i][n + 1] = System.Math.Sqrt((float)i);
+ }
+
+ Inner(t, out det, ref n);
+
+ for (i = 1; i <= n; i++)
+ {
+ for (j = 1; j <= n; j++)
+ {
+ p = t[i][j];
+ t[i][j] = t[i][n + 1 + j];
+ t[i][n + 1 + j] = p;
+ }
+ }
+
+ Inner(t, out detinv, ref n);
+
+ ber = 0.0;
+ for (i = 1; i <= n; i++)
+ {
+ ber = ber + System.Math.Abs(System.Math.Sqrt((double)i) - t[i][n + 1]);
+ }
+
+ return true;
+ }
+
+ private static void Inner(double[][] t, out double det, ref int n)
+ {
+ double tik, tkk;
+
+ det = 1.0;
+ for (int k = 1; k <= n; k++)
+ {
+ tkk = t[k][k];
+ det = det * tkk;
+
+ for (int j = 1; j <= (2 * n + 1); j++)
+ {
+ t[k][j] = t[k][j] / tkk;
+ }
+
+ for (int i = 1; i <= n; i++)
+ {
+ if (i != k)
+ {
+ tik = t[i][k];
+ for (int j = 1; j <= (2 * n + 1); j++)
+ {
+ t[i][j] = t[i][j] - t[k][j] * tik;
+ }
+ }
+ }
+ }
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/InvMt/InvMt.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/InvMt/InvMt.csproj
new file mode 100644
index 0000000000..c7a4bb91b0
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/InvMt/InvMt.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="InvMt.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/BenchF/LLoops/LLoops.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/LLoops/LLoops.cs
new file mode 100644
index 0000000000..6dcb6c435c
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/LLoops/LLoops.cs
@@ -0,0 +1,650 @@
+// 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.
+//
+// C# adaptation of C implementation of Livermore Loops Fortran benchmark.
+
+/* Livermore Loops coded in C Latest File Modification 20 Oct 92,
+ * by Tim Peters, Kendall Square Res. Corp. tim@ksr.com, ksr!tim@uunet.uu.net
+ * SUBROUTINE KERNEL( TK) replaces the Fortran routine in LFK Test program.
+ ************************************************************************
+ * *
+ * KERNEL executes 24 samples of "C" computation *
+ * *
+ * TK(1) - total cpu time to execute only the 24 kernels.*
+ * TK(2) - total Flops executed by the 24 Kernels *
+ * *
+ ************************************************************************
+ * *
+ * L. L. N. L. " C " K E R N E L S: M F L O P S *
+ * *
+ * These kernels measure " C " numerical computation *
+ * rates for a spectrum of cpu-limited computational *
+ * structures or benchmarks. Mathematical through-put *
+ * is measured in units of millions of floating-point *
+ * operations executed per second, called Megaflops/sec. *
+ * *
+ * Fonzi's Law: There is not now and there never will be a language *
+ * in which it is the least bit difficult to write *
+ * bad programs. *
+ * F.H.MCMAHON 1972 *
+ ************************************************************************
+ *Originally from Greg Astfalk, AT&T, P.O.Box 900, Princeton, NJ. 08540*
+ * by way of Frank McMahon (LLNL). *
+ * *
+ * REFERENCE *
+ * *
+ * F.H.McMahon, The Livermore Fortran Kernels: *
+ * A Computer Test Of The Numerical Performance Range, *
+ * Lawrence Livermore National Laboratory, *
+ * Livermore, California, UCRL-53745, December 1986. *
+ * *
+ * from: National Technical Information Service *
+ * U.S. Department of Commerce *
+ * 5285 Port Royal Road *
+ * Springfield, VA. 22161 *
+ * *
+ * Changes made to correct many array subscripting problems, *
+ * make more readable (added #define's), include the original *
+ * FORTRAN versions of the runs as comments, and make more *
+ * portable by Kelly O'Hair (LLNL) and Chuck Rasbold (LLNL). *
+ * *
+ ************************************************************************
+ */
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class LLoops
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 4000;
+#endif
+
+ private const double MaxErr = 1.0e-6;
+
+ private double[] _x = new double[1002];
+ private double[] _y = new double[1002];
+ private double[] _z = new double[1002];
+ private double[] _u = new double[501];
+ private double[][] _px;
+ private double[][] _cx;
+ private double[][][] _u1;
+ private double[][][] _u2;
+ private double[][][] _u3;
+ private double[][] _b;
+ private double[] _bnk1 = new double[6];
+ private double[][] _c;
+ private double[] _bnk2 = new double[6];
+ private double[][] _p;
+ private double[] _bnk3 = new double[6];
+ private double[][] _h;
+ private double[] _bnk4 = new double[6];
+ private double[] _bnk5 = new double[6];
+ private double[] _ex = new double[68];
+ private double[] _rh = new double[68];
+ private double[] _dex = new double[68];
+ private double[] _vx = new double[151];
+ private double[] _xx = new double[151];
+ private double[] _grd = new double[151];
+ private int[] _e = new int[193];
+ private int[] _f = new int[193];
+ private int[] _nrops = { 0, 5, 10, 2, 2, 2, 2, 16, 36, 17, 9, 1, 1, 7, 11 };
+ private int[] _loops = { 0, 400, 200, 1000, 510, 1000, 1000, 120, 40, 100, 100, 1000, 1000, 128, 150 };
+ private double[] _checks = {
+ 0, 0.811986948148e+07, 0.356310000000e+03, 0.356310000000e+03, -0.402412007078e+05,
+ 0.136579037764e+06, 0.419716278716e+06,
+ 0.429449847526e+07, 0.314064400000e+06,
+ 0.182709000000e+07, -0.140415250000e+09,
+ 0.374895020500e+09, 0.000000000000e+00,
+ 0.171449024000e+06, -0.510829560800e+07
+ };
+
+ public static volatile object VolatileObject;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void Escape(object obj)
+ {
+ VolatileObject = obj;
+ }
+
+ private static T[][] AllocArray<T>(int n1, int n2)
+ {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i)
+ {
+ a[i] = new T[n2];
+ }
+ return a;
+ }
+
+ private static T[][][] AllocArray<T>(int n1, int n2, int n3)
+ {
+ T[][][] a = new T[n1][][];
+ for (int i = 0; i < n1; ++i)
+ {
+ a[i] = new T[n2][];
+ for (int j = 0; j < n2; j++)
+ {
+ a[i][j] = new T[n3];
+ }
+ }
+
+ return a;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private bool Bench()
+ {
+ _px = AllocArray<double>(16, 101);
+ _cx = AllocArray<double>(16, 101);
+
+ _u1 = AllocArray<double>(6, 23, 3);
+ _u2 = AllocArray<double>(6, 23, 3);
+ _u3 = AllocArray<double>(6, 23, 3);
+
+ _b = AllocArray<double>(65, 9);
+ _c = AllocArray<double>(65, 9);
+ _h = AllocArray<double>(65, 9);
+
+ _p = AllocArray<double>(5, 513);
+
+ for (int i = 0; i < Iterations; i++)
+ {
+ Main1(i < Iterations - 1 ? 0 : 1);
+ }
+
+ return true;
+ }
+
+ private static int Clock()
+ {
+ return 0;
+ }
+
+ private void Main1(int output)
+ {
+ int nt, lw, nl1, nl2;
+ int i, i1, i2, ip, ir, ix, j, j1, j2, k, kx, ky, l, m;
+ double[] ts = new double[21];
+ double[] rt = new double[21];
+ double[] rpm = new double[21];
+ double[] cksum = new double[21];
+ double r, t, a11, a12, a13, sig, a21, a22, a23, a31, a32, a33;
+ double b28, b27, b26, b25, b24, b23, b22, c0, flx, rx1;
+ double q, s, scale, uu, du1, du2, du3, ar, br, cr, xi, ri;
+ int[] mops = new int[20];
+
+ for (i = 1; i <= 20; i++)
+ {
+ cksum[i] = 0.0;
+ }
+
+ r = 4.86;
+ t = 276.0;
+ a11 = 0.5;
+ a12 = 0.33;
+ a13 = 0.25;
+ sig = 0.8;
+ a21 = 0.20;
+ a22 = 0.167;
+ a23 = 0.141;
+ a31 = 0.125;
+ a32 = 0.111;
+ a33 = 0.10;
+ b28 = 0.1;
+ b27 = 0.2;
+ b26 = 0.3;
+ b25 = 0.4;
+ b24 = 0.5;
+ b23 = 0.6;
+ b22 = 0.7;
+ c0 = 0.8;
+ flx = 4.689;
+ rx1 = 64.0;
+
+ /*
+ * end of initialization -- begin timing
+ */
+
+ /* loop 1 hydro excerpt */
+
+ Init();
+ ts[1] = (double)Clock();
+ q = 0.0;
+ for (k = 1; k <= 400; k++)
+ {
+ _x[k] = q + _y[k] * (r * _z[k + 10] + t * _z[k + 11]);
+ }
+ ts[1] = (double)Clock() - ts[1];
+ for (k = 1; k <= 400; k++)
+ {
+ cksum[1] += (double)k * _x[k];
+ }
+
+ /* loop 2 mlr, inner product */
+
+ Init();
+ ts[2] = (double)Clock();
+ q = 0.0;
+ for (k = 1; k <= 996; k += 5)
+ {
+ q += _z[k] * _x[k] + _z[k + 1] * _x[k + 1] + _z[k + 2] * _x[k + 2] + _z[k + 3] * _x[k + 3] + _z[k + 4] * _x[k + 4];
+ }
+ ts[2] = (double)Clock() - ts[2];
+ cksum[2] = q;
+
+ /* loop 3 inner prod */
+
+ Init();
+ ts[3] = (double)Clock();
+ q = 0.0;
+ for (k = 1; k <= 1000; k++)
+ {
+ q += _z[k] * _x[k];
+ }
+ ts[3] = (double)Clock() - ts[3];
+ cksum[3] = q;
+
+ /* loop 4 banded linear equarions */
+
+ Init();
+ ts[4] = (double)Clock();
+ for (l = 7; l <= 107; l += 50)
+ {
+ lw = l;
+ for (j = 30; j <= 870; j += 5)
+ {
+ _x[l - 1] -= _x[lw++] * _y[j];
+ }
+ _x[l - 1] = _y[5] * _x[l - 1];
+ }
+ ts[4] = (double)Clock() - ts[4];
+ for (l = 7; l <= 107; l += 50)
+ {
+ cksum[4] += (double)l * _x[l - 1];
+ }
+
+ /* loop 5 tri-diagonal elimination, below diagonal */
+
+ Init();
+ ts[5] = (double)Clock();
+ for (i = 2; i <= 998; i += 3)
+ {
+ _x[i] = _z[i] * (_y[i] - _x[i - 1]);
+ _x[i + 1] = _z[i + 1] * (_y[i + 1] - _x[i]);
+ _x[i + 2] = _z[i + 2] * (_y[i + 2] - _x[i + 1]);
+ }
+ ts[5] = (double)Clock() - ts[5];
+ for (i = 2; i <= 1000; i++)
+ {
+ cksum[5] += (double)i * _x[i];
+ }
+
+ /* loop 6 tri-diagonal elimination, above diagonal */
+
+ Init();
+ ts[6] = (double)Clock();
+ for (j = 3; j <= 999; j += 3)
+ {
+ i = 1003 - j;
+ _x[i] = _x[i] - _z[i] * _x[i + 1];
+ _x[i - 1] = _x[i - 1] - _z[i - 1] * _x[i];
+ _x[i - 2] = _x[i - 2] - _z[i - 2] * _x[i - 1];
+ }
+ ts[6] = (double)Clock() - ts[6];
+ for (j = 1; j <= 999; j++)
+ {
+ l = 1001 - j;
+ cksum[6] += (double)j * _x[l];
+ }
+
+ /* loop 7 equation of state excerpt */
+
+ Init();
+ ts[7] = (double)Clock();
+ for (m = 1; m <= 120; m++)
+ {
+ _x[m] = _u[m] + r * (_z[m] + r * _y[m]) + t * (_u[m + 3] + r * (_u[m + 2] + r * _u[m + 1]) + t * (_u[m + 6] + r * (_u[m + 5] + r * _u[m + 4])));
+ }
+ ts[7] = (double)Clock() - ts[7];
+ for (m = 1; m <= 120; m++)
+ {
+ cksum[7] += (double)m * _x[m];
+ }
+
+ /* loop 8 p.d.e. integration */
+
+ Init();
+ ts[8] = (double)Clock();
+ nl1 = 1;
+ nl2 = 2;
+ for (kx = 2; kx <= 3; kx++)
+ {
+ for (ky = 2; ky <= 21; ky++)
+ {
+ du1 = _u1[kx][ky + 1][nl1] - _u1[kx][ky - 1][nl1];
+ du2 = _u2[kx][ky + 1][nl1] - _u2[kx][ky - 1][nl1];
+ du3 = _u3[kx][ky + 1][nl1] - _u3[kx][ky - 1][nl1];
+ _u1[kx][ky][nl2] = _u1[kx][ky][nl1] + a11 * du1 + a12 * du2 + a13 * du3 + sig * (_u1[kx + 1][ky][nl1]
+ - 2.0 * _u1[kx][ky][nl1] + _u1[kx - 1][ky][nl1]);
+ _u2[kx][ky][nl2] = _u2[kx][ky][nl1] + a21 * du1 + a22 * du2 + a23 * du3 + sig * (_u2[kx + 1][ky][nl1]
+ - 2.0 * _u2[kx][ky][nl1] + _u2[kx - 1][ky][nl1]);
+ _u3[kx][ky][nl2] = _u3[kx][ky][nl1] + a31 * du1 + a32 * du2 + a33 * du3 + sig * (_u3[kx + 1][ky][nl1]
+ - 2.0 * _u3[kx][ky][nl1] + _u3[kx - 1][ky][nl1]);
+ }
+ }
+ ts[8] = (double)Clock() - ts[8];
+ for (i = 1; i <= 2; i++)
+ {
+ for (kx = 2; kx <= 3; kx++)
+ {
+ for (ky = 2; ky <= 21; ky++)
+ {
+ cksum[8] += (double)kx * (double)ky * (double)i * (_u1[kx][ky][i] + _u2[kx][ky][i] + _u3[kx][ky][i]);
+ }
+ }
+ }
+
+ /* loop 9 integrate predictors */
+
+ Init();
+ ts[9] = (double)Clock();
+ for (i = 1; i <= 100; i++)
+ {
+ _px[1][i] = b28 * _px[13][i] + b27 * _px[12][i] + b26 * _px[11][i] + b25 * _px[10][i] + b24 * _px[9][i] +
+ b23 * _px[8][i] + b22 * _px[7][i] + c0 * (_px[5][i] + _px[6][i]) + _px[3][i];
+ }
+ ts[9] = (double)Clock() - ts[9];
+ for (i = 1; i <= 100; i++)
+ {
+ cksum[9] += (double)i * _px[1][i];
+ }
+
+ /* loop 10 difference predictors */
+
+ Init();
+ ts[10] = (double)Clock();
+ for (i = 1; i <= 100; i++)
+ {
+ ar = _cx[5][i];
+ br = ar - _px[5][i];
+ _px[5][i] = ar;
+ cr = br - _px[6][i];
+ _px[6][i] = br;
+ ar = cr - _px[7][i];
+ _px[7][i] = cr;
+ br = ar - _px[8][i];
+ _px[8][i] = ar;
+ cr = br - _px[9][i];
+ _px[9][i] = br;
+ ar = cr - _px[10][i];
+ _px[10][i] = cr;
+ br = ar - _px[11][i];
+ _px[11][i] = ar;
+ cr = br - _px[12][i];
+ _px[12][i] = br;
+ _px[14][i] = cr - _px[13][i];
+ _px[13][i] = cr;
+ }
+ ts[10] = (double)Clock() - ts[10];
+ for (i = 1; i <= 100; i++)
+ {
+ for (k = 5; k <= 14; k++)
+ {
+ cksum[10] += (double)k * (double)i * _px[k][i];
+ }
+ }
+
+ /* loop 11 first sum. */
+
+ Init();
+ ts[11] = (double)Clock();
+ _x[1] = _y[1];
+ for (k = 2; k <= 1000; k++)
+ {
+ _x[k] = _x[k - 1] + _y[k];
+ }
+ ts[11] = (double)Clock() - ts[11];
+ for (k = 1; k <= 1000; k++)
+ {
+ cksum[11] += (double)k * _x[k];
+ }
+
+ /* loop 12 first diff. */
+
+ Init();
+ ts[12] = (double)Clock();
+ for (k = 1; k <= 999; k++)
+ {
+ _x[k] = _y[k + 1] - _y[k];
+ }
+ ts[12] = (double)Clock() - ts[12];
+ for (k = 1; k <= 999; k++)
+ {
+ cksum[12] += (double)k * _x[k];
+ }
+
+ /* loop 13 2-d particle pusher */
+
+ Init();
+ ts[13] = (double)Clock();
+ for (ip = 1; ip <= 128; ip++)
+ {
+ i1 = (int)_p[1][ip];
+ j1 = (int)_p[2][ip];
+ _p[3][ip] += _b[i1][j1];
+ _p[4][ip] += _c[i1][j1];
+ _p[1][ip] += _p[3][ip];
+ _p[2][ip] += _p[4][ip];
+ // Each element of m_p, m_b and m_c is initialized to 1.00025 in Init().
+ // From the assignments above,
+ // i2 = m_p[1][ip] = m_p[1][ip] + m_p[3][ip] = m_p[1][ip] + m_p[3][ip] + m_b[i1][j1] = 1 + 1 + 1 = 3
+ // j2 = m_p[2][ip] = m_p[2][ip] + m_p[4][ip] = m_p[2][ip] + m_p[4][ip] + m_c[i1][j1] = 1 + 1 + 1 = 3
+ i2 = (int)_p[1][ip];
+ j2 = (int)_p[2][ip];
+ // Accessing m_y, m_z upto 35
+ _p[1][ip] += _y[i2 + 32];
+ _p[2][ip] += _z[j2 + 32];
+
+ i2 += _e[i2 + 32];
+ j2 += _f[j2 + 32];
+ _h[i2][j2] += 1.0;
+ }
+ ts[13] = (double)Clock() - ts[13];
+ for (ip = 1; ip <= 128; ip++)
+ {
+ cksum[13] += (double)ip * (_p[3][ip] + _p[4][ip] + _p[1][ip] + _p[2][ip]);
+ }
+ for (k = 1; k <= 64; k++)
+ {
+ for (ix = 1; ix <= 8; ix++)
+ {
+ cksum[13] += (double)k * (double)ix * _h[k][ix];
+ }
+ }
+
+ /* loop 14 1-d particle pusher */
+
+ Init();
+ ts[14] = (double)Clock();
+ for (k = 1; k <= 150; k++)
+ {
+ // m_grd[150] = 13.636
+ // Therefore ix <= 13
+ ix = (int)_grd[k];
+ xi = (double)ix;
+ _vx[k] += _ex[ix] + (_xx[k] - xi) * _dex[ix];
+ _xx[k] += _vx[k] + flx;
+ ir = (int)_xx[k];
+ ri = (double)ir;
+ rx1 = _xx[k] - ri;
+ ir = System.Math.Abs(ir % 64);
+ _xx[k] = ri + rx1;
+ // ir < 64 since ir = ir % 64
+ // So m_rh is accessed upto 64
+ _rh[ir] += 1.0 - rx1;
+ _rh[ir + 1] += rx1;
+ }
+ ts[14] = (double)Clock() - ts[14];
+ for (k = 1; k <= 150; k++)
+ {
+ cksum[14] += (double)k * (_vx[k] + _xx[k]);
+ }
+ for (k = 1; k <= 67; k++)
+ {
+ cksum[14] += (double)k * _rh[k];
+ }
+
+ /* time the clock call */
+
+ ts[15] = (double)Clock();
+ ts[15] = (double)Clock() - ts[15];
+
+ /* scale= set to convert time to micro-seconds */
+
+ scale = 1.0;
+ rt[15] = ts[15] * scale;
+
+ nt = 14;
+ t = s = uu = 0.0;
+ for (k = 1; k <= nt; k++)
+ {
+ rt[k] = (ts[k] - ts[15]) * scale;
+ t += rt[k];
+ mops[k] = _nrops[k] * _loops[k];
+ s += (double)mops[k];
+ rpm[k] = 0.0;
+ if (rt[k] != 0.0)
+ {
+ rpm[k] = (double)mops[k] / rt[k];
+ }
+ uu += rpm[k];
+ }
+ uu /= (double)nt;
+ s /= t;
+
+ // Ensure that the array elements are live-out
+ Escape(ts);
+ Escape(rt);
+ Escape(rpm);
+ Escape(cksum);
+ Escape(mops);
+ }
+
+ private void Init()
+ {
+ int j, k, l;
+
+ for (k = 1; k <= 1000; k++)
+ {
+ _x[k] = 1.11;
+ _y[k] = 1.123;
+ _z[k] = 0.321;
+ }
+
+ for (k = 1; k <= 500; k++)
+ {
+ _u[k] = 0.00025;
+ }
+
+ for (k = 1; k <= 15; k++)
+ {
+ for (l = 1; l <= 100; l++)
+ {
+ _px[k][l] = l;
+ _cx[k][l] = l;
+ }
+ }
+
+ for (j = 1; j < 6; j++)
+ {
+ for (k = 1; k < 23; k++)
+ {
+ for (l = 1; l < 3; l++)
+ {
+ _u1[j][k][l] = k;
+ _u2[j][k][l] = k + k;
+ _u3[j][k][l] = k + k + k;
+ }
+ }
+ }
+
+ for (j = 1; j < 65; j++)
+ {
+ for (k = 1; k < 9; k++)
+ {
+ _b[j][k] = 1.00025;
+ _c[j][k] = 1.00025;
+ _h[j][k] = 1.00025;
+ }
+ }
+
+ for (j = 1; j < 6; j++)
+ {
+ _bnk1[j] = j * 100;
+ _bnk2[j] = j * 110;
+ _bnk3[j] = j * 120;
+ _bnk4[j] = j * 130;
+ _bnk5[j] = j * 140;
+ }
+
+ for (j = 1; j < 5; j++)
+ {
+ for (k = 1; k < 513; k++)
+ {
+ _p[j][k] = 1.00025;
+ }
+ }
+
+ for (j = 1; j < 193; j++)
+ {
+ _e[j] = _f[j] = 1;
+ }
+
+ for (j = 1; j < 68; j++)
+ {
+ _ex[j] = _rh[j] = _dex[j] = (double)j;
+ }
+
+ for (j = 1; j < 151; j++)
+ {
+ _vx[j] = 0.001;
+ _xx[j] = 0.001;
+ _grd[j] = (double)(j / 8 + 3);
+ }
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ var lloops = new LLoops();
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ lloops.Bench();
+ }
+ }
+ }
+
+ private bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ var lloops = new LLoops();
+ bool result = lloops.TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/LLoops/LLoops.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/LLoops/LLoops.csproj
new file mode 100644
index 0000000000..cabdbd6607
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/LLoops/LLoops.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="LLoops.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/BenchF/Lorenz/Lorenz.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Lorenz/Lorenz.cs
new file mode 100644
index 0000000000..bff6398d3b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Lorenz/Lorenz.cs
@@ -0,0 +1,134 @@
+// 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.
+//
+// This program solves the "lorenz" equations using Runge-Kutta 4
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Lorenz
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 8000000;
+#endif
+
+ private static double s_t = 0.0;
+ private static double s_x = 5.0;
+ private static double s_y = 2.0;
+ private static double s_z = 27.0;
+
+ private static int s_nsteps = Iterations;
+ private static double s_h = -1.0;
+ private static int s_printDerivative = -1;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ double k1, k2, k3, k4;
+ double l1, l2, l3, l4;
+ double m1, m2, m3, m4;
+ double hdiv2, hdiv6;
+ int i;
+
+ if (s_h < 0.0)
+ {
+ s_h = 20.0 / (double)s_nsteps;
+ }
+ if (s_printDerivative < 0)
+ {
+ s_printDerivative = s_nsteps;
+ }
+
+ hdiv2 = s_h / 2.0;
+ hdiv6 = s_h / 6.0;
+
+ for (i = 0; i < s_nsteps; ++i)
+ {
+ double t_arg, x_arg, y_arg, z_arg;
+
+ k1 = F(s_t, s_x, s_y, s_z);
+ l1 = G(s_t, s_x, s_y, s_z);
+ m1 = H(s_t, s_x, s_y, s_z);
+
+ t_arg = s_t + hdiv2;
+ x_arg = s_x + hdiv2 * k1;
+ y_arg = s_y + hdiv2 * l1;
+ z_arg = s_z + hdiv2 * m1;
+
+ k2 = F(t_arg, x_arg, y_arg, z_arg);
+ l2 = G(t_arg, x_arg, y_arg, z_arg);
+ m2 = H(t_arg, x_arg, y_arg, z_arg);
+
+ x_arg = s_x + hdiv2 * k2;
+ y_arg = s_y + hdiv2 * l2;
+ z_arg = s_z + hdiv2 * m2;
+
+ k3 = F(t_arg, x_arg, y_arg, z_arg);
+ l3 = G(t_arg, x_arg, y_arg, z_arg);
+ m3 = H(t_arg, x_arg, y_arg, z_arg);
+
+ t_arg = s_t + s_h;
+ x_arg = s_x + s_h * k3;
+ y_arg = s_y + s_h * l3;
+ z_arg = s_z + s_h * m3;
+
+ k4 = F(t_arg, x_arg, y_arg, z_arg);
+ l4 = G(t_arg, x_arg, y_arg, z_arg);
+ m4 = H(t_arg, x_arg, y_arg, z_arg);
+
+ s_x = s_x + hdiv6 * (k1 + 2.0 * k2 + 2.0 * k3 + k4);
+ s_y = s_y + hdiv6 * (l1 + 2.0 * l2 + 2.0 * l3 + l4);
+ s_z = s_z + hdiv6 * (m1 + 2.0 * m2 + 2.0 * m3 + m4);
+ s_t = t_arg;
+ }
+
+ return true;
+ }
+
+ private static double F(double t, double x, double y, double z)
+ {
+ return (10.0 * (y - x));
+ }
+
+ private static double G(double t, double x, double y, double z)
+ {
+ return (x * (28.0 - z) - y);
+ }
+
+ private static double H(double t, double x, double y, double z)
+ {
+ return (x * y - (8.0 * z) / 3.0);
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Lorenz/Lorenz.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/Lorenz/Lorenz.csproj
new file mode 100644
index 0000000000..593474426a
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Lorenz/Lorenz.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Lorenz.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/BenchF/MatInv4/MatInv4.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/MatInv4/MatInv4.cs
new file mode 100644
index 0000000000..eb5e33b130
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/MatInv4/MatInv4.cs
@@ -0,0 +1,495 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class MatInv4
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 60;
+#endif
+
+ private static float s_det;
+
+ private struct X
+ {
+ public float[] A;
+ public X(int size)
+ {
+ A = new float[size];
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ X a = new X(Iterations * Iterations);
+ float[] b = new float[Iterations * Iterations];
+ float[] c = new float[Iterations * Iterations];
+ float[] d = new float[Iterations * Iterations];
+ float[] l1 = new float[Iterations];
+ float[] l2 = new float[Iterations];
+
+ int i, k, n, nsq;
+
+ n = Iterations;
+ nsq = n * n;
+ for (i = 0; i < n; ++i)
+ {
+ for (k = 0; k < n; ++k)
+ {
+ if (i == k)
+ {
+ a.A[i * n + k] = 40.0F;
+ }
+ else
+ {
+ a.A[i * n + k] = 0.0F;
+ }
+ }
+ }
+
+ for (i = 0; i < n; ++i)
+ {
+ for (k = i; k < nsq; k += n)
+ {
+ b[k] = a.A[k];
+ }
+ }
+
+ /*** second(&t1); ***/
+
+ MinV1(b, ref n, out s_det, l1, l2);
+
+ if (s_det == 0.0F)
+ {
+ goto L990;
+ }
+
+ /*** second(&tx); ***/
+
+ MProd(b, a.A, c, ref n);
+ for (k = 1; k <= nsq; ++k)
+ {
+ b[k - 1] = a.A[k - 1];
+ }
+
+ /*** second(&tx); ***/
+
+ MinV2(b, ref n, out s_det, l1, l2);
+
+ if (s_det == 0.0F)
+ {
+ goto L990;
+ }
+
+ /*** second(&ty); ***/
+
+ MProd(b, a.A, d, ref n);
+ CompM(c, d, ref n);
+
+ /*** second(&t2); ***/
+
+ return true;
+
+ L990:
+ {
+ }
+
+ return true;
+ }
+
+ private static void MinV1(float[] a, ref int n, out float d, float[] l, float[] m)
+ {
+ float biga, hold;
+ int i, j, k, ij, ik, ji, jk, nk, ki, kj, kk, iz, jp, jq, jr;
+
+ d = 1.0F;
+ ji = 0;
+ hold = 0.0F;
+ nk = -n;
+ for (k = 1; k <= n; ++k)
+ {
+ nk = nk + n;
+ l[k - 1] = k;
+ m[k - 1] = k;
+ kk = nk + k;
+ biga = a[kk - 1];
+ for (j = k; j <= n; ++j)
+ {
+ // j <= n, so iz <= n^2 - n
+ iz = n * (j - 1);
+ for (i = k; i <= n; ++i)
+ {
+ // iz <= n^2 - n and i <= n, so ij <= n^2
+ ij = iz + i;
+ if (System.Math.Abs(biga) >= System.Math.Abs(a[ij - 1]))
+ {
+ continue;
+ }
+ // accessing up to n^2 - 1
+ biga = a[ij - 1];
+ l[k - 1] = i;
+ m[k - 1] = j;
+ }
+ }
+
+ j = (int)l[k - 1];
+
+ if (j <= k)
+ {
+ goto L35;
+ }
+
+ // -n < ki <= 0
+ ki = k - n;
+ for (i = 1; i <= n; ++i)
+ {
+ // i <= n, ki <= n + n + ... + n (n times) i.e. k <= n * n (when ki = 0 initially)
+ ki = ki + n;
+ // Accessing upto n^2 -1
+ hold = -a[ki - 1];
+ // ji <= n^2 - n + n (for ki = 0 initially when k = n and 0 < j <= n)
+ // Therefore ji <= n^2
+ ji = ki - k + j;
+ a[ki - 1] = a[ji - 1];
+ a[ji - 1] = hold;
+ }
+ L35:
+ i = (int)m[k - 1];
+ if (i <= k)
+ {
+ goto L45;
+ }
+
+ // 0 <= jp <= n^2 - n
+ jp = n * (i - 1);
+ for (j = 1; j <= n; ++j)
+ {
+ // 0 < nk <= n * (n-1)
+ // jk <= n^2 - n + n
+ // jk <= n^2
+ jk = nk + j;
+ // jp <= n^2 - n
+ // ji <= n^2 - n + n or ji <= n^2 (since 0 < j <= n)
+ ji = jp + j;
+ hold = -a[jk - 1];
+ a[jk - 1] = a[ji - 1];
+ a[ji - 1] = hold;
+ }
+ L45:
+ if (biga != 0.0F)
+ {
+ goto L48;
+ }
+ d = 0.0F;
+ return;
+
+ L48:
+ for (i = 1; i <= n; ++i)
+ {
+ if (i == k)
+ {
+ break;
+ }
+ // 0 < nk <= n * (n-1)
+ // 0 < ik <= n^2
+ ik = nk + i;
+ a[ik - 1] = a[ik - 1] / (-biga);
+ }
+
+ for (i = 1; i <= n; ++i)
+ {
+ if (i == k)
+ {
+ continue;
+ }
+ // 0 < nk <= n * (n-1)
+ // 0 < ik <= n^2
+ ik = nk + i;
+ hold = a[ik - 1];
+ // -n < ij <= 0
+ ij = i - n;
+ for (j = 1; j <= n; ++j)
+ {
+ // i <= n, ij <= n + n + ... + n (n times) or ij <= n * n
+ ij = ij + n;
+ if (j == k)
+ {
+ continue;
+ }
+ // if i=1, kj = (1 + (n-1) * n) - 1 + n ==> ij = n^2
+ // if i=n, kj = (n * n) - n + n ==> ij = n ^2
+ // So j <= n^2
+ kj = ij - i + k;
+ a[ij - 1] = hold * a[kj - 1] + a[ij - 1];
+ }
+ }
+ kj = k - n;
+ for (j = 1; j <= n; ++j)
+ {
+ // k <= n, kj <= n + n + ... + n (n times) or kj <= n * n
+ kj = kj + n;
+ if (j == k)
+ {
+ continue;
+ }
+ // Accessing upto n^2 - 1
+ a[kj - 1] = a[kj - 1] / biga;
+ }
+ d = d * biga;
+ a[kk - 1] = 1.0F / biga;
+ }
+ k = n;
+ L100:
+ k = k - 1;
+ if (k < 1)
+ {
+ return;
+ }
+ i = (int)l[k - 1];
+ if (i <= k)
+ {
+ goto L120;
+ }
+
+ // 0 <= jq <= n^2 - n
+ // 0 <= jr <= n^2 - n
+ jq = n * (k - 1);
+ jr = n * (i - 1);
+ for (j = 1; j <= n; ++j)
+ {
+ // jk <= n^2 - n + n
+ // jk <= n^2
+ jk = jq + j;
+ hold = a[jk - 1];
+ // ji <= n^2 - n + n
+ // ji <= n^2
+ ji = jr + j;
+ a[jk - 1] = -a[ji - 1];
+ a[ji - 1] = hold;
+ }
+ L120:
+ j = (int)m[k - 1];
+ if (j <= k)
+ {
+ goto L100;
+ }
+ // 0 <= jr <= n^2 - n
+ ki = k - n;
+ for (i = 1; i <= n; ++i)
+ {
+ // ki <= n + n + ... + n (n times) or ki <= n * n
+ ki = ki + n;
+ hold = a[ki - 1];
+ // if i=1, ji = (1 + (n-1) * n) - 1 + n ==> ij = n^2
+ // if i=n, ji = (n * n) - n + n ==> ij = n ^2
+ // Therefore ji <= n^2
+ ji = ki - k + j;
+ a[ki - 1] = -a[ji - 1];
+ }
+ a[ji - 1] = hold;
+ goto L100;
+ }
+
+ private static void MinV2(float[] a, ref int n, out float d, float[] l, float[] m)
+ {
+ float biga, hold;
+ int i, j, k;
+
+ d = 1.0F;
+ for (k = 1; k <= n; ++k)
+ {
+ l[k - 1] = k;
+ m[k - 1] = k;
+ biga = a[(k - 1) * n + (k - 1)];
+ for (j = k; j <= n; ++j)
+ {
+ for (i = k; i <= n; ++i)
+ {
+ // Accessing upto n^2 - n + n - 1 ==> n^2 - 1
+ if (System.Math.Abs(biga) >= System.Math.Abs(a[(i - 1) * n + (j - 1)]))
+ {
+ continue;
+ }
+ biga = a[(i - 1) * n + (j - 1)];
+ l[k - 1] = i;
+ m[k - 1] = j;
+ }
+ }
+ j = (int)l[k - 1];
+ if (l[k - 1] <= k)
+ {
+ goto L200;
+ }
+ for (i = 1; i <= n; ++i)
+ {
+ // Accessing upto n^2 - n + n - 1 ==> n^2 - 1
+ hold = -a[(k - 1) * n + (i - 1)];
+ a[(k - 1) * n + (i - 1)] = a[(j - 1) * n + (i - 1)];
+ a[(j - 1) * n + (i - 1)] = hold;
+ }
+ L200:
+ i = (int)m[k - 1];
+ if (m[k - 1] <= k)
+ {
+ goto L250;
+ }
+ for (j = 1; j <= n; ++j)
+ {
+ // Accessing upto n^2 - n + n - 1 ==> n^2 - 1
+ hold = -a[(j - 1) * n + (k - 1)];
+ a[(j - 1) * n + (k - 1)] = a[(j - 1) * n + (i - 1)];
+ a[(j - 1) * n + (i - 1)] = hold;
+ }
+ L250:
+ if (biga != 0.0F)
+ {
+ goto L300;
+ }
+ d = 0.0F;
+ return;
+
+ L300:
+ for (i = 1; i <= n; ++i)
+ {
+ if (i != k)
+ {
+ // Accessing upto n^2 - n + n - 1 ==> n^2 - 1
+ a[(i - 1) * n + (k - 1)] = a[(i - 1) * n + (k - 1)] / (-biga);
+ }
+ }
+ for (i = 1; i <= n; ++i)
+ {
+ if (i == k)
+ {
+ continue;
+ }
+ for (j = 1; j <= n; ++j)
+ {
+ if (j != k)
+ {
+ // Accessing upto n^2 - n + n - 1 ==> n^2 - 1
+ a[(i - 1) * n + (j - 1)] = a[(i - 1) * n + (k - 1)] * a[(k - 1) * n + (j - 1)] + a[(i - 1) * n + (j - 1)];
+ }
+ }
+ }
+ for (j = 1; j < n; ++j)
+ {
+ if (j != k)
+ {
+ // Accessing upto n^2 - n + n - 1 ==> n^2 - 1
+ a[(k - 1) * n + (j - 1)] = a[(k - 1) * n + (j - 1)] / biga;
+ }
+ }
+ d = d * biga;
+ a[(k - 1) * n + (k - 1)] = 1.0F / biga;
+ }
+ k = n;
+ L400:
+ k = k - 1;
+ if (k < 1)
+ {
+ return;
+ }
+ i = (int)l[k - 1];
+ if (i <= k)
+ {
+ goto L450;
+ }
+ for (j = 1; j <= n; ++j)
+ {
+ // Accessing upto n^2 - n + n - 1 ==> n^2 - 1
+ hold = a[(j - 1) * n + (k - 1)];
+ a[(j - 1) * n + (k - 1)] = -a[(j - 1) * n + (i - 1)];
+ a[(j - 1) * n + (i - 1)] = hold;
+ }
+ L450:
+ j = (int)m[k - 1];
+ if (j <= k)
+ {
+ goto L400;
+ }
+ for (i = 1; i <= n; ++i)
+ {
+ // Accessing upto n^2 - n + n - 1 ==> n^2 - 1
+ hold = a[(k - 1) * n + (i - 1)];
+ a[(k - 1) * n + (i - 1)] = -a[(j - 1) * n + (i - 1)];
+ a[(j - 1) * n + (i - 1)] = hold;
+ }
+ goto L400;
+ }
+
+ private static void MProd(float[] a, float[] b, float[] c, ref int n)
+ {
+ int i, j, k;
+
+ for (i = 1; i <= n; ++i)
+ {
+ for (j = 1; j <= n; ++j)
+ {
+ // Accessing upto n^2 - n + n - 1 ==> n^2 - 1
+ c[(i - 1) * n + (j - 1)] = 0.0F;
+ for (k = 1; k <= n; ++k)
+ {
+ c[(i - 1) * n + (j - 1)] = c[(i - 1) * n + (j - 1)] + a[(i - 1) * n + (k - 1)] * b[(k - 1) * n + (j - 1)];
+ }
+ }
+ }
+ return;
+ }
+
+ private static void CompM(float[] a, float[] b, ref int n)
+ {
+ int i, j;
+ float x, sum = 0.0F;
+
+ //(starting compare.)
+ for (i = 1; i <= n; ++i)
+ {
+ for (j = 1; j <= n; ++j)
+ {
+ x = 0.0F;
+ if (i == j)
+ {
+ x = 1.0F;
+ }
+ sum = sum + System.Math.Abs(System.Math.Abs(a[(i - 1) * n + (j - 1)]) - x);
+ }
+ }
+ return;
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/MatInv4/MatInv4.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/MatInv4/MatInv4.csproj
new file mode 100644
index 0000000000..13238071d2
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/MatInv4/MatInv4.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="MatInv4.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/BenchF/NewtE/NewtE.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtE/NewtE.cs
new file mode 100644
index 0000000000..0fc14132f1
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtE/NewtE.cs
@@ -0,0 +1,135 @@
+// 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.
+//
+// Simultaneous equations by Newton's method adapted from Conte and De Boor
+// to solve F(X,Y)=0 and G(X,Y)=0
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class NewtE
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 1000000;
+#endif
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ double idgb, a, b, x, y, deltaX, deltaY;
+ a = 0;
+ b = 0;
+ x = 0;
+ y = 0;
+ idgb = 0;
+
+ if (idgb != 0)
+ {
+ System.Console.WriteLine("{0}, {1}, F(x,y) , G(x,y) \n", x, y);
+ }
+
+ for (int j = 1; j <= Iterations; j++)
+ {
+ x = 1.0;
+ y = (-2.0);
+ a = F(x, y);
+ b = G(x, y);
+ if (idgb != 0)
+ {
+ System.Console.WriteLine(" {0}, {1}, {2}, {3}\n", x, y, a, b);
+ }
+
+ for (int i = 1; i <= 20; i++)
+ {
+ deltaX = (-F(x, y) * GY(x, y) + G(x, y) * FY(x, y)) / (FX(x, y) * GY(x, y) - FY(x, y) * GX(x, y));
+ deltaY = (-G(x, y) * FX(x, y) + F(x, y) * GX(x, y)) / (FX(x, y) * GY(x, y) - FY(x, y) * GX(x, y));
+ x = x + deltaX;
+ y = y + deltaY;
+ a = F(x, y);
+ b = G(x, y);
+ if (idgb != 0)
+ {
+ System.Console.WriteLine("{0}, {1}, {2}, {3}, {4}\n", i, x, y, a, b);
+ }
+
+ if ((System.Math.Abs(deltaX) < 0.000001) && (System.Math.Abs(deltaY) < 0.000001) &&
+ (System.Math.Abs(a) < 0.000001) && (System.Math.Abs(b) < 0.000001))
+ {
+ goto L11;
+ }
+ }
+ if (idgb != 0)
+ {
+ System.Console.WriteLine("FAILED TO CONVERGE IN 20 ITERATIONS\n");
+ }
+
+ L11:
+ {
+ }
+ }
+
+ return true;
+ }
+
+ private static double F(double x, double y)
+ {
+ return ((x) + 3 * System.Math.Log(x) / System.Math.Log(10.0) - (y) * (y));
+ }
+
+ private static double G(double x, double y)
+ {
+ return (2 * (x) * (x) - (x) * (y) - 5 * (x) + 1);
+ }
+
+ private static double FX(double x, double y)
+ {
+ return (1 + 3 / (System.Math.Log(10.0) * (x)));
+ }
+
+ private static double FY(double x, double y)
+ {
+ return ((-2) * (y));
+ }
+
+ private static double GX(double x, double y)
+ {
+ return (4 * (x) - (y) - 5);
+ }
+
+ private static double GY(double x, double y)
+ {
+ return (-(x));
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/NewtE/NewtE.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtE/NewtE.csproj
new file mode 100644
index 0000000000..dcf02d3f67
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtE/NewtE.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="NewtE.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/BenchF/NewtR/NewtR.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtR/NewtR.cs
new file mode 100644
index 0000000000..cf945bc110
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtR/NewtR.cs
@@ -0,0 +1,131 @@
+// 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.
+//
+// Newton's method adapted from Conte and De Boor
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class NewtR
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 80000000;
+#endif
+
+ public static volatile object VolatileObject;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void Escape(object obj)
+ {
+ VolatileObject = obj;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ int idbg, iflag;
+ double x0, fx0;
+
+ iflag = 0;
+ idbg = 0;
+ fx0 = 0.0;
+ x0 = 1.0;
+
+ for (int i = 1; i <= Iterations; i++)
+ {
+ Inner(ref x0, 0.0000001, 0.0000001, 10, out iflag);
+ if (iflag > 1)
+ {
+ goto L888;
+ }
+
+ fx0 = FF(x0);
+ if (idbg != 0)
+ {
+ System.Console.WriteLine(" THE ROOT IS {0:e} F(ROOT) := {1:E}\n", x0, fx0);
+ }
+
+ L888:
+ {
+ }
+ }
+
+ // Escape iflag, x0, and fx0 so that they appear live
+ Escape(iflag);
+ Escape(x0);
+ Escape(fx0);
+
+ return true;
+ }
+
+ private static double FF(double x)
+ {
+ return (-1.0 - ((x) * (1.0 - ((x) * (x)))));
+ }
+
+ private static double FFDer(double x)
+ {
+ return (3.0 * (x) * (x) - 1.0);
+ }
+
+ private static void Inner(ref double x0, double xtol, double ftol, int ntol, out int iflag)
+ {
+ double fx0, deriv, deltax;
+
+ iflag = 0;
+ for (int n = 1; n <= ntol; n++)
+ {
+ fx0 = FF(x0);
+ if (System.Math.Abs(fx0) < ftol)
+ {
+ goto L999;
+ }
+ deriv = FFDer(x0);
+
+ if (deriv == 0.0)
+ {
+ goto L999;
+ }
+ deltax = fx0 / deriv;
+ x0 = x0 - deltax;
+ if (System.Math.Abs(deltax) < xtol)
+ {
+ goto L999;
+ }
+ }
+ L999:
+ iflag = 2;
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/NewtR/NewtR.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtR/NewtR.csproj
new file mode 100644
index 0000000000..1502b85410
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/NewtR/NewtR.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="NewtR.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/BenchF/Regula/Regula.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Regula/Regula.cs
new file mode 100644
index 0000000000..9743ab698c
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Regula/Regula.cs
@@ -0,0 +1,193 @@
+// 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.
+//
+// The modified regula-falsi routine adapted from Conte and De Boor
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Regula
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 4000000;
+#endif
+
+ public static volatile object VolatileObject;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void Escape(object obj)
+ {
+ VolatileObject = obj;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ double error, fxi;
+ double a, b, xi;
+ int idbg, iflag;
+
+ iflag = 0;
+ idbg = 0;
+ xi = 0;
+ error = 0.0;
+ fxi = 0.0;
+
+ for (int i = 1; i <= Iterations; i++)
+ {
+ a = 1.0;
+ b = 2.0;
+ Inner(ref a, ref b, 0.0000001, 0.0000000001, 30, out iflag);
+ if (iflag > 2)
+ {
+ goto L999;
+ }
+
+ xi = (a + b) / 2.0;
+ error = System.Math.Abs(b - a) / 2.0;
+ fxi = FG(xi);
+
+ if (idbg != 0)
+ {
+ System.Console.WriteLine(" the root is {0:E}", xi);
+ System.Console.WriteLine(" plus/minus {0}\n", error);
+ System.Console.WriteLine(" fg(root):= {0:E}\n", fxi);
+ }
+
+ L999:
+ {
+ }
+ }
+
+ // Escape iflag, xi, error, and fxi so that they appear live
+ Escape(iflag);
+ Escape(xi);
+ Escape(error);
+ Escape(fxi);
+
+ return true;
+ }
+
+ private static double FG(double x)
+ {
+ return (-1.0 - (x * (1.0 - (x * x))));
+ }
+
+ private static void Inner(ref double a, ref double b, double xtol, double ftol, int ntol, out int iflag)
+ {
+ double signfa, prevfw, fa, fb, fw, w;
+
+ iflag = 0;
+ fa = FG(a);
+ if (fa < 0.0)
+ {
+ signfa = -1.0;
+ }
+ else
+ {
+ signfa = 1.0;
+ }
+
+ fb = FG(b);
+ if (signfa * fb <= 0.0)
+ {
+ goto L5;
+ }
+
+ iflag = 3;
+ goto L99;
+
+ L5:
+ w = a;
+ fw = fa;
+ for (int i = 1; i <= ntol; i++)
+ {
+ if (System.Math.Abs(b - a) / 2.0 <= xtol)
+ {
+ goto L99;
+ }
+ if (System.Math.Abs(fw) > ftol)
+ {
+ goto L9;
+ }
+
+ a = w;
+ b = w;
+ iflag = 1;
+ goto L99;
+
+ L9:
+ w = (fa * b - fb * a) / (fa - fb);
+ if (fw < 0.0)
+ {
+ prevfw = -1.0;
+ }
+ else
+ {
+ prevfw = 1.0;
+ }
+ fw = FG(w);
+
+ if (signfa * fw < 0.0)
+ {
+ goto L10;
+ }
+ a = w;
+ fa = fw;
+ if (fw * prevfw > 0.0)
+ {
+ fb = fb / 2.0;
+ }
+ goto L20;
+
+ L10:
+ b = w;
+ fb = fw;
+ if (fw * prevfw > 0.0)
+ {
+ fa = fa / 2.0;
+ }
+
+ L20:
+ {
+ }
+ }
+
+ iflag = 2;
+ L99:
+ {
+ }
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Regula/Regula.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/Regula/Regula.csproj
new file mode 100644
index 0000000000..4cd3e0e069
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Regula/Regula.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Regula.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/BenchF/Romber/Romber.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Romber/Romber.cs
new file mode 100644
index 0000000000..5824cd43cc
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Romber/Romber.cs
@@ -0,0 +1,169 @@
+// 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.
+//
+// Integration by romberg method adapted from Conte and de Boor
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Romber
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 640000;
+#endif
+
+ private static T[][] AllocArray<T>(int n1, int n2)
+ {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i)
+ {
+ a[i] = new T[n2];
+ }
+ return a;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ double[][] r = AllocArray<double>(11, 11);
+ double[][] t = AllocArray<double>(11, 11);
+
+ int idbg, m, n, i, kmax, fourj, j, kmaxm2, l, k, mm1;
+ double sum, ratio, t1, h, a, b;
+
+ for (l = 1; l <= Iterations; l++)
+ {
+ idbg = 0;
+ m = 2;
+ kmax = 6;
+ a = 0;
+ b = 1;
+ h = (b - a) / (m);
+ sum = (F(a) + F(b)) / 2;
+
+ mm1 = m - 1;
+ if (mm1 < 0)
+ {
+ goto L40;
+ }
+ if (mm1 == 0)
+ {
+ goto L10;
+ }
+ for (i = 1; i <= mm1; i++)
+ {
+ t1 = a + i * h;
+ sum = sum + F(t1);
+ }
+
+ L10:
+ t[1][1] = sum * h;
+ if (idbg != 0)
+ {
+ System.Console.WriteLine(" romberg t-table \n");
+ System.Console.WriteLine("{0}\n", t[1][1]);
+ }
+
+ for (k = 2; k <= kmax; k++)
+ {
+ h = h / 2;
+ n = m * 2;
+ sum = 0;
+ for (i = 1; i <= n / 2; i++)
+ {
+ r[k][1] = r[k - 1][1] * System.Math.Sqrt(b * mm1);
+ t1 = a + i * h;
+ sum = sum + F(t1);
+ }
+
+ t[k][1] = t[k - 1][1] / 2 + sum * h;
+ fourj = 1;
+ for (j = 2; j <= k; j++)
+ {
+ fourj = fourj * 4;
+ t[k - 1][j - 1] = t[k][j - 1] - t[k - 1][j - 1];
+ t[k][j] = t[k][j - 1] + t[k - 1][j - 1] / (fourj - 1);
+ }
+
+ if (idbg != 0)
+ {
+ j = 1;
+ System.Console.WriteLine("{0} {1} {2}d\n", t[k][j], j, k);
+ }
+ }
+
+ kmaxm2 = kmax - 2;
+ if (kmaxm2 <= 0)
+ {
+ goto L40;
+ }
+
+ if (idbg != 0)
+ {
+ System.Console.WriteLine(" table of ratios \n");
+ }
+
+ for (k = 1; k <= kmaxm2; k++)
+ {
+ for (j = 1; j <= k; j++)
+ {
+ ratio = 0;
+ if (System.Math.Abs(t[k + 1][j]) > 0)
+ {
+ ratio = t[k][j] / t[k + 1][j];
+ }
+ t[k][j] = ratio;
+ }
+ }
+
+ if (idbg != 0)
+ {
+ j = 1;
+ System.Console.WriteLine("{0} {1} {2}\n", t[k][j], j, k);
+ }
+
+ L40:
+ {
+ }
+ }
+
+ return true;
+ }
+
+ private static double F(double x)
+ {
+ return (System.Math.Exp((-(x)) * (x)));
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Romber/Romber.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/Romber/Romber.csproj
new file mode 100644
index 0000000000..64bbe04cdb
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Romber/Romber.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Romber.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/BenchF/Secant/Secant.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Secant/Secant.cs
new file mode 100644
index 0000000000..e7d1ace2e6
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Secant/Secant.cs
@@ -0,0 +1,142 @@
+// 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.
+//
+// The secant algorithm adapted from Conte and DeBoor
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Secant
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 3000000;
+#endif
+
+ public static volatile object VolatileObject;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void Escape(object obj)
+ {
+ VolatileObject = obj;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ int idbg, iflag;
+ double x0, x1, fx1;
+
+ iflag = 0;
+ idbg = 0;
+ x1 = 0;
+ fx1 = 0.0;
+
+ for (int i = 1; i <= Iterations; i++)
+ {
+ x0 = 1.0;
+ x1 = 2.0;
+ Inner(ref x0, ref x1, 0.0000001, 0.0000001, 30, out iflag);
+ if (iflag > 1)
+ {
+ goto L888;
+ }
+
+ fx1 = FF(x1);
+ if (idbg != 0)
+ {
+ System.Console.WriteLine(" the root is {0:E}, F(ROOT):= {1:E}\n", x1, fx1);
+ }
+ L888:
+ {
+ }
+ }
+
+ // Escape iflag, x1, and fx1 so that they appear live
+ Escape(iflag);
+ Escape(x1);
+ Escape(fx1);
+
+ return true;
+ }
+
+ private static double FF(double x)
+ {
+ return (-1.0 - (x * (1.0 - (x * x))));
+ }
+
+ private static void Inner(ref double x0, ref double x1, double xtol, double ftol, int ntol, out int iflag)
+ {
+ double deltax, deltaf, f0, f1;
+
+ iflag = 0;
+ f0 = FF(x0);
+ deltax = x1 - x0;
+
+ for (int n = 1; n <= ntol; n++)
+ {
+ f1 = FF(x1);
+
+ if (System.Math.Abs(f1) <= ftol)
+ {
+ goto L30;
+ }
+
+ deltaf = f0 - f1;
+ if (deltaf == 0.0)
+ {
+ goto L999;
+ }
+
+ deltax = f1 / deltaf * deltax;
+ x0 = x1;
+ x1 = x1 + deltax;
+ if (System.Math.Abs(deltax) <= xtol)
+ {
+ goto L88;
+ }
+
+ f0 = f1;
+ }
+
+ L999:
+ iflag = 2;
+ goto L88;
+ L30:
+ iflag = 1;
+ L88:
+ {
+ }
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Secant/Secant.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/Secant/Secant.csproj
new file mode 100644
index 0000000000..1a0758ba51
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Secant/Secant.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Secant.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/BenchF/Simpsn/Simpsn.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Simpsn/Simpsn.cs
new file mode 100644
index 0000000000..e1e9f0eb1f
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Simpsn/Simpsn.cs
@@ -0,0 +1,93 @@
+// 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.
+//
+// Integration by Simpson's rule adapted from Conte and de Boor
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Simpsn
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 90000;
+#endif
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ double a, b, x, s, c, h, hov2, half, t1;
+ int idbg, n, nm1;
+
+ s = 0;
+ idbg = 0;
+ if (idbg != 0)
+ {
+ System.Console.WriteLine("simpsons rule\n");
+ }
+
+ for (int j = 1; j <= Iterations; j++)
+ {
+ a = 0;
+ b = 1;
+ c = 4;
+ n = 100;
+ h = (b - a) / n;
+ hov2 = h / System.Math.Sqrt(c);
+ s = 0;
+ t1 = a + hov2;
+ half = F(t1);
+ nm1 = n - 1;
+ for (int i = 1; i <= nm1; i++)
+ {
+ x = a + i * h;
+ s = s + F(x);
+ t1 = x + hov2;
+ half = half + F(t1);
+ s = (h / 6) * (F(a) + 4 * half + 2 * s + F(b));
+ if (idbg != 0)
+ {
+ System.Console.WriteLine(" integral from a = {0} to b = {1} for n = {2} is {3}\n", a, b, n, s);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private static double F(double x)
+ {
+ return (System.Math.Exp((-(x)) * 2));
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Simpsn/Simpsn.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/Simpsn/Simpsn.csproj
new file mode 100644
index 0000000000..67f81313f6
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Simpsn/Simpsn.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Simpsn.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/BenchF/SqMtx/SqMtx.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/SqMtx/SqMtx.cs
new file mode 100644
index 0000000000..673757cedf
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/SqMtx/SqMtx.cs
@@ -0,0 +1,103 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class SqMtx
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 4000;
+#endif
+
+ private const int MatrixSize = 40;
+
+ private static T[][] AllocArray<T>(int n1, int n2)
+ {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i)
+ {
+ a[i] = new T[n2];
+ }
+ return a;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ double[][] a = AllocArray<double>(41, 41);
+ double[][] c = AllocArray<double>(41, 41);
+
+ int i, j;
+
+ for (i = 1; i <= MatrixSize; i++)
+ {
+ for (j = 1; j <= MatrixSize; j++)
+ {
+ a[i][j] = i + j;
+ }
+ }
+
+ for (i = 1; i <= Iterations; i++)
+ {
+ Inner(a, c, MatrixSize);
+ }
+
+ if (c[1][1] == 23820.0)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private static void Inner(double[][] a, double[][] c, int n)
+ {
+ for (int i = 1; i <= n; i++)
+ {
+ for (int j = 1; j <= n; j++)
+ {
+ c[i][j] = 0.0;
+ for (int k = 1; k <= n; k++)
+ {
+ c[i][j] = c[i][j] + a[i][k] * a[k][j];
+ }
+ }
+ }
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/SqMtx/SqMtx.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/SqMtx/SqMtx.csproj
new file mode 100644
index 0000000000..d371554449
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/SqMtx/SqMtx.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="SqMtx.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/BenchF/Trap/Trap.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Trap/Trap.cs
new file mode 100644
index 0000000000..a5e3e5c0d6
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Trap/Trap.cs
@@ -0,0 +1,96 @@
+// 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.
+//
+// Integration by corrected trapezoid rule adapted from Conte and de Boor
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Trap
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 240000;
+#endif
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ int nm1, idbg;
+ double t2, cortrp, trap, a, b, h;
+ trap = 0.0;
+ cortrp = 0.0;
+
+ idbg = 0;
+ for (int j = 1; j <= Iterations; j++)
+ {
+ a = 0;
+ b = 1;
+ if (idbg != 0)
+ {
+ System.Console.WriteLine("trapazoid sum corr.trap sum \n");
+ }
+
+ for (int n = 10; n <= 15; n++)
+ {
+ h = (b - a) / n;
+ nm1 = n - 1;
+ trap = (F(a) + F(b)) / 2;
+ for (int i = 1; i <= nm1; i++)
+ {
+ t2 = a + i * h;
+ trap = trap + F(t2);
+ }
+ trap = trap * h;
+ cortrp = trap + h * h * (FPrime(a) - FPrime(b)) / 12;
+ if (idbg != 0)
+ {
+ System.Console.WriteLine("{0}, {1}, {2}\n", n, trap, cortrp);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private static double F(double x)
+ {
+ return (System.Math.Exp(-(x) * (x)));
+ }
+
+ private static double FPrime(double x)
+ {
+ return ((-2) * (x) * (F(x)));
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Trap/Trap.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/Trap/Trap.csproj
new file mode 100644
index 0000000000..8a46ca61d7
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Trap/Trap.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Trap.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/BenchF/Whetsto/Whetsto.cs b/tests/src/JIT/Performance/CodeQuality/BenchF/Whetsto/Whetsto.cs
new file mode 100644
index 0000000000..2ab0b61ee0
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Whetsto/Whetsto.cs
@@ -0,0 +1,242 @@
+// 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.
+//
+// C# translation of Whetstone Double Precision Benchmark
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Whetsto
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 50000;
+#endif
+
+ private static int s_j, s_k, s_l;
+ private static double s_t, s_t2;
+
+ public static volatile int Volatile_out;
+
+ private static void Escape(int n, int j, int k, double x1, double x2, double x3, double x4)
+ {
+ Volatile_out = n;
+ Volatile_out = j;
+ Volatile_out = k;
+ Volatile_out = (int)x1;
+ Volatile_out = (int)x2;
+ Volatile_out = (int)x3;
+ Volatile_out = (int)x4;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ double[] e1 = new double[4];
+ double x1, x2, x3, x4, x, y, z, t1;
+ int i, n1, n2, n3, n4, n6, n7, n8, n9, n10, n11;
+
+ s_t = 0.499975;
+ t1 = 0.50025;
+ s_t2 = 2.0;
+ n1 = 0 * Iterations;
+ n2 = 12 * Iterations;
+ n3 = 14 * Iterations;
+ n4 = 345 * Iterations;
+ n6 = 210 * Iterations;
+ n7 = 32 * Iterations;
+ n8 = 899 * Iterations;
+ n9 = 616 * Iterations;
+ n10 = 0 * Iterations;
+ n11 = 93 * Iterations;
+ x1 = 1.0;
+ x2 = x3 = x4 = -1.0;
+
+ for (i = 1; i <= n1; i += 1)
+ {
+ x1 = (x1 + x2 + x3 - x4) * s_t;
+ x2 = (x1 + x2 - x3 - x4) * s_t;
+ x3 = (x1 - x2 + x3 + x4) * s_t;
+ x4 = (-x1 + x2 + x3 + x4) * s_t;
+ }
+ Escape(n1, n1, n1, x1, x2, x3, x4);
+
+ /* MODULE 2: array elements */
+ e1[0] = 1.0;
+ e1[1] = e1[2] = e1[3] = -1.0;
+ for (i = 1; i <= n2; i += 1)
+ {
+ e1[0] = (e1[0] + e1[1] + e1[2] - e1[3]) * s_t;
+ e1[1] = (e1[0] + e1[1] - e1[2] + e1[3]) * s_t;
+ e1[2] = (e1[0] - e1[1] + e1[2] + e1[3]) * s_t;
+ e1[3] = (-e1[0] + e1[1] + e1[2] + e1[3]) * s_t;
+ }
+ Escape(n2, n3, n2, e1[0], e1[1], e1[2], e1[3]);
+
+ /* MODULE 3: array as parameter */
+ for (i = 1; i <= n3; i += 1)
+ {
+ PA(e1);
+ }
+ Escape(n3, n2, n2, e1[0], e1[1], e1[2], e1[3]);
+
+ /* MODULE 4: conditional jumps */
+ s_j = 1;
+ for (i = 1; i <= n4; i += 1)
+ {
+ if (s_j == 1)
+ {
+ s_j = 2;
+ }
+ else
+ {
+ s_j = 3;
+ }
+ if (s_j > 2)
+ {
+ s_j = 0;
+ }
+ else
+ {
+ s_j = 1;
+ }
+ if (s_j < 1)
+ {
+ s_j = 1;
+ }
+ else
+ {
+ s_j = 0;
+ }
+ }
+ Escape(n4, s_j, s_j, x1, x2, x3, x4);
+
+ /* MODULE 5: omitted */
+ /* MODULE 6: integer Math */
+ s_j = 1;
+ s_k = 2;
+ s_l = 3;
+ for (i = 1; i <= n6; i += 1)
+ {
+ s_j = s_j * (s_k - s_j) * (s_l - s_k);
+ s_k = s_l * s_k - (s_l - s_j) * s_k;
+ s_l = (s_l - s_k) * (s_k + s_j);
+ e1[s_l - 2] = s_j + s_k + s_l;
+ e1[s_k - 2] = s_j * s_k * s_l;
+ }
+ Escape(n6, s_j, s_k, e1[0], e1[1], e1[2], e1[3]);
+
+ /* MODULE 7: trig. functions */
+ x = y = 0.5;
+ for (i = 1; i <= n7; i += 1)
+ {
+ x = s_t * System.Math.Atan(s_t2 * System.Math.Sin(x) * System.Math.Cos(x) / (System.Math.Cos(x + y) + System.Math.Cos(x - y) - 1.0));
+ y = s_t * System.Math.Atan(s_t2 * System.Math.Sin(y) * System.Math.Cos(y) / (System.Math.Cos(x + y) + System.Math.Cos(x - y) - 1.0));
+ }
+ Escape(n7, s_j, s_k, x, x, y, y);
+
+ /* MODULE 8: procedure calls */
+ x = y = z = 1.0;
+ for (i = 1; i <= n8; i += 1)
+ {
+ P3(x, y, out z);
+ }
+ Escape(n8, s_j, s_k, x, y, z, z);
+
+ /* MODULE9: array references */
+ s_j = 1;
+ s_k = 2;
+ s_l = 3;
+ e1[0] = 1.0;
+ e1[1] = 2.0;
+ e1[2] = 3.0;
+ for (i = 1; i <= n9; i += 1)
+ {
+ P0(e1);
+ }
+ Escape(n9, s_j, s_k, e1[0], e1[1], e1[2], e1[3]);
+
+ /* MODULE10: integer System.Math */
+ s_j = 2;
+ s_k = 3;
+ for (i = 1; i <= n10; i += 1)
+ {
+ s_j = s_j + s_k;
+ s_k = s_j + s_k;
+ s_j = s_k - s_j;
+ s_k = s_k - s_j - s_j;
+ }
+ Escape(n10, s_j, s_k, x1, x2, x3, x4);
+
+ /* MODULE11: standard functions */
+ x = 0.75;
+ for (i = 1; i <= n11; i += 1)
+ {
+ x = System.Math.Sqrt(System.Math.Exp(System.Math.Log(x) / t1));
+ }
+ Escape(n11, s_j, s_k, x, x, x, x);
+
+ return true;
+ }
+
+ private static void PA(double[] e)
+ {
+ int j;
+ j = 0;
+ lab:
+ e[0] = (e[0] + e[1] + e[2] - e[3]) * s_t;
+ e[1] = (e[0] + e[1] - e[2] + e[3]) * s_t;
+ e[2] = (e[0] - e[1] + e[2] + e[3]) * s_t;
+ e[3] = (-e[0] + e[1] + e[2] + e[3]) / s_t2;
+ j += 1;
+ if (j < 6)
+ {
+ goto lab;
+ }
+ }
+
+ private static void P3(double x, double y, out double z)
+ {
+ x = s_t * (x + y);
+ y = s_t * (x + y);
+ z = (x + y) / s_t2;
+ }
+
+ private static void P0(double[] e1)
+ {
+ e1[s_j] = e1[s_k];
+ e1[s_k] = e1[s_l];
+ e1[s_l] = e1[s_j];
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchF/Whetsto/Whetsto.csproj b/tests/src/JIT/Performance/CodeQuality/BenchF/Whetsto/Whetsto.csproj
new file mode 100644
index 0000000000..46898e3188
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchF/Whetsto/Whetsto.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Whetsto.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/BenchI/8Queens/8Queens.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/8Queens/8Queens.cs
new file mode 100644
index 0000000000..76ed0c8e71
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/8Queens/8Queens.cs
@@ -0,0 +1,100 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class EightQueens
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 100000;
+#endif
+
+ static int[] m_c = new int[15];
+ static int[] m_x = new int[9];
+
+ static void TryMe(int i, ref int q, int[] a, int[] b)
+ {
+ int j = 0;
+ q = 0;
+ while ((q == 0) && (j != 8)) {
+ j = j + 1;
+ q = 0;
+ if ((b[j] == 1) && (a[i + j] == 1) && (m_c[i - j + 7] == 1)) {
+ m_x[i] = j;
+ b[j] = 0;
+ a[i + j] = 0;
+ m_c[i - j + 7] = 0;
+ if (i < 8) {
+ TryMe(i + 1, ref q, a, b);
+ if (q == 0) {
+ b[j] = 1;
+ a[i + j] = 1;
+ m_c[i - j + 7] = 1;
+ }
+ }
+ else {
+ q = 1;
+ }
+ }
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ int[] a = new int[9];
+ int[] b = new int[17];
+ int q = 0;
+ int i = 0;
+ while (i <= 16) {
+ if ((i >= 1) && (i <= 8)) {
+ a[i] = 1;
+ }
+ if (i >= 2) {
+ b[i] = 1;
+ }
+ if (i <= 14) {
+ m_c[i] = 1;
+ }
+ i = i + 1;
+ }
+
+ TryMe(1, ref q, b, a);
+
+ return (q == 1);
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench();
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/8Queens/8Queens.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/8Queens/8Queens.csproj
new file mode 100644
index 0000000000..efef461379
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/8Queens/8Queens.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="8Queens.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/BenchI/Ackermann/Ackermann.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Ackermann/Ackermann.cs
new file mode 100644
index 0000000000..512f35f82d
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Ackermann/Ackermann.cs
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Ackermann
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 100000;
+#endif
+
+ static int Acker(int m, int n) {
+ if (m == 0) {
+ return n + 1;
+ }
+ else if (n == 0) {
+ return Acker(m - 1, 1);
+ }
+ else {
+ return Acker(m - 1, Acker(m, n - 1));
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ int a00 = Acker(0, 0);
+ int a11 = Acker(1, 1);
+ int a22 = Acker(2, 2);
+ int a33 = Acker(3, 3);
+ return (a00 == 1) && (a11 == 3) && (a22 == 7) & (a33 == 61);
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench();
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Ackermann/Ackermann.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/Ackermann/Ackermann.csproj
new file mode 100644
index 0000000000..8d0feb5a01
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Ackermann/Ackermann.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Ackermann.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/BenchI/AddArray/AddArray.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray/AddArray.cs
new file mode 100644
index 0000000000..0fa2ff90eb
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray/AddArray.cs
@@ -0,0 +1,91 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class AddArray
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 15000;
+#endif
+
+ const int Size = 6000;
+
+ public static volatile object VolatileObject;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Escape(object obj) {
+ VolatileObject = obj;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+
+ int[] flags1 = new int[Size + 1];
+ int[] flags2 = new int[Size + 1];
+ int[] flags3 = new int[Size + 1];
+ int[] flags4 = new int[Size + 1];
+
+ int j, k, l, m;
+
+ for (j = 0; j <= Size; j++) {
+ flags1[j] = 70000 + j;
+ k = j;
+ flags2[k] = flags1[j] + k + k;
+ l = j;
+ flags3[l] = flags2[k] + l + l + l;
+ m = j;
+ flags4[m] = flags3[l] + m + m + m + m;
+ }
+
+ for (j = 0; j <= Size; j++) {
+ k = j;
+ l = j;
+ m = j;
+ flags1[j] = flags1[j] + flags2[k] + flags3[l] + flags4[m] - flags2[k - j + l];
+ }
+
+ // Escape each flags array so that their elements will appear live-out
+ Escape(flags1);
+ Escape(flags2);
+ Escape(flags3);
+ Escape(flags4);
+
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench();
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray/AddArray.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray/AddArray.csproj
new file mode 100644
index 0000000000..2fd1aae521
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray/AddArray.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AddArray.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/BenchI/AddArray2/AddArray2.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray2/AddArray2.cs
new file mode 100644
index 0000000000..865b9445f6
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray2/AddArray2.cs
@@ -0,0 +1,131 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class AddArray2
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 50;
+#endif
+
+ private const int Dim = 200;
+
+ private static T[][] AllocArray<T>(int n1, int n2)
+ {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i)
+ {
+ a[i] = new T[n2];
+ }
+ return a;
+ }
+
+ private static
+ void BenchInner1(int[][] a, ref int nn)
+ {
+ int n;
+ int l, m;
+ n = nn;
+ for (int i = 1; i <= n; i++)
+ {
+ for (int j = (i + 1); j <= n; j++)
+ {
+ for (int k = 1; k <= n; k++)
+ {
+ l = a[i][k];
+ m = a[j][k];
+ unchecked
+ {
+ a[j][k] = l + m;
+ }
+ }
+ }
+ }
+ }
+
+ private static
+ void BenchInner2(int[][] a, ref int nn)
+ {
+ int n;
+ int l, m;
+ n = nn;
+ for (int i = 1; i <= n; i++)
+ {
+ for (int j = (i + 1); j <= n; j++)
+ {
+ for (int k = 1; k <= n; k++)
+ {
+ l = a[k][i];
+ m = a[k][j];
+ unchecked
+ {
+ a[k][j] = l + m;
+ }
+ }
+ }
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench(int[][] a)
+ {
+ int n = Dim;
+ for (int i = 1; i <= n; i++)
+ {
+ for (int j = 1; j <= n; j++)
+ {
+ a[i][j] = i + j;
+ }
+ }
+
+ BenchInner1(a, ref n);
+ n = Dim;
+ BenchInner2(a, ref n);
+
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ int[][] array = AllocArray<int>(Dim + 1, Dim + 1);
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 1; i <= Iterations; i++)
+ {
+ Bench(array);
+ }
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ int[][] array = AllocArray<int>(Dim + 1, Dim + 1);
+ bool result = true;
+ for (int i = 1; i <= Iterations; i++)
+ {
+ result &= Bench(array);
+ }
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray2/AddArray2.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray2/AddArray2.csproj
new file mode 100644
index 0000000000..cb8f12ddb2
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/AddArray2/AddArray2.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AddArray2.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/BenchI/Array1/Array1.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Array1/Array1.cs
new file mode 100644
index 0000000000..8d5dbd6153
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Array1/Array1.cs
@@ -0,0 +1,154 @@
+// 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.
+//
+// The sorting benchmark calls a random number generator the number
+// of times specified by Maxnum to create an array of int integers,
+// then does a quicksort on the array of ints. Random numbers
+// are produced using a multiplicative modulus method with known
+// seed, so that the generated array is constant across compilers.
+//
+// This is adapted from a benchmark in BYTE Magazine, August 1984.
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Array1
+{
+#if DEBUG
+ private const int Iterations = 1;
+ private const int Maxnum = 100;
+#else
+ private const int Iterations = 125;
+ private const int Maxnum = 1000;
+#endif
+
+ private const int Modulus = ((int)0x20000);
+ private const int C = 13849;
+ private const int A = 25173;
+ static int s_seed = 7;
+
+ private static void Quick(int lo, int hi, int[] input)
+ {
+ int i, j;
+ int pivot, temp;
+
+ if (lo < hi)
+ {
+ // 0 <= lo < hi
+ for (i = lo, j = (hi + 1), pivot = input[lo]; ;)
+ {
+ do
+ {
+ ++i;
+ } while (input[i] < pivot);
+
+ do
+ {
+ --j;
+ // Accessing upto hi
+ } while (input[j] > pivot);
+
+ if (i < j)
+ {
+ temp = input[i];
+ input[i] = input[j];
+ input[j] = temp;
+ }
+ else
+ {
+ break;
+ }
+ }
+ temp = input[j];
+ input[j] = input[lo];
+ input[lo] = temp;
+ Quick(lo, j - 1, input);
+ Quick(j + 1, hi, input);
+ }
+ }
+
+ private static int Random(int size)
+ {
+ unchecked
+ {
+ s_seed = s_seed * A + C;
+ }
+
+ return (s_seed % size);
+ }
+
+ private static bool VerifySort(int[] buffer)
+ {
+ for (int y = 0; y < Maxnum - 2; y++)
+ {
+ if (buffer[y] > buffer[y + 1])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ int[] buffer = new int[Maxnum + 1];
+
+ for (int i = 0; i < Iterations; ++i)
+ {
+ for (int j = 0; j < Maxnum; ++j)
+ {
+ int temp = Random(Modulus);
+ if (temp < 0L)
+ {
+ temp = (-temp);
+ }
+ buffer[j] = temp;
+ }
+ buffer[Maxnum] = Modulus;
+
+ Quick(0, Maxnum - 1, buffer);
+ }
+
+ bool result = VerifySort(buffer);
+
+ return result;
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ Bench();
+ }
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++)
+ {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Array1/Array1.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/Array1/Array1.csproj
new file mode 100644
index 0000000000..b7d7918823
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Array1/Array1.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Array1.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/BenchI/Array2/Array2.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Array2/Array2.cs
new file mode 100644
index 0000000000..1b720b94fa
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Array2/Array2.cs
@@ -0,0 +1,100 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Array2
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 500000;
+#endif
+
+ static T[][][] AllocArray<T>(int n1, int n2, int n3) {
+ T[][][] a = new T[n1][][];
+ for (int i = 0; i < n1; ++i) {
+ a[i] = new T[n2][];
+ for (int j = 0; j < n2; j++) {
+ a[i][j] = new T[n3];
+ }
+ }
+
+ return a;
+ }
+
+ static void Initialize(int[][][] s) {
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 10; j++) {
+ for (int k = 0; k < 10; k++) {
+ s[i][j][k] = (2 * i) - (3 * j) + (5 * k);
+ }
+ }
+ }
+ }
+
+ static bool VerifyCopy(int[][][] s, int[][][] d) {
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 10; j++) {
+ for (int k = 0; k < 10; k++) {
+ if (s[i][j][k] != d[i][j][k]) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench(int loop) {
+
+ int[][][] s = AllocArray<int>(10, 10, 10);
+ int[][][] d = AllocArray<int>(10, 10, 10);
+
+ Initialize(s);
+
+ for (; loop != 0; loop--) {
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 10; j++) {
+ for (int k = 0; k < 10; k++) {
+ d[i][j][k] = s[i][j][k];
+ }
+ }
+ }
+ }
+
+ bool result = VerifyCopy(s, d);
+
+ return result;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ Bench(Iterations);
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = Bench(Iterations);
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Array2/Array2.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/Array2/Array2.csproj
new file mode 100644
index 0000000000..0932bfb0ea
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Array2/Array2.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Array2.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/BenchI/BenchE/BenchE.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/BenchE/BenchE.cs
new file mode 100644
index 0000000000..9cf7d770dc
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/BenchE/BenchE.cs
@@ -0,0 +1,117 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class BenchE
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 5000000;
+#endif
+
+ private static int s_position;
+
+ private static int Strsch(char[] s, char[] k, int ns, int nk)
+ {
+ int i, j;
+ int start, ksave, cont;
+ int kend, ssave;
+ int r;
+
+ start = 0;
+ ksave = 0;
+ cont = ns - nk + start;
+ kend = ksave + nk - 1;
+ i = 0;
+ j = 0;
+ top:
+ while (s[i] != k[j])
+ {
+ // s is accessed upto cont i.e. ns - nk + 0
+ if (i >= cont)
+ {
+ r = -1;
+ goto bottom;
+ }
+ i = i + 1;
+ }
+ ssave = i;
+ j = j + 1;
+ while (j <= kend)
+ {
+ i = i + 1;
+ // j <= kend, so k is accessed upto 0 + nk - 1
+ if (s[i] != k[j])
+ {
+ i = ssave + 1;
+ j = ksave;
+ goto top;
+ }
+ j = j + 1;
+ }
+ r = ssave - start + 1;
+ bottom:
+ return r;
+ }
+
+ private static void BenchInner(char[] s, char[] k)
+ {
+ int ns, nk;
+
+ ns = 120;
+ nk = 15;
+ s_position = Strsch(s, k, ns, nk);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench()
+ {
+ char[] s = {
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 'H', 'E', 'R', 'E', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
+ 'H', 'E', 'R', 'E', ' ', 'I', 'S', ' ', 'A', ' ', 'M', 'A', 'T', 'C', 'H', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
+ };
+
+ char[] k = { 'H', 'E', 'R', 'E', ' ', 'I', 'S', ' ', 'A', ' ', 'M', 'A', 'T', 'C', 'H', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
+
+ for (int i = 0; i < Iterations; i++)
+ {
+ BenchInner(s, k);
+ }
+
+ return (s_position == 91);
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/BenchE/BenchE.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/BenchE/BenchE.csproj
new file mode 100644
index 0000000000..0def91ffa2
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/BenchE/BenchE.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BenchE.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/BenchI/BubbleSort/BubbleSort.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort/BubbleSort.cs
new file mode 100644
index 0000000000..78626fffc9
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort/BubbleSort.cs
@@ -0,0 +1,87 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class BubbleSort
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 55000;
+#endif
+
+ static void SortArray(int[] tab, int last) {
+ bool swap;
+ int temp;
+ do {
+ swap = false;
+ for (int i = 0; i < last; i++) {
+ if (tab[i] > tab[i + 1]) {
+ temp = tab[i];
+ tab[i] = tab[i + 1];
+ tab[i + 1] = temp;
+ swap = true;
+ }
+ }
+ }
+ while (swap);
+ }
+
+ static bool VerifySort(int[] tab, int last) {
+ for (int i = 0; i < last; i++) {
+ if (tab[i] > tab[i + 1]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static public bool Bench() {
+ int[] tab = new int[100];
+ int k = 0;
+ for (int i = 9; i >= 0; i--) {
+ for (int j = i * 10; j < (i + 1) * 10; j++) {
+ tab[k++] = ((j & 1) == 1) ? j + 1 : j - 1;
+ }
+ }
+ SortArray(tab, 99);
+ bool result = VerifySort(tab, 99);
+ return result;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench();
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort/BubbleSort.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort/BubbleSort.csproj
new file mode 100644
index 0000000000..6fabe89c8e
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort/BubbleSort.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BubbleSort.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/BenchI/BubbleSort2/BubbleSort2.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort2/BubbleSort2.cs
new file mode 100644
index 0000000000..55e5a5f8c5
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort2/BubbleSort2.cs
@@ -0,0 +1,90 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class BubbleSort2
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+ public const int Bound = 5 * Iterations;
+#else
+ public const int Iterations = 15;
+ public const int Bound = 500 * Iterations;
+#endif
+
+ static void Inner(int[] x) {
+ int limit1 = Bound - 1;
+ for (int i = 1; i <= limit1; i++) {
+ for (int j = i; j <= Bound; j++) {
+ if (x[i] > x[j]) {
+ int temp = x[j];
+ x[j] = x[i];
+ x[i] = temp;
+ }
+ }
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ int[] x = new int[Bound + 1];
+ int i, j;
+ int limit;
+ j = 99999;
+ limit = Bound - 2;
+ i = 1;
+ do {
+ x[i] = j & 32767;
+ x[i + 1] = (j + 11111) & 32767;
+ x[i + 2] = (j + 22222) & 32767;
+ j = j + 33333;
+ i = i + 3;
+ } while (i <= limit);
+ x[Bound - 1] = j;
+ x[Bound] = j;
+
+ Inner(x);
+
+ for (i = 0; i < Bound - 1; i++) {
+ if (x[i] > x[i + 1]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench();
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort2/BubbleSort2.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort2/BubbleSort2.csproj
new file mode 100644
index 0000000000..7b5fb93ed9
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/BubbleSort2/BubbleSort2.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BubbleSort2.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/BenchI/CSieve/CSieve.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/CSieve/CSieve.cs
new file mode 100644
index 0000000000..606f740fb6
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/CSieve/CSieve.cs
@@ -0,0 +1,82 @@
+// 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.
+//
+// Based on Eratosthenes Sieve Prime Number Program in C, Byte Magazine, January 1983.
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class CSieve
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 200;
+#endif
+
+ const int Size = 8190;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ bool[] flags = new bool[Size + 1];
+ int count = 0;
+ for (int iter = 1; iter <= Iterations; iter++)
+ {
+ count = 0;
+
+ // Initially, assume all are prime
+ for (int i = 0; i <= Size; i++)
+ {
+ flags[i] = true;
+ }
+
+ // Refine
+ for (int i = 2; i <= Size; i++)
+ {
+ if (flags[i])
+ {
+ // Found a prime
+ for (int k = i + i; k <= Size; k += i)
+ {
+ // Cancel its multiples
+ flags[k] = false;
+ }
+ count++;
+ }
+ }
+ }
+
+ return (count == 1027);
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench();
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/CSieve/CSieve.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/CSieve/CSieve.csproj
new file mode 100644
index 0000000000..599dcd7b74
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/CSieve/CSieve.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="CSieve.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/BenchI/Fib/Fib.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Fib/Fib.cs
new file mode 100644
index 0000000000..01064bb168
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Fib/Fib.cs
@@ -0,0 +1,63 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Fib
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 3500;
+#endif
+
+ const int Number = 24;
+
+ static int Fibonacci(int x) {
+ if (x > 2) {
+ return (Fibonacci(x - 1) + Fibonacci(x - 2));
+ }
+ else {
+ return 1;
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ int fib = Fibonacci(Number);
+ return (fib == 46368);
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench();
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Fib/Fib.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/Fib/Fib.csproj
new file mode 100644
index 0000000000..2b8c995bd8
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Fib/Fib.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Fib.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/BenchI/HeapSort/HeapSort.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/HeapSort/HeapSort.cs
new file mode 100644
index 0000000000..9fd7aa32e0
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/HeapSort/HeapSort.cs
@@ -0,0 +1,121 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class HeapSort
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 2500;
+#endif
+
+ const int ArraySize = 5500;
+
+ static void Inner(int[] x, int n) {
+ int i, j, k, m;
+
+ // pass1 -- put vector in heap form
+ // that is to say, guarantee that x(i)>=x(2*i) and x(i)>=x(2*i+1).
+ // after pass 1, the largest item will be at x(1).
+ for (i = 2; i <= n; i++) {
+ j = i;
+ k = j / 2;
+ m = x[i];
+
+ // 0 < k <= (n / 2)
+ // 1 <= j <= n
+ while (k > 0) {
+ if (m <= x[k]) {
+ break;
+ }
+ x[j] = x[k];
+ j = k;
+ k = k / 2;
+ }
+ x[j] = m;
+ }
+
+ // pass 2 -- swap first and last items. now with the last
+ // item correctly placed, consider the list shorter by one item.
+ // restore the shortened list to heap sort, and repeat
+ // process until list is only two items long.
+ i = n;
+ do {
+ // do i = n to 2 by -1;
+ m = x[i];
+ x[i] = x[1]; // last item, i.e. item(i) now correct.
+ j = 1; // we now find the appropriate resting point for m
+ k = 2;
+
+ // 2 <= k < i ==> 2 <= k < n
+ // 1 <= j < n
+ while (k < i) {
+ if ((k + 1) < i) {
+ if (x[k + 1] > x[k]) {
+ k = k + 1;
+ }
+ }
+ if (x[k] <= m) {
+ break;
+ }
+
+ x[j] = x[k];
+ j = k;
+ k = k + k;
+ }
+
+ x[j] = m;
+ i = i - 1;
+ } while (i >= 2);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ int[] x = new int[ArraySize + 1];
+ for (int i = 1; i <= ArraySize; i++) {
+ x[i] = ArraySize - i + 1;
+ }
+ Inner(x, ArraySize);
+ for (int j = 1; j <= ArraySize; j++) {
+ if (x[j] != j) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench();
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/HeapSort/HeapSort.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/HeapSort/HeapSort.csproj
new file mode 100644
index 0000000000..2afbe54997
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/HeapSort/HeapSort.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="HeapSort.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/BenchI/IniArray/IniArray.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/IniArray/IniArray.cs
new file mode 100644
index 0000000000..78fa233dbf
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/IniArray/IniArray.cs
@@ -0,0 +1,60 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class IniArray
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 10000000;
+#endif
+
+ const int Allotted = 16;
+ static volatile object VolatileObject;
+
+ static void Escape(object obj) {
+ VolatileObject = obj;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ char[] workarea = new char[Allotted];
+ for (int i = 0; i < Iterations; i++) {
+ for (int j = 0; j < Allotted; j++) {
+ workarea[j] = ' ';
+ }
+ }
+ Escape(workarea);
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ Bench();
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/IniArray/IniArray.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/IniArray/IniArray.csproj
new file mode 100644
index 0000000000..2fab51071a
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/IniArray/IniArray.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="IniArray.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/BenchI/LogicArray/LogicArray.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/LogicArray/LogicArray.cs
new file mode 100644
index 0000000000..f5ff746b86
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/LogicArray/LogicArray.cs
@@ -0,0 +1,97 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class LogicArray
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 3000;
+#endif
+
+ const int ArraySize = 50;
+
+ struct Workarea
+ {
+ public int X;
+ public int[][] A;
+ }
+
+ static T[][] AllocArray<T>(int n1, int n2) {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i) {
+ a[i] = new T[n2];
+ }
+ return a;
+ }
+
+ static bool Inner(ref Workarea cmn) {
+ int i, j, k;
+ cmn.X = 0;
+ for (i = 1; i <= 50; i++) {
+ for (j = 1; j <= 50; j++) {
+ cmn.A[i][j] = 1;
+ }
+ }
+ for (k = 1; k <= 50; k++) {
+ for (j = 1; j <= 50; j++) {
+ i = 1;
+ do {
+ cmn.X = cmn.X | cmn.A[i][j] & cmn.A[i + 1][k];
+ i = i + 2;
+ } while (i <= 50);
+ }
+ }
+ if (cmn.X != 1) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ Workarea cmn = new Workarea();
+ cmn.X = 0;
+ cmn.A = AllocArray<int>(51, 51);
+ for (int n = 1; n <= Iterations; n++) {
+ bool result = Inner(ref cmn);
+ if (!result) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ Bench();
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/LogicArray/LogicArray.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/LogicArray/LogicArray.csproj
new file mode 100644
index 0000000000..0281fb4ca7
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/LogicArray/LogicArray.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="LogicArray.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/BenchI/Midpoint/Midpoint.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Midpoint/Midpoint.cs
new file mode 100644
index 0000000000..6e4f193746
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Midpoint/Midpoint.cs
@@ -0,0 +1,104 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Midpoint
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 70000;
+#endif
+
+ static T[][] AllocArray<T>(int n1, int n2) {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i) {
+ a[i] = new T[n2];
+ }
+ return a;
+ }
+
+ static int Inner(ref int x, ref int y, ref int z) {
+ int mid;
+
+ if (x < y) {
+ if (y < z) {
+ mid = y;
+ }
+ else {
+ if (x < z) {
+ mid = z;
+ }
+ else {
+ mid = x;
+ }
+ }
+ }
+ else {
+ if (x < z) {
+ mid = x;
+ }
+ else {
+ if (y < z) {
+ mid = z;
+ }
+ else {
+ mid = y;
+ }
+ }
+ }
+
+ return (mid);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ int[][] a = AllocArray<int>(2001, 4);
+ int[] mid = new int[2001];
+ int j = 99999;
+
+ for (int i = 1; i <= 2000; i++) {
+ a[i][1] = j & 32767;
+ a[i][2] = (j + 11111) & 32767;
+ a[i][3] = (j + 22222) & 32767;
+ j = j + 33333;
+ }
+
+ for (int k = 1; k <= Iterations; k++) {
+ for (int l = 1; l <= 2000; l++) {
+ mid[l] = Inner(ref a[l][1], ref a[l][2], ref a[l][3]);
+ }
+ }
+
+ return (mid[2000] == 17018);
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ Bench();
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Midpoint/Midpoint.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/Midpoint/Midpoint.csproj
new file mode 100644
index 0000000000..e7e379be83
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Midpoint/Midpoint.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Midpoint.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/BenchI/MulMatrix/MulMatrix.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/MulMatrix/MulMatrix.cs
new file mode 100644
index 0000000000..3f9c224d3d
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/MulMatrix/MulMatrix.cs
@@ -0,0 +1,140 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class MulMatrix
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 100;
+#endif
+
+ const int Size = 75;
+ static volatile object VolatileObject;
+
+ static void Escape(object obj) {
+ VolatileObject = obj;
+ }
+
+ static T[][] AllocArray<T>(int n1, int n2) {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i) {
+ a[i] = new T[n2];
+ }
+ return a;
+ }
+
+ static void Inner(int[][] a, int[][] b, int[][] c) {
+
+ int i, j, k, l;
+
+ // setup
+ for (j = 0; j < Size; j++) {
+ for (i = 0; i < Size; i++) {
+ a[i][j] = i;
+ b[i][j] = 2 * j;
+ c[i][j] = a[i][j] + b[i][j];
+ }
+ }
+
+ // jkl
+ for (j = 0; j < Size; j++) {
+ for (k = 0; k < Size; k++) {
+ for (l = 0; l < Size; l++) {
+ c[j][k] += a[j][l] * b[l][k];
+ }
+ }
+ }
+
+ // jlk
+ for (j = 0; j < Size; j++) {
+ for (l = 0; l < Size; l++) {
+ for (k = 0; k < Size; k++) {
+ c[j][k] += a[j][l] * b[l][k];
+ }
+ }
+ }
+
+ // kjl
+ for (k = 0; k < Size; k++) {
+ for (j = 0; j < Size; j++) {
+ for (l = 0; l < Size; l++) {
+ c[j][k] += a[j][l] * b[l][k];
+ }
+ }
+ }
+
+ // klj
+ for (k = 0; k < Size; k++) {
+ for (l = 0; l < Size; l++) {
+ for (j = 0; j < Size; j++) {
+ c[j][k] += a[j][l] * b[l][k];
+ }
+ }
+ }
+
+ // ljk
+ for (l = 0; l < Size; l++) {
+ for (j = 0; j < Size; j++) {
+ for (k = 0; k < Size; k++) {
+ c[j][k] += a[j][l] * b[l][k];
+ }
+ }
+ }
+
+ // lkj
+ for (l = 0; l < Size; l++) {
+ for (k = 0; k < Size; k++) {
+ for (j = 0; j < Size; j++) {
+ c[j][k] += a[j][l] * b[l][k];
+ }
+ }
+ }
+
+ return;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ int[][] a = AllocArray<int>(Size, Size);
+ int[][] b = AllocArray<int>(Size, Size);
+ int[][] c = AllocArray<int>(Size, Size);
+
+ for (int i = 0; i < Iterations; ++i) {
+ Inner(a, b, c);
+ }
+
+ Escape(c);
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ Bench();
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/MulMatrix/MulMatrix.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/MulMatrix/MulMatrix.csproj
new file mode 100644
index 0000000000..5046b02d9e
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/MulMatrix/MulMatrix.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="MulMatrix.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/BenchI/NDhrystone/NDhrystone.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/NDhrystone/NDhrystone.cs
new file mode 100644
index 0000000000..c2526748ce
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/NDhrystone/NDhrystone.cs
@@ -0,0 +1,286 @@
+// 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.
+//
+// Adapted from
+//
+// Dhrystone: a synthetic systems programming benchmark
+// Reinhold P. Weicker
+// Communications of the ACM, Volume 27 Issue 10, Oct 1984, Pages 1013-1030
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class NDhrystone
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 7000000;
+#endif
+
+ static T[][] AllocArray<T>(int n1, int n2) {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i) {
+ a[i] = new T[n2];
+ }
+ return a;
+ }
+
+ enum Enumeration
+ {
+ Ident1 = 1, Ident2, Ident3, Ident4, Ident5
+ }
+
+ sealed class Record
+ {
+ public Record PtrComp;
+ public Enumeration Discr;
+ public Enumeration EnumComp;
+ public int IntComp;
+ public char[] StringComp;
+ }
+
+ static int s_intGlob;
+ static bool s_boolGlob;
+ static char s_char1Glob;
+ static char s_char2Glob;
+ static int[] m_array1Glob = new int[51];
+ static int[][] m_array2Glob;
+ static Record m_ptrGlb = new Record();
+ static Record m_ptrGlbNext = new Record();
+ static char[] m_string1Loc;
+ static char[] m_string2Loc;
+
+ static void Proc0() {
+ int intLoc1;
+ int intLoc2;
+ int intLoc3 = 0;
+ Enumeration enumLoc;
+
+ int i; /* modification */
+
+ m_ptrGlb.PtrComp = m_ptrGlbNext;
+ m_ptrGlb.Discr = Enumeration.Ident1;
+ m_ptrGlb.EnumComp = Enumeration.Ident3;
+ m_ptrGlb.IntComp = 40;
+ m_ptrGlb.StringComp = "DHRYSTONE PROGRAM, SOME STRING".ToCharArray();
+ m_string1Loc = "DHRYSTONE PROGRAM, 1'ST STRING".ToCharArray();
+ m_array2Glob[8][7] = 10; /* Was missing in published program */
+
+ for (i = 0; i < Iterations; ++i) {
+ Proc5();
+ Proc4();
+ intLoc1 = 2;
+ intLoc2 = 3;
+ m_string2Loc = "DHRYSTONE PROGRAM, 2'ND STRING".ToCharArray();
+ enumLoc = Enumeration.Ident2;
+ s_boolGlob = !Func2(m_string1Loc, m_string2Loc);
+ while (intLoc1 < intLoc2) {
+ intLoc3 = 5 * intLoc1 - intLoc2;
+ Proc7(intLoc1, intLoc2, ref intLoc3);
+ ++intLoc1;
+ }
+ Proc8(m_array1Glob, m_array2Glob, intLoc1, intLoc3);
+ Proc1(ref m_ptrGlb);
+ for (char charIndex = 'A'; charIndex <= s_char2Glob; ++charIndex) {
+ if (enumLoc == Func1(charIndex, 'C')) {
+ Proc6(Enumeration.Ident1, ref enumLoc);
+ }
+ }
+ intLoc3 = intLoc2 * intLoc1;
+ intLoc2 = intLoc3 / intLoc1;
+ intLoc2 = 7 * (intLoc3 - intLoc2) - intLoc1;
+ Proc2(ref intLoc1);
+ }
+ }
+
+ static void Proc1(ref Record ptrParIn) {
+ ptrParIn.PtrComp = m_ptrGlb;
+ ptrParIn.IntComp = 5;
+ ptrParIn.PtrComp.IntComp = ptrParIn.IntComp;
+ ptrParIn.PtrComp.PtrComp = ptrParIn.PtrComp;
+ Proc3(ref ptrParIn.PtrComp.PtrComp);
+ if (ptrParIn.PtrComp.Discr == Enumeration.Ident1) {
+ ptrParIn.PtrComp.IntComp = 6;
+ Proc6(ptrParIn.EnumComp, ref ptrParIn.PtrComp.EnumComp);
+ ptrParIn.PtrComp.PtrComp = m_ptrGlb.PtrComp;
+ Proc7(ptrParIn.PtrComp.IntComp, 10, ref ptrParIn.PtrComp.IntComp);
+ }
+ else {
+ ptrParIn = ptrParIn.PtrComp;
+ }
+ }
+
+ static void Proc2(ref int intParIO) {
+ int intLoc;
+ Enumeration enumLoc = Enumeration.Ident2;
+ intLoc = intParIO + 10;
+
+ for (;;) {
+ if (s_char1Glob == 'A') {
+ --intLoc;
+ intParIO = intLoc - s_intGlob;
+ enumLoc = Enumeration.Ident1;
+ }
+ if (enumLoc == Enumeration.Ident1) {
+ break;
+ }
+ }
+ }
+
+ static void Proc3(ref Record ptrParOut) {
+ if (m_ptrGlb != null) {
+ ptrParOut = m_ptrGlb.PtrComp;
+ }
+ else {
+ s_intGlob = 100;
+ }
+
+ Proc7(10, s_intGlob, ref m_ptrGlb.IntComp);
+ }
+
+ static void Proc4() {
+ bool boolLoc;
+ boolLoc = s_char1Glob == 'A';
+ boolLoc |= s_boolGlob;
+ s_char2Glob = 'B';
+ }
+
+ static void Proc5() {
+ s_char1Glob = 'A';
+ s_boolGlob = false;
+ }
+
+ static void Proc6(Enumeration enumParIn, ref Enumeration enumParOut) {
+ enumParOut = enumParIn;
+ if (!Func3(enumParIn)) {
+ enumParOut = Enumeration.Ident4;
+ }
+
+ switch (enumParIn) {
+ case Enumeration.Ident1:
+ enumParOut = Enumeration.Ident1;
+ break;
+ case Enumeration.Ident2:
+ if (s_intGlob > 100) {
+ enumParOut = Enumeration.Ident1;
+ }
+ else {
+ enumParOut = Enumeration.Ident4;
+ }
+ break;
+ case Enumeration.Ident3:
+ enumParOut = Enumeration.Ident2;
+ break;
+ case Enumeration.Ident4:
+ break;
+ case Enumeration.Ident5:
+ enumParOut = Enumeration.Ident3;
+ break;
+ }
+ }
+
+ static void Proc7(int intParI1, int intParI2, ref int intParOut) {
+ int intLoc;
+ intLoc = intParI1 + 2;
+ intParOut = intParI2 + intLoc;
+ }
+
+ static void Proc8(int[] array1Par, int[][] array2Par, int intParI1, int intParI2) {
+ int intLoc;
+ intLoc = intParI1 + 5;
+ array1Par[intLoc] = intParI2;
+ array1Par[intLoc + 1] = array1Par[intLoc];
+ array1Par[intLoc + 30] = intLoc;
+ for (int intIndex = intLoc; intIndex <= (intLoc + 1); ++intIndex) {
+ array2Par[intLoc][intIndex] = intLoc;
+ }
+ ++array2Par[intLoc][intLoc - 1];
+ array2Par[intLoc + 20][intLoc] = array1Par[intLoc];
+ s_intGlob = 5;
+ }
+
+ static Enumeration Func1(char charPar1, char charPar2) {
+ char charLoc1;
+ char charLoc2;
+ charLoc1 = charPar1;
+ charLoc2 = charLoc1;
+ if (charLoc2 != charPar2) {
+ return (Enumeration.Ident1);
+ }
+ else {
+ return (Enumeration.Ident2);
+ }
+ }
+
+ static bool Func2(char[] strParI1, char[] strParI2) {
+ int intLoc;
+ char charLoc = '\0';
+ intLoc = 1;
+ while (intLoc <= 1) {
+ if (Func1(strParI1[intLoc], strParI2[intLoc + 1]) == Enumeration.Ident1) {
+ charLoc = 'A';
+ ++intLoc;
+ }
+ }
+ if (charLoc >= 'W' && charLoc <= 'Z') {
+ intLoc = 7;
+ }
+ if (charLoc == 'X') {
+ return true;
+ }
+ else {
+ for (int i = 0; i < 30; i++) {
+ if (strParI1[i] > strParI2[i]) {
+ intLoc += 7;
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ static bool Func3(Enumeration enumParIn) {
+ Enumeration enumLoc;
+ enumLoc = enumParIn;
+ if (enumLoc == Enumeration.Ident3) {
+ return true;
+ }
+
+ return false;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ m_array2Glob = AllocArray<int>(51, 51);
+ Proc0();
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ Bench();
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = Bench();
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/NDhrystone/NDhrystone.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/NDhrystone/NDhrystone.csproj
new file mode 100644
index 0000000000..ea175a5d04
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/NDhrystone/NDhrystone.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="NDhrystone.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/BenchI/Permutate/Permutate.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Permutate/Permutate.cs
new file mode 100644
index 0000000000..d7457cdbc1
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Permutate/Permutate.cs
@@ -0,0 +1,116 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class Permutate
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 20000;
+#endif
+
+ private int[] _permArray = new int[11];
+ private static int s_pctr;
+
+ private static
+ void Swap(int[] arr, int i, int j)
+ {
+ int t = arr[i];
+ arr[i] = arr[j];
+ arr[j] = t;
+ }
+
+ private void Initialize()
+ {
+ for (int i = 1; i <= 7; i++)
+ {
+ _permArray[i] = i - 1;
+ }
+ }
+
+ private void PermuteArray(int n)
+ {
+ int k;
+ s_pctr = s_pctr + 1;
+ if (n != 1)
+ {
+ PermuteArray(n - 1);
+ for (k = n - 1; k >= 1; k--)
+ {
+ Swap(_permArray, n, k);
+ PermuteArray(n - 1);
+ Swap(_permArray, n, k);
+ }
+ }
+ }
+
+ private bool Validate()
+ {
+ int k = 0;
+
+ for (int i = 0; i <= 6; i++)
+ {
+ for (int j = 1; j <= 7; j++)
+ {
+ if (_permArray[j] == i)
+ {
+ k = k + 1;
+ }
+ }
+ }
+
+ return (k == 7);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private bool Bench()
+ {
+ Initialize();
+
+ for (int i = 0; i < Iterations; ++i)
+ {
+ s_pctr = 0;
+ PermuteArray(7);
+ }
+
+ bool result = Validate();
+
+ return result;
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ Permutate P = new Permutate();
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ P.Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ Permutate P = new Permutate();
+ bool result = P.Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Permutate/Permutate.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/Permutate/Permutate.csproj
new file mode 100644
index 0000000000..cbe2114304
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Permutate/Permutate.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Permutate.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/BenchI/Pi/Pi.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Pi/Pi.cs
new file mode 100644
index 0000000000..112ff6df9b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Pi/Pi.cs
@@ -0,0 +1,86 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class Pi
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 100;
+#endif
+
+ static int[] ComputePi(int[] a) {
+
+ int d = 4;
+ int r = 10000;
+ int n = 251;
+ int m = (int)(3.322 * n * d);
+ int[] digits = new int[n];
+ int i, k, q;
+
+ for (i = 0; i <= m; i++) {
+ a[i] = 2;
+ }
+
+ a[m] = 4;
+
+ for (i = 1; i <= n; i++) {
+ q = 0;
+ for (k = m; k > 0L; k--) {
+ a[k] = a[k] * r + q;
+ q = a[k] / (2 * k + 1);
+ a[k] -= (2 * k + 1) * q;
+ q *= k;
+ }
+ a[0] = a[0] * r + q;
+ q = a[0] / r;
+ a[0] -= q * r;
+ digits[i-1] = q;
+ }
+
+ return digits;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench(int[] a) {
+ int[] digits = ComputePi(a);
+ return (digits[0] == 3 && digits[1] == 1415 && digits[2] == 9265 && digits[250] == 1989);
+ }
+
+ [Benchmark]
+ public static void Test() {
+ int[] a = new int[3340];
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench(a);
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ int[] a = new int[3340];
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench(a);
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Pi/Pi.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/Pi/Pi.csproj
new file mode 100644
index 0000000000..d7d212eace
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Pi/Pi.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Pi.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/BenchI/Puzzle/Puzzle.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/Puzzle/Puzzle.cs
new file mode 100644
index 0000000000..2b1c2847f4
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Puzzle/Puzzle.cs
@@ -0,0 +1,393 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class Puzzle
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 400;
+#endif
+
+ private const int PuzzleSize = 511;
+ private const int ClassMax = 3;
+ private const int TypeMax = 12;
+ private const int D = 8;
+
+ private int[] _pieceCount = new int[ClassMax + 1];
+ private int[] _class = new int[TypeMax + 1];
+ private int[] _pieceMax = new int[TypeMax + 1];
+ private bool[] _puzzle = new bool[PuzzleSize + 1];
+ private bool[][] _p;
+ private int _count;
+
+ private static T[][] AllocArray<T>(int n1, int n2)
+ {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i)
+ {
+ a[i] = new T[n2];
+ }
+
+ return a;
+ }
+
+ private bool Fit(int i, int j)
+ {
+ for (int k = 0; k <= _pieceMax[i]; k++)
+ {
+ if (_p[i][k])
+ {
+ if (_puzzle[j + k])
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private int Place(int i, int j)
+ {
+ int k;
+ for (k = 0; k <= _pieceMax[i]; k++)
+ {
+ if (_p[i][k])
+ {
+ _puzzle[j + k] = true;
+ }
+ }
+
+ _pieceCount[_class[i]] = _pieceCount[_class[i]] - 1;
+
+ for (k = j; k <= PuzzleSize; k++)
+ {
+ if (!_puzzle[k])
+ {
+ return k;
+ }
+ }
+
+ return 0;
+ }
+
+ private void RemoveLocal(int i, int j)
+ {
+ for (int k = 0; k <= _pieceMax[i]; k++)
+ {
+ if (_p[i][k])
+ {
+ _puzzle[j + k] = false;
+ }
+ }
+
+ _pieceCount[_class[i]] = _pieceCount[_class[i]] + 1;
+ }
+
+ private bool Trial(int j)
+ {
+ for (int i = 0; i <= TypeMax; i++)
+ {
+ if (_pieceCount[_class[i]] != 0)
+ {
+ if (Fit(i, j))
+ {
+ int k = Place(i, j);
+ if (Trial(k) || (k == 0))
+ {
+ _count = _count + 1;
+ return true;
+ }
+ else
+ {
+ RemoveLocal(i, j);
+ }
+ }
+ }
+ }
+
+ _count = _count + 1;
+ return false;
+ }
+
+ private bool DoIt()
+ {
+ int i, j, k, m, n;
+
+ for (m = 0; m <= PuzzleSize; m++)
+ {
+ _puzzle[m] = true;
+ }
+
+ for (i = 1; i <= 5; i++)
+ {
+ for (j = 1; j <= 5; j++)
+ {
+ for (k = 1; k <= 5; k++)
+ {
+ _puzzle[i + D * (j + D * k)] = false;
+ }
+ }
+ }
+
+ for (i = 0; i <= TypeMax; i++)
+ {
+ for (m = 0; m <= PuzzleSize; m++)
+ {
+ _p[i][m] = false;
+ }
+ }
+
+ for (i = 0; i <= 3; i++)
+ {
+ for (j = 0; j <= 1; j++)
+ {
+ for (k = 0; k <= 0; k++)
+ {
+ _p[0][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+
+ _class[0] = 0;
+ _pieceMax[0] = 3 + D * 1 + D * D * 0;
+
+ for (i = 0; i <= 1; i++)
+ {
+ for (j = 0; j <= 0; j++)
+ {
+ for (k = 0; k <= 3; k++)
+ {
+ _p[1][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+
+ _class[1] = 0;
+ _pieceMax[1] = 1 + D * 0 + D * D * 3;
+
+ for (i = 0; i <= 0; i++)
+ {
+ for (j = 0; j <= 3; j++)
+ {
+ for (k = 0; k <= 1; k++)
+ {
+ _p[2][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+ _class[2] = 0;
+ _pieceMax[2] = 0 + D * 3 + D * D * 1;
+
+ for (i = 0; i <= 1; i++)
+ {
+ for (j = 0; j <= 3; j++)
+ {
+ for (k = 0; k <= 0; k++)
+ {
+ _p[3][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+
+ _class[3] = 0;
+ _pieceMax[3] = 1 + D * 3 + D * D * 0;
+
+ for (i = 0; i <= 3; i++)
+ {
+ for (j = 0; j <= 0; j++)
+ {
+ for (k = 0; k <= 1; k++)
+ {
+ _p[4][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+
+ _class[4] = 0;
+ _pieceMax[4] = 3 + D * 0 + D * D * 1;
+
+ for (i = 0; i <= 0; i++)
+ {
+ for (j = 0; j <= 1; j++)
+ {
+ for (k = 0; k <= 3; k++)
+ {
+ _p[5][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+
+ _class[5] = 0;
+ _pieceMax[5] = 0 + D * 1 + D * D * 3;
+
+ for (i = 0; i <= 2; i++)
+ {
+ for (j = 0; j <= 0; j++)
+ {
+ for (k = 0; k <= 0; k++)
+ {
+ _p[6][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+
+ _class[6] = 1;
+ _pieceMax[6] = 2 + D * 0 + D * D * 0;
+
+ for (i = 0; i <= 0; i++)
+ {
+ for (j = 0; j <= 2; j++)
+ {
+ for (k = 0; k <= 0; k++)
+ {
+ _p[7][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+
+ _class[7] = 1;
+ _pieceMax[7] = 0 + D * 2 + D * D * 0;
+
+ for (i = 0; i <= 0; i++)
+ {
+ for (j = 0; j <= 0; j++)
+ {
+ for (k = 0; k <= 2; k++)
+ {
+ _p[8][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+
+ _class[8] = 1;
+ _pieceMax[8] = 0 + D * 0 + D * D * 2;
+
+ for (i = 0; i <= 1; i++)
+ {
+ for (j = 0; j <= 1; j++)
+ {
+ for (k = 0; k <= 0; k++)
+ {
+ _p[9][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+ _class[9] = 2;
+ _pieceMax[9] = 1 + D * 1 + D * D * 0;
+
+ for (i = 0; i <= 1; i++)
+ {
+ for (j = 0; j <= 0; j++)
+ {
+ for (k = 0; k <= 1; k++)
+ {
+ _p[10][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+
+ _class[10] = 2;
+ _pieceMax[10] = 1 + D * 0 + D * D * 1;
+
+ for (i = 0; i <= 0; i++)
+ {
+ for (j = 0; j <= 1; j++)
+ {
+ for (k = 0; k <= 1; k++)
+ {
+ _p[11][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+
+ _class[11] = 2;
+ _pieceMax[11] = 0 + D * 1 + D * D * 1;
+
+ for (i = 0; i <= 1; i++)
+ {
+ for (j = 0; j <= 1; j++)
+ {
+ for (k = 0; k <= 1; k++)
+ {
+ _p[12][i + D * (j + D * k)] = true;
+ }
+ }
+ }
+
+ _class[12] = 3;
+ _pieceMax[12] = 1 + D * 1 + D * D * 1;
+ _pieceCount[0] = 13;
+ _pieceCount[1] = 3;
+ _pieceCount[2] = 1;
+ _pieceCount[3] = 1;
+ m = 1 + D * (1 + D * 1);
+ _count = 0;
+
+ bool result = true;
+
+ if (Fit(0, m))
+ {
+ n = Place(0, m);
+ result = Trial(n);
+ }
+ else
+ {
+ result = false;
+ }
+
+ return result;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private bool Bench()
+ {
+ _p = AllocArray<bool>(TypeMax + 1, PuzzleSize + 1);
+
+ bool result = true;
+
+ for (int i = 0; i < Iterations; ++i)
+ {
+ result &= DoIt();
+ }
+
+ return result;
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ Puzzle P = new Puzzle();
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ P.Bench();
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ Puzzle P = new Puzzle();
+ bool result = P.Bench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/Puzzle/Puzzle.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/Puzzle/Puzzle.csproj
new file mode 100644
index 0000000000..185bb7c08e
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/Puzzle/Puzzle.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Puzzle.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/BenchI/QuickSort/QuickSort.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/QuickSort/QuickSort.cs
new file mode 100644
index 0000000000..191211aaa8
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/QuickSort/QuickSort.cs
@@ -0,0 +1,116 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class QuickSort
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 80000;
+#endif
+
+ const int MAXNUM = 200;
+ const int MODULUS = 0x20000;
+ const int C = 13849;
+ const int A = 25173;
+ static int s_seed = 7;
+
+ static int Random(int size) {
+ unchecked {
+ s_seed = s_seed * A + C;
+ }
+ return (s_seed % size);
+ }
+
+ static void Quick(int lo, int hi, int[] arr) {
+
+ int i, j;
+ int pivot, temp;
+
+ if (lo < hi) {
+ for (i = lo, j = hi, pivot = arr[hi]; i < j;) {
+ while (i < j && arr[i] <= pivot){
+ ++i;
+ }
+ while (j > i && arr[j] >= pivot) {
+ --j;
+ }
+ if (i < j) {
+ temp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = temp;
+ }
+ }
+
+ // need to swap the pivot and a[i](or a[j] as i==j) so
+ // that the pivot will be at its final place in the sorted array
+
+ if (i != hi) {
+ temp = arr[i];
+ arr[i] = pivot;
+ arr[hi] = temp;
+ }
+ Quick(lo, i - 1, arr);
+ Quick(i + 1, hi, arr);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+
+ int[] buffer = new int[MAXNUM];
+
+ for (int j = 0; j < MAXNUM; ++j) {
+ int temp = Random(MODULUS);
+ if (temp < 0){
+ temp = (-temp);
+ }
+ buffer[j] = temp;
+ }
+
+ Quick(0, MAXNUM - 1, buffer);
+
+ for (int j = 0; j < MAXNUM - 1; ++j) {
+ if (buffer[j] > buffer[j+1]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench();
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/QuickSort/QuickSort.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/QuickSort/QuickSort.csproj
new file mode 100644
index 0000000000..f079692c3c
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/QuickSort/QuickSort.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="QuickSort.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/BenchI/TreeInsert/TreeInsert.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeInsert/TreeInsert.cs
new file mode 100644
index 0000000000..8a24240538
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeInsert/TreeInsert.cs
@@ -0,0 +1,138 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class TreeInsert
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 15000;
+#endif
+
+ private struct Node
+ {
+ public int A;
+ public int L;
+ public int R;
+ }
+
+ private struct Tree
+ {
+ public int Root;
+ public int NextAvail;
+ public Node[] Nodes;
+ }
+
+ private Tree _s;
+
+ public TreeInsert()
+ {
+ _s.Nodes = new Node[10001];
+ }
+
+ private void BenchInner(int x)
+ {
+ /* a tree insertion routine from knuth */
+ int i = _s.Root;
+ int j = _s.NextAvail;
+
+ L10:
+ /* compare */
+ if (_s.Nodes[i].A < x)
+ {
+ if (_s.Nodes[i].L != 0)
+ {
+ i = _s.Nodes[i].L;
+ goto L10;
+ }
+ else
+ {
+ _s.Nodes[i].L = j;
+ goto L20;
+ }
+ }
+ else
+ {
+ if (_s.Nodes[i].R != 0)
+ {
+ i = _s.Nodes[i].R;
+ goto L10;
+ }
+ else
+ {
+ _s.Nodes[i].R = j;
+ goto L20;
+ }
+ }
+
+ L20:
+ /* insert */
+ _s.Nodes[j].A = x;
+ _s.Nodes[j].L = 0;
+ _s.Nodes[j].R = 0;
+ _s.NextAvail = j + 1;
+ }
+
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private bool Bench()
+ {
+ _s.Root = 1;
+ _s.NextAvail = 2;
+ _s.Nodes[1].A = 300;
+ _s.Nodes[1].L = 0;
+ _s.Nodes[1].R = 0;
+
+ int j = 99999;
+ for (int i = 1; i <= 900; i++)
+ {
+ BenchInner(j & 4095);
+ j = j + 33333;
+ }
+
+ return (_s.Nodes[500].A == 441);
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ TreeInsert T = new TreeInsert();
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 1; i <= Iterations; i++)
+ {
+ T.Bench();
+ }
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ TreeInsert T = new TreeInsert();
+ bool result = true;
+ for (int i = 1; i <= Iterations; i++)
+ {
+ result &= T.Bench();
+ }
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/TreeInsert/TreeInsert.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeInsert/TreeInsert.csproj
new file mode 100644
index 0000000000..919c7d2b6e
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeInsert/TreeInsert.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="TreeInsert.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/BenchI/TreeSort/TreeSort.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeSort/TreeSort.cs
new file mode 100644
index 0000000000..68b5c965f7
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeSort/TreeSort.cs
@@ -0,0 +1,151 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class TreeSort
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 1200;
+#endif
+
+ const int SortElements = 5000;
+ const int Modulus = 65536;
+
+ sealed class Node
+ {
+ public Node Left;
+ public Node Right;
+ public int Val;
+ public Node(int n)
+ {
+ Left = null;
+ Right = null;
+ Val = n;
+ }
+ }
+
+ static int s_biggest;
+ static int s_littlest;
+ static int s_seed;
+
+ static void InitRand() {
+ s_seed = 33;
+ }
+
+ static int Rand(ref int seed) {
+ int multiplier = 25173;
+ int increment = 13849;
+ seed = (multiplier * seed + increment) % Modulus;
+ return seed;
+ }
+
+ static void InitArray(int[] sortList) {
+ InitRand();
+ s_biggest = 0;
+ s_littlest = Modulus;
+ for (int i = 1; i <= SortElements; i++) {
+ sortList[i] = Rand(ref s_seed) - 1;
+ if (sortList[i] > s_biggest) {
+ s_biggest = sortList[i];
+ }
+ else if (sortList[i] < s_littlest) {
+ s_littlest = sortList[i];
+ }
+ }
+ }
+
+ static void Insert(int n, Node t) {
+ if (n > t.Val) {
+ if (t.Left == null) {
+ t.Left = new Node(n);
+ }
+ else {
+ Insert(n, t.Left);
+ }
+ }
+ else if (n < t.Val) {
+ if (t.Right == null) {
+ t.Right = new Node(n);
+ }
+ else {
+ Insert(n, t.Right);
+ }
+ }
+ }
+
+ static bool CheckTree(Node p) {
+ bool result = true;
+ if (p.Left != null) {
+ if (p.Left.Val <= p.Val) {
+ result = false;
+ }
+ else {
+ result &= CheckTree(p.Left);
+ }
+ }
+
+ if (p.Right != null) {
+ if (p.Right.Val >= p.Val) {
+ result = false;
+ }
+ else {
+ result &= CheckTree(p.Right);
+ }
+ }
+
+ return result;
+ }
+
+ static bool Trees(int[] sortList) {
+ InitArray(sortList);
+ Node tree = new Node(sortList[1]);
+ for (int i = 2; i <= SortElements; i++) {
+ Insert(sortList[i], tree);
+ }
+ bool result = CheckTree(tree);
+ return result;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench() {
+ int[] sortList = new int[SortElements + 1];
+ bool result = Trees(sortList);
+ return result;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench();
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/TreeSort/TreeSort.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeSort/TreeSort.csproj
new file mode 100644
index 0000000000..b9f78517a9
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/TreeSort/TreeSort.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="TreeSort.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/BenchI/XposMatrix/XposMatrix.cs b/tests/src/JIT/Performance/CodeQuality/BenchI/XposMatrix/XposMatrix.cs
new file mode 100644
index 0000000000..0bb17b8cc5
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/XposMatrix/XposMatrix.cs
@@ -0,0 +1,90 @@
+// 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.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class XposMatrix
+{
+ public const int ArraySize = 100;
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 25000;
+#endif
+
+ static T[][] AllocArray<T>(int n1, int n2) {
+ T[][] a = new T[n1][];
+ for (int i = 0; i < n1; ++i) {
+ a[i] = new T[n2];
+ }
+ return a;
+ }
+
+ static void Inner(int[][] x, int n) {
+ for (int i = 1; i <= n; i++) {
+ for (int j = 1; j <= n; j++) {
+ int t = x[i][j];
+ x[i][j] = x[j][i];
+ x[j][i] = t;
+ }
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench(int[][] matrix) {
+
+ int n = ArraySize;
+ for (int i = 1; i <= n; i++) {
+ for (int j = 1; j <= n; j++) {
+ matrix[i][j] = 1;
+ }
+ }
+
+ if (matrix[n][n] != 1) {
+ return false;
+ }
+
+ Inner(matrix, n);
+
+ if (matrix[n][n] != 1) {
+ return false;
+ }
+
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ int[][] matrix = AllocArray<int>(ArraySize + 1, ArraySize + 1);
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench(matrix);
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ int[][] matrix = AllocArray<int>(ArraySize + 1, ArraySize + 1);
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench(matrix);
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchI/XposMatrix/XposMatrix.csproj b/tests/src/JIT/Performance/CodeQuality/BenchI/XposMatrix/XposMatrix.csproj
new file mode 100644
index 0000000000..922fd5fc39
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchI/XposMatrix/XposMatrix.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="XposMatrix.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/BenchmarksGame/LICENSE.TXT b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/LICENSE.TXT
new file mode 100644
index 0000000000..5e0fbafb8d
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/LICENSE.TXT
@@ -0,0 +1,18 @@
+Revised BSD license
+
+This is a specific instance of the Open Source Initiative (OSI) BSD license template
+http://www.opensource.org/licenses/bsd-license.php
+
+
+Copyright © 2004-2008 Brent Fulgham, 2005-2015 Isaac Gouy
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+ Neither the name of "The Computer Language Benchmarks Game" nor the name of "The Computer Language Shootout Benchmarks" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/README.TXT b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/README.TXT
new file mode 100644
index 0000000000..b95d43c361
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/README.TXT
@@ -0,0 +1,37 @@
+The benchmarks in these sub-directories are based on
+
+ The Computer Language Benchmarks Game
+ http://benchmarksgame.alioth.debian.org/
+
+See the adjoining LICENSE.TXT file for license terms.
+
+Our intention with these tests is to provide interesting test cases
+for jit developers to use in daily development practice -- not to
+produce variants that give the maximum possible performance.
+
+The benchmarks have been modified to fit into the CoreCLR test and
+performance test framework, as follows:
+
+ - adding validity checks to ensure optimizers correctly optimize
+ and do not remove computation
+ - adding return codes to main based on those checks
+ - adding an xunit-performance entry point, and adjusting work so each
+ xunit-performance iteration is approximately 1 second on modern x64
+ hardware
+ - reducing verbosity when run as a benchmark
+ - reformatting (via the codeformatter tool)
+
+These benchmarks are just a subset of the benchmarks available in C# from
+the Benchmarks Game site. We've selected variants that do not rely on
+multiple threads to ensure relative benchmark stability across a
+variety of machines.
+
+We've excluded two benchmarks that are inherently multitheaded:
+chamenosredux and threadring. We may revisit this as we improve our
+ability to harness threading tests in a stable way.
+
+We've also excluded benchmarks that read in large input files:
+knucleotide, regexdna, revcomp.
+
+
+
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp.cs
new file mode 100644
index 0000000000..e4118b2963
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp.cs
@@ -0,0 +1,151 @@
+// 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.
+/* The Computer Language Benchmarks Game
+ http://benchmarksgame.alioth.debian.org/
+
+ contributed by Marek Safar
+
+ modified for use with xunit-performance
+*/
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class BinaryTrees
+{
+ private const int minDepth = 4;
+ private const int Iterations = 1;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static bool Bench(bool verbose = false)
+ {
+ int n = 16;
+ int maxDepth = Math.Max(minDepth + 2, n);
+ int stretchDepth = maxDepth + 1;
+ int t = 0;
+
+ int check = (TreeNode.bottomUpTree(0, stretchDepth)).itemCheck();
+ if (verbose)
+ {
+ Console.WriteLine("stretch tree of depth {0}\t check: {1}", stretchDepth, check);
+ }
+ t += check;
+
+ TreeNode longLivedTree = TreeNode.bottomUpTree(0, maxDepth);
+
+ for (int depth = minDepth; depth <= maxDepth; depth += 2)
+ {
+ int iterations = 1 << (maxDepth - depth + minDepth);
+
+ check = 0;
+ for (int i = 1; i <= iterations; i++)
+ {
+ check += (TreeNode.bottomUpTree(i, depth)).itemCheck();
+ check += (TreeNode.bottomUpTree(-i, depth)).itemCheck();
+ }
+
+ if (verbose)
+ {
+ Console.WriteLine("{0}\t trees of depth {1}\t check: {2}",
+ iterations * 2, depth, check);
+ }
+
+ t += check;
+ }
+
+ if (verbose)
+ {
+ Console.WriteLine("long lived tree of depth {0}\t check: {1}",
+ maxDepth, longLivedTree.itemCheck());
+ }
+
+ t += check;
+
+ return (t == -174785);
+ }
+
+ private struct TreeNode
+ {
+ private class Next
+ {
+ public TreeNode left, right;
+ }
+
+ private Next _next;
+ private int _item;
+
+ private TreeNode(int item)
+ {
+ _item = item;
+ _next = null;
+ }
+
+ internal static TreeNode bottomUpTree(int item, int depth)
+ {
+ if (depth > 0)
+ {
+ return new TreeNode(
+ bottomUpTree(2 * item - 1, depth - 1)
+ , bottomUpTree(2 * item, depth - 1)
+ , item
+ );
+ }
+ else
+ {
+ return new TreeNode(item);
+ }
+ }
+
+ private TreeNode(TreeNode left, TreeNode right, int item)
+ {
+ _next = new Next();
+ _next.left = left;
+ _next.right = right;
+ _item = item;
+ }
+
+ internal int itemCheck()
+ {
+ // if necessary deallocate here
+ if (_next == null) return _item;
+ else return _item + _next.left.itemCheck() - _next.right.itemCheck();
+ }
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ Bench();
+ }
+ }
+ }
+ }
+
+ private static bool TestBase()
+ {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++)
+ {
+ result &= Bench(true);
+ }
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csproj
new file mode 100644
index 0000000000..d970a78c23
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csproj
@@ -0,0 +1,44 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ <GCStressIncompatible>true</GCStressIncompatible>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="binarytrees.csharp.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/BenchmarksGame/fasta/fasta.csharp-2.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csharp-2.cs
new file mode 100644
index 0000000000..c58ce0bd97
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csharp-2.cs
@@ -0,0 +1,220 @@
+// 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.
+/* The Computer Language Benchmarks Game
+ http://benchmarksgame.alioth.debian.org/
+
+ contributed by Isaac Gouy
+ optimizations by Alp Toker <alp@atoker.com>
+
+ modified for use with xunit-performance
+*/
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.IO;
+using System.Text;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class Fasta
+{
+#if DEBUG
+ private const int Iterations = 1;
+#else
+ const int Iterations = 800;
+#endif
+
+ public static int Main(string[] args)
+ {
+ MakeCumulative(s_homoSapiens);
+ MakeCumulative(s_IUB);
+
+ int n = args.Length > 0 ? Int32.Parse(args[0]) : 1000;
+
+ using (Stream s = Console.OpenStandardOutput())
+ {
+ MakeRepeatFasta("ONE", "Homo sapiens alu", Encoding.ASCII.GetBytes(s_ALU), n * 2, s);
+ MakeRandomFasta("TWO", "IUB ambiguity codes", s_IUB, n * 3, s);
+ MakeRandomFasta("THREE", "Homo sapiens frequency", s_homoSapiens, n * 5, s);
+ }
+ return 100;
+ }
+
+ [Benchmark]
+ public static void Bench()
+ {
+ int n = 5000;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ using (Stream s = Stream.Null)
+ {
+ MakeRepeatFasta("ONE", "Homo sapiens alu", Encoding.ASCII.GetBytes(s_ALU), n * 2, s);
+ MakeRandomFasta("TWO", "IUB ambiguity codes", s_IUB, n * 3, s);
+ MakeRandomFasta("THREE", "Homo sapiens frequency", s_homoSapiens, n * 5, s);
+ }
+ }
+ }
+ }
+ }
+
+ // The usual pseudo-random number generator
+
+ private const int IM = 139968;
+ private const int IA = 3877;
+ private const int IC = 29573;
+ private static int s_seed = 42;
+
+ private static double random(double max)
+ {
+ return max * ((s_seed = (s_seed * IA + IC) % IM) * (1.0 / IM));
+ }
+
+ // Weighted selection from alphabet
+
+ private static string s_ALU =
+ "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
+ "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
+ "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
+ "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
+ "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
+ "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
+ "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
+
+ private class Frequency
+ {
+ public byte c;
+ public double p;
+
+ public Frequency(char c, double p)
+ {
+ this.c = (byte)c;
+ this.p = p;
+ }
+ }
+
+ private static Frequency[] s_IUB = {
+ new Frequency ('a', 0.27)
+ ,new Frequency ('c', 0.12)
+ ,new Frequency ('g', 0.12)
+ ,new Frequency ('t', 0.27)
+
+ ,new Frequency ('B', 0.02)
+ ,new Frequency ('D', 0.02)
+ ,new Frequency ('H', 0.02)
+ ,new Frequency ('K', 0.02)
+ ,new Frequency ('M', 0.02)
+ ,new Frequency ('N', 0.02)
+ ,new Frequency ('R', 0.02)
+ ,new Frequency ('S', 0.02)
+ ,new Frequency ('V', 0.02)
+ ,new Frequency ('W', 0.02)
+ ,new Frequency ('Y', 0.02)
+ };
+
+ private static Frequency[] s_homoSapiens = {
+ new Frequency ('a', 0.3029549426680)
+ ,new Frequency ('c', 0.1979883004921)
+ ,new Frequency ('g', 0.1975473066391)
+ ,new Frequency ('t', 0.3015094502008)
+ };
+
+ private static void MakeCumulative(Frequency[] a)
+ {
+ double cp = 0.0;
+ for (int i = 0; i < a.Length; i++)
+ {
+ cp += a[i].p;
+ a[i].p = cp;
+ }
+ }
+
+ // naive
+ private static byte SelectRandom(Frequency[] a)
+ {
+ double r = random(1.0);
+
+ for (int i = 0; i < a.Length; i++)
+ if (r < a[i].p)
+ return a[i].c;
+
+ return a[a.Length - 1].c;
+ }
+
+ private const int LineLength = 60;
+ private static int s_index = 0;
+ private static byte[] s_buf = new byte[1024];
+
+ private static void MakeRandomFasta(string id, string desc, Frequency[] a, int n, Stream s)
+ {
+ s_index = 0;
+ int m = 0;
+
+ byte[] descStr = Encoding.ASCII.GetBytes(">" + id + " " + desc + "\n");
+ s.Write(descStr, 0, descStr.Length);
+
+ while (n > 0)
+ {
+ m = n < LineLength ? n : LineLength;
+
+ if (s_buf.Length - s_index < m)
+ {
+ s.Write(s_buf, 0, s_index);
+ s_index = 0;
+ }
+
+ for (int i = 0; i < m; i++)
+ {
+ s_buf[s_index++] = SelectRandom(a);
+ }
+
+ s_buf[s_index++] = (byte)'\n';
+ n -= LineLength;
+ }
+
+ if (s_index != 0)
+ s.Write(s_buf, 0, s_index);
+ }
+
+ private static void MakeRepeatFasta(string id, string desc, byte[] alu, int n, Stream s)
+ {
+ s_index = 0;
+ int m = 0;
+ int k = 0;
+ int kn = alu.Length;
+
+ byte[] descStr = Encoding.ASCII.GetBytes(">" + id + " " + desc + "\n");
+ s.Write(descStr, 0, descStr.Length);
+
+ while (n > 0)
+ {
+ m = n < LineLength ? n : LineLength;
+
+ if (s_buf.Length - s_index < m)
+ {
+ s.Write(s_buf, 0, s_index);
+ s_index = 0;
+ }
+
+ for (int i = 0; i < m; i++)
+ {
+ if (k == kn)
+ k = 0;
+
+ s_buf[s_index++] = alu[k];
+ k++;
+ }
+
+ s_buf[s_index++] = (byte)'\n';
+ n -= LineLength;
+ }
+
+ if (s_index != 0)
+ s.Write(s_buf, 0, s_index);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csproj
new file mode 100644
index 0000000000..c153dfae39
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="fasta.csharp-2.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/BenchmarksGame/fastaredux/fastaredux.csharp.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csharp.cs
new file mode 100644
index 0000000000..7128e326fc
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csharp.cs
@@ -0,0 +1,184 @@
+// 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.
+/* The Computer Language Benchmarks Game
+ http://benchmarksgame.alioth.debian.org/
+
+ contributed by Robert F. Tobler
+ optimized based on java & C# by Enotus, Isaac Gouy, and Alp Toker
+
+ modified for use with xunit-performance
+*/
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.IO;
+using System.Text;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class FastaRedux
+{
+#if DEBUG
+ private const int Iterations = 1;
+#else
+ const int Iterations = 5;
+#endif
+
+ public static int Main(string[] args)
+ {
+ AccumulateAndScale(s_homoSapiens);
+ AccumulateAndScale(s_IUB);
+ int n = args.Length > 0 ? Int32.Parse(args[0]) : 2500;
+ using (Stream s = Console.OpenStandardOutput())
+ {
+ s.WriteRepeatFasta("ONE", "Homo sapiens alu", Encoding.ASCII.GetBytes(s_ALU), n * 2);
+ s.WriteRandomFasta("TWO", "IUB ambiguity codes", s_IUB, n * 3);
+ s.WriteRandomFasta("THREE", "Homo sapiens frequency", s_homoSapiens, n * 5);
+ }
+ return 100;
+ }
+
+ [Benchmark]
+ public static void Bench()
+ {
+ int n = 2500000;
+ AccumulateAndScale(s_homoSapiens);
+ AccumulateAndScale(s_IUB);
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ using (Stream s = Stream.Null)
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ s.WriteRepeatFasta("ONE", "Homo sapiens alu", Encoding.ASCII.GetBytes(s_ALU), n * 2);
+ s.WriteRandomFasta("TWO", "IUB ambiguity codes", s_IUB, n * 3);
+ s.WriteRandomFasta("THREE", "Homo sapiens frequency", s_homoSapiens, n * 5);
+ }
+ }
+ }
+ }
+ }
+
+ private const int LINE_LEN = 60;
+ private const int BUF_LEN = 64 * 1024;
+ private const byte LF = (byte)'\n';
+
+ private const int LOOKUP_LEN = 1024;
+ private const double LOOKUP_SCALE = LOOKUP_LEN - 1;
+
+ private static readonly string s_ALU =
+ "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
+ "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
+ "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
+ "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
+ "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
+ "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
+ "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
+
+ private struct Freq
+ {
+ public double P;
+ public byte C;
+
+ public Freq(char c, double p) { C = (byte)c; P = p; }
+ }
+
+ private static Freq[] s_IUB = {
+ new Freq('a', 0.27), new Freq('c', 0.12), new Freq('g', 0.12),
+ new Freq('t', 0.27), new Freq('B', 0.02), new Freq('D', 0.02),
+ new Freq('H', 0.02), new Freq('K', 0.02), new Freq('M', 0.02),
+ new Freq('N', 0.02), new Freq('R', 0.02), new Freq('S', 0.02),
+ new Freq('V', 0.02), new Freq('W', 0.02), new Freq('Y', 0.02),
+ };
+
+ private static Freq[] s_homoSapiens = {
+ new Freq ('a', 0.3029549426680), new Freq ('c', 0.1979883004921),
+ new Freq ('g', 0.1975473066391), new Freq ('t', 0.3015094502008),
+ };
+
+ private static void AccumulateAndScale(Freq[] a)
+ {
+ double cp = 0.0;
+ for (int i = 0; i < a.Length; i++)
+ a[i].P = (cp += a[i].P) * LOOKUP_SCALE;
+ a[a.Length - 1].P = LOOKUP_SCALE;
+ }
+
+ private static byte[] s_buf = new byte[BUF_LEN];
+
+ private static int WriteDesc(this byte[] buf, string id, string desc)
+ {
+ var ds = Encoding.ASCII.GetBytes(">" + id + " " + desc + "\n");
+ for (int i = 0; i < ds.Length; i++) buf[i] = ds[i];
+ return BUF_LEN - ds.Length;
+ }
+
+ private static int Min(int a, int b) { return a < b ? a : b; }
+
+ private static void WriteRepeatFasta(
+ this Stream s, string id, string desc, byte[] alu, int nr)
+ {
+ int alen = alu.Length;
+ int ar = alen, br = s_buf.WriteDesc(id, desc), lr = LINE_LEN;
+ while (nr > 0)
+ {
+ int r = Min(Min(nr, lr), Min(ar, br));
+ for (int ai = alen - ar, bi = BUF_LEN - br, be = bi + r;
+ bi < be; bi++, ai++)
+ s_buf[bi] = alu[ai];
+ nr -= r; lr -= r; br -= r; ar -= r;
+ if (ar == 0) ar = alen;
+ if (br == 0) { s.Write(s_buf, 0, BUF_LEN); br = BUF_LEN; }
+ if (lr == 0) { s_buf[BUF_LEN - (br--)] = LF; lr = LINE_LEN; }
+ if (br == 0) { s.Write(s_buf, 0, BUF_LEN); br = BUF_LEN; }
+ }
+ if (lr < LINE_LEN) s_buf[BUF_LEN - (br--)] = LF;
+ if (br < BUF_LEN) s.Write(s_buf, 0, BUF_LEN - br);
+ }
+
+ private static Freq[] s_lookup = new Freq[LOOKUP_LEN];
+
+ private static void CreateLookup(Freq[] fr)
+ {
+ for (int i = 0, j = 0; i < LOOKUP_LEN; i++)
+ {
+ while (fr[j].P < i) j++;
+ s_lookup[i] = fr[j];
+ }
+ }
+
+ private const int IM = 139968;
+ private const int IA = 3877;
+ private const int IC = 29573;
+ private const double SCALE = LOOKUP_SCALE / IM;
+
+ private static int s_last = 42;
+
+ private static void WriteRandomFasta(
+ this Stream s, string id, string desc, Freq[] fr, int nr)
+ {
+ CreateLookup(fr);
+ int br = s_buf.WriteDesc(id, desc), lr = LINE_LEN;
+ while (nr > 0)
+ {
+ int r = Min(Min(nr, lr), br);
+ for (int bi = BUF_LEN - br, be = bi + r; bi < be; bi++)
+ {
+ double p = SCALE * (s_last = (s_last * IA + IC) % IM);
+ int ai = (int)p; if (s_lookup[ai].P < p) ai++;
+ s_buf[bi] = s_lookup[ai].C;
+ }
+ nr -= r; lr -= r; br -= r;
+ if (br == 0) { s.Write(s_buf, 0, BUF_LEN); br = BUF_LEN; }
+ if (lr == 0) { s_buf[BUF_LEN - (br--)] = LF; lr = LINE_LEN; }
+ if (br == 0) { s.Write(s_buf, 0, BUF_LEN); br = BUF_LEN; }
+ }
+ if (lr < LINE_LEN) s_buf[BUF_LEN - (br--)] = LF;
+ if (br < BUF_LEN) s.Write(s_buf, 0, BUF_LEN - br);
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csproj
new file mode 100644
index 0000000000..38459d270f
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="fastaredux.csharp.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/BenchmarksGame/nbody/nbody.csharp-3.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs
new file mode 100644
index 0000000000..70c87095ad
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs
@@ -0,0 +1,156 @@
+// 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.
+/* The Computer Language Benchmarks Game
+ http://benchmarksgame.alioth.debian.org/
+
+ contributed by Isaac Gouy, optimization and use of more C# idioms by Robert F. Tobler
+
+ modified for use with xunit-performance
+*/
+
+using Microsoft.Xunit.Performance;
+using System;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class NBody
+{
+ public static int Main(String[] args)
+ {
+ int n = args.Length > 0 ? Int32.Parse(args[0]) : 10000;
+ NBodySystem bodies = new NBodySystem();
+ double initialEnergy = bodies.Energy();
+ Console.WriteLine("{0:f9}", initialEnergy);
+ for (int i = 0; i < n; i++) bodies.Advance(0.01);
+ double finalEnergy = bodies.Energy();
+ Console.WriteLine("{0:f9}", finalEnergy);
+ double deltaEnergy = Math.Abs(initialEnergy - finalEnergy);
+ bool result = deltaEnergy < 1e-4;
+ Console.WriteLine("Energy {0} conserved", result ? "was" : "was not");
+ return (result ? 100 : -1);
+ }
+
+ [Benchmark]
+ public static void Bench()
+ {
+ int n = 5000000;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ NBodySystem bodies = new NBodySystem();
+ for (int i = 0; i < n; i++) bodies.Advance(0.01);
+ }
+ }
+ }
+}
+
+internal class Body { public double x, y, z, vx, vy, vz, mass; }
+internal class Pair { public Body bi, bj; }
+
+internal class NBodySystem
+{
+ private Body[] _bodies;
+ private Pair[] _pairs;
+
+ private const double Pi = 3.141592653589793;
+ private const double Solarmass = 4 * Pi * Pi;
+ private const double DaysPeryear = 365.24;
+
+ public NBodySystem()
+ {
+ _bodies = new Body[] {
+ new Body() { // Sun
+ mass = Solarmass,
+ },
+ new Body() { // Jupiter
+ x = 4.84143144246472090e+00,
+ y = -1.16032004402742839e+00,
+ z = -1.03622044471123109e-01,
+ vx = 1.66007664274403694e-03 * DaysPeryear,
+ vy = 7.69901118419740425e-03 * DaysPeryear,
+ vz = -6.90460016972063023e-05 * DaysPeryear,
+ mass = 9.54791938424326609e-04 * Solarmass,
+ },
+ new Body() { // Saturn
+ x = 8.34336671824457987e+00,
+ y = 4.12479856412430479e+00,
+ z = -4.03523417114321381e-01,
+ vx = -2.76742510726862411e-03 * DaysPeryear,
+ vy = 4.99852801234917238e-03 * DaysPeryear,
+ vz = 2.30417297573763929e-05 * DaysPeryear,
+ mass = 2.85885980666130812e-04 * Solarmass,
+ },
+ new Body() { // Uranus
+ x = 1.28943695621391310e+01,
+ y = -1.51111514016986312e+01,
+ z = -2.23307578892655734e-01,
+ vx = 2.96460137564761618e-03 * DaysPeryear,
+ vy = 2.37847173959480950e-03 * DaysPeryear,
+ vz = -2.96589568540237556e-05 * DaysPeryear,
+ mass = 4.36624404335156298e-05 * Solarmass,
+ },
+ new Body() { // Neptune
+ x = 1.53796971148509165e+01,
+ y = -2.59193146099879641e+01,
+ z = 1.79258772950371181e-01,
+ vx = 2.68067772490389322e-03 * DaysPeryear,
+ vy = 1.62824170038242295e-03 * DaysPeryear,
+ vz = -9.51592254519715870e-05 * DaysPeryear,
+ mass = 5.15138902046611451e-05 * Solarmass,
+ },
+ };
+
+ _pairs = new Pair[_bodies.Length * (_bodies.Length - 1) / 2];
+ int pi = 0;
+ for (int i = 0; i < _bodies.Length - 1; i++)
+ for (int j = i + 1; j < _bodies.Length; j++)
+ _pairs[pi++] = new Pair() { bi = _bodies[i], bj = _bodies[j] };
+
+ double px = 0.0, py = 0.0, pz = 0.0;
+ foreach (var b in _bodies)
+ {
+ px += b.vx * b.mass; py += b.vy * b.mass; pz += b.vz * b.mass;
+ }
+ var sol = _bodies[0];
+ sol.vx = -px / Solarmass; sol.vy = -py / Solarmass; sol.vz = -pz / Solarmass;
+ }
+
+ public void Advance(double dt)
+ {
+ foreach (var p in _pairs)
+ {
+ Body bi = p.bi, bj = p.bj;
+ double dx = bi.x - bj.x, dy = bi.y - bj.y, dz = bi.z - bj.z;
+ double d2 = dx * dx + dy * dy + dz * dz;
+ double mag = dt / (d2 * Math.Sqrt(d2));
+ bi.vx -= dx * bj.mass * mag; bj.vx += dx * bi.mass * mag;
+ bi.vy -= dy * bj.mass * mag; bj.vy += dy * bi.mass * mag;
+ bi.vz -= dz * bj.mass * mag; bj.vz += dz * bi.mass * mag;
+ }
+ foreach (var b in _bodies)
+ {
+ b.x += dt * b.vx; b.y += dt * b.vy; b.z += dt * b.vz;
+ }
+ }
+
+ public double Energy()
+ {
+ double e = 0.0;
+ for (int i = 0; i < _bodies.Length; i++)
+ {
+ var bi = _bodies[i];
+ e += 0.5 * bi.mass * (bi.vx * bi.vx + bi.vy * bi.vy + bi.vz * bi.vz);
+ for (int j = i + 1; j < _bodies.Length; j++)
+ {
+ var bj = _bodies[j];
+ double dx = bi.x - bj.x, dy = bi.y - bj.y, dz = bi.z - bj.z;
+ e -= (bi.mass * bj.mass) / Math.Sqrt(dx * dx + dy * dy + dz * dz);
+ }
+ }
+ return e;
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csproj
new file mode 100644
index 0000000000..8bf75d660e
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="nbody.csharp-3.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/BenchmarksGame/pidigits/pi-digits.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.cs
new file mode 100644
index 0000000000..3395e29a55
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.cs
@@ -0,0 +1,114 @@
+// 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.
+/* The Computer Language Benchmarks Game
+ * http://benchmarksgame.alioth.debian.org/
+ *
+ * Port of the C code that uses GMP
+ * Just switched it to use C#'s BigInteger instead
+ *
+ * To compile use csc /o+ /r:System.Numerics.dll
+ *
+ * modified for use with xunit-performance
+*/
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Numerics;
+using System.Text;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class pidigits
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 50;
+#endif
+
+ private BigInteger _acc,_den,_num;
+
+ public pidigits()
+ {
+ _acc = BigInteger.Zero;
+ _den = BigInteger.One;
+ _num = BigInteger.One;
+ }
+
+ public uint extract_digit(uint nth)
+ {
+ return (uint)((_num * nth + _acc) / _den);
+ }
+
+ public void eliminate_digit(uint d)
+ {
+ _acc -= _den * d;
+ _acc *= 10;
+ _num *= 10;
+ }
+
+ public void next_term(uint k)
+ {
+ uint k2 = k * 2 + 1;
+ _acc += _num * 2;
+ _acc *= k2;
+ _den *= k2;
+ _num *= k;
+ }
+
+ public void Calculate(int n, bool verbose = false)
+ {
+ StringBuilder sb = new StringBuilder(20);
+ uint d, k, i;
+ for (i = k = 0; i < n;)
+ {
+ next_term(++k);
+ if (_num > _acc)
+ continue;
+ d = extract_digit(3);
+ if (d != extract_digit(4))
+ continue;
+ sb.Append((char)('0' + d));
+ if (++i % 10 == 0)
+ {
+ if (verbose)
+ {
+ Console.WriteLine("{0}\t:{1}", sb, i);
+ }
+ sb.Clear();
+ }
+ eliminate_digit(d);
+ }
+ }
+
+ public static int Main(String[] args)
+ {
+ int length = args.Length == 0 ? 10 : Int32.Parse(args[0]);
+ for (int i = 0; i < Iterations; i++)
+ {
+ pidigits p = new pidigits();
+ p.Calculate(length, true);
+ }
+ return 100;
+ }
+
+ [Benchmark]
+ public static void Bench()
+ {
+ int length = 600;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ pidigits p = new pidigits();
+ p.Calculate(length);
+ }
+ }
+ }
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.csproj
new file mode 100644
index 0000000000..005e93a306
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="pi-digits.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/BenchmarksGame/spectralnorm/spectralnorm.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.cs
new file mode 100644
index 0000000000..9e984864a7
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.cs
@@ -0,0 +1,126 @@
+// 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.
+/* The Computer Language Benchmarks Game
+ http://benchmarksgame.alioth.debian.org/
+
+ contributed by Isaac Gouy
+
+ modified for use with xunit-performance
+*/
+
+using Microsoft.Xunit.Performance;
+using System;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class SpectralNorm
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 300;
+#endif
+
+ public static int Main(String[] args)
+ {
+ int n = 100;
+ if (args.Length > 0) n = Int32.Parse(args[0]);
+ double norm = new SpectralNorm().Approximate(n);
+ Console.WriteLine("Norm={0:f9}", norm);
+ double expected = 1.274219991;
+ bool result = Math.Abs(norm - expected) < 1e-4;
+ return (result ? 100 : -1);
+ }
+
+ [Benchmark]
+ public static void Bench()
+ {
+ int n = 100;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ double a = 0;
+
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ SpectralNorm s = new SpectralNorm();
+ a += s.Approximate(n);
+ }
+ }
+
+ double norm = a / Iterations;
+ double expected = 1.274219991;
+ bool valid = Math.Abs(norm - expected) < 1e-4;
+ if (!valid)
+ {
+ throw new Exception("Benchmark failed to validate");
+ }
+ }
+ }
+
+ private double Approximate(int n)
+ {
+ // create unit vector
+ double[] u = new double[n];
+ for (int i = 0; i < n; i++) u[i] = 1;
+
+ // 20 steps of the power method
+ double[] v = new double[n];
+ for (int i = 0; i < n; i++) v[i] = 0;
+
+ for (int i = 0; i < 10; i++)
+ {
+ MultiplyAtAv(n, u, v);
+ MultiplyAtAv(n, v, u);
+ }
+
+ // B=AtA A multiplied by A transposed
+ // v.Bv /(v.v) eigenvalue of v
+ double vBv = 0, vv = 0;
+ for (int i = 0; i < n; i++)
+ {
+ vBv += u[i] * v[i];
+ vv += v[i] * v[i];
+ }
+
+ return Math.Sqrt(vBv / vv);
+ }
+
+
+ /* return element i,j of infinite matrix A */
+ private double A(int i, int j)
+ {
+ return 1.0 / ((i + j) * (i + j + 1) / 2 + i + 1);
+ }
+
+ /* multiply vector v by matrix A */
+ private void MultiplyAv(int n, double[] v, double[] Av)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ Av[i] = 0;
+ for (int j = 0; j < n; j++) Av[i] += A(i, j) * v[j];
+ }
+ }
+
+ /* multiply vector v by matrix A transposed */
+ private void MultiplyAtv(int n, double[] v, double[] Atv)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ Atv[i] = 0;
+ for (int j = 0; j < n; j++) Atv[i] += A(j, i) * v[j];
+ }
+ }
+
+ /* multiply vector v by matrix A and then by matrix A transposed */
+ private void MultiplyAtAv(int n, double[] v, double[] AtAv)
+ {
+ double[] u = new double[n];
+ MultiplyAv(n, v, u);
+ MultiplyAtv(n, u, AtAv);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.csproj
new file mode 100644
index 0000000000..74ec22ac53
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="spectralnorm.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/Burgers/Burgers.cs b/tests/src/JIT/Performance/CodeQuality/Burgers/Burgers.cs
new file mode 100644
index 0000000000..11eccec14d
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Burgers/Burgers.cs
@@ -0,0 +1,339 @@
+// 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.
+//
+// .NET SIMD to solve Burgers' equation
+//
+// Benchmark based on
+// http://taumuon-jabuka.blogspot.co.uk/2014/10/net-simd-to-solve-burgers-equation.html
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Linq;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class Burgers
+{
+ private static double BurgersAnalytical(double t, double x, double nu)
+ {
+ return -2 * nu * (-(-8 * t + 2 * x) * Math.Exp(-Math.Pow((-4 * t + x), 2) / (4 * nu * (t + 1))) / (4 * nu * (t + 1)) - (-8 * t + 2 * x - 12.5663706143592) * Math.Exp(-Math.Pow(-4 * t + x - 6.28318530717959, 2) / (4 * nu * (t + 1))) / (4 * nu * (t + 1))) / (Math.Exp(-Math.Pow(-4 * t + x - 6.28318530717959, 2) / (4 * nu * (t + 1))) + Math.Exp(-Math.Pow(-4 * t + x, 2) / (4 * nu * (t + 1)))) + 4;
+ }
+
+ private static double[] linspace(double first, double last, int num)
+ {
+ var step = (last - first) / (double)num;
+ return Enumerable.Range(0, num).Select(v => (v * step) + first).ToArray();
+ }
+
+ private static double[] GetAnalytical(double[] x, double t, double nu)
+ {
+ double[] u = new double[x.Length];
+
+ for (int i = 0; i < x.Length; ++i)
+ {
+ u[i] = BurgersAnalytical(t, x[i], nu);
+ }
+
+ return u;
+ }
+
+ private static double[] GetCalculated0(int nt, int nx, double dx, double dt, double nu, double[] initial)
+ {
+ double[] u = new double[nx];
+ Array.Copy(initial, u, u.Length);
+
+ for (int tStep = 0; tStep < nt; tStep++)
+ {
+ double[] un = new double[nx];
+ Array.Copy(u, un, u.Length);
+
+ for (int i = 1; i < nx - 1; i++)
+ {
+ u[i] = un[i] - un[i] * dt / dx * (un[i] - un[i - 1]) + Math.Pow(nu * dt / dx, 2.0) *
+ (un[i + 1] - 2 * un[i] + un[i - 1]);
+ }
+
+ u[0] = un[0] - un[0] * dt / dx * (un[0] - un[nx - 1]) + Math.Pow(nu * dt / dx, 2.0) *
+ (un[1] - 2 * un[0] + un[nx - 1]);
+
+ u[nx - 1] = un[nx - 1] - un[nx - 1] * dt / dx * (un[nx - 1] - un[nx - 2]) + Math.Pow(nu * dt / dx, 2.0) *
+ (un[0] - 2 * un[nx - 1] + un[nx - 2]);
+ }
+
+ return u;
+ }
+
+ // Reduce new array allocation and copying, ping-pong between them
+ private static double[] GetCalculated1(int nt, int nx, double dx, double dt, double nu, double[] initial)
+ {
+ double[] u = new double[nx];
+ double[] un = new double[nx];
+ Array.Copy(initial, un, un.Length);
+
+ for (int tStep = 0; tStep < nt; tStep++)
+ {
+ for (int i = 1; i < nx - 1; i++)
+ {
+ u[i] = un[i] - un[i] * dt / dx * (un[i] - un[i - 1]) + Math.Pow(nu * dt / dx, 2.0) *
+ (un[i + 1] - 2 * un[i] + un[i - 1]);
+ }
+
+ u[0] = un[0] - un[0] * dt / dx * (un[0] - un[nx - 1]) + Math.Pow(nu * dt / dx, 2.0) *
+ (un[1] - 2 * un[0] + un[nx - 1]);
+
+ u[nx - 1] = un[nx - 1] - un[nx - 1] * dt / dx * (un[nx - 1] - un[nx - 2]) + Math.Pow(nu * dt / dx, 2.0) *
+ (un[0] - 2 * un[nx - 1] + un[nx - 2]);
+
+ double[] swap = u;
+ u = un;
+ un = swap;
+ }
+
+ return un;
+ }
+
+ // Pull calculation of (nu * dt / dx)^2 out into a variable
+ private static double[] GetCalculated2(int nt, int nx, double dx, double dt, double nu, double[] initial)
+ {
+ double[] u = new double[nx];
+ double[] un = new double[nx];
+ Array.Copy(initial, un, un.Length);
+
+ double factor = Math.Pow(nu * dt / dx, 2.0);
+
+ for (int tStep = 0; tStep < nt; tStep++)
+ {
+ for (int i = 1; i < nx - 1; i++)
+ {
+ u[i] = un[i] - un[i] * dt / dx * (un[i] - un[i - 1]) + factor *
+ (un[i + 1] - 2 * un[i] + un[i - 1]);
+ }
+
+ u[0] = un[0] - un[0] * dt / dx * (un[0] - un[nx - 1]) + factor *
+ (un[1] - 2 * un[0] + un[nx - 1]);
+
+ u[nx - 1] = un[nx - 1] - un[nx - 1] * dt / dx * (un[nx - 1] - un[nx - 2]) + factor *
+ (un[0] - 2 * un[nx - 1] + un[nx - 2]);
+
+ double[] swap = u;
+ u = un;
+ un = swap;
+ }
+
+ return un;
+ }
+
+ // SIMD
+ private static double[] GetCalculated3(int nt, int nx, double dx, double dt, double nu, double[] initial)
+ {
+ var nx2 = nx + (Vector<double>.Count - (nx % Vector<double>.Count));
+
+ double[] u = new double[nx2];
+ double[] un = new double[nx2];
+ Array.Copy(initial, un, initial.Length);
+
+ double factor = Math.Pow(nu * dt / dx, 2.0);
+
+ for (int tStep = 0; tStep < nt; tStep++)
+ {
+ for (int i = 1; i < nx2 - Vector<double>.Count + 1; i += Vector<double>.Count)
+ {
+ var vectorIn0 = new Vector<double>(un, i);
+ var vectorInPrev = new Vector<double>(un, i - 1);
+ var vectorInNext = new Vector<double>(un, i + 1);
+
+ var vectorOut = vectorIn0 - vectorIn0 * (dt / dx) * (vectorIn0 - vectorInPrev) + factor *
+ (vectorInNext - 2.0 * vectorIn0 + vectorInPrev);
+
+ vectorOut.CopyTo(u, i);
+ }
+
+ u[0] = un[0] - un[0] * dt / dx * (un[0] - un[nx - 1]) + factor *
+ (un[1] - 2 * un[0] + un[nx - 1]);
+
+ u[nx - 1] = un[nx - 1] - un[nx - 1] * dt / dx * (un[nx - 1] - un[nx - 2]) + factor *
+ (un[0] - 2 * un[nx - 1] + un[nx - 2]);
+
+ double[] swap = u;
+ u = un;
+ un = swap;
+ }
+
+ return un;
+ }
+
+ public static int Main()
+ {
+ if (!Vector.IsHardwareAccelerated)
+ {
+ Console.WriteLine("Not hardware accelerated!");
+ }
+ else
+ {
+ Console.WriteLine("Vector<double>.Length: " + Vector<double>.Count);
+ }
+
+ int nx = 10001;
+
+#if DEBUG
+ int nt = 10;
+#else
+ int nt = 10000;
+#endif
+
+ double dx = 2.0 * Math.PI / (nx - 1.0);
+ double nu = 0.07;
+ double dt = dx * nu;
+ double[] x = linspace(0.0, 2.0 * Math.PI, nx);
+ double[] initial = GetAnalytical(x, 0.0, nu);
+
+ // Warmup
+
+ GetCalculated0(1, nx, dx, dt, nu, initial);
+ GetCalculated1(1, nx, dx, dt, nu, initial);
+ GetCalculated2(1, nx, dx, dt, nu, initial);
+ GetCalculated3(1, nx, dx, dt, nu, initial);
+
+ double[][] results = new double[4][];
+
+ var stopwatch = new System.Diagnostics.Stopwatch();
+
+ stopwatch.Start();
+ results[0] = GetCalculated0(nt, nx, dx, dt, nu, initial);
+ stopwatch.Stop();
+ Console.WriteLine("Baseline: " + stopwatch.ElapsedMilliseconds);
+ stopwatch.Reset();
+
+ stopwatch.Start();
+ results[1] = GetCalculated1(nt, nx, dx, dt, nu, initial);
+ stopwatch.Stop();
+ Console.WriteLine("Reduce copy: " + stopwatch.ElapsedMilliseconds);
+ stopwatch.Reset();
+
+ stopwatch.Start();
+ results[2] = GetCalculated2(nt, nx, dx, dt, nu, initial);
+ stopwatch.Stop();
+ Console.WriteLine("CSE of Math.Pow: " + stopwatch.ElapsedMilliseconds);
+ stopwatch.Reset();
+
+ stopwatch.Start();
+ results[3] = GetCalculated3(nt, nx, dx, dt, nu, initial);
+ stopwatch.Stop();
+ Console.WriteLine("SIMD: " + stopwatch.ElapsedMilliseconds);
+ stopwatch.Reset();
+
+ for (int i = 0; i < x.Length; i += 33)
+ {
+ double expected = results[0][i];
+ for (int j = 1; j < results.Length; j++)
+ {
+ bool valid = Math.Abs(expected - results[j][i]) < 1e-4;
+ if (!valid)
+ {
+ Console.WriteLine("Failed to validate");
+ return -1;
+ }
+ }
+ }
+
+ return 100;
+ }
+
+ static volatile object VolatileObject;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Escape(object obj)
+ {
+ VolatileObject = obj;
+ }
+
+ [Benchmark]
+ public static void Test0()
+ {
+ int nx = 10001;
+ int nt = 10000;
+ double dx = 2.0 * Math.PI / (nx - 1.0);
+ double nu = 0.07;
+ double dt = dx * nu;
+ double[] x = linspace(0.0, 2.0 * Math.PI, nx);
+ double[] initial = GetAnalytical(x, 0.0, nu);
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ double[] results = GetCalculated0(nt, nx, dx, dt, nu, initial);
+ Escape(results);
+ }
+ }
+ }
+
+ [Benchmark]
+ public static void Test1()
+ {
+ int nx = 10001;
+ int nt = 10000;
+ double dx = 2.0 * Math.PI / (nx - 1.0);
+ double nu = 0.07;
+ double dt = dx * nu;
+ double[] x = linspace(0.0, 2.0 * Math.PI, nx);
+ double[] initial = GetAnalytical(x, 0.0, nu);
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ double[] results = GetCalculated1(nt, nx, dx, dt, nu, initial);
+ Escape(results);
+ }
+ }
+ }
+
+ [Benchmark]
+ public static void Test2()
+ {
+ int nx = 10001;
+ int nt = 10000;
+ double dx = 2.0 * Math.PI / (nx - 1.0);
+ double nu = 0.07;
+ double dt = dx * nu;
+ double[] x = linspace(0.0, 2.0 * Math.PI, nx);
+ double[] initial = GetAnalytical(x, 0.0, nu);
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ double[] results = GetCalculated2(nt, nx, dx, dt, nu, initial);
+ Escape(results);
+ }
+ }
+ }
+
+ [Benchmark]
+ public static void Test3()
+ {
+ // Make SIMD version work a bit harder....
+ int nx = 10001;
+ int nt = 2 * 10000;
+ double dx = 2.0 * Math.PI / (nx - 1.0);
+ double nu = 0.07;
+ double dt = dx * nu;
+ double[] x = linspace(0.0, 2.0 * Math.PI, nx);
+ double[] initial = GetAnalytical(x, 0.0, nu);
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ double[] results = GetCalculated3(nt, nx, dx, dt, nu, initial);
+ Escape(results);
+ }
+ }
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/Burgers/Burgers.csproj b/tests/src/JIT/Performance/CodeQuality/Burgers/Burgers.csproj
new file mode 100644
index 0000000000..c26f227657
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Burgers/Burgers.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Burgers.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/Bytemark/ByteMark.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/ByteMark.cs
new file mode 100644
index 0000000000..10699c67dc
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/ByteMark.cs
@@ -0,0 +1,1546 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.IO;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+internal class global
+{
+ // Following should be modified accordingly per each compilation.
+ public const String SysName = "Generic 486/Pentium";
+ public const String CompilerName = "CoreCLR";
+ public const String CompilerVersion = "ver 0.0";
+
+ public static long min_ticks;
+ public static int min_secs;
+ public static bool allstats;
+ public static String ofile_name; // Output file name
+ public static StreamWriter ofile; // Output file
+ public static bool custrun; // Custom run flag
+ public static bool write_to_file; // Write output to file
+ public static int align; // Memory alignment
+
+ /*
+ ** Following are global structures, one built for
+ ** each of the tests.
+ */
+ public static SortStruct numsortstruct_jagged; // For numeric sort
+ public static SortStruct numsortstruct_rect; // For numeric sort
+ public static StringSort strsortstruct; // For string sort
+ public static BitOpStruct bitopstruct; // For bitfield ops
+ public static EmFloatStruct emfloatstruct_struct; // For emul. float. pt.
+ public static EmFloatStruct emfloatstruct_class; // For emul. float. pt.
+ public static FourierStruct fourierstruct; // For fourier test
+ public static AssignStruct assignstruct_jagged; // For assignment algs
+ public static AssignStruct assignstruct_rect; // For assignment algs
+ public static IDEAStruct ideastruct; // For IDEA encryption
+ public static HuffStruct huffstruct; // For Huffman compression
+ public static NNetStruct nnetstruct_jagged; // For Neural Net
+ public static NNetStruct nnetstruct_rect; // For Neural Net
+ public static LUStruct lustruct; // For LU decomposition
+
+ public const long TICKS_PER_SEC = 1000;
+ public const long MINIMUM_TICKS = 60; // 60 msecs
+
+#if DEBUG
+ public const int MINIMUM_SECONDS = 1;
+#else
+ public const int MINIMUM_SECONDS = 1;
+#endif
+
+ public const int NUMNUMARRAYS = 1000;
+ public const int NUMARRAYSIZE = 8111;
+ public const int STRINGARRAYSIZE = 8111;
+ // This is the upper limit of number of string arrays to sort in one
+ // iteration. If we can sort more than this number of arrays in less
+ // than MINIMUM_TICKS an exception is thrown.
+ public const int NUMSTRARRAYS = 100;
+ public const int HUFFARRAYSIZE = 5000;
+ public const int MAXHUFFLOOPS = 50000;
+
+ // Assignment constants
+ public const int ASSIGNROWS = 101;
+ public const int ASSIGNCOLS = 101;
+ public const int MAXPOSLONG = 0x7FFFFFFF;
+
+ // BitOps constants
+#if LONG64
+ public const int BITFARRAYSIZE = 16384;
+#else
+ public const int BITFARRAYSIZE = 32768;
+#endif
+
+ // IDEA constants
+ public const int MAXIDEALOOPS = 5000;
+ public const int IDEAARRAYSIZE = 4000;
+ public const int IDEAKEYSIZE = 16;
+ public const int IDEABLOCKSIZE = 8;
+ public const int ROUNDS = 8;
+ public const int KEYLEN = (6 * ROUNDS + 4);
+
+ // LUComp constants
+ public const int LUARRAYROWS = 101;
+ public const int LUARRAYCOLS = 101;
+
+
+ // EMFLOAT constants
+ public const int CPUEMFLOATLOOPMAX = 50000;
+ public const int EMFARRAYSIZE = 3000;
+}
+
+/*
+** TYPEDEFS
+*/
+
+public abstract class HarnessTest
+{
+ public bool bRunTest = true;
+ public double score;
+ public int adjust; /* Set adjust code */
+ public int request_secs; /* # of seconds requested */
+
+ public abstract string Name();
+ public abstract void ShowStats();
+ public abstract double Run();
+}
+
+public abstract class SortStruct : HarnessTest
+{
+ public short numarrays = global.NUMNUMARRAYS; /* # of arrays */
+ public int arraysize = global.NUMARRAYSIZE; /* # of elements in array */
+ public override void ShowStats()
+ {
+ ByteMark.OutputString(
+ string.Format(" Number of arrays: {0}", numarrays));
+ ByteMark.OutputString(
+ string.Format(" Array size: {0}", arraysize));
+ }
+}
+
+public abstract class StringSortStruct : HarnessTest
+{
+ public short numarrays = global.NUMNUMARRAYS; /* # of arrays */
+ public int arraysize = global.STRINGARRAYSIZE; /* # of elements in array */
+ public override void ShowStats()
+ {
+ ByteMark.OutputString(
+ string.Format(" Number of arrays: {0}", numarrays));
+ ByteMark.OutputString(
+ string.Format(" Array size: {0}", arraysize));
+ }
+}
+
+public abstract class HuffStruct : HarnessTest
+{
+ public int arraysize = global.HUFFARRAYSIZE;
+ public int loops = 0;
+ public override void ShowStats()
+ {
+ ByteMark.OutputString(
+ string.Format(" Array size: {0}", arraysize));
+ ByteMark.OutputString(
+ string.Format(" Number of loops: {0}", loops));
+ }
+}
+
+public abstract class FourierStruct : HarnessTest
+{
+ public int arraysize; /* Size of coeff. arrays */
+ public override void ShowStats()
+ {
+ ByteMark.OutputString(
+ string.Format(" Number of coefficients: {0}", arraysize));
+ }
+}
+
+public abstract class AssignStruct : HarnessTest
+{
+ public short numarrays = global.NUMNUMARRAYS; /* # of elements in array */
+ public override void ShowStats()
+ {
+ ByteMark.OutputString(
+ string.Format(" Number of arrays: {0}", numarrays));
+ }
+}
+
+public abstract class BitOpStruct : HarnessTest
+{
+ public int bitoparraysize; /* Total # of bitfield ops */
+ public int bitfieldarraysize = global.BITFARRAYSIZE; /* Bit field array size */
+ public override void ShowStats()
+ {
+ ByteMark.OutputString(
+ string.Format(" Operations array size: {0}", bitoparraysize));
+ ByteMark.OutputString(
+ string.Format(" Bitfield array size: {0}", bitfieldarraysize));
+ }
+}
+
+public abstract class IDEAStruct : HarnessTest
+{
+ public int arraysize = global.IDEAARRAYSIZE; /* Size of array */
+ public int loops; /* # of times to convert */
+ public override void ShowStats()
+ {
+ ByteMark.OutputString(
+ string.Format(" Array size: {0}", arraysize));
+ ByteMark.OutputString(
+ string.Format(" Number of loops: {0}", loops));
+ }
+}
+
+public abstract class LUStruct : HarnessTest
+{
+ public int numarrays;
+ public override void ShowStats()
+ {
+ ByteMark.OutputString(
+ string.Format(" Number of arrays: {0}", numarrays));
+ }
+}
+
+public abstract class NNetStruct : HarnessTest
+{
+ public int loops; /* # of times to learn */
+ public double iterspersec; /* Results */
+ public override void ShowStats()
+ {
+ ByteMark.OutputString(
+ string.Format(" Number of loops: {0}", loops));
+ }
+}
+
+public abstract class EmFloatStruct : HarnessTest
+{
+ public int arraysize = global.EMFARRAYSIZE; /* Size of array */
+ public int loops; /* Loops per iterations */
+ public override void ShowStats()
+ {
+ ByteMark.OutputString(
+ string.Format(" Number of loops: {0}", loops));
+ ByteMark.OutputString(
+ string.Format(" Array size: {0}", arraysize));
+ }
+}
+
+public class ByteMark
+{
+ private static int[] s_randw;
+ private static double[] s_bindex;
+ private static HarnessTest[] s_tests;
+
+ public static int Main(string[] args)
+ {
+ ByteMark app = new ByteMark();
+ int result = app.ExecuteCore(args);
+ return result;
+ }
+
+ public int ExecuteCore(string[] argv)
+ {
+ s_randw = new int[2] { 13, 117 };
+
+ global.min_ticks = global.MINIMUM_TICKS;
+ global.min_secs = global.MINIMUM_SECONDS;
+ global.allstats = false;
+ global.custrun = false;
+ global.align = 8;
+ global.write_to_file = false;
+
+ /*
+ ** Indexes -- Baseline is DELL Pentium XP90
+ ** 11/28/94
+ */
+ // JTR: Should make member of HarnessTest, but left
+ // this way to keep similar to original test.
+ s_bindex = new double[14] {
+ 38.993, /* Numeric sort */
+ 38.993, /* Numeric sort */
+ 2.238, /* String sort */
+ 5829704, /* Bitfield */
+ 2.084, /* FP Emulation */
+ 2.084, /* FP Emulation */
+ 879.278, /* Fourier */
+ .2628, /* Assignment */
+ .2628, /* Assignment */
+ 65.382, /* IDEA */
+ 36.062, /* Huffman */
+ .6225, /* Neural Net */
+ .6225, /* Neural Net */
+ 19.3031 /* LU Decomposition */
+ };
+
+ s_tests = new HarnessTest[14]
+ {
+ global.numsortstruct_jagged = new NumericSortJagged(),
+ global.numsortstruct_rect = new NumericSortRect(),
+ global.strsortstruct = new StringSort(),
+ global.bitopstruct = new BitOps(),
+ global.emfloatstruct_struct = new EMFloat(),
+ global.emfloatstruct_class = new EMFloatClass(),
+ global.fourierstruct = new Fourier(),
+ global.assignstruct_jagged = new AssignJagged(),
+ global.assignstruct_rect = new AssignRect(),
+ global.ideastruct = new IDEAEncryption(),
+ global.huffstruct = new Huffman(),
+ global.nnetstruct_jagged = new NeuralJagged(),
+ global.nnetstruct_rect = new Neural(),
+ global.lustruct = new LUDecomp(),
+ };
+
+ SetRequestSecs();
+
+ /*
+ ** Handle any command-line arguments.
+ */
+ int argc = argv.Length;
+ if (argc > 0)
+ {
+ for (int i = 0; i < argc; i++)
+ {
+ if (parse_arg(argv[i]) == -1)
+ {
+ display_help("Bytemark");
+ return -1;
+ }
+ }
+ }
+
+ /*
+ ** Output header
+ */
+ OutputString("BBBBBB YYY Y TTTTTTT EEEEEEE");
+ OutputString("BBB B YYY Y TTT EEE");
+ OutputString("BBB B YYY Y TTT EEE");
+ OutputString("BBBBBB YYY Y TTT EEEEEEE");
+ OutputString("BBB B YYY TTT EEE");
+ OutputString("BBB B YYY TTT EEE");
+ OutputString("BBBBBB YYY TTT EEEEEEE");
+ OutputString("");
+ OutputString("BYTEmark (tm) C# Mode Benchmark ver. 2 (06/99)");
+
+ if (global.allstats)
+ {
+ OutputString("========== ALL STATISTICS ==========");
+ DateTime time_and_date = DateTime.Now;
+ OutputString("**" +
+ time_and_date.ToString("ddd MMM dd HH:mm:ss yyyy"));
+ OutputString("**" + global.SysName);
+ OutputString("**" + global.CompilerName);
+ OutputString("**" + global.CompilerVersion);
+ OutputString("**Sizeof: int:4 short:2 long:8");
+ OutputString("====================================");
+ OutputString("");
+ }
+
+ try
+ {
+ /*
+ ** Execute the tests.
+ */
+ int fpcount = 0;
+ int intcount = 0;
+ double intindex = 1.0; /* Integer index */
+ double fpindex = 1.0; /* Floating-point index */
+ for (int i = 0; i < s_tests.Length; i++)
+ {
+ if (s_tests[i].bRunTest)
+ {
+ double bmean; /* Benchmark mean */
+ double bstdev; /* Benchmark stdev */
+ int bnumrun; /* # of runs */
+ OutputStringPart(
+ string.Format("{0}:", s_tests[i].Name()));
+ bench_with_confidence(i,
+ out bmean,
+ out bstdev,
+ out bnumrun);
+ OutputString(
+ string.Format(" Iterations/sec: {0:F5} Index: {1:F5}",
+ bmean,
+ bmean / s_bindex[i]));
+
+ /*
+ ** Gather integer or FP indexes
+ */
+ // JTR: indexes all have 1 added to them to compensate
+ // for splitting int sort into 2 tests
+ if ((i == 6) || (i == 12) || (i == 13) || (i == 11))
+ {
+ /* FP index */
+ fpindex = fpindex * (bmean / s_bindex[i]);
+ fpcount++;
+ }
+ else
+ {
+ /* Integer index */
+ intindex = intindex * (bmean / s_bindex[i]);
+ intcount++;
+ }
+
+ if (global.allstats)
+ {
+ OutputString(
+ string.Format(" Standard Deviation: {0}", bstdev));
+ OutputString(
+ string.Format(" Number of runs: {0}", bnumrun));
+ s_tests[i].ShowStats();
+ }
+ }
+ }
+ /*
+ ** Output the total indexes
+ */
+ if (!global.custrun)
+ {
+ OutputString("===========OVERALL============");
+ OutputString(
+ string.Format("INTEGER INDEX: {0:F5}", Math.Pow(intindex, (double)1.0 / (double)intcount)));
+ OutputString(
+ string.Format("FLOATING-POINT INDEX: {0:F5}", Math.Pow(fpindex, (double)1.0 / (double)fpcount)));
+ OutputString(" (90 MHz Dell Pentium = 1.00)");
+ OutputString("==============================");
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("ExecuteCore - Exception {0}", e.ToString());
+ if (global.ofile != null)
+ {
+ global.ofile.Flush();
+ }
+ Console.WriteLine("Exception: {0}", e.ToString());
+ return -1;
+ }
+
+ return 100;
+ }
+
+ /**************
+ ** parse_arg **
+ ***************
+ ** Given a pointer to a string, we assume that's an argument.
+ ** Parse that argument and act accordingly.
+ ** Return 0 if ok, else return -1.
+ */
+ private int parse_arg(String arg)
+ {
+ int i = 0; /* Index */
+ StreamReader cfile = null; /* Command file identifier */
+
+ /*
+ ** First character has got to be a hyphen.
+ */
+ if (arg[i++] != '-') return (-1);
+
+ /*
+ ** Convert the rest of the argument to upper case
+ ** so there's little chance of confusion.
+ */
+ arg = arg.ToUpper();
+
+ /*
+ ** Next character picks the action.
+ */
+ switch (arg[i++])
+ {
+ case '?': return (-1); /* Will display help */
+
+ case 'C': /* Command file name */
+ /*
+ ** First try to open the file for reading.
+ */
+ String inputFileName = arg.Substring(i);
+
+ try
+ {
+ cfile = File.OpenText(inputFileName);
+ }
+ catch (IOException)
+ {
+ Console.WriteLine("**Error opening file: {0}", inputFileName);
+ return (-1);
+ }
+
+ read_comfile(cfile); /* Read commands */
+ break;
+ default:
+ return (-1);
+ }
+ return (0);
+ }
+
+ /*******************
+ ** display_help() **
+ ********************
+ ** Display a help message showing argument requirements and such.
+ ** Exit when you're done...I mean, REALLY exit.
+ */
+ private static void display_help(String progname)
+ {
+ Console.WriteLine("Usage: {0} [-c<FILE>]", progname);
+ Console.WriteLine(" -c = Input parameters thru command file <FILE>");
+ }
+
+ private enum PF
+ { // parameter flags
+ GMTICKS = 0, /* GLOBALMINTICKS */
+ MINSECONDS = 1, /* MINSECONDS */
+ ALLSTATS = 2, /* ALLSTATS */
+ OUTFILE = 3, /* OUTFILE */
+ CUSTOMRUN = 4, /* CUSTOMRUN */
+ DONUM = 5, /* DONUMSORT */
+ NUMNUMA = 6, /* NUMNUMARRAYS */
+ NUMASIZE = 7, /* NUMARRAYSIZE */
+ NUMMINS = 8, /* NUMMINSECONDS */
+ DOSTR = 9, /* DOSTRINGSORT */
+ STRASIZE = 10, /* STRARRAYSIZE */
+ NUMSTRA = 11, /* NUMSTRARRAYS */
+ STRMINS = 12, /* STRMINSECONDS */
+ DOBITF = 13, /* DOBITFIELD */
+ NUMBITOPS = 14, /* NUMBITOPS */
+ BITFSIZE = 15, /* BITFIELDSIZE */
+ BITMINS = 16, /* BITMINSECONDS */
+ DOEMF = 17, /* DOEMF */
+ EMFASIZE = 18, /* EMFARRAYSIZE */
+ EMFLOOPS = 19, /* EMFLOOPS */
+ EMFMINS = 20, /* EMFMINSECOND */
+ DOFOUR = 21, /* DOFOUR */
+ FOURASIZE = 22, /* FOURASIZE */
+ FOURMINS = 23, /* FOURMINSECONDS */
+ DOASSIGN = 24, /* DOASSIGN */
+ AARRAYS = 25, /* ASSIGNARRAYS */
+ ASSIGNMINS = 26, /* ASSIGNMINSECONDS */
+ DOIDEA = 27, /* DOIDEA */
+ IDEAASIZE = 28, /* IDEAARRAYSIZE */
+ IDEALOOPS = 29, /* IDEALOOPS */
+ IDEAMINS = 30, /* IDEAMINSECONDS */
+ DOHUFF = 31, /* DOHUFF */
+ HUFFASIZE = 32, /* HUFFARRAYSIZE */
+ HUFFLOOPS = 33, /* HUFFLOOPS */
+ HUFFMINS = 34, /* HUFFMINSECONDS */
+ DONNET = 35, /* DONNET */
+ NNETLOOPS = 36, /* NNETLOOPS */
+ NNETMINS = 37, /* NNETMINSECONDS */
+ DOLU = 38, /* DOLU */
+ LUNARRAYS = 39, /* LUNUMARRAYS */
+ LUMINS = 40, /* LUMINSECONDS */
+ ALIGN = 41, /* ALIGN */
+
+ // Added for control of new C# rect/jagged struct/class tests
+ DONUMJAGGED = 42, /* DONUMSORTJAGGED */
+ DONUMRECT = 43, /* DONUMSORTRECT */
+ DOEMFSTRUCT = 44, /* DOEMFSTRUCT */
+ DOEMFCLASS = 45, /* DOEMFCLASS */
+ DOASSIGNJAGGED = 46, /* DOASSIGNJAGGED */
+ DOASSIGNRECT = 47, /* DOASSIGNRECT */
+ DONNETJAGGED = 48, /* DONNETJAGGED */
+ DONNETRECT = 49, /* DONNETRECT */
+
+ MAXPARAM = 49
+ }
+
+ /* Parameter names */
+ private static String[] s_paramnames = {
+ "GLOBALMINTICKS",
+ "MINSECONDS",
+ "ALLSTATS",
+ "OUTFILE",
+ "CUSTOMRUN",
+ "DONUMSORT",
+ "NUMNUMARRAYS",
+ "NUMARRAYSIZE",
+ "NUMMINSECONDS",
+ "DOSTRINGSORT",
+ "STRARRAYSIZE",
+ "NUMSTRARRAYS",
+ "STRMINSECONDS",
+ "DOBITFIELD",
+ "NUMBITOPS",
+ "BITFIELDSIZE",
+ "BITMINSECONDS",
+ "DOEMF",
+ "EMFARRAYSIZE",
+ "EMFLOOPS",
+ "EMFMINSECONDS",
+ "DOFOUR",
+ "FOURSIZE",
+ "FOURMINSECONDS",
+ "DOASSIGN",
+ "ASSIGNARRAYS",
+ "ASSIGNMINSECONDS",
+ "DOIDEA",
+ "IDEARRAYSIZE",
+ "IDEALOOPS",
+ "IDEAMINSECONDS",
+ "DOHUFF",
+ "HUFARRAYSIZE",
+ "HUFFLOOPS",
+ "HUFFMINSECONDS",
+ "DONNET",
+ "NNETLOOPS",
+ "NNETMINSECONDS",
+ "DOLU",
+ "LUNUMARRAYS",
+ "LUMINSECONDS",
+ "ALIGN",
+
+ // Added for control of new C# rect/jagged struct/class tests
+ "DONUMSORTJAGGED",
+ "DONUMSORTRECT",
+ "DOEMFSTRUCT",
+ "DOEMFCLASS",
+ "DOASSIGNJAGGED",
+ "DOASSIGNRECT",
+ "DONNETJAGGED",
+ "DONNETRECT"
+ };
+
+ /*****************
+ ** read_comfile **
+ ******************
+ ** Read the command file. Set global parameters as
+ ** specified. This routine assumes that the command file
+ ** is already open.
+ */
+ private static void read_comfile(StreamReader cfile)
+ {
+ String inbuf;
+
+ String eptr; /* Offset to "=" sign */
+ /* markples: now the value half of the key=value pair */
+
+ int eIndex; /* markples: now this is the "=" offset */
+
+ PF i; /* Index */
+
+ /*
+ ** Sit in a big loop, reading a line from the file at each
+ ** pass. Terminate on EOF.
+ */
+ while ((inbuf = cfile.ReadLine()) != null)
+ {
+ /*
+ ** Parse up to the "=" sign. If we don't find an
+ ** "=", then flag an error.
+ */
+ if ((eIndex = inbuf.IndexOf('=')) == -1)
+ {
+ Console.WriteLine("**COMMAND FILE ERROR at LINE:");
+ Console.WriteLine(" " + inbuf);
+ goto skipswitch; /* A GOTO!!!! */
+ }
+
+ /*
+ ** Insert a null where the "=" was, then convert
+ ** the substring to uppercase. That will enable
+ ** us to perform the match.
+ */
+ String name = inbuf.Substring(0, eIndex);
+ eptr = inbuf.Substring(eIndex + 1);
+ name = name.ToUpper();
+ i = PF.MAXPARAM;
+ do
+ {
+ if (name == s_paramnames[(int)i])
+ {
+ break;
+ }
+ } while (--i >= 0);
+
+ if (i < 0)
+ {
+ Console.WriteLine("**COMMAND FILE ERROR -- UNKNOWN PARAM: "
+ + name);
+ goto skipswitch;
+ }
+
+ /*
+ ** Advance eptr to the next field...which should be
+ ** the value assigned to the parameter.
+ */
+ switch (i)
+ {
+ case PF.GMTICKS: /* GLOBALMINTICKS */
+ global.min_ticks = Int64.Parse(eptr);
+ break;
+
+ case PF.MINSECONDS: /* MINSECONDS */
+ global.min_secs = Int32.Parse(eptr);
+ SetRequestSecs();
+ break;
+
+ case PF.ALLSTATS: /* ALLSTATS */
+ global.allstats = getflag(eptr);
+ break;
+
+ case PF.OUTFILE: /* OUTFILE */
+ global.ofile_name = eptr;
+ try
+ {
+ global.ofile = File.AppendText(global.ofile_name);
+ global.write_to_file = true;
+ /*
+ ** Open the output file.
+ */
+ }
+ catch (IOException)
+ {
+ Console.WriteLine("**Error opening output file: {0}", global.ofile_name);
+ global.write_to_file = false;
+ }
+ break;
+
+ case PF.CUSTOMRUN: /* CUSTOMRUN */
+ global.custrun = getflag(eptr);
+ for (i = 0; (int)i < s_tests.Length; i++)
+ {
+ s_tests[(int)i].bRunTest = !global.custrun;
+ }
+ break;
+
+ case PF.DONUM: /* DONUMSORT */
+ global.numsortstruct_jagged.bRunTest =
+ global.numsortstruct_rect.bRunTest = getflag(eptr);
+ break;
+
+ case PF.NUMNUMA: /* NUMNUMARRAYS */
+ global.numsortstruct_rect.numarrays = Int16.Parse(eptr);
+ global.numsortstruct_jagged.numarrays = global.numsortstruct_rect.numarrays;
+ global.numsortstruct_jagged.adjust =
+ global.numsortstruct_rect.adjust = 1;
+ break;
+
+ case PF.NUMASIZE: /* NUMARRAYSIZE */
+ global.numsortstruct_rect.arraysize = Int32.Parse(eptr);
+ global.numsortstruct_jagged.arraysize = global.numsortstruct_rect.arraysize;
+ break;
+
+ case PF.NUMMINS: /* NUMMINSECONDS */
+ global.numsortstruct_rect.request_secs = Int32.Parse(eptr);
+ global.numsortstruct_jagged.request_secs = global.numsortstruct_rect.request_secs;
+ break;
+
+ case PF.DOSTR: /* DOSTRINGSORT */
+ global.strsortstruct.bRunTest = getflag(eptr);
+ break;
+
+ case PF.STRASIZE: /* STRARRAYSIZE */
+ global.strsortstruct.arraysize = Int32.Parse(eptr);
+ break;
+
+ case PF.NUMSTRA: /* NUMSTRARRAYS */
+ global.strsortstruct.numarrays = Int16.Parse(eptr);
+ global.strsortstruct.adjust = 1;
+ break;
+
+ case PF.STRMINS: /* STRMINSECONDS */
+ global.strsortstruct.request_secs = Int32.Parse(eptr);
+ break;
+
+ case PF.DOBITF: /* DOBITFIELD */
+ global.bitopstruct.bRunTest = getflag(eptr);
+ break;
+
+ case PF.NUMBITOPS: /* NUMBITOPS */
+ global.bitopstruct.bitoparraysize = Int32.Parse(eptr);
+ global.bitopstruct.adjust = 1;
+ break;
+
+ case PF.BITFSIZE: /* BITFIELDSIZE */
+ global.bitopstruct.bitfieldarraysize = Int32.Parse(eptr);
+ break;
+
+ case PF.BITMINS: /* BITMINSECONDS */
+ global.bitopstruct.request_secs = Int32.Parse(eptr);
+ break;
+
+ case PF.DOEMF: /* DOEMF */
+ global.emfloatstruct_struct.bRunTest =
+ global.emfloatstruct_class.bRunTest = getflag(eptr);
+ break;
+
+ case PF.EMFASIZE: /* EMFARRAYSIZE */
+ global.emfloatstruct_class.arraysize = Int32.Parse(eptr);
+ global.emfloatstruct_struct.arraysize = global.emfloatstruct_class.arraysize;
+ break;
+
+ case PF.EMFLOOPS: /* EMFLOOPS */
+ global.emfloatstruct_class.loops = Int32.Parse(eptr);
+ break;
+
+ case PF.EMFMINS: /* EMFMINSECOND */
+ global.emfloatstruct_class.request_secs = Int32.Parse(eptr);
+ global.emfloatstruct_struct.request_secs = global.emfloatstruct_class.request_secs;
+ break;
+
+ case PF.DOFOUR: /* DOFOUR */
+ global.fourierstruct.bRunTest = getflag(eptr);
+ break;
+
+ case PF.FOURASIZE: /* FOURASIZE */
+ global.fourierstruct.arraysize = Int32.Parse(eptr);
+ global.fourierstruct.adjust = 1;
+ break;
+
+ case PF.FOURMINS: /* FOURMINSECONDS */
+ global.fourierstruct.request_secs = Int32.Parse(eptr);
+ break;
+
+ case PF.DOASSIGN: /* DOASSIGN */
+ global.assignstruct_jagged.bRunTest =
+ global.assignstruct_rect.bRunTest = getflag(eptr);
+ break;
+
+ case PF.AARRAYS: /* ASSIGNARRAYS */
+ global.assignstruct_rect.numarrays = Int16.Parse(eptr);
+ global.assignstruct_jagged.numarrays = global.assignstruct_rect.numarrays;
+ break;
+
+ case PF.ASSIGNMINS: /* ASSIGNMINSECONDS */
+ global.assignstruct_rect.request_secs = Int32.Parse(eptr);
+ global.assignstruct_jagged.request_secs = global.assignstruct_rect.request_secs;
+ break;
+
+ case PF.DOIDEA: /* DOIDEA */
+ global.ideastruct.bRunTest = getflag(eptr);
+ break;
+
+ case PF.IDEAASIZE: /* IDEAARRAYSIZE */
+ global.ideastruct.arraysize = Int32.Parse(eptr);
+ break;
+
+ case PF.IDEALOOPS: /* IDEALOOPS */
+ global.ideastruct.loops = Int32.Parse(eptr);
+ break;
+
+ case PF.IDEAMINS: /* IDEAMINSECONDS */
+ global.ideastruct.request_secs = Int32.Parse(eptr);
+ break;
+
+ case PF.DOHUFF: /* DOHUFF */
+ global.huffstruct.bRunTest = getflag(eptr);
+ break;
+
+ case PF.HUFFASIZE: /* HUFFARRAYSIZE */
+ global.huffstruct.arraysize = Int32.Parse(eptr);
+ break;
+
+ case PF.HUFFLOOPS: /* HUFFLOOPS */
+ global.huffstruct.loops = Int32.Parse(eptr);
+ global.huffstruct.adjust = 1;
+ break;
+
+ case PF.HUFFMINS: /* HUFFMINSECONDS */
+ global.huffstruct.request_secs = Int32.Parse(eptr);
+ break;
+
+ case PF.DONNET: /* DONNET */
+ global.nnetstruct_jagged.bRunTest =
+ global.nnetstruct_rect.bRunTest = getflag(eptr);
+ break;
+
+ case PF.NNETLOOPS: /* NNETLOOPS */
+ global.nnetstruct_rect.loops = Int32.Parse(eptr);
+ global.nnetstruct_jagged.loops = global.nnetstruct_rect.loops;
+ global.nnetstruct_jagged.adjust =
+ global.nnetstruct_rect.adjust = 1;
+ break;
+
+ case PF.NNETMINS: /* NNETMINSECONDS */
+ global.nnetstruct_rect.request_secs = Int32.Parse(eptr);
+ global.nnetstruct_jagged.request_secs = global.nnetstruct_rect.request_secs;
+ break;
+
+ case PF.DOLU: /* DOLU */
+ global.lustruct.bRunTest = getflag(eptr);
+ break;
+
+ case PF.LUNARRAYS: /* LUNUMARRAYS */
+ global.lustruct.numarrays = Int32.Parse(eptr);
+ global.lustruct.adjust = 1;
+ break;
+
+ case PF.LUMINS: /* LUMINSECONDS */
+ global.lustruct.request_secs = Int32.Parse(eptr);
+ break;
+
+ case PF.ALIGN: /* ALIGN */
+ global.align = Int32.Parse(eptr);
+ break;
+
+ case PF.DONUMJAGGED: /* DONUMSORTJAGGED */
+ global.numsortstruct_jagged.bRunTest = getflag(eptr);
+ break;
+
+ case PF.DONUMRECT: /* DONUMSORTRECT */
+ global.numsortstruct_rect.bRunTest = getflag(eptr);
+ break;
+
+ case PF.DOEMFSTRUCT: /* DOEMFSTRUCT */
+ global.emfloatstruct_struct.bRunTest = getflag(eptr);
+ break;
+
+ case PF.DOEMFCLASS: /* DOEMFCLASS */
+ global.emfloatstruct_class.bRunTest = getflag(eptr);
+ break;
+
+ case PF.DOASSIGNJAGGED: /* DOASSIGNJAGGED */
+ global.assignstruct_jagged.bRunTest = getflag(eptr);
+ break;
+
+ case PF.DOASSIGNRECT: /* DOASSIGNRECT */
+ global.assignstruct_rect.bRunTest = getflag(eptr);
+ break;
+
+ case PF.DONNETJAGGED: /* DONNETJAGGED */
+ global.nnetstruct_jagged.bRunTest = getflag(eptr);
+ break;
+
+ case PF.DONNETRECT: /* DONNETRECT */
+ global.nnetstruct_rect.bRunTest = getflag(eptr);
+ break;
+ }
+ skipswitch:
+ continue;
+ } /* End while */
+
+ return;
+ }
+
+ /************
+ ** getflag **
+ *************
+ ** Return 1 if cptr points to "T"; 0 otherwise.
+ */
+ private static bool getflag(String cptr)
+ {
+ return cptr[0] == 'T' || cptr[0] == 't';
+ }
+
+ /*********************
+ ** set_request_secs **
+ **********************
+ ** Set everyone's "request_secs" entry to whatever
+ ** value is in global.min_secs. This is done
+ ** at the beginning, and possibly later if the
+ ** user redefines global.min_secs in the command file.
+ */
+ private static void SetRequestSecs()
+ {
+ foreach (HarnessTest ht in s_tests)
+ {
+ ht.request_secs = global.min_secs;
+ }
+ return;
+ }
+
+ /**************************
+ ** bench_with_confidence **
+ ***************************
+ ** Given a benchmark id that indicates a function, this
+ ** routine repeatedly calls that benchmark, seeking
+ ** to collect enough scores to get 5 that meet the confidence
+ ** criteria. Return 0 if ok, -1 if failure.
+ ** Returns mean ans std. deviation of results if successful.
+ */
+ private static
+ int bench_with_confidence(int fid, /* Function id */
+ out double mean, /* Mean of scores */
+ out double stdev, /* Standard deviation */
+ out int numtries) /* # of attempts */
+ {
+ double[] myscores = new double[5]; /* Need at least 5 scores */
+ double c_half_interval; /* Confidence half interval */
+ int i; /* Index */
+ double newscore; /* For improving confidence interval */
+
+ /*
+ ** Get first 5 scores. Then begin confidence testing.
+ */
+ for (i = 0; i < 5; i++)
+ {
+ myscores[i] = s_tests[fid].Run();
+ }
+ numtries = 5; /* Show 5 attempts */
+
+ /*
+ ** The system allows a maximum of 10 tries before it gives
+ ** up. Since we've done 5 already, we'll allow 5 more.
+ */
+
+ /*
+ ** Enter loop to test for confidence criteria.
+ */
+ while (true)
+ {
+ /*
+ ** Calculate confidence.
+ */
+ calc_confidence(myscores,
+ out c_half_interval,
+ out mean,
+ out stdev);
+
+ /*
+ ** Is half interval 5% or less of mean?
+ ** If so, we can go home. Otherwise,
+ ** we have to continue.
+ */
+ if (c_half_interval / mean <= (double)0.05)
+ break;
+
+ /*
+ ** Go get a new score and see if it
+ ** improves existing scores.
+ */
+ do
+ {
+ if (numtries == 10)
+ return (-1);
+ newscore = s_tests[fid].Run();
+ numtries += 1;
+ } while (seek_confidence(myscores, ref newscore,
+ out c_half_interval, out mean, out stdev) == 0);
+ }
+
+ return (0);
+ }
+
+ /********************
+ ** seek_confidence **
+ *********************
+ ** Pass this routine an array of 5 scores PLUS a new score.
+ ** This routine tries the new score in place of each of
+ ** the other five scores to determine if the new score,
+ ** when replacing one of the others, improves the confidence
+ ** half-interval.
+ ** Return 0 if failure. Original 5 scores unchanged.
+ ** Return -1 if success. Also returns new half-interval,
+ ** mean, and stand. dev.
+ */
+ private static int seek_confidence(double[] scores,
+ ref double newscore,
+ out double c_half_interval,
+ out double smean,
+ out double sdev)
+ {
+ double sdev_to_beat; /* Original sdev to be beaten */
+ double temp; /* For doing a swap */
+ int is_beaten; /* Indicates original was beaten */
+ int i; /* Index */
+
+ /*
+ ** First calculate original standard deviation
+ */
+ calc_confidence(scores, out c_half_interval, out smean, out sdev);
+ sdev_to_beat = sdev;
+ is_beaten = -1;
+
+ /*
+ ** Try to beat original score. We'll come out of this
+ ** loop with a flag.
+ */
+ for (i = 0; i < 5; i++)
+ {
+ temp = scores[i];
+ scores[i] = newscore;
+ calc_confidence(scores, out c_half_interval, out smean, out sdev);
+ scores[i] = temp;
+ if (sdev_to_beat > sdev)
+ {
+ is_beaten = i;
+ sdev_to_beat = sdev;
+ }
+ }
+
+ if (is_beaten != -1)
+ {
+ scores[is_beaten] = newscore;
+ return (-1);
+ }
+ return (0);
+ }
+
+ /********************
+ ** calc_confidence **
+ *********************
+ ** Given a set of 5 scores, calculate the confidence
+ ** half-interval. We'l also return the sample mean and sample
+ ** standard deviation.
+ ** NOTE: This routines presumes a confidence of 95% and
+ ** a confidence coefficient of .95
+ */
+ private static void calc_confidence(double[] scores, /* Array of scores */
+ out double c_half_interval, /* Confidence half-int */
+ out double smean, /* Standard mean */
+ out double sdev) /* Sample stand dev */
+ {
+ int i; /* Index */
+ /*
+ ** First calculate mean.
+ */
+ smean = (scores[0] + scores[1] + scores[2] + scores[3] + scores[4]) /
+ (double)5.0;
+
+ /*
+ ** Get standard deviation - first get variance
+ */
+ sdev = (double)0.0;
+ for (i = 0; i < 5; i++)
+ {
+ sdev += (scores[i] - smean) * (scores[i] - smean);
+ }
+ sdev /= (double)4.0;
+ sdev = Math.Sqrt(sdev) / Math.Sqrt(5.0);
+
+ /*
+ ** Now calculate the confidence half-interval.
+ ** For a confidence level of 95% our confidence coefficient
+ ** gives us a multiplying factor of 2.776
+ ** (The upper .025 quartile of a t distribution with 4 degrees
+ ** of freedom.)
+ */
+ c_half_interval = (double)2.776 * sdev;
+ return;
+ }
+
+ public static void OutputStringPart(String s)
+ {
+ Console.Write(s);
+ if (global.write_to_file)
+ {
+ global.ofile.Write(s);
+ }
+ }
+
+ public static void OutputString(String s)
+ {
+ Console.WriteLine(s);
+ if (global.write_to_file)
+ {
+ global.ofile.WriteLine(s);
+ global.ofile.Flush();
+ }
+ }
+
+ /****************************
+ ** TicksToSecs
+ ** Converts ticks to seconds. Converts ticks to integer
+ ** seconds, discarding any fractional amount.
+ */
+ public static int TicksToSecs(long tickamount)
+ {
+ return ((int)(tickamount / global.TICKS_PER_SEC));
+ }
+
+ /****************************
+ ** TicksToFracSecs
+ ** Converts ticks to fractional seconds. In other words,
+ ** this returns the exact conversion from ticks to
+ ** seconds.
+ */
+ public static double TicksToFracSecs(long tickamount)
+ {
+ return ((double)tickamount / (double)global.TICKS_PER_SEC);
+ }
+
+ public static long StartStopwatch()
+ {
+ //DateTime t = DateTime.Now;
+ //return(t.Ticks);
+ return Environment.TickCount;
+ }
+
+ public static long StopStopwatch(long start)
+ {
+ //DateTime t = DateTime.Now;
+ //Console.WriteLine(t.Ticks - start);
+ //return(t.Ticks-start);
+ long x = Environment.TickCount - start;
+ //Console.WriteLine(x);
+ return x;
+ }
+
+ /****************************
+ * randwc() *
+ *****************************
+ ** Returns int random modulo num.
+ */
+ public static int randwc(int num)
+ {
+ return (randnum(0) % num);
+ }
+
+ /***************************
+ ** abs_randwc() **
+ ****************************
+ ** Same as randwc(), only this routine returns only
+ ** positive numbers.
+ */
+ public static int abs_randwc(int num)
+ {
+ int temp; /* Temporary storage */
+
+ temp = randwc(num);
+ if (temp < 0) temp = 0 - temp;
+
+ return temp;
+ }
+
+ /****************************
+ * randnum() *
+ *****************************
+ ** Second order linear congruential generator.
+ ** Constants suggested by J. G. Skellam.
+ ** If val==0, returns next member of sequence.
+ ** val!=0, restart generator.
+ */
+ public static int randnum(int lngval)
+ {
+ int interm;
+
+ if (lngval != 0L)
+ { s_randw[0] = 13; s_randw[1] = 117; }
+
+ unchecked
+ {
+ interm = (s_randw[0] * 254754 + s_randw[1] * 529562) % 999563;
+ }
+ s_randw[1] = s_randw[0];
+ s_randw[0] = interm;
+ return (interm);
+ }
+
+ static void Setup()
+ {
+ s_randw = new int[2] { 13, 117 };
+ global.min_ticks = global.MINIMUM_TICKS;
+ global.min_secs = global.MINIMUM_SECONDS;
+ global.allstats = false;
+ global.custrun = false;
+ global.align = 8;
+ global.write_to_file = false;
+ }
+
+ const int NumericSortJaggedIterations = 20;
+
+ [Benchmark]
+ public static void BenchNumericSortJagged()
+ {
+ Setup();
+ NumericSortJagged t = new NumericSortJagged();
+ t.numarrays = 1000;
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < NumericSortJaggedIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+
+ const int NumericSortRectangularIterations = 20;
+
+ [Benchmark]
+ public static void BenchNumericSortRectangular()
+ {
+ Setup();
+ NumericSortRect t = new NumericSortRect();
+ t.numarrays = 1000;
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < NumericSortRectangularIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+
+ const int StringSortIterations = 15;
+
+ [Benchmark]
+ public static void BenchStringSort()
+ {
+ Setup();
+ StringSort t = new StringSort();
+ t.numarrays = 1000;
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < StringSortIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+ const int BitOpsIterations = 15;
+
+ [Benchmark]
+ public static void BenchBitOps()
+ {
+ Setup();
+ BitOps t = new BitOps();
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < BitOpsIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+
+ const int EmFloatIterations = 8;
+
+ [Benchmark]
+ public static void BenchEmFloat()
+ {
+ Setup();
+ EmFloatStruct t = new EMFloat();
+ t.loops = 100;
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < EmFloatIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+
+ const int EmFloatClassIterations = 8;
+
+ [Benchmark]
+ public static void BenchEmFloatClass()
+ {
+ Setup();
+ EmFloatStruct t = new EMFloatClass();
+ t.loops = 100;
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < EmFloatClassIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+
+ const int FourierIterations = 20;
+
+ [Benchmark]
+ public static void BenchFourier()
+ {
+ Setup();
+ FourierStruct t = new Fourier();
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < FourierIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+
+ const int AssignJaggedIterations = 15;
+
+ [Benchmark]
+ public static void BenchAssignJagged()
+ {
+ Setup();
+ AssignStruct t = new AssignJagged();
+ t.numarrays = 1000;
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < AssignJaggedIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+
+ const int AssignRectangularIterations = 20;
+
+ [Benchmark]
+ public static void BenchAssignRectangular()
+ {
+ Setup();
+ AssignStruct t = new AssignRect();
+ t.numarrays = 1000;
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < AssignRectangularIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+
+ const int IDEAEncryptionIterations = 20;
+
+ [Benchmark]
+ public static void BenchIDEAEncryption()
+ {
+ Setup();
+ IDEAStruct t = new IDEAEncryption();
+ t.loops = 100;
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < IDEAEncryptionIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+
+ const int NeuralJaggedIterations = 20;
+
+ [Benchmark]
+ public static void BenchNeuralJagged()
+ {
+ Setup();
+ NNetStruct t = new NeuralJagged();
+ t.loops = 100;
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < NeuralJaggedIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+
+ const int NeuralIterations = 12;
+
+ [Benchmark]
+ public static void BenchNeural()
+ {
+ Setup();
+ NNetStruct t = new Neural();
+ t.loops = 100;
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < NeuralIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+
+ const int LUDecompIterations = 20;
+
+ [Benchmark]
+ public static void BenchLUDecomp()
+ {
+ Setup();
+ LUStruct t = new LUDecomp();
+ t.numarrays = 1000;
+ t.adjust = 0;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < LUDecompIterations; i++)
+ {
+ t.Run();
+ }
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/Bytemark.csproj b/tests/src/JIT/Performance/CodeQuality/Bytemark/Bytemark.csproj
new file mode 100644
index 0000000000..160660c9df
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/Bytemark.csproj
@@ -0,0 +1,59 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ <GCStressIncompatible>true</GCStressIncompatible>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ByteMark.cs" />
+ <Compile Include="Huffman.cs" />
+ <Compile Include="StringSort.cs" />
+ <Compile Include="assign_jagged.cs" />
+ <Compile Include="assign_rect.cs" />
+ <Compile Include="bitops.cs" />
+ <Compile Include="emfloat.cs" />
+ <Compile Include="emfloatclass.cs" />
+ <Compile Include="fourier.cs" />
+ <Compile Include="idea.cs" />
+ <Compile Include="ludecomp.cs" />
+ <Compile Include="neural.cs" />
+ <Compile Include="neuraljagged.cs" />
+ <Compile Include="neural-dat.cs" />
+ <Compile Include="numericsort.cs" />
+ <Compile Include="utility.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/Bytemark/Huffman.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/Huffman.cs
new file mode 100644
index 0000000000..bfe9965919
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/Huffman.cs
@@ -0,0 +1,570 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+using System;
+
+/*
+** TYPEDEFS
+*/
+internal struct huff_node
+{
+ public byte c; /* Byte value */
+ public float freq; /* Frequency */
+ public int parent; /* Parent node */
+ public int left; /* Left pointer = 0 */
+ public int right; /* Right pointer = 1 */
+};
+
+/************************
+** HUFFMAN COMPRESSION **
+************************/
+public class Huffman : HuffStruct
+{
+ public override string Name()
+ {
+ return "HUFFMAN";
+ }
+
+ /**************
+ ** DoHuffman **
+ ***************
+ ** Execute a huffman compression on a block of plaintext.
+ ** Note that (as with IDEA encryption) an iteration of the
+ ** Huffman test includes a compression AND a decompression.
+ ** Also, the compression cycle includes building the
+ ** Huffman tree.
+ */
+ public override double Run()
+ {
+ huff_node[] hufftree;
+ long accumtime;
+ double iterations;
+ byte[] comparray;
+ byte[] decomparray;
+ byte[] plaintext;
+
+ InitWords();
+
+ /*
+ ** Allocate memory for the plaintext and the compressed text.
+ ** We'll be really pessimistic here, and allocate equal amounts
+ ** for both (though we know...well, we PRESUME) the compressed
+ ** stuff will take less than the plain stuff.
+ ** Also note that we'll build a 3rd buffer to decompress
+ ** into, and we preallocate space for the huffman tree.
+ ** (We presume that the Huffman tree will grow no larger
+ ** than 512 bytes. This is actually a super-conservative
+ ** estimate...but, who cares?)
+ */
+ plaintext = new byte[this.arraysize];
+ comparray = new byte[this.arraysize];
+ decomparray = new byte[this.arraysize];
+
+ hufftree = new huff_node[512];
+
+ /*
+ ** Build the plaintext buffer. Since we want this to
+ ** actually be able to compress, we'll use the
+ ** wordcatalog to build the plaintext stuff.
+ */
+ create_text_block(plaintext, this.arraysize - 1, 500);
+ // for (int i = 0; i < this.arraysize-1; i++) {
+ // Console.Write((char)plaintext[i]);
+ // }
+ plaintext[this.arraysize - 1] = (byte)'\0';
+ // plaintextlen=this.arraysize;
+
+ /*
+ ** See if we need to perform self adjustment loop.
+ */
+ if (this.adjust == 0)
+ {
+ /*
+ ** Do self-adjustment. This involves initializing the
+ ** # of loops and increasing the loop count until we
+ ** get a number of loops that we can use.
+ */
+
+ for (this.loops = 100;
+ this.loops < global.MAXHUFFLOOPS;
+ this.loops += 10)
+ {
+ if (DoHuffIteration(plaintext,
+ comparray,
+ decomparray,
+ this.arraysize,
+ this.loops,
+ hufftree) > global.min_ticks)
+ break;
+ }
+ }
+
+ /*
+ ** All's well if we get here. Do the test.
+ */
+ accumtime = 0L;
+ iterations = (double)0.0;
+
+ do
+ {
+ accumtime += DoHuffIteration(plaintext,
+ comparray,
+ decomparray,
+ this.arraysize,
+ this.loops,
+ hufftree);
+ iterations += (double)this.loops;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ /*
+ ** Clean up, calculate results, and go home. Be sure to
+ ** show that we don't have to rerun adjustment code.
+ */
+ //this.iterspersec=iterations / TicksToFracSecs(accumtime);
+
+ if (this.adjust == 0)
+ this.adjust = 1;
+
+ return (iterations / ByteMark.TicksToFracSecs(accumtime));
+ }
+
+
+ /*********************
+ ** create_text_line **
+ **********************
+ ** Create a random line of text, stored at *dt. The line may be
+ ** no more than nchars long.
+ */
+ private static void create_text_line(byte[] dt, int nchars, int lower)
+ {
+ int charssofar; /* # of characters so far */
+ int tomove; /* # of characters to move */
+ string myword; /* Local buffer for words */
+
+ int index = 0;
+
+ charssofar = 0;
+
+ do
+ {
+ /*
+ ** Grab a random word from the wordcatalog
+ */
+ myword = wordcatarray[ByteMark.abs_randwc(Huffman.WORDCATSIZE)];
+
+ /*
+ ** Append a blank.
+ */
+ myword += " ";
+ tomove = myword.Length;
+
+ /*
+ ** See how long it is. If its length+charssofar > nchars, we have
+ ** to trim it.
+ */
+ if ((tomove + charssofar) > nchars)
+ tomove = nchars - charssofar;
+ /*
+ ** Attach the word to the current line. Increment counter.
+ */
+ for (int i = 0; i < tomove; i++)
+ {
+ dt[lower + index++] = (byte)myword[i];
+ }
+ charssofar += tomove;
+
+ /*
+ ** If we're done, bail out. Otherwise, go get another word.
+ */
+ } while (charssofar < nchars);
+
+ return;
+ }
+
+ /**********************
+ ** create_text_block **
+ ***********************
+ ** Build a block of text randomly loaded with words. The words
+ ** come from the wordcatalog (which must be loaded before you
+ ** call this).
+ ** *tb points to the memory where the text is to be built.
+ ** tblen is the # of bytes to put into the text block
+ ** maxlinlen is the maximum length of any line (line end indicated
+ ** by a carriage return).
+ */
+ private static void create_text_block(byte[] tb,
+ int tblen,
+ short maxlinlen)
+ {
+ int bytessofar; /* # of bytes so far */
+ int linelen; /* Line length */
+
+ bytessofar = 0;
+ do
+ {
+ /*
+ ** Pick a random length for a line and fill the line.
+ ** Make sure the line can fit (haven't exceeded tablen) and also
+ ** make sure you leave room to append a carriage return.
+ */
+ linelen = ByteMark.abs_randwc(maxlinlen - 6) + 6;
+ if ((linelen + bytessofar) > tblen)
+ linelen = tblen - bytessofar;
+
+ if (linelen > 1)
+ {
+ create_text_line(tb, linelen, bytessofar);
+ }
+ tb[linelen] = (byte)'\n'; /* Add the carriage return */
+
+ bytessofar += linelen;
+ } while (bytessofar < tblen);
+ }
+
+ /********************
+ ** DoHuffIteration **
+ *********************
+ ** Perform the huffman benchmark. This routine
+ ** (a) Builds the huffman tree
+ ** (b) Compresses the text
+ ** (c) Decompresses the text and verifies correct decompression
+ */
+ private static long DoHuffIteration(byte[] plaintext,
+ byte[] comparray,
+ byte[] decomparray,
+ int arraysize,
+ int nloops,
+ huff_node[] hufftree)
+ {
+ int i; /* Index */
+ int j; /* Bigger index */
+ int root; /* Pointer to huffman tree root */
+ float lowfreq1, lowfreq2; /* Low frequency counters */
+ int lowidx1, lowidx2; /* Indexes of low freq. elements */
+ int bitoffset; /* Bit offset into text */
+ int textoffset; /* Char offset into text */
+ int maxbitoffset; /* Holds limit of bit offset */
+ int bitstringlen; /* Length of bitstring */
+ int c; /* Character from plaintext */
+ byte[] bitstring = new byte[30]; /* Holds bitstring */
+ long elapsed; /* For stopwatch */
+
+ /*
+ ** Start the stopwatch
+ */
+ elapsed = ByteMark.StartStopwatch();
+
+ /*
+ ** Do everything for nloops
+ */
+ while (nloops-- != 0)
+ {
+ /*
+ ** Calculate the frequency of each byte value. Store the
+ ** results in what will become the "leaves" of the
+ ** Huffman tree. Interior nodes will be built in those
+ ** nodes greater than node #255.
+ */
+ for (i = 0; i < 256; i++)
+ {
+ hufftree[i].freq = (float)0.0;
+ hufftree[i].c = (byte)i;
+ }
+
+ for (j = 0; j < arraysize; j++)
+ hufftree[plaintext[j]].freq += (float)1.0;
+
+ for (i = 0; i < 256; i++)
+ if (hufftree[i].freq != (float)0.0)
+ hufftree[i].freq /= (float)arraysize;
+
+ /*
+ ** Build the huffman tree. First clear all the parent
+ ** pointers and left/right pointers. Also, discard all
+ ** nodes that have a frequency of true 0.
+ */
+ for (i = 0; i < 512; i++)
+ {
+ if (hufftree[i].freq == (float)0.0)
+ hufftree[i].parent = EXCLUDED;
+ else
+ hufftree[i].parent = hufftree[i].left = hufftree[i].right = -1;
+ }
+
+ /*
+ ** Go through the tree. Finding nodes of really low
+ ** frequency.
+ */
+ root = 255; /* Starting root node-1 */
+ while (true)
+ {
+ lowfreq1 = (float)2.0; lowfreq2 = (float)2.0;
+ lowidx1 = -1; lowidx2 = -1;
+ /*
+ ** Find first lowest frequency.
+ */
+ for (i = 0; i <= root; i++)
+ if (hufftree[i].parent < 0)
+ if (hufftree[i].freq < lowfreq1)
+ {
+ lowfreq1 = hufftree[i].freq;
+ lowidx1 = i;
+ }
+
+ /*
+ ** Did we find a lowest value? If not, the
+ ** tree is done.
+ */
+ if (lowidx1 == -1) break;
+
+ /*
+ ** Find next lowest frequency
+ */
+ for (i = 0; i <= root; i++)
+ if ((hufftree[i].parent < 0) && (i != lowidx1))
+ if (hufftree[i].freq < lowfreq2)
+ {
+ lowfreq2 = hufftree[i].freq;
+ lowidx2 = i;
+ }
+
+ /*
+ ** If we could only find one item, then that
+ ** item is surely the root, and (as above) the
+ ** tree is done.
+ */
+ if (lowidx2 == -1) break;
+
+ /*
+ ** Attach the two new nodes to the current root, and
+ ** advance the current root.
+ */
+ root++; /* New root */
+ hufftree[lowidx1].parent = root;
+ hufftree[lowidx2].parent = root;
+ hufftree[root].freq = lowfreq1 + lowfreq2;
+ hufftree[root].left = lowidx1;
+ hufftree[root].right = lowidx2;
+ hufftree[root].parent = -2; /* Show root */
+ }
+
+ /*
+ ** Huffman tree built...compress the plaintext
+ */
+ bitoffset = 0; /* Initialize bit offset */
+ for (i = 0; i < arraysize; i++)
+ {
+ c = (int)plaintext[i]; /* Fetch character */
+ /*
+ ** Build a bit string for byte c
+ */
+ bitstringlen = 0;
+ while (hufftree[c].parent != -2)
+ {
+ if (hufftree[hufftree[c].parent].left == c)
+ bitstring[bitstringlen] = (byte)'0';
+ else
+ bitstring[bitstringlen] = (byte)'1';
+ c = hufftree[c].parent;
+ bitstringlen++;
+ }
+
+ /*
+ ** Step backwards through the bit string, setting
+ ** bits in the compressed array as you go.
+ */
+ while (bitstringlen-- != 0)
+ {
+ SetCompBit(comparray, bitoffset, bitstring[bitstringlen]);
+ bitoffset++;
+ }
+ }
+
+ /*
+ ** Compression done. Perform de-compression.
+ */
+ maxbitoffset = bitoffset;
+ bitoffset = 0;
+ textoffset = 0;
+ do
+ {
+ i = root;
+ while (hufftree[i].left != -1)
+ {
+ if (GetCompBit(comparray, bitoffset) == 0)
+ i = hufftree[i].left;
+ else
+ i = hufftree[i].right;
+ bitoffset++;
+ }
+ decomparray[textoffset] = hufftree[i].c;
+
+#if DEBUG
+ if (hufftree[i].c != plaintext[textoffset])
+ {
+ /* Show error */
+ string error = String.Format("Huffman: error at textoffset {0}", textoffset);
+ throw new Exception(error);
+ }
+#endif
+ textoffset++;
+ } while (bitoffset < maxbitoffset);
+ } /* End the big while(nloops--) from above */
+
+ /*
+ ** All done
+ */
+ return (ByteMark.StopStopwatch(elapsed));
+ }
+
+ /***************
+ ** SetCompBit **
+ ****************
+ ** Set a bit in the compression array. The value of the
+ ** bit is set according to char bitchar.
+ */
+ private static void SetCompBit(byte[] comparray,
+ int bitoffset,
+ byte bitchar)
+ {
+ int byteoffset;
+ int bitnumb;
+
+ /*
+ ** First calculate which element in the comparray to
+ ** alter. and the bitnumber.
+ */
+ byteoffset = bitoffset >> 3;
+ bitnumb = bitoffset % 8;
+
+ /*
+ ** Set or clear
+ */
+ if (bitchar == '1')
+ comparray[byteoffset] |= ((byte)(1 << bitnumb));
+ else
+ {
+ // JTR: Work around compiler bug: (byte)~(1<<bitnumb);
+ //int b = ~(1<<bitnumb);
+ comparray[byteoffset] &= unchecked((byte)(~(1 << bitnumb)));
+ }
+
+ return;
+ }
+
+ /***************
+ ** GetCompBit **
+ ****************
+ ** Return the bit value of a bit in the comparession array.
+ ** Returns 0 if the bit is clear, nonzero otherwise.
+ */
+ private static int GetCompBit(byte[] comparray,
+ int bitoffset)
+ {
+ int byteoffset;
+ int bitnumb;
+
+ /*
+ ** Calculate byte offset and bit number.
+ */
+ byteoffset = bitoffset >> 3;
+ bitnumb = bitoffset % 8;
+
+ /*
+ ** Fetch
+ */
+ return ((1 << bitnumb) & comparray[byteoffset]);
+ }
+
+ protected const int WORDCATSIZE = 50;
+ protected const int EXCLUDED = 32000; /* Big positive value */
+ protected static string[] wordcatarray;
+ protected static void InitWords()
+ {
+ wordcatarray = new string[]
+ { "Hello",
+ "He",
+ "Him",
+ "the",
+ "this",
+ "that",
+ "though",
+ "rough",
+ "cough",
+ "obviously",
+ "But",
+ "but",
+ "bye",
+ "begin",
+ "beginning",
+ "beginnings",
+ "of",
+ "our",
+ "ourselves",
+ "yourselves",
+ "to",
+ "together",
+ "togetherness",
+ "from",
+ "either",
+ "I",
+ "A",
+ "return",
+ "However",
+ "that",
+ "example",
+ "yet",
+ "quickly",
+ "all",
+ "if",
+ "were",
+ "includes",
+ "always",
+ "never",
+ "not",
+ "small",
+ "returns",
+ "set",
+ "basic",
+ "Entered",
+ "with",
+ "used",
+ "shown",
+ "you",
+ "know" };
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/StringSort.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/StringSort.cs
new file mode 100644
index 0000000000..e4888b2edd
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/StringSort.cs
@@ -0,0 +1,348 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+**
+*/
+
+using System;
+using System.Text;
+
+/********************
+** STRING HEAPSORT **
+********************/
+
+/*****************
+** DoStringSort **
+******************
+** This routine performs the CPU string sort test.
+** Arguments:
+** requested_secs = # of seconds to execute test
+** stringspersec = # of strings per second sorted (RETURNED)
+*/
+
+internal static class StringOrdinalComparer
+{
+ public static int Compare(String left, String right)
+ {
+ return String.CompareOrdinal(left, right);
+ }
+}
+
+public class StringSort : StringSortStruct
+{
+ public override string Name()
+ {
+ return "STRING SORT";
+ }
+ public override double Run()
+ {
+ string[][] arraybase; /* Base pointers of array */
+ long accumtime; /* Accumulated time */
+ double iterations; /* Iteration counter */
+
+ /*
+ ** See if we need to do self adjustment code.
+ */
+ if (this.adjust == 0)
+ {
+ /*
+ ** Self-adjustment code. The system begins by sorting 1
+ ** array. If it does that in no time, then two arrays
+ ** are built and sorted. This process continues until
+ ** enough arrays are built to handle the tolerance.
+ */
+ this.numarrays = 1;
+ while (true)
+ {
+ /*
+ ** Allocate space for arrays
+ */
+ arraybase = new string[this.numarrays][];
+ for (int i = 0; i < this.numarrays; i++)
+ arraybase[i] = new string[this.arraysize];
+
+ /*
+ ** Do an iteration of the string sort. If the
+ ** elapsed time is less than or equal to the permitted
+ ** minimum, then allocate for more arrays and
+ ** try again.
+ */
+ if (DoStringSortIteration(arraybase,
+ this.numarrays,
+ this.arraysize) > global.min_ticks)
+ break; /* We're ok...exit */
+
+ if (this.numarrays++ > global.NUMSTRARRAYS)
+ {
+ throw new Exception("CPU:SSORT -- NUMSTRARRAYS hit.");
+ }
+ }
+ }
+ else
+ {
+ /*
+ ** Allocate space for arrays
+ */
+ arraybase = new string[this.numarrays][];
+ for (int i = 0; i < this.numarrays; i++)
+ arraybase[i] = new string[this.arraysize];
+ }
+
+ /*
+ ** All's well if we get here. Repeatedly perform sorts until the
+ ** accumulated elapsed time is greater than # of seconds requested.
+ */
+ accumtime = 0L;
+ iterations = (double)0.0;
+
+ do
+ {
+ accumtime += DoStringSortIteration(arraybase,
+ this.numarrays,
+ this.arraysize);
+ iterations += (double)this.numarrays;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ if (this.adjust == 0)
+ this.adjust = 1;
+
+ /*
+ ** Clean up, calculate results, and go home.
+ ** Set flag to show we don't need to rerun adjustment code.
+ */
+
+ return (iterations * (double)this.numarrays / ByteMark.TicksToFracSecs(accumtime));
+ }
+
+ /**************************
+ ** DoStringSortIteration **
+ ***************************
+ ** This routine executes one iteration of the string
+ ** sort benchmark. It returns the number of ticks
+ ** Note that this routine also builds the offset pointer
+ ** array.
+ */
+
+ private static int DoStringSortIteration(string[][] arraybase, int numarrays, int arraysize)
+ {
+ long elapsed; /* Elapsed ticks */
+ int i;
+
+ /*
+ ** Load up the array(s) with random numbers
+ */
+ LoadStringArray(arraybase, arraysize, numarrays);
+
+ /*
+ ** Start the stopwatch
+ */
+ elapsed = ByteMark.StartStopwatch();
+
+ /*
+ ** Execute heapsorts
+ */
+ for (i = 0; i < numarrays; i++)
+ {
+ // StrHeapSort(tempobase,tempsbase,nstrings,0L,nstrings-1);
+ StrHeapSort(arraybase[i], 0, arraysize - 1);
+ }
+
+ /*
+ ** Record elapsed time
+ */
+ elapsed = ByteMark.StopStopwatch(elapsed);
+
+#if DEBUG
+ for (i = 0; i < arraysize - 1; i++)
+ {
+ /*
+ ** Compare strings to check for proper
+ ** sort.
+ */
+ if (StringOrdinalComparer.Compare(arraybase[0][i + 1], arraybase[0][i]) < 0)
+ {
+ Console.Write("Error in StringSort! arraybase[0][{0}]='{1}', arraybase[0][{2}]='{3}\n", i, arraybase[0][i], i + 1, arraybase[0][i + 1]);
+ break;
+ }
+ }
+#endif
+
+ return ((int)elapsed);
+ }
+
+
+ /********************
+ ** LoadStringArray **
+ *********************
+ ** Initialize the string array with random strings of
+ ** varying sizes.
+ ** Returns the pointer to the offset pointer array.
+ ** Note that since we're creating a number of arrays, this
+ ** routine builds one array, then copies it into the others.
+ */
+ private static void LoadStringArray(string[][] array, /* String array */
+ int arraysize, /* Size of array */
+ int numarrays) /* # of arrays */
+ {
+ /*
+ ** Initialize random number generator.
+ */
+ ByteMark.randnum(13);
+
+ /*
+ ** Load up the first array with randoms
+ */
+
+ int i;
+ for (i = 0; i < arraysize; i++)
+ {
+ int length;
+
+ length = 4 + ByteMark.abs_randwc(76);
+ array[0][i] = "";
+
+ /*
+ ** Fill up the string with random bytes.
+ */
+ StringBuilder builder = new StringBuilder(length);
+
+ int add;
+ for (add = 0; add < length; add++)
+ {
+ char myChar = (char)(ByteMark.abs_randwc(96) + 32);
+ builder.Append(myChar);
+ }
+ array[0][i] = builder.ToString();
+ }
+
+ /*
+ ** We now have initialized a single full array. If there
+ ** is more than one array, copy the original into the
+ ** others.
+ */
+ int k;
+ for (k = 1; k < numarrays; k++)
+ {
+ for (i = 0; i < arraysize; i++)
+ {
+ array[k][i] = array[0][i];
+ }
+ }
+ }
+
+
+ /****************
+ ** strheapsort **
+ *****************
+ ** Pass this routine a pointer to an array of unsigned char.
+ ** The array is presumed to hold strings occupying at most
+ ** 80 bytes (counts a byte count).
+ ** This routine also needs a pointer to an array of offsets
+ ** which represent string locations in the array, and
+ ** an unsigned long indicating the number of strings
+ ** in the array.
+ */
+ private static void StrHeapSort(string[] array,
+ int bottom, /* lower bound */
+ int top) /* upper bound */
+ {
+ int i;
+ string temp;
+
+ /*
+ ** Build a heap in the array
+ */
+ for (i = (top / 2); i > 0; --i)
+ strsift(array, i, top);
+
+ /*
+ ** Repeatedly extract maximum from heap and place it at the
+ ** end of the array. When we get done, we'll have a sorted
+ ** array.
+ */
+ for (i = top; i > 0; --i)
+ {
+ strsift(array, bottom, i);
+ temp = array[0];
+ array[0] = array[i]; /* perform exchange */
+ array[i] = temp;
+ }
+ return;
+ }
+
+
+ /************
+ ** strsift **
+ *************
+ ** Pass this function:
+ ** 1) A pointer to an array of offset pointers
+ ** 2) A pointer to a string array
+ ** 3) The number of elements in the string array
+ ** 4) Offset within which to sort.
+ ** Sift the array within the bounds of those offsets (thus
+ ** building a heap).
+ */
+ private static void strsift(string[] array,
+ int i,
+ int j)
+ {
+ int k;
+ string temp;
+
+ while ((i + i) <= j)
+ {
+ k = i + i;
+ if (k < j)
+ {
+ //array[k].CompareTo(array[k+1]);
+ if (StringOrdinalComparer.Compare(array[k], array[k + 1]) < 0)
+ ++k;
+ }
+
+ //if(array[i]<array[k])
+ if (StringOrdinalComparer.Compare(array[i], array[k]) < 0)
+ {
+ temp = array[k];
+ array[k] = array[i];
+ array[i] = temp;
+ i = k;
+ }
+ else
+ i = j + 1;
+ }
+ return;
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/assign_jagged.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/assign_jagged.cs
new file mode 100644
index 0000000000..1ad69ff129
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/assign_jagged.cs
@@ -0,0 +1,551 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/*************
+** DoAssign **
+**************
+** Perform an assignment algorithm.
+** The algorithm was adapted from the step by step guide found
+** in "Quantitative Decision Making for Business" (Gordon,
+** Pressman, and Cohn; Prentice-Hall)
+**
+**
+** NOTES:
+** 1. Even though the algorithm distinguishes between
+** ASSIGNROWS and ASSIGNCOLS, as though the two might
+** be different, it does presume a square matrix.
+** I.E., ASSIGNROWS and ASSIGNCOLS must be the same.
+** This makes for some algorithmically-correct but
+** probably non-optimal constructs.
+**
+*/
+
+using System;
+
+public class AssignJagged : AssignStruct
+{
+ public override string Name()
+ {
+ return "ASSIGNMENT(jagged)";
+ }
+ public override double Run()
+ {
+ int[][][] arraybase;
+ long accumtime;
+ double iterations;
+
+ /*
+ ** See if we need to do self adjustment code.
+ */
+ if (this.adjust == 0)
+ {
+ /*
+ ** Self-adjustment code. The system begins by working on 1
+ ** array. If it does that in no time, then two arrays
+ ** are built. This process continues until
+ ** enough arrays are built to handle the tolerance.
+ */
+ this.numarrays = 1;
+ while (true)
+ {
+ /*
+ ** Allocate space for arrays
+ */
+ arraybase = new int[this.numarrays][][];
+ for (int i = 0; i < this.numarrays; i++)
+ {
+ arraybase[i] = new int[global.ASSIGNROWS][];
+ for (int j = 0; j < global.ASSIGNROWS; j++)
+ arraybase[i][j] = new int[global.ASSIGNCOLS];
+ }
+
+ /*
+ ** Do an iteration of the assignment alg. If the
+ ** elapsed time is less than or equal to the permitted
+ ** minimum, then allocate for more arrays and
+ ** try again.
+ */
+ if (DoAssignIteration(arraybase,
+ this.numarrays) > global.min_ticks)
+ break; /* We're ok...exit */
+
+ this.numarrays++;
+ }
+ }
+ else
+ { /*
+ ** Allocate space for arrays
+ */
+ arraybase = new int[this.numarrays][][];
+ for (int i = 0; i < this.numarrays; i++)
+ {
+ arraybase[i] = new int[global.ASSIGNROWS][];
+ for (int j = 0; j < global.ASSIGNROWS; j++)
+ arraybase[i][j] = new int[global.ASSIGNCOLS];
+ }
+ }
+
+ /*
+ ** All's well if we get here. Do the tests.
+ */
+ accumtime = 0;
+ iterations = (double)0.0;
+
+ do
+ {
+ accumtime += DoAssignIteration(arraybase, this.numarrays);
+ iterations += (double)1.0;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ if (this.adjust == 0)
+ this.adjust = 1;
+
+ return (iterations * (double)this.numarrays
+ / ByteMark.TicksToFracSecs(accumtime));
+ }
+
+ /**********************
+ ** DoAssignIteration **
+ ***********************
+ ** This routine executes one iteration of the assignment test.
+ ** It returns the number of ticks elapsed in the iteration.
+ */
+ private static long DoAssignIteration(int[][][] arraybase, int numarrays)
+ {
+ long elapsed; /* Elapsed ticks */
+ int i;
+
+ /*
+ ** Load up the arrays with a random table.
+ */
+ LoadAssignArrayWithRand(arraybase, numarrays);
+
+ /*
+ ** Start the stopwatch
+ */
+ elapsed = ByteMark.StartStopwatch();
+
+ /*
+ ** Execute assignment algorithms
+ */
+ for (i = 0; i < numarrays; i++)
+ {
+ Assignment(arraybase[i]);
+ }
+
+ /*
+ ** Get elapsed time
+ */
+ return (ByteMark.StopStopwatch(elapsed));
+ }
+
+ /****************************
+ ** LoadAssignArrayWithRand **
+ *****************************
+ ** Load the assignment arrays with random numbers. All positive.
+ ** These numbers represent costs.
+ */
+ private static void LoadAssignArrayWithRand(int[][][] arraybase, int numarrays)
+ {
+ int i;
+
+ /*
+ ** Set up the first array. Then just copy it into the
+ ** others.
+ */
+ LoadAssign(arraybase[0]);
+ if (numarrays > 1)
+ for (i = 1; i < numarrays; i++)
+ {
+ CopyToAssign(arraybase[0], arraybase[i]);
+ }
+
+ return;
+ }
+
+ /***************
+ ** LoadAssign **
+ ****************
+ ** The array given by arraybase is loaded with positive random
+ ** numbers. Elements in the array are capped at 5,000,000.
+ */
+ private static void LoadAssign(int[][] arraybase)
+ {
+ short i, j;
+
+ /*
+ ** Reset random number generator so things repeat.
+ */
+ ByteMark.randnum(13);
+
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ arraybase[i][j] = ByteMark.abs_randwc(5000000);
+ return;
+ }
+
+ /*****************
+ ** CopyToAssign **
+ ******************
+ ** Copy the contents of one array to another. This is called by
+ ** the routine that builds the initial array, and is used to copy
+ ** the contents of the intial array into all following arrays.
+ */
+ private static void CopyToAssign(int[][] arrayfrom,
+ int[][] arrayto)
+ {
+ short i, j;
+
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ arrayto[i][j] = arrayfrom[i][j];
+
+ return;
+ }
+
+ /***************
+ ** Assignment **
+ ***************/
+ private static void Assignment(int[][] arraybase)
+ {
+ short[][] assignedtableau = new short[global.ASSIGNROWS][];
+ for (int z = 0; z < global.ASSIGNROWS; z++)
+ assignedtableau[z] = new short[global.ASSIGNCOLS];
+
+ /*
+ ** First, calculate minimum costs
+ */
+ calc_minimum_costs(arraybase);
+
+ /*
+ ** Repeat following until the number of rows selected
+ ** equals the number of rows in the tableau.
+ */
+ while (first_assignments(arraybase, assignedtableau) != global.ASSIGNROWS)
+ {
+ second_assignments(arraybase, assignedtableau);
+ }
+
+ return;
+ }
+
+ /***********************
+ ** calc_minimum_costs **
+ ************************
+ ** Revise the tableau by calculating the minimum costs on a
+ ** row and column basis. These minima are subtracted from
+ ** their rows and columns, creating a new tableau.
+ */
+ private static void calc_minimum_costs(int[][] tableau)
+ {
+ short i, j; /* Index variables */
+ int currentmin; /* Current minimum */
+ /*
+ ** Determine minimum costs on row basis. This is done by
+ ** subtracting -- on a row-per-row basis -- the minum value
+ ** for that row.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ {
+ currentmin = global.MAXPOSLONG; /* Initialize minimum */
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (tableau[i][j] < currentmin)
+ currentmin = tableau[i][j];
+
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ tableau[i][j] -= currentmin;
+ }
+
+ /*
+ ** Determine minimum cost on a column basis. This works
+ ** just as above, only now we step through the array
+ ** column-wise
+ */
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ {
+ currentmin = global.MAXPOSLONG; /* Initialize minimum */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if (tableau[i][j] < currentmin)
+ currentmin = tableau[i][j];
+
+ /*
+ ** Here, we'll take the trouble to see if the current
+ ** minimum is zero. This is likely worth it, since the
+ ** preceding loop will have created at least one zero in
+ ** each row. We can save ourselves a few iterations.
+ */
+ if (currentmin != 0)
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ tableau[i][j] -= currentmin;
+ }
+
+ return;
+ }
+
+ /**********************
+ ** first_assignments **
+ ***********************
+ ** Do first assignments.
+ ** The assignedtableau[] array holds a set of values that
+ ** indicate the assignment of a value, or its elimination.
+ ** The values are:
+ ** 0 = Item is neither assigned nor eliminated.
+ ** 1 = Item is assigned
+ ** 2 = Item is eliminated
+ ** Returns the number of selections made. If this equals
+ ** the number of rows, then an optimum has been determined.
+ */
+ private static int first_assignments(int[][] tableau, short[][] assignedtableau)
+ {
+ short i, j, k; /* Index variables */
+ short numassigns; /* # of assignments */
+ short totnumassigns; /* Total # of assignments */
+ short numzeros; /* # of zeros in row */
+ int selected = 0; /* Flag used to indicate selection */
+
+ /*
+ ** Clear the assignedtableau, setting all members to show that
+ ** no one is yet assigned, eliminated, or anything.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ assignedtableau[i][j] = 0;
+
+ totnumassigns = 0;
+ do
+ {
+ numassigns = 0;
+ /*
+ ** Step through rows. For each one that is not currently
+ ** assigned, see if the row has only one zero in it. If so,
+ ** mark that as an assigned row/col. Eliminate other zeros
+ ** in the same column.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ {
+ numzeros = 0;
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (tableau[i][j] == 0)
+ if (assignedtableau[i][j] == 0)
+ {
+ numzeros++;
+ selected = j;
+ }
+ if (numzeros == 1)
+ {
+ numassigns++;
+ totnumassigns++;
+ assignedtableau[i][selected] = 1;
+ for (k = 0; k < global.ASSIGNROWS; k++)
+ if ((k != i) &&
+ (tableau[k][selected] == 0))
+ assignedtableau[k][selected] = 2;
+ }
+ }
+ /*
+ ** Step through columns, doing same as above. Now, be careful
+ ** of items in the other rows of a selected column.
+ */
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ {
+ numzeros = 0;
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if (tableau[i][j] == 0)
+ if (assignedtableau[i][j] == 0)
+ {
+ numzeros++;
+ selected = i;
+ }
+ if (numzeros == 1)
+ {
+ numassigns++;
+ totnumassigns++;
+ assignedtableau[selected][j] = 1;
+ for (k = 0; k < global.ASSIGNCOLS; k++)
+ if ((k != j) &&
+ (tableau[selected][k] == 0))
+ assignedtableau[selected][k] = 2;
+ }
+ }
+ /*
+ ** Repeat until no more assignments to be made.
+ */
+ } while (numassigns != 0);
+
+ /*
+ ** See if we can leave at this point.
+ */
+ if (totnumassigns == global.ASSIGNROWS) return (totnumassigns);
+
+ /*
+ ** Now step through the array by row. If you find any unassigned
+ ** zeros, pick the first in the row. Eliminate all zeros from
+ ** that same row & column. This occurs if there are multiple optima...
+ ** possibly.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ {
+ selected = -1;
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if ((tableau[i][j] == 0) &&
+ (assignedtableau[i][j] == 0))
+ {
+ selected = j;
+ break;
+ }
+ if (selected != -1)
+ {
+ assignedtableau[i][selected] = 1;
+ totnumassigns++;
+ for (k = 0; k < global.ASSIGNCOLS; k++)
+ if ((k != selected) &&
+ (tableau[i][k] == 0))
+ assignedtableau[i][k] = 2;
+ for (k = 0; k < global.ASSIGNROWS; k++)
+ if ((k != i) &&
+ (tableau[k][selected] == 0))
+ assignedtableau[k][selected] = 2;
+ }
+ }
+
+ return (totnumassigns);
+ }
+
+ /***********************
+ ** second_assignments **
+ ************************
+ ** This section of the algorithm creates the revised
+ ** tableau, and is difficult to explain. I suggest you
+ ** refer to the algorithm's source, mentioned in comments
+ ** toward the beginning of the program.
+ */
+ private static void second_assignments(int[][] tableau, short[][] assignedtableau)
+ {
+ int i, j; /* Indexes */
+ short[] linesrow = new short[global.ASSIGNROWS];
+ short[] linescol = new short[global.ASSIGNCOLS];
+ int smallest; /* Holds smallest value */
+ short numassigns; /* Number of assignments */
+ short newrows; /* New rows to be considered */
+ /*
+ ** Clear the linesrow and linescol arrays.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ linesrow[i] = 0;
+ for (i = 0; i < global.ASSIGNCOLS; i++)
+ linescol[i] = 0;
+
+ /*
+ ** Scan rows, flag each row that has no assignment in it.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ {
+ numassigns = 0;
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (assignedtableau[i][j] == 1)
+ {
+ numassigns++;
+ break;
+ }
+ if (numassigns == 0) linesrow[i] = 1;
+ }
+
+ do
+ {
+ newrows = 0;
+ /*
+ ** For each row checked above, scan for any zeros. If found,
+ ** check the associated column.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ {
+ if (linesrow[i] == 1)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (tableau[i][j] == 0)
+ linescol[j] = 1;
+ }
+
+ /*
+ ** Now scan checked columns. If any contain assigned zeros, check
+ ** the associated row.
+ */
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (linescol[j] == 1)
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if ((assignedtableau[i][j] == 1) &&
+ (linesrow[i] != 1))
+ {
+ linesrow[i] = 1;
+ newrows++;
+ }
+ } while (newrows != 0);
+
+ /*
+ ** linesrow[n]==0 indicate rows covered by imaginary line
+ ** linescol[n]==1 indicate cols covered by imaginary line
+ ** For all cells not covered by imaginary lines, determine smallest
+ ** value.
+ */
+ smallest = global.MAXPOSLONG;
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if (linesrow[i] != 0)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (linescol[j] != 1)
+ if (tableau[i][j] < smallest)
+ smallest = tableau[i][j];
+
+ /*
+ ** Subtract smallest from all cells in the above set.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if (linesrow[i] != 0)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (linescol[j] != 1)
+ tableau[i][j] -= smallest;
+
+ /*
+ ** Add smallest to all cells covered by two lines.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if (linesrow[i] == 0)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (linescol[j] == 1)
+ tableau[i][j] += smallest;
+
+ return;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/assign_rect.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/assign_rect.cs
new file mode 100644
index 0000000000..43cab8a0ea
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/assign_rect.cs
@@ -0,0 +1,545 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/*************
+** DoAssign **
+**************
+** Perform an assignment algorithm.
+** The algorithm was adapted from the step by step guide found
+** in "Quantitative Decision Making for Business" (Gordon,
+** Pressman, and Cohn; Prentice-Hall)
+**
+**
+** NOTES:
+** 1. Even though the algorithm distinguishes between
+** ASSIGNROWS and ASSIGNCOLS, as though the two might
+** be different, it does presume a square matrix.
+** I.E., ASSIGNROWS and ASSIGNCOLS must be the same.
+** This makes for some algorithmically-correct but
+** probably non-optimal constructs.
+**
+*/
+
+using System;
+
+public class AssignRect : AssignStruct
+{
+ public override string Name()
+ {
+ return "ASSIGNMENT(rectangle)";
+ }
+
+ public override double Run()
+ {
+ int[][,] arraybase;
+ long accumtime;
+ double iterations;
+
+ /*
+ ** See if we need to do self adjustment code.
+ */
+ if (this.adjust == 0)
+ {
+ /*
+ ** Self-adjustment code. The system begins by working on 1
+ ** array. If it does that in no time, then two arrays
+ ** are built. This process continues until
+ ** enough arrays are built to handle the tolerance.
+ */
+ this.numarrays = 1;
+ while (true)
+ {
+ /*
+ ** Allocate space for arrays
+ */
+ arraybase = new int[this.numarrays][,];
+ for (int i = 0; i < this.numarrays; i++)
+ arraybase[i] = new int[global.ASSIGNROWS, global.ASSIGNCOLS];
+
+ /*
+ ** Do an iteration of the assignment alg. If the
+ ** elapsed time is less than or equal to the permitted
+ ** minimum, then allocate for more arrays and
+ ** try again.
+ */
+ if (DoAssignIteration(arraybase,
+ this.numarrays) > global.min_ticks)
+ break; /* We're ok...exit */
+
+ this.numarrays++;
+ }
+ }
+ else
+ { /*
+ ** Allocate space for arrays
+ */
+ arraybase = new int[this.numarrays][,];
+ for (int i = 0; i < this.numarrays; i++)
+ arraybase[i] = new int[global.ASSIGNROWS, global.ASSIGNCOLS];
+ }
+
+
+ /*
+ ** All's well if we get here. Do the tests.
+ */
+ accumtime = 0;
+ iterations = (double)0.0;
+
+ do
+ {
+ accumtime += DoAssignIteration(arraybase, this.numarrays);
+ iterations += (double)1.0;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ if (this.adjust == 0)
+ this.adjust = 1;
+
+
+
+ return (iterations * (double)this.numarrays
+ / ByteMark.TicksToFracSecs(accumtime));
+ }
+
+ /**********************
+ ** DoAssignIteration **
+ ***********************
+ ** This routine executes one iteration of the assignment test.
+ ** It returns the number of ticks elapsed in the iteration.
+ */
+ private static long DoAssignIteration(int[][,] arraybase, int numarrays)
+ {
+ long elapsed; /* Elapsed ticks */
+ int i;
+
+ /*
+ ** Load up the arrays with a random table.
+ */
+ LoadAssignArrayWithRand(arraybase, numarrays);
+
+ /*
+ ** Start the stopwatch
+ */
+ elapsed = ByteMark.StartStopwatch();
+
+ /*
+ ** Execute assignment algorithms
+ */
+ for (i = 0; i < numarrays; i++)
+ {
+ Assignment(arraybase[i]);
+ }
+
+ /*
+ ** Get elapsed time
+ */
+ return (ByteMark.StopStopwatch(elapsed));
+ }
+
+ /****************************
+ ** LoadAssignArrayWithRand **
+ *****************************
+ ** Load the assignment arrays with random numbers. All positive.
+ ** These numbers represent costs.
+ */
+ private static void LoadAssignArrayWithRand(int[][,] arraybase, int numarrays)
+ {
+ int i;
+
+ /*
+ ** Set up the first array. Then just copy it into the
+ ** others.
+ */
+ LoadAssign(arraybase[0]);
+ if (numarrays > 1)
+ for (i = 1; i < numarrays; i++)
+ {
+ CopyToAssign(arraybase[0], arraybase[i]);
+ }
+
+ return;
+ }
+
+ /***************
+ ** LoadAssign **
+ ****************
+ ** The array given by arraybase is loaded with positive random
+ ** numbers. Elements in the array are capped at 5,000,000.
+ */
+ private static void LoadAssign(int[,] arraybase)
+ {
+ short i, j;
+
+ /*
+ ** Reset random number generator so things repeat.
+ */
+ ByteMark.randnum(13);
+
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ for (j = 0; j < global.ASSIGNROWS; j++)
+ arraybase[i, j] = ByteMark.abs_randwc(5000000);
+ return;
+ }
+
+ /*****************
+ ** CopyToAssign **
+ ******************
+ ** Copy the contents of one array to another. This is called by
+ ** the routine that builds the initial array, and is used to copy
+ ** the contents of the intial array into all following arrays.
+ */
+ private static void CopyToAssign(int[,] arrayfrom,
+ int[,] arrayto)
+ {
+ short i, j;
+
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ arrayto[i, j] = arrayfrom[i, j];
+
+ return;
+ }
+
+ /***************
+ ** Assignment **
+ ***************/
+ private static void Assignment(int[,] arraybase)
+ {
+ short[,] assignedtableau = new short[global.ASSIGNROWS, global.ASSIGNCOLS];
+
+ /*
+ ** First, calculate minimum costs
+ */
+ calc_minimum_costs(arraybase);
+
+ /*
+ ** Repeat following until the number of rows selected
+ ** equals the number of rows in the tableau.
+ */
+ while (first_assignments(arraybase, assignedtableau) != global.ASSIGNROWS)
+ {
+ second_assignments(arraybase, assignedtableau);
+ }
+
+ return;
+ }
+
+ /***********************
+ ** calc_minimum_costs **
+ ************************
+ ** Revise the tableau by calculating the minimum costs on a
+ ** row and column basis. These minima are subtracted from
+ ** their rows and columns, creating a new tableau.
+ */
+ private static void calc_minimum_costs(int[,] tableau)
+ {
+ short i, j; /* Index variables */
+ int currentmin; /* Current minimum */
+ /*
+ ** Determine minimum costs on row basis. This is done by
+ ** subtracting -- on a row-per-row basis -- the minum value
+ ** for that row.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ {
+ currentmin = global.MAXPOSLONG; /* Initialize minimum */
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (tableau[i, j] < currentmin)
+ currentmin = tableau[i, j];
+
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ tableau[i, j] -= currentmin;
+ }
+
+ /*
+ ** Determine minimum cost on a column basis. This works
+ ** just as above, only now we step through the array
+ ** column-wise
+ */
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ {
+ currentmin = global.MAXPOSLONG; /* Initialize minimum */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if (tableau[i, j] < currentmin)
+ currentmin = tableau[i, j];
+
+ /*
+ ** Here, we'll take the trouble to see if the current
+ ** minimum is zero. This is likely worth it, since the
+ ** preceding loop will have created at least one zero in
+ ** each row. We can save ourselves a few iterations.
+ */
+ if (currentmin != 0)
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ tableau[i, j] -= currentmin;
+ }
+
+ return;
+ }
+
+ /**********************
+ ** first_assignments **
+ ***********************
+ ** Do first assignments.
+ ** The assignedtableau[] array holds a set of values that
+ ** indicate the assignment of a value, or its elimination.
+ ** The values are:
+ ** 0 = Item is neither assigned nor eliminated.
+ ** 1 = Item is assigned
+ ** 2 = Item is eliminated
+ ** Returns the number of selections made. If this equals
+ ** the number of rows, then an optimum has been determined.
+ */
+ private static int first_assignments(int[,] tableau, short[,] assignedtableau)
+ {
+ short i, j, k; /* Index variables */
+ short numassigns; /* # of assignments */
+ short totnumassigns; /* Total # of assignments */
+ short numzeros; /* # of zeros in row */
+ int selected = 0; /* Flag used to indicate selection */
+
+ /*
+ ** Clear the assignedtableau, setting all members to show that
+ ** no one is yet assigned, eliminated, or anything.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ assignedtableau[i, j] = 0;
+
+ totnumassigns = 0;
+ do
+ {
+ numassigns = 0;
+ /*
+ ** Step through rows. For each one that is not currently
+ ** assigned, see if the row has only one zero in it. If so,
+ ** mark that as an assigned row/col. Eliminate other zeros
+ ** in the same column.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ {
+ numzeros = 0;
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (tableau[i, j] == 0)
+ if (assignedtableau[i, j] == 0)
+ {
+ numzeros++;
+ selected = j;
+ }
+ if (numzeros == 1)
+ {
+ numassigns++;
+ totnumassigns++;
+ assignedtableau[i, selected] = 1;
+ for (k = 0; k < global.ASSIGNROWS; k++)
+ if ((k != i) &&
+ (tableau[k, selected] == 0))
+ assignedtableau[k, selected] = 2;
+ }
+ }
+ /*
+ ** Step through columns, doing same as above. Now, be careful
+ ** of items in the other rows of a selected column.
+ */
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ {
+ numzeros = 0;
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if (tableau[i, j] == 0)
+ if (assignedtableau[i, j] == 0)
+ {
+ numzeros++;
+ selected = i;
+ }
+ if (numzeros == 1)
+ {
+ numassigns++;
+ totnumassigns++;
+ assignedtableau[selected, j] = 1;
+ for (k = 0; k < global.ASSIGNCOLS; k++)
+ if ((k != j) &&
+ (tableau[selected, k] == 0))
+ assignedtableau[selected, k] = 2;
+ }
+ }
+ /*
+ ** Repeat until no more assignments to be made.
+ */
+ } while (numassigns != 0);
+
+ /*
+ ** See if we can leave at this point.
+ */
+ if (totnumassigns == global.ASSIGNROWS) return (totnumassigns);
+
+ /*
+ ** Now step through the array by row. If you find any unassigned
+ ** zeros, pick the first in the row. Eliminate all zeros from
+ ** that same row & column. This occurs if there are multiple optima...
+ ** possibly.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ {
+ selected = -1;
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if ((tableau[i, j] == 0) &&
+ (assignedtableau[i, j] == 0))
+ {
+ selected = j;
+ break;
+ }
+ if (selected != -1)
+ {
+ assignedtableau[i, selected] = 1;
+ totnumassigns++;
+ for (k = 0; k < global.ASSIGNCOLS; k++)
+ if ((k != selected) &&
+ (tableau[i, k] == 0))
+ assignedtableau[i, k] = 2;
+ for (k = 0; k < global.ASSIGNROWS; k++)
+ if ((k != i) &&
+ (tableau[k, selected] == 0))
+ assignedtableau[k, selected] = 2;
+ }
+ }
+
+ return (totnumassigns);
+ }
+
+ /***********************
+ ** second_assignments **
+ ************************
+ ** This section of the algorithm creates the revised
+ ** tableau, and is difficult to explain. I suggest you
+ ** refer to the algorithm's source, mentioned in comments
+ ** toward the beginning of the program.
+ */
+ private static void second_assignments(int[,] tableau, short[,] assignedtableau)
+ {
+ int i, j; /* Indexes */
+ short[] linesrow = new short[global.ASSIGNROWS];
+ short[] linescol = new short[global.ASSIGNCOLS];
+ int smallest; /* Holds smallest value */
+ short numassigns; /* Number of assignments */
+ short newrows; /* New rows to be considered */
+ /*
+ ** Clear the linesrow and linescol arrays.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ linesrow[i] = 0;
+ for (i = 0; i < global.ASSIGNCOLS; i++)
+ linescol[i] = 0;
+
+ /*
+ ** Scan rows, flag each row that has no assignment in it.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ {
+ numassigns = 0;
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (assignedtableau[i, j] == 1)
+ {
+ numassigns++;
+ break;
+ }
+ if (numassigns == 0) linesrow[i] = 1;
+ }
+
+ do
+ {
+ newrows = 0;
+ /*
+ ** For each row checked above, scan for any zeros. If found,
+ ** check the associated column.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ {
+ if (linesrow[i] == 1)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (tableau[i, j] == 0)
+ linescol[j] = 1;
+ }
+
+ /*
+ ** Now scan checked columns. If any contain assigned zeros, check
+ ** the associated row.
+ */
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (linescol[j] == 1)
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if ((assignedtableau[i, j] == 1) &&
+ (linesrow[i] != 1))
+ {
+ linesrow[i] = 1;
+ newrows++;
+ }
+ } while (newrows != 0);
+
+ /*
+ ** linesrow[n]==0 indicate rows covered by imaginary line
+ ** linescol[n]==1 indicate cols covered by imaginary line
+ ** For all cells not covered by imaginary lines, determine smallest
+ ** value.
+ */
+ smallest = global.MAXPOSLONG;
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if (linesrow[i] != 0)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (linescol[j] != 1)
+ if (tableau[i, j] < smallest)
+ smallest = tableau[i, j];
+
+ /*
+ ** Subtract smallest from all cells in the above set.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if (linesrow[i] != 0)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (linescol[j] != 1)
+ tableau[i, j] -= smallest;
+
+ /*
+ ** Add smallest to all cells covered by two lines.
+ */
+ for (i = 0; i < global.ASSIGNROWS; i++)
+ if (linesrow[i] == 0)
+ for (j = 0; j < global.ASSIGNCOLS; j++)
+ if (linescol[j] == 1)
+ tableau[i, j] += smallest;
+
+ return;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/bitops.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/bitops.cs
new file mode 100644
index 0000000000..d692eeea23
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/bitops.cs
@@ -0,0 +1,279 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/************************
+** BITFIELD OPERATIONS **
+*************************/
+
+/*************
+** DoBitops **
+**************
+** Perform the bit operations test portion of the CPU
+** benchmark. Returns the iterations per second.
+*/
+
+using System;
+
+public class BitOps : BitOpStruct
+{
+ public override string Name()
+ {
+ return "BITFIELD";
+ }
+
+ public override double Run()
+ {
+ int[] bitarraybase; /* Base of bitmap array */
+ int[] bitoparraybase; /* Base of bitmap operations array */
+ int nbitops = 0; /* # of bitfield operations */
+ long accumtime; /* Accumulated time in ticks */
+ double iterations; /* # of iterations */
+
+ /*
+ ** See if we need to run adjustment code.
+ */
+ if (this.adjust == 0)
+ {
+ bitarraybase = new int[this.bitfieldarraysize];
+
+ /*
+ ** Initialize bitfield operations array to [2,30] elements
+ */
+ this.bitoparraysize = 30;
+
+ while (true)
+ {
+ /*
+ ** Allocate space for operations array
+ */
+ bitoparraybase = new int[this.bitoparraysize * 2];
+
+ /*
+ ** Do an iteration of the bitmap test. If the
+ ** elapsed time is less than or equal to the permitted
+ ** minimum, then de-allocate the array, reallocate a
+ ** larger version, and try again.
+ */
+ if (DoBitfieldIteration(bitarraybase,
+ bitoparraybase,
+ this.bitoparraysize,
+ ref nbitops) > global.min_ticks)
+ break; /* We're ok...exit */
+
+ this.bitoparraysize += 100;
+ }
+ }
+ else
+ {
+ /*
+ ** Don't need to do self adjustment, just allocate
+ ** the array space.
+ */
+ bitarraybase = new int[this.bitfieldarraysize];
+ bitoparraybase = new int[this.bitoparraysize * 2];
+ }
+
+ /*
+ ** All's well if we get here. Repeatedly perform bitops until the
+ ** accumulated elapsed time is greater than # of seconds requested.
+ */
+ accumtime = 0;
+ iterations = (double)0.0;
+
+ do
+ {
+ accumtime += DoBitfieldIteration(bitarraybase,
+ bitoparraybase,
+ this.bitoparraysize,
+ ref nbitops);
+ iterations += (double)nbitops;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ /*
+ ** Clean up, calculate results, and go home.
+ ** Also, set adjustment flag to show that we don't have
+ ** to do self adjusting in the future.
+ */
+ if (this.adjust == 0)
+ this.adjust = 1;
+
+ return (iterations / ByteMark.TicksToFracSecs(accumtime));
+ }
+
+ /************************
+ ** DoBitfieldIteration **
+ *************************
+ ** Perform a single iteration of the bitfield benchmark.
+ ** Return the # of ticks accumulated by the operation.
+ */
+ private static long DoBitfieldIteration(int[] bitarraybase,
+ int[] bitoparraybase,
+ int bitoparraysize,
+ ref int nbitops)
+ {
+ int i; /* Index */
+ int bitoffset; /* Offset into bitmap */
+ long elapsed; /* Time to execute */
+
+ /*
+ ** Clear # bitops counter
+ */
+ nbitops = 0;
+
+ /*
+ ** Construct a set of bitmap offsets and run lengths.
+ ** The offset can be any random number from 0 to the
+ ** size of the bitmap (in bits). The run length can
+ ** be any random number from 1 to the number of bits
+ ** between the offset and the end of the bitmap.
+ ** Note that the bitmap has 8192 * 32 bits in it.
+ ** (262,144 bits)
+ */
+ for (i = 0; i < bitoparraysize; i++)
+ {
+ /* First item is offset */
+ bitoparraybase[i + i] = bitoffset = ByteMark.abs_randwc(262140);
+
+ /* Next item is run length */
+ nbitops += bitoparraybase[i + i + 1] = ByteMark.abs_randwc(262140 - bitoffset);
+ }
+
+ /*
+ ** Array of offset and lengths built...do an iteration of
+ ** the test.
+ ** Start the stopwatch.
+ */
+ elapsed = ByteMark.StartStopwatch();
+
+ /*
+ ** Loop through array off offset/run length pairs.
+ ** Execute operation based on modulus of index.
+ */
+ for (i = 0; i < bitoparraysize; i++)
+ {
+ switch (i % 3)
+ {
+ case 0: /* Set run of bits */
+ ToggleBitRun(bitarraybase,
+ bitoparraybase[i + i],
+ bitoparraybase[i + i + 1],
+ 1);
+ break;
+
+ case 1: /* Clear run of bits */
+ ToggleBitRun(bitarraybase,
+ bitoparraybase[i + i],
+ bitoparraybase[i + i + 1],
+ 0);
+ break;
+
+ case 2: /* Complement run of bits */
+ FlipBitRun(bitarraybase,
+ bitoparraybase[i + i],
+ bitoparraybase[i + i + 1]);
+ break;
+ }
+ }
+
+ /*
+ ** Return elapsed time
+ */
+ return (ByteMark.StopStopwatch(elapsed));
+ }
+
+
+ /*****************************
+ ** ToggleBitRun *
+ ******************************
+ ** Set or clear a run of nbits starting at
+ ** bit_addr in bitmap.
+ */
+ private static void ToggleBitRun(int[] bitmap, /* Bitmap */
+ int bit_addr, /* Address of bits to set */
+ int nbits, /* # of bits to set/clr */
+ int val) /* 1 or 0 */
+ {
+ int bindex; /* Index into array */
+ int bitnumb; /* Bit number */
+
+ while (nbits-- > 0)
+ {
+#if LONG64
+ bindex=bit_addr>>>6; /* Index is number /64 */
+ bindex=bit_addr % 64; /* Bit number in word */
+#else
+ bindex = (int)((uint)bit_addr) >> 5; /* Index is number /32 */
+ bitnumb = bit_addr % 32; /* bit number in word */
+#endif
+
+ if (val != 0)
+ bitmap[bindex] |= (1 << bitnumb);
+ else
+ bitmap[bindex] &= ~(1 << bitnumb);
+ bit_addr++;
+ }
+ return;
+ }
+
+ /***************
+ ** FlipBitRun **
+ ****************
+ ** Complements a run of bits.
+ */
+ private static void FlipBitRun(int[] bitmap, /* Bit map */
+ int bit_addr, /* Bit address */
+ int nbits) /* # of bits to flip */
+ {
+ int bindex; /* Index into array */
+ int bitnumb; /* Bit number */
+
+ while (nbits-- > 0)
+ {
+#if LONG64
+ bindex=bit_addr>>6; /* Index is number /64 */
+ bitnumb=bit_addr % 32; /* Bit number in longword */
+#else
+ bindex = bit_addr >> 5; /* Index is number /32 */
+ bitnumb = bit_addr % 32; /* Bit number in longword */
+#endif
+ bitmap[bindex] ^= (1 << bitnumb);
+ bit_addr++;
+ }
+
+ return;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/assignjagged.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/assignjagged.dat
new file mode 100644
index 0000000000..52537e4558
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/assignjagged.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DOASSIGNJAGGED=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/assignrect.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/assignrect.dat
new file mode 100644
index 0000000000..67ef988420
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/assignrect.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DOASSIGNRECT=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/bitfield.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/bitfield.dat
new file mode 100644
index 0000000000..1577f86bfb
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/bitfield.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DOBITFIELD=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/emfclass.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/emfclass.dat
new file mode 100644
index 0000000000..421f4a44a5
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/emfclass.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DOEMFCLASS=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/emfstruct.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/emfstruct.dat
new file mode 100644
index 0000000000..aca1caf27d
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/emfstruct.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DOEMFSTRUCT=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/four.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/four.dat
new file mode 100644
index 0000000000..6c7a13376b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/four.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DOFOUR=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/huff.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/huff.dat
new file mode 100644
index 0000000000..d498cc008f
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/huff.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DOHUFF=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/idea.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/idea.dat
new file mode 100644
index 0000000000..f19f9ee28b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/idea.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DOIDEA=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/lu.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/lu.dat
new file mode 100644
index 0000000000..73d3b730c5
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/lu.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DOLU=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/nnetjagged.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/nnetjagged.dat
new file mode 100644
index 0000000000..d7c2baab28
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/nnetjagged.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DONNETJAGGED=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/nnetrect.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/nnetrect.dat
new file mode 100644
index 0000000000..5c74684b23
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/nnetrect.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DONNETRECT=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/numsortjagged.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/numsortjagged.dat
new file mode 100644
index 0000000000..3ce1748daf
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/numsortjagged.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DONUMSORTJAGGED=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/numsortrect.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/numsortrect.dat
new file mode 100644
index 0000000000..035f90c9f1
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/numsortrect.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DONUMSORTRECT=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/stringsort.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/stringsort.dat
new file mode 100644
index 0000000000..74b0a2fc2f
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/commands/stringsort.dat
@@ -0,0 +1,2 @@
+CUSTOMRUN=T
+DOSTRINGSORT=T
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/emfloat.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/emfloat.cs
new file mode 100644
index 0000000000..e61b9380ab
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/emfloat.cs
@@ -0,0 +1,1577 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+using System;
+
+/*
+** DEFINES
+*/
+public class EMFloat : EmFloatStruct
+{
+ public override string Name()
+ {
+ return "FP EMULATION(struct)";
+ }
+
+ private const int MAX_EXP = 32767;
+ private const int MIN_EXP = (-32767);
+
+ private enum IFPF : byte
+ {
+ IFPF_IS_ZERO = 0,
+ IFPF_IS_SUBNORMAL = 1,
+ IFPF_IS_NORMAL = 2,
+ IFPF_IS_INFINITY = 3,
+ IFPF_IS_NAN = 4,
+ IFPF_TYPE_COUNT = 5,
+ };
+
+ private enum STATE
+ {
+ ZERO_ZERO = 0,
+ ZERO_SUBNORMAL = 1,
+ ZERO_NORMAL = 2,
+ ZERO_INFINITY = 3,
+ ZERO_NAN = 4,
+
+ SUBNORMAL_ZERO = 5,
+ SUBNORMAL_SUBNORMAL = 6,
+ SUBNORMAL_NORMAL = 7,
+ SUBNORMAL_INFINITY = 8,
+ SUBNORMAL_NAN = 9,
+
+ NORMAL_ZERO = 10,
+ NORMAL_SUBNORMAL = 11,
+ NORMAL_NORMAL = 12,
+ NORMAL_INFINITY = 13,
+ NORMAL_NAN = 14,
+
+ INFINITY_ZERO = 15,
+ INFINITY_SUBNORMAL = 16,
+ INFINITY_NORMAL = 17,
+ INFINITY_INFINITY = 18,
+ INFINITY_NAN = 19,
+
+ NAN_ZERO = 20,
+ NAN_SUBNORMAL = 21,
+ NAN_NORMAL = 22,
+ NAN_INFINITY = 23,
+ NAN_NAN = 24,
+ };
+
+ private enum OPERAND
+ {
+ OPERAND_ZERO = 0,
+ OPERAND_SUBNORMAL = 1,
+ OPERAND_NORMAL = 2,
+ OPERAND_INFINITY = 3,
+ OPERAND_NAN = 4,
+ };
+
+ /*
+ ** Following was already defined in NMGLOBAL.H
+ **
+ */
+ private const int INTERNAL_FPF_PRECISION = 4;
+
+ /*
+ ** TYPEDEFS
+ */
+
+ private struct InternalFPF
+ {
+ public InternalFPF(int len)
+ {
+ type = IFPF.IFPF_IS_ZERO; sign = (byte)0;
+ exp = (short)0; mantissa = new char[len];
+ }
+
+ public IFPF type; /* Indicates, NORMAL, SUBNORMAL, etc. */
+ public byte sign; /* Mantissa sign */
+ public short exp; /* Signed exponent...no bias */
+ public char[] mantissa; // [INTERNAL_FPF_PRECISION]
+ };
+
+
+ /*
+ ** emfloat.c
+ ** Source for emulated floating-point routines.
+ ** BYTEmark (tm)
+ ** BYTE's Native Mode Benchmarks
+ ** Rick Grehan, BYTE Magazine.
+ **
+ ** Created:
+ ** Last update: 3/95
+ **
+ ** DISCLAIMER
+ ** The source, executable, and documentation files that comprise
+ ** the BYTEmark benchmarks are made available on an "as is" basis.
+ ** This means that we at BYTE Magazine have made every reasonable
+ ** effort to verify that the there are no errors in the source and
+ ** executable code. We cannot, however, guarantee that the programs
+ ** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+ ** no claims in regard to the fitness of the source code, executable
+ ** code, and documentation of the BYTEmark.
+ ** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+ ** of McGraw-Hill cannot be held responsible for any damages resulting
+ ** from the use of this code or the results obtained from using
+ ** this code.
+ */
+
+ /*
+ ** Floating-point emulator.
+ ** These routines are only "sort of" IEEE-compliant. All work is
+ ** done using an internal representation. Also, the routines do
+ ** not check for many of the exceptions that might occur.
+ ** Still, the external formats produced are IEEE-compatible,
+ ** with the restriction that they presume a low-endian machine
+ ** (though the endianism will not effect the performance).
+ **
+ ** Some code here was based on work done by Steve Snelgrove of
+ ** Orem, UT. Other code comes from routines presented in
+ ** the long-ago book: "Microprocessor Programming for
+ ** Computer Hobbyists" by Neill Graham.
+ */
+
+ /*****************************
+ ** FLOATING-POINT EMULATION **
+ *****************************/
+
+ /**************
+ ** DoEmFloat **
+ ***************
+ ** Perform the floating-point emulation routines portion of the
+ ** CPU benchmark. Returns the operations per second.
+ */
+ public override double Run()
+ {
+ InternalFPF[] abase; /* Base of A array */
+ InternalFPF[] bbase; /* Base of B array */
+ InternalFPF[] cbase; /* Base of C array */
+ long accumtime; /* Accumulated time in ticks */
+ double iterations; /* # of iterations */
+ long tickcount; /* # of ticks */
+ int loops; /* # of loops */
+
+ /*
+ ** Test the emulation routines.
+ */
+
+ abase = new InternalFPF[this.arraysize];
+ bbase = new InternalFPF[this.arraysize];
+ cbase = new InternalFPF[this.arraysize];
+
+
+ for (int i = 0; i < this.arraysize; i++)
+ {
+ abase[i] = new InternalFPF(INTERNAL_FPF_PRECISION);
+ bbase[i] = new InternalFPF(INTERNAL_FPF_PRECISION);
+ cbase[i] = new InternalFPF(INTERNAL_FPF_PRECISION);
+ }
+
+
+ /*
+ for (int i = 0; i < this.arraysize; i++)
+ {
+ abase[i].type = IFPF.IFPF_IS_ZERO;
+ abase[i].sign = (byte)0;
+ abase[i].exp = (short)0;
+ abase[i].mantissa = new char[INTERNAL_FPF_PRECISION];
+
+ bbase[i].type = IFPF.IFPF_IS_ZERO;
+ bbase[i].sign = (byte)0;
+ bbase[i].exp = (short)0;
+ bbase[i].mantissa = new char[INTERNAL_FPF_PRECISION];
+
+ cbase[i].type = IFPF.IFPF_IS_ZERO;
+ cbase[i].sign = (byte)0;
+ cbase[i].exp = (short)0;
+ cbase[i].mantissa = new char[INTERNAL_FPF_PRECISION];
+ }
+ */
+
+
+ /*
+ ** Set up the arrays
+ */
+ SetupCPUEmFloatArrays(abase, bbase, cbase, this.arraysize);
+
+ /*
+ ** See if we need to do self-adjusting code.
+ */
+ if (this.adjust == 0)
+ {
+ this.loops = 0;
+
+ /*
+ ** Do an iteration of the tests. If the elapsed time is
+ ** less than minimum, increase the loop count and try
+ ** again.
+ */
+ for (loops = 1; loops < global.CPUEMFLOATLOOPMAX; loops += loops)
+ {
+ tickcount = DoEmFloatIteration(abase, bbase, cbase,
+ this.arraysize,
+ loops);
+ if (tickcount > global.min_ticks)
+ {
+ this.loops = loops;
+ break;
+ }
+ }
+ }
+
+ /*
+ ** Verify that selft adjustment code worked.
+ */
+ if (this.loops == 0)
+ {
+ throw new Exception("CPU:EMFPU -- CMPUEMFLOATLOOPMAX limit hit\n");
+ }
+
+ /*
+ ** All's well if we get here. Repeatedly perform floating
+ ** tests until the accumulated time is greater than the
+ ** # of seconds requested.
+ ** Each iteration performs arraysize * 3 operations.
+ */
+ accumtime = 0L;
+ iterations = (double)0.0;
+ do
+ {
+ accumtime += DoEmFloatIteration(abase, bbase, cbase,
+ this.arraysize,
+ this.loops);
+ iterations += (double)1.0;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ /*
+ ** Clean up, calculate results, and go home.
+ ** Also, indicate that adjustment is done.
+ */
+
+ if (this.adjust == 0)
+ this.adjust = 1;
+ double emflops = (iterations * (double)this.loops) /
+ (double)ByteMark.TicksToFracSecs(accumtime);
+
+ return (emflops);
+ }
+
+
+
+
+
+ /**************************
+ ** SetupCPUEmFloatArrays **
+ ***************************
+ ** Set up the arrays that will be used in the emulated
+ ** floating-point tests.
+ ** This is done by loading abase and bbase elements with
+ ** random numbers. We use our long-to-floating point
+ ** routine to set them up.
+ ** NOTE: We really don't need the pointer to cbase...cbase
+ ** is overwritten in the benchmark.
+ */
+ private static
+ void SetupCPUEmFloatArrays(InternalFPF[] abase,
+ InternalFPF[] bbase,
+ InternalFPF[] cbase,
+ int arraysize)
+ {
+ int i;
+ InternalFPF locFPF1, locFPF2;
+ locFPF1 = new InternalFPF(INTERNAL_FPF_PRECISION);
+ locFPF2 = new InternalFPF(INTERNAL_FPF_PRECISION);
+
+ for (i = 0; i < arraysize; i++)
+ {
+ LongToInternalFPF(ByteMark.randwc(50000), ref locFPF1);
+ LongToInternalFPF(ByteMark.randwc(50000) + 1, ref locFPF2);
+ DivideInternalFPF(ref locFPF1, ref locFPF2, ref abase[i]);
+ LongToInternalFPF(ByteMark.randwc(50000) + 1, ref locFPF2);
+ DivideInternalFPF(ref locFPF1, ref locFPF2, ref bbase[i]);
+ }
+ return;
+ }
+
+ /***********************
+ ** DoEmFloatIteration **
+ ************************
+ ** Perform an iteration of the emulated floating-point
+ ** benchmark. Note that "an iteration" can involve multiple
+ ** loops through the benchmark.
+ */
+ private static
+ long DoEmFloatIteration(InternalFPF[] abase,
+ InternalFPF[] bbase,
+ InternalFPF[] cbase,
+ int arraysize, int loops)
+ {
+ long elapsed; /* For the stopwatch */
+ byte[] jtable = new byte[] { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3 };
+ int i;
+
+ /*
+ ** Begin timing
+ */
+ elapsed = ByteMark.StartStopwatch();
+
+ /*
+ ** Each pass through the array performs operations in
+ ** the followingratios:
+ ** 4 adds, 4 subtracts, 5 multiplies, 3 divides
+ ** (adds and subtracts being nearly the same operation)
+ */
+ while (loops-- > 0)
+ {
+ for (i = 0; i < arraysize; i++)
+ switch (jtable[i % 16])
+ {
+ case 0: /* Add */
+ AddSubInternalFPF(0, ref abase[i],
+ ref bbase[i],
+ ref cbase[i]);
+ break;
+ case 1: /* Subtract */
+ AddSubInternalFPF(1, ref abase[i],
+ ref bbase[i],
+ ref cbase[i]);
+ break;
+ case 2: /* Multiply */
+ MultiplyInternalFPF(ref abase[i],
+ ref bbase[i],
+ ref cbase[i]);
+ break;
+ case 3: /* Divide */
+ DivideInternalFPF(ref abase[i],
+ ref bbase[i],
+ ref cbase[i]);
+ break;
+ }
+ }
+
+ return (ByteMark.StopStopwatch(elapsed));
+ }
+
+ /***********************
+ ** SetInternalFPFZero **
+ ************************
+ ** Set an internal floating-point-format number to zero.
+ ** sign determines the sign of the zero.
+ */
+ private static void SetInternalFPFZero(ref InternalFPF dest,
+ byte sign)
+ {
+ int i; /* Index */
+
+ dest.type = IFPF.IFPF_IS_ZERO;
+ dest.sign = sign;
+ dest.exp = MIN_EXP;
+
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ dest.mantissa[i] = (char)0;
+ return;
+ }
+
+ /***************************
+ ** SetInternalFPFInfinity **
+ ****************************
+ ** Set an internal floating-point-format number to infinity.
+ ** This can happen if the exponent exceeds MAX_EXP.
+ ** As above, sign picks the sign of infinity.
+ */
+ private static void SetInternalFPFInfinity(ref InternalFPF dest,
+ byte sign)
+ {
+ int i; /* Index */
+
+ dest.type = IFPF.IFPF_IS_INFINITY;
+ dest.sign = sign;
+ dest.exp = MIN_EXP;
+
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ dest.mantissa[i] = (char)0;
+ return;
+ }
+
+ /**********************
+ ** SetInternalFPFNaN **
+ ***********************
+ ** Set an internal floating-point-format number to Nan
+ ** (not a number). Note that we "emulate" an 80x87 as far
+ ** as the mantissa bits go.
+ */
+ private static void SetInternalFPFNaN(ref InternalFPF dest)
+ {
+ int i; /* Index */
+
+ dest.type = IFPF.IFPF_IS_NAN;
+ dest.exp = MAX_EXP;
+ dest.sign = 1;
+
+ dest.mantissa[0] = (char)0x4000;
+ for (i = 1; i < INTERNAL_FPF_PRECISION; i++)
+ dest.mantissa[i] = (char)0;
+
+ return;
+ }
+
+ /*******************
+ ** IsMantissaZero **
+ ********************
+ ** Pass this routine a pointer to an internal floating point format
+ ** number's mantissa. It checks for an all-zero mantissa.
+ ** Returns 0 if it is NOT all zeros, !=0 otherwise.
+ */
+ private static bool IsMantissaZero(char[] mant)
+ {
+ int i; /* Index */
+ int n; /* Return value */
+
+ n = 0;
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ n |= mant[i];
+
+ return (n == 0);
+ }
+
+ /**************
+ ** Add16Bits **
+ ***************
+ ** Add b, c, and carry. Retult in a. New carry in carry.
+ */
+ private static void Add16Bits(ref char carry,
+ out char a,
+ char b,
+ char c)
+ {
+ int accum; /* Accumulator */
+
+ /*
+ ** Do the work in the 32-bit accumulator so we can return
+ ** the carry.
+ */
+ accum = b;
+ accum += c;
+ accum += carry;
+ carry = (char)(((accum & 0x00010000) != 0) ? 1 : 0); /* New carry */
+ a = (char)(accum & 0xFFFF); /* Result is lo 16 bits */
+ return;
+ }
+
+ /**************
+ ** Sub16Bits **
+ ***************
+ ** Additive inverse of above.
+ */
+ private static void Sub16Bits(ref char borrow,
+ out char a,
+ char b,
+ char c)
+ {
+ int accum; /* Accumulator */
+
+ accum = b;
+ accum -= c;
+ accum -= borrow;
+ borrow = (char)(((accum & 0x00010000) != 0) ? 1 : 0); /* New borrow */
+ a = (char)(accum & 0xFFFF);
+ return;
+ }
+
+ /*******************
+ ** ShiftMantLeft1 **
+ ********************
+ ** Shift a vector of 16-bit numbers left 1 bit. Also provides
+ ** a carry bit, which is shifted in at the beginning, and
+ ** shifted out at the end.
+ */
+ private static void ShiftMantLeft1(ref char carry,
+ char[] mantissa)
+ {
+ int i; /* Index */
+ int new_carry;
+ char accum; /* Temporary holding placed */
+
+ for (i = INTERNAL_FPF_PRECISION - 1; i >= 0; i--)
+ {
+ accum = mantissa[i];
+ new_carry = accum & 0x8000; /* Get new carry */
+ accum = unchecked((char)(accum << 1)); /* Do the shift */
+ if (carry != 0)
+ accum |= (char)1; /* Insert previous carry */
+ carry = (char)new_carry;
+ mantissa[i] = accum; /* Return shifted value */
+ }
+ return;
+ }
+
+ /********************
+ ** ShiftMantRight1 **
+ *********************
+ ** Shift a mantissa right by 1 bit. Provides carry, as
+ ** above
+ */
+ private static void ShiftMantRight1(ref char carry,
+ char[] mantissa)
+ {
+ int i; /* Index */
+ int new_carry;
+ char accum;
+
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ {
+ accum = mantissa[i];
+ new_carry = accum & 1; /* Get new carry */
+ accum = (char)(accum >> 1);
+ if (carry != 0)
+ accum |= (char)0x8000;
+ carry = (char)new_carry;
+ mantissa[i] = accum;
+ }
+ return;
+ }
+
+
+ /*****************************
+ ** StickyShiftMantRight **
+ ******************************
+ ** This is a shift right of the mantissa with a "sticky bit".
+ ** I.E., if a carry of 1 is shifted out of the least significant
+ ** bit, the least significant bit is set to 1.
+ */
+ private static void StickyShiftRightMant(ref InternalFPF ptr,
+ int amount)
+ {
+ int i; /* Index */
+ char carry; /* Self-explanatory */
+
+ if (ptr.type != IFPF.IFPF_IS_ZERO) /* Don't bother shifting a zero */
+ {
+ /*
+ ** If the amount of shifting will shift everyting
+ ** out of existence, then just clear the whole mantissa
+ ** and set the lowmost bit to 1.
+ */
+ if (amount >= INTERNAL_FPF_PRECISION * 16)
+ {
+ for (i = 0; i < INTERNAL_FPF_PRECISION - 1; i++)
+ ptr.mantissa[i] = (char)0;
+ ptr.mantissa[INTERNAL_FPF_PRECISION - 1] = (char)1;
+ }
+ else
+ for (i = 0; i < amount; i++)
+ {
+ carry = (char)0;
+ ShiftMantRight1(ref carry, ptr.mantissa);
+ if (carry != 0)
+ ptr.mantissa[INTERNAL_FPF_PRECISION - 1] |= (char)1;
+ }
+ }
+ return;
+ }
+
+
+ /**************************************************
+ ** POST ARITHMETIC PROCESSING **
+ ** (NORMALIZE, ROUND, OVERFLOW, AND UNDERFLOW) **
+ **************************************************/
+
+ /**************
+ ** normalize **
+ ***************
+ ** Normalize an internal-representation number. Normalization
+ ** discards empty most-significant bits.
+ */
+ private static void normalize(ref InternalFPF ptr)
+ {
+ char carry;
+
+ /*
+ ** As long as there's a highmost 0 bit, shift the significand
+ ** left 1 bit. Each time you do this, though, you've
+ ** gotta decrement the exponent.
+ */
+ while ((ptr.mantissa[0] & 0x8000) == 0)
+ {
+ carry = (char)0;
+ ShiftMantLeft1(ref carry, ptr.mantissa);
+ ptr.exp--;
+ }
+ return;
+ }
+
+ /****************
+ ** denormalize **
+ *****************
+ ** Denormalize an internal-representation number. This means
+ ** shifting it right until its exponent is equivalent to
+ ** minimum_exponent. (You have to do this often in order
+ ** to perform additions and subtractions).
+ */
+ private static void denormalize(ref InternalFPF ptr,
+ int minimum_exponent)
+ {
+ int exponent_difference;
+
+ if (IsMantissaZero(ptr.mantissa))
+ {
+ throw new Exception("Error: zero significand in denormalize");
+ }
+
+ exponent_difference = ptr.exp - minimum_exponent;
+ if (exponent_difference < 0)
+ {
+ /*
+ ** The number is subnormal
+ */
+ exponent_difference = -exponent_difference;
+ if (exponent_difference >= (INTERNAL_FPF_PRECISION * 16))
+ {
+ /* Underflow */
+ SetInternalFPFZero(ref ptr, ptr.sign);
+ }
+ else
+ {
+ ptr.exp += (short)exponent_difference;
+ StickyShiftRightMant(ref ptr, exponent_difference);
+ }
+ }
+ return;
+ }
+
+
+ /*********************
+ ** RoundInternalFPF **
+ **********************
+ ** Round an internal-representation number.
+ ** The kind of rounding we do here is simplest...referred to as
+ ** "chop". "Extraneous" rightmost bits are simply hacked off.
+ */
+ private static
+ void RoundInternalFPF(ref InternalFPF ptr)
+ {
+ /* int i; */
+
+ if (ptr.type == IFPF.IFPF_IS_NORMAL ||
+ ptr.type == IFPF.IFPF_IS_SUBNORMAL)
+ {
+ denormalize(ref ptr, MIN_EXP);
+ if (ptr.type != IFPF.IFPF_IS_ZERO)
+ {
+ /* clear the extraneous bits */
+ ptr.mantissa[3] &= (char)0xfff8;
+ /* for (i=4; i<INTERNAL_FPF_PRECISION; i++)
+ {
+ ptr->mantissa[i] = 0;
+ }
+ */
+ /*
+ ** Check for overflow
+ */
+ if (ptr.exp > MAX_EXP)
+ {
+ SetInternalFPFInfinity(ref ptr, ptr.sign);
+ }
+ }
+ }
+ return;
+ }
+
+ /*******************************************************
+ ** ARITHMETIC OPERATIONS ON INTERNAL REPRESENTATION **
+ *******************************************************/
+
+ private static void memmove(ref InternalFPF dest, ref InternalFPF src)
+ {
+ dest.type = src.type;
+ dest.sign = src.sign;
+ dest.exp = src.exp;
+ for (int i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ {
+ dest.mantissa[i] = src.mantissa[i];
+ }
+ /* This implementation only loses about .1 on the rating. Surprising.
+ dest = src;
+ dest.mantissa = new char[INTERNAL_FPF_PRECISION];
+ for (int i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ {
+ dest.mantissa[i] = src.mantissa[i];
+ }
+ */
+ }
+
+ /***************
+ ** choose_nan **
+ ****************
+ ** Called by routines that are forced to perform math on
+ ** a pair of NaN's. This routine "selects" which NaN is
+ ** to be returned.
+ */
+ private static void choose_nan(ref InternalFPF x,
+ ref InternalFPF y,
+ ref InternalFPF z,
+ int intel_flag)
+ {
+ int i;
+
+ /*
+ ** Compare the two mantissas,
+ ** return the larger. Note that we will be emulating
+ ** an 80387 in this operation.
+ */
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ {
+ if (x.mantissa[i] > y.mantissa[i])
+ {
+ memmove(ref z, ref x);
+ return;
+ }
+ if (x.mantissa[i] < y.mantissa[i])
+ {
+ memmove(ref z, ref y);
+ return;
+ }
+ }
+
+ /*
+ ** They are equal
+ */
+ if (intel_flag == 0)
+ /* if the operation is addition */
+ memmove(ref z, ref x);
+ else
+ /* if the operation is multiplication */
+ memmove(ref z, ref y);
+ return;
+ }
+
+
+ /**********************
+ ** AddSubInternalFPF **
+ ***********************
+ ** Adding or subtracting internal-representation numbers.
+ ** Internal-representation numbers pointed to by x and y are
+ ** added/subtracted and the result returned in z.
+ */
+ private static void AddSubInternalFPF(byte operation,
+ ref InternalFPF x,
+ ref InternalFPF y,
+ ref InternalFPF z)
+ {
+ int exponent_difference;
+ char borrow;
+ char carry;
+ int i;
+ InternalFPF locx, locy; /* Needed since we alter them */
+ /*
+ ** Following big switch statement handles the
+ ** various combinations of operand types.
+ */
+ int count = (int)IFPF.IFPF_TYPE_COUNT;
+ switch ((STATE)(((int)x.type * count) + (int)y.type))
+ {
+ case STATE.ZERO_ZERO:
+ memmove(ref z, ref x);
+ if ((x.sign ^ y.sign ^ operation) != 0)
+ {
+ z.sign = 0; /* positive */
+ }
+ break;
+
+ case STATE.NAN_ZERO:
+ case STATE.NAN_SUBNORMAL:
+ case STATE.NAN_NORMAL:
+ case STATE.NAN_INFINITY:
+ case STATE.SUBNORMAL_ZERO:
+ case STATE.NORMAL_ZERO:
+ case STATE.INFINITY_ZERO:
+ case STATE.INFINITY_SUBNORMAL:
+ case STATE.INFINITY_NORMAL:
+ memmove(ref z, ref x);
+ break;
+
+
+ case STATE.ZERO_NAN:
+ case STATE.SUBNORMAL_NAN:
+ case STATE.NORMAL_NAN:
+ case STATE.INFINITY_NAN:
+ memmove(ref z, ref y);
+ break;
+
+ case STATE.ZERO_SUBNORMAL:
+ case STATE.ZERO_NORMAL:
+ case STATE.ZERO_INFINITY:
+ case STATE.SUBNORMAL_INFINITY:
+ case STATE.NORMAL_INFINITY:
+ memmove(ref z, ref x);
+ z.sign ^= operation;
+ break;
+
+ case STATE.SUBNORMAL_SUBNORMAL:
+ case STATE.SUBNORMAL_NORMAL:
+ case STATE.NORMAL_SUBNORMAL:
+ case STATE.NORMAL_NORMAL:
+ /*
+ ** Copy x and y to locals, since we may have
+ ** to alter them.
+ */
+ locx = new InternalFPF(INTERNAL_FPF_PRECISION);
+ locy = new InternalFPF(INTERNAL_FPF_PRECISION);
+ memmove(ref locx, ref x);
+ memmove(ref locy, ref y);
+
+ /* compute sum/difference */
+ exponent_difference = locx.exp - locy.exp;
+ if (exponent_difference == 0)
+ {
+ /*
+ ** locx.exp == locy.exp
+ ** so, no shifting required
+ */
+ if (locx.type == IFPF.IFPF_IS_SUBNORMAL ||
+ locy.type == IFPF.IFPF_IS_SUBNORMAL)
+ z.type = IFPF.IFPF_IS_SUBNORMAL;
+ else
+ z.type = IFPF.IFPF_IS_NORMAL;
+
+ /*
+ ** Assume that locx.mantissa > locy.mantissa
+ */
+ z.sign = locx.sign;
+ z.exp = locx.exp;
+ }
+ else
+ if (exponent_difference > 0)
+ {
+ /*
+ ** locx.exp > locy.exp
+ */
+ StickyShiftRightMant(ref locy,
+ exponent_difference);
+ z.type = locx.type;
+ z.sign = locx.sign;
+ z.exp = locx.exp;
+ }
+ else /* if (exponent_difference < 0) */
+ {
+ /*
+ ** locx.exp < locy.exp
+ */
+ StickyShiftRightMant(ref locx,
+ -exponent_difference);
+ z.type = locy.type;
+ z.sign = (byte)(locy.sign ^ operation);
+ z.exp = locy.exp;
+ }
+
+ if ((locx.sign ^ locy.sign ^ operation) != 0)
+ {
+ /*
+ ** Signs are different, subtract mantissas
+ */
+ borrow = (char)0;
+ for (i = (INTERNAL_FPF_PRECISION - 1); i >= 0; i--)
+ Sub16Bits(ref borrow,
+ out z.mantissa[i],
+ locx.mantissa[i],
+ locy.mantissa[i]);
+
+ if (borrow != 0)
+ {
+ /* The y->mantissa was larger than the
+ ** x->mantissa leaving a negative
+ ** result. Change the result back to
+ ** an unsigned number and flip the
+ ** sign flag.
+ */
+ z.sign = (byte)(locy.sign ^ operation);
+ borrow = (char)0;
+ for (i = (INTERNAL_FPF_PRECISION - 1); i >= 0; i--)
+ {
+ Sub16Bits(ref borrow,
+ out z.mantissa[i],
+ (char)0,
+ z.mantissa[i]);
+ }
+ }
+ else
+ {
+ /* The assumption made above
+ ** (i.e. x->mantissa >= y->mantissa)
+ ** was correct. Therefore, do nothing.
+ ** z->sign = x->sign;
+ */
+ }
+
+ if (IsMantissaZero(z.mantissa))
+ {
+ z.type = IFPF.IFPF_IS_ZERO;
+ z.sign = 0; /* positive */
+ }
+ else
+ if (locx.type == IFPF.IFPF_IS_NORMAL ||
+ locy.type == IFPF.IFPF_IS_NORMAL)
+ {
+ normalize(ref z);
+ }
+ }
+ else
+ {
+ /* signs are the same, add mantissas */
+ carry = (char)0;
+ for (i = (INTERNAL_FPF_PRECISION - 1); i >= 0; i--)
+ {
+ Add16Bits(ref carry,
+ out z.mantissa[i],
+ locx.mantissa[i],
+ locy.mantissa[i]);
+ }
+
+ if (carry != 0)
+ {
+ z.exp++;
+ carry = (char)0;
+ ShiftMantRight1(ref carry, z.mantissa);
+ z.mantissa[0] |= (char)0x8000;
+ z.type = IFPF.IFPF_IS_NORMAL;
+ }
+ else
+ if ((z.mantissa[0] & 0x8000) != 0)
+ z.type = IFPF.IFPF_IS_NORMAL;
+ }
+ break;
+
+ case STATE.INFINITY_INFINITY:
+ SetInternalFPFNaN(ref z);
+ break;
+
+ case STATE.NAN_NAN:
+ choose_nan(ref x, ref y, ref z, 1);
+ break;
+ }
+
+ /*
+ ** All the math is done; time to round.
+ */
+ RoundInternalFPF(ref z);
+ return;
+ }
+
+
+ /************************
+ ** MultiplyInternalFPF **
+ *************************
+ ** Two internal-representation numbers x and y are multiplied; the
+ ** result is returned in z.
+ */
+ private static void MultiplyInternalFPF(
+ ref InternalFPF x,
+ ref InternalFPF y,
+ ref InternalFPF z)
+ {
+ int i;
+ int j;
+ char carry;
+ char[] extra_bits = new char[INTERNAL_FPF_PRECISION];
+ InternalFPF locy; /* Needed since this will be altered */
+ /*
+ ** As in the preceding function, this large switch
+ ** statement selects among the many combinations
+ ** of operands.
+ */
+ int count = (int)IFPF.IFPF_TYPE_COUNT;
+ switch ((STATE)(((int)x.type * count) + (int)y.type))
+ {
+ case STATE.INFINITY_SUBNORMAL:
+ case STATE.INFINITY_NORMAL:
+ case STATE.INFINITY_INFINITY:
+ case STATE.ZERO_ZERO:
+ case STATE.ZERO_SUBNORMAL:
+ case STATE.ZERO_NORMAL:
+ memmove(ref z, ref x);
+ z.sign ^= y.sign;
+ break;
+
+ case STATE.SUBNORMAL_INFINITY:
+ case STATE.NORMAL_INFINITY:
+ case STATE.SUBNORMAL_ZERO:
+ case STATE.NORMAL_ZERO:
+ memmove(ref z, ref y);
+ z.sign ^= x.sign;
+ break;
+
+ case STATE.ZERO_INFINITY:
+ case STATE.INFINITY_ZERO:
+ SetInternalFPFNaN(ref z);
+ break;
+
+ case STATE.NAN_ZERO:
+ case STATE.NAN_SUBNORMAL:
+ case STATE.NAN_NORMAL:
+ case STATE.NAN_INFINITY:
+ memmove(ref z, ref x);
+ break;
+
+ case STATE.ZERO_NAN:
+ case STATE.SUBNORMAL_NAN:
+ case STATE.NORMAL_NAN:
+ case STATE.INFINITY_NAN:
+ memmove(ref z, ref y);
+ break;
+
+
+ case STATE.SUBNORMAL_SUBNORMAL:
+ case STATE.SUBNORMAL_NORMAL:
+ case STATE.NORMAL_SUBNORMAL:
+ case STATE.NORMAL_NORMAL:
+ /*
+ ** Make a local copy of the y number, since we will be
+ ** altering it in the process of multiplying.
+ */
+ locy = new InternalFPF(INTERNAL_FPF_PRECISION);
+ memmove(ref locy, ref y);
+
+ /*
+ ** Check for unnormal zero arguments
+ */
+ if (IsMantissaZero(x.mantissa) || IsMantissaZero(y.mantissa))
+ {
+ SetInternalFPFInfinity(ref z, 0);
+ }
+
+ /*
+ ** Initialize the result
+ */
+ if (x.type == IFPF.IFPF_IS_SUBNORMAL ||
+ y.type == IFPF.IFPF_IS_SUBNORMAL)
+ z.type = IFPF.IFPF_IS_SUBNORMAL;
+ else
+ z.type = IFPF.IFPF_IS_NORMAL;
+
+ z.sign = (byte)(x.sign ^ y.sign);
+ z.exp = (short)(x.exp + y.exp);
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ {
+ z.mantissa[i] = (char)0;
+ extra_bits[i] = (char)0;
+ }
+
+ for (i = 0; i < (INTERNAL_FPF_PRECISION * 16); i++)
+ {
+ /*
+ ** Get rightmost bit of the multiplier
+ */
+ carry = (char)0;
+ ShiftMantRight1(ref carry, locy.mantissa);
+ if (carry != 0)
+ {
+ /*
+ ** Add the multiplicand to the product
+ */
+ carry = (char)0;
+ for (j = (INTERNAL_FPF_PRECISION - 1); j >= 0; j--)
+ Add16Bits(ref carry,
+ out z.mantissa[j],
+ z.mantissa[j],
+ x.mantissa[j]);
+ }
+ else
+ {
+ carry = (char)0;
+ }
+
+ /*
+ ** Shift the product right. Overflow bits get
+ ** shifted into extra_bits. We'll use it later
+ ** to help with the "sticky" bit.
+ */
+ ShiftMantRight1(ref carry, z.mantissa);
+ ShiftMantRight1(ref carry, extra_bits);
+ }
+
+ /*
+ ** Normalize
+ ** Note that we use a "special" normalization routine
+ ** because we need to use the extra bits. (These are
+ ** bits that may have been shifted off the bottom that
+ ** we want to reclaim...if we can.
+ */
+ while ((z.mantissa[0] & 0x8000) == 0)
+ {
+ carry = (char)0;
+ ShiftMantLeft1(ref carry, extra_bits);
+ ShiftMantLeft1(ref carry, z.mantissa);
+ z.exp--;
+ }
+
+ /*
+ ** Set the sticky bit if any bits set in extra bits.
+ */
+ if (IsMantissaZero(extra_bits))
+ {
+ z.mantissa[INTERNAL_FPF_PRECISION - 1] |= (char)1;
+ }
+ break;
+
+ case STATE.NAN_NAN:
+ choose_nan(ref x, ref y, ref z, 0);
+ break;
+ }
+
+ /*
+ ** All math done...do rounding.
+ */
+ RoundInternalFPF(ref z);
+ return;
+ }
+
+
+ /**********************
+ ** DivideInternalFPF **
+ ***********************
+ ** Divide internal FPF number x by y. Return result in z.
+ */
+ private static void DivideInternalFPF(
+ ref InternalFPF x,
+ ref InternalFPF y,
+ ref InternalFPF z)
+ {
+ int i;
+ int j;
+ char carry;
+ char[] extra_bits = new char[INTERNAL_FPF_PRECISION];
+ InternalFPF locx; /* Local for x number */
+
+ /*
+ ** As with preceding function, the following switch
+ ** statement selects among the various possible
+ ** operands.
+ */
+ int count = (int)IFPF.IFPF_TYPE_COUNT;
+ switch ((STATE)(((int)x.type * count) + (int)y.type))
+ {
+ case STATE.ZERO_ZERO:
+ case STATE.INFINITY_INFINITY:
+ SetInternalFPFNaN(ref z);
+ break;
+
+ case STATE.ZERO_SUBNORMAL:
+ case STATE.ZERO_NORMAL:
+ if (IsMantissaZero(y.mantissa))
+ {
+ SetInternalFPFNaN(ref z);
+ break;
+ }
+ goto case STATE.ZERO_INFINITY;
+
+ case STATE.ZERO_INFINITY:
+ case STATE.SUBNORMAL_INFINITY:
+ case STATE.NORMAL_INFINITY:
+ SetInternalFPFZero(ref z, (byte)(x.sign ^ y.sign));
+ break;
+
+ case STATE.SUBNORMAL_ZERO:
+ case STATE.NORMAL_ZERO:
+ if (IsMantissaZero(x.mantissa))
+ {
+ SetInternalFPFNaN(ref z);
+ break;
+ }
+ goto case STATE.INFINITY_ZERO;
+
+ case STATE.INFINITY_ZERO:
+ case STATE.INFINITY_SUBNORMAL:
+ case STATE.INFINITY_NORMAL:
+ SetInternalFPFInfinity(ref z, 0);
+ z.sign = (byte)(x.sign ^ y.sign);
+ break;
+
+ case STATE.NAN_ZERO:
+ case STATE.NAN_SUBNORMAL:
+ case STATE.NAN_NORMAL:
+ case STATE.NAN_INFINITY:
+ memmove(ref z, ref x);
+ break;
+
+ case STATE.ZERO_NAN:
+ case STATE.SUBNORMAL_NAN:
+ case STATE.NORMAL_NAN:
+ case STATE.INFINITY_NAN:
+ memmove(ref z, ref y);
+ break;
+
+ case STATE.SUBNORMAL_SUBNORMAL:
+ case STATE.NORMAL_SUBNORMAL:
+ case STATE.SUBNORMAL_NORMAL:
+ case STATE.NORMAL_NORMAL:
+ /*
+ ** Make local copy of x number, since we'll be
+ ** altering it in the process of dividing.
+ */
+ locx = new InternalFPF(INTERNAL_FPF_PRECISION);
+ memmove(ref locx, ref x);
+
+ /*
+ ** Check for unnormal zero arguments
+ */
+ if (IsMantissaZero(locx.mantissa))
+ {
+ if (IsMantissaZero(y.mantissa))
+ SetInternalFPFNaN(ref z);
+ else
+ SetInternalFPFZero(ref z, 0);
+ break;
+ }
+ if (IsMantissaZero(y.mantissa))
+ {
+ SetInternalFPFInfinity(ref z, 0);
+ break;
+ }
+
+ /*
+ ** Initialize the result
+ */
+ z.type = x.type;
+ z.sign = (byte)(x.sign ^ y.sign);
+ z.exp = (short)(x.exp - y.exp +
+ ((INTERNAL_FPF_PRECISION * 16 * 2)));
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ {
+ z.mantissa[i] = (char)0;
+ extra_bits[i] = (char)0;
+ }
+
+ while ((z.mantissa[0] & 0x8000) == 0)
+ {
+ carry = (char)0;
+ ShiftMantLeft1(ref carry, locx.mantissa);
+ ShiftMantLeft1(ref carry, extra_bits);
+
+ /*
+ ** Time to subtract yet?
+ */
+ if (carry == 0)
+ for (j = 0; j < INTERNAL_FPF_PRECISION; j++)
+ {
+ if (y.mantissa[j] > extra_bits[j])
+ {
+ carry = (char)0;
+ goto no_subtract;
+ }
+ if (y.mantissa[j] < extra_bits[j])
+ break;
+ }
+ /*
+ ** Divisor (y) <= dividend (x), subtract
+ */
+ carry = (char)0;
+ for (j = (INTERNAL_FPF_PRECISION - 1); j >= 0; j--)
+ Sub16Bits(ref carry,
+ out extra_bits[j],
+ extra_bits[j],
+ y.mantissa[j]);
+ carry = (char)1; /* 1 shifted into quotient */
+ no_subtract:
+ ShiftMantLeft1(ref carry, z.mantissa);
+ z.exp--;
+ }
+ break;
+
+ case STATE.NAN_NAN:
+ choose_nan(ref x, ref y, ref z, 0);
+ break;
+ }
+
+ /*
+ ** Math complete...do rounding
+ */
+ RoundInternalFPF(ref z);
+ }
+
+ /**********************
+ ** LongToInternalFPF **
+ ***********************
+ ** Convert a signed long integer into an internal FPF number.
+ */
+ private static void LongToInternalFPF(
+ int mylong,
+ ref InternalFPF dest)
+ {
+ int i; /* Index */
+ char myword; /* Used to hold converted stuff */
+ /*
+ ** Save the sign and get the absolute value. This will help us
+ ** with 64-bit machines, since we use only the lower 32
+ ** bits just in case.
+ */
+ if (mylong < 0)
+ {
+ dest.sign = 1;
+ mylong = 0 - mylong;
+ }
+ else
+ dest.sign = 0;
+ /*
+ ** Prepare the destination floating point number
+ */
+ dest.type = IFPF.IFPF_IS_NORMAL;
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ dest.mantissa[i] = (char)0;
+
+ /*
+ ** See if we've got a zero. If so, make the resultant FP
+ ** number a true zero and go home.
+ */
+ if (mylong == 0)
+ {
+ dest.type = IFPF.IFPF_IS_ZERO;
+ dest.exp = 0;
+ return;
+ }
+
+ /*
+ ** Not a true zero. Set the exponent to 32 (internal FPFs have
+ ** no bias) and load the low and high words into their proper
+ ** locations in the mantissa. Then normalize. The action of
+ ** normalizing slides the mantissa bits into place and sets
+ ** up the exponent properly.
+ */
+ dest.exp = 32;
+ myword = (char)((mylong >> 16) & 0xFFFFL);
+ dest.mantissa[0] = myword;
+ myword = (char)(mylong & 0xFFFFL);
+ dest.mantissa[1] = myword;
+ normalize(ref dest);
+ return;
+ }
+
+ /************************
+ ** InternalFPFToString **
+ *************************
+ ** FOR DEBUG PURPOSES
+ ** This routine converts an internal floating point representation
+ ** number to a string. Used in debugging the package.
+ ** Returns length of converted number.
+ ** NOTE: dest must point to a buffer big enough to hold the
+ ** result. Also, this routine does append a null (an effect
+ ** of using the sprintf() function). It also returns
+ ** a length count.
+ ** NOTE: This routine returns 5 significant digits. Thats
+ ** about all I feel safe with, given the method of
+ ** conversion. It should be more than enough for programmers
+ ** to determine whether the package is properly ported.
+ */
+ private static int InternalFPFToString(
+ out string dest,
+ ref InternalFPF src)
+ {
+ InternalFPF locFPFNum; /* Local for src (will be altered) */
+ InternalFPF IFPF10; /* Floating-point 10 */
+ InternalFPF IFPFComp; /* For doing comparisons */
+ int msign; /* Holding for mantissa sign */
+ int expcount; /* Exponent counter */
+ int ccount; /* Character counter */
+ int i, j, k; /* Index */
+ char carryaccum; /* Carry accumulator */
+ char mycarry; /* Local for carry */
+
+ locFPFNum = new InternalFPF(INTERNAL_FPF_PRECISION);
+ IFPF10 = new InternalFPF(INTERNAL_FPF_PRECISION);
+ IFPFComp = new InternalFPF(INTERNAL_FPF_PRECISION);
+ dest = "";
+ /*
+ ** Check first for the simple things...Nan, Infinity, Zero.
+ ** If found, copy the proper string in and go home.
+ */
+ switch (src.type)
+ {
+ case IFPF.IFPF_IS_NAN:
+ dest = "NaN";
+ return (3);
+
+ case IFPF.IFPF_IS_INFINITY:
+ if (src.sign == 0)
+ dest = "+Inf";
+ else
+ dest = "-Inf";
+ return (4);
+
+ case IFPF.IFPF_IS_ZERO:
+ if (src.sign == 0)
+ dest = "+0";
+ else
+ dest = "-0";
+ return (2);
+ }
+
+ /*
+ ** Move the internal number into our local holding area, since
+ ** we'll be altering it to print it out.
+ */
+ memmove(ref locFPFNum, ref src);
+
+ /*
+ ** Set up a floating-point 10...which we'll use a lot in a minute.
+ */
+ LongToInternalFPF(10, ref IFPF10);
+
+ /*
+ ** Save the mantissa sign and make it positive.
+ */
+ msign = src.sign;
+ src.sign = 0;
+
+ expcount = 0; /* Init exponent counter */
+
+ /*
+ ** See if the number is less than 10. If so, multiply
+ ** the number repeatedly by 10 until it's not. For each
+ ** multiplication, decrement a counter so we can keep track
+ ** of the exponent.
+ */
+ while (true)
+ {
+ AddSubInternalFPF(1, ref locFPFNum, ref IFPF10, ref IFPFComp);
+ if (IFPFComp.sign == 0)
+ break;
+ MultiplyInternalFPF(ref locFPFNum, ref IFPF10, ref IFPFComp);
+ expcount--;
+ memmove(ref locFPFNum, ref IFPFComp);
+ }
+
+ /*
+ ** Do the reverse of the above. As long as the number is
+ ** greater than or equal to 10, divide it by 10. Increment the
+ ** exponent counter for each multiplication.
+ */
+ while (true)
+ {
+ AddSubInternalFPF(1, ref locFPFNum, ref IFPF10, ref IFPFComp);
+ if (IFPFComp.sign != 0)
+ break;
+ DivideInternalFPF(ref locFPFNum, ref IFPF10, ref IFPFComp);
+ expcount++;
+ memmove(ref locFPFNum, ref IFPFComp);
+ }
+
+ /*
+ ** About time to start storing things. First, store the
+ ** mantissa sign.
+ */
+ ccount = 1; /* Init character counter */
+ if (msign == 0)
+ dest += "+";
+ else
+ dest += "-";
+
+ /*
+ ** At this point we know that the number is in the range
+ ** 10 > n >=1. We need to "strip digits" out of the
+ ** mantissa. We do this by treating the mantissa as
+ ** an integer and multiplying by 10. (Not a floating-point
+ ** 10, but an integer 10. Since this is debug code and we
+ ** could care less about speed, we'll do it the stupid
+ ** way and simply add the number to itself 10 times.
+ ** Anything that makes it to the left of the implied binary point
+ ** gets stripped off and emitted. We'll do this for
+ ** 5 significant digits (which should be enough to
+ ** verify things).
+ */
+ /*
+ ** Re-position radix point
+ */
+ carryaccum = (char)0;
+ while (locFPFNum.exp > 0)
+ {
+ mycarry = (char)0;
+ ShiftMantLeft1(ref mycarry, locFPFNum.mantissa);
+ carryaccum = (char)(carryaccum << 1);
+ if (mycarry != 0)
+ carryaccum++;
+ locFPFNum.exp--;
+ }
+
+ while (locFPFNum.exp < 0)
+ {
+ mycarry = (char)0;
+ ShiftMantRight1(ref mycarry, locFPFNum.mantissa);
+ locFPFNum.exp++;
+ }
+
+ for (i = 0; i < 6; i++)
+ if (i == 1)
+ { /* Emit decimal point */
+ dest += ".";
+ ccount++;
+ }
+ else
+ { /* Emit a digit */
+ string s = "0"; // (char)('0'+carryaccum)); // this isn't ever called
+ dest += s;
+ ccount++;
+
+ carryaccum = (char)0;
+ memmove(ref IFPF10, ref locFPFNum);
+
+ /* Do multiply via repeated adds */
+ for (j = 0; j < 9; j++)
+ {
+ mycarry = (char)0;
+ for (k = (INTERNAL_FPF_PRECISION - 1); k >= 0; k--)
+ Add16Bits(ref mycarry, out IFPFComp.mantissa[k],
+ locFPFNum.mantissa[k],
+ IFPF10.mantissa[k]);
+ carryaccum += (char)(mycarry != 0 ? 1 : 0);
+ memmove(ref locFPFNum, ref IFPFComp);
+ }
+ }
+
+ /*
+ ** Now move the 'E', the exponent sign, and the exponent
+ ** into the string.
+ */
+ dest += "E";
+ dest += expcount.ToString();
+
+ /*
+ ** All done, go home.
+ */
+ return (dest.Length);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/emfloatclass.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/emfloatclass.cs
new file mode 100644
index 0000000000..0ae261c16b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/emfloatclass.cs
@@ -0,0 +1,1566 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+using System;
+
+/*
+** DEFINES
+*/
+public class EMFloatClass : EmFloatStruct
+{
+ public override string Name()
+ {
+ return "FP EMULATION(class)";
+ }
+
+ private const int MAX_EXP = 32767;
+ private const int MIN_EXP = (-32767);
+
+ private enum IFPF : byte
+ {
+ IFPF_IS_ZERO = 0,
+ IFPF_IS_SUBNORMAL = 1,
+ IFPF_IS_NORMAL = 2,
+ IFPF_IS_INFINITY = 3,
+ IFPF_IS_NAN = 4,
+ IFPF_TYPE_COUNT = 5,
+ };
+
+ private enum STATE
+ {
+ ZERO_ZERO = 0,
+ ZERO_SUBNORMAL = 1,
+ ZERO_NORMAL = 2,
+ ZERO_INFINITY = 3,
+ ZERO_NAN = 4,
+
+ SUBNORMAL_ZERO = 5,
+ SUBNORMAL_SUBNORMAL = 6,
+ SUBNORMAL_NORMAL = 7,
+ SUBNORMAL_INFINITY = 8,
+ SUBNORMAL_NAN = 9,
+
+ NORMAL_ZERO = 10,
+ NORMAL_SUBNORMAL = 11,
+ NORMAL_NORMAL = 12,
+ NORMAL_INFINITY = 13,
+ NORMAL_NAN = 14,
+
+ INFINITY_ZERO = 15,
+ INFINITY_SUBNORMAL = 16,
+ INFINITY_NORMAL = 17,
+ INFINITY_INFINITY = 18,
+ INFINITY_NAN = 19,
+
+ NAN_ZERO = 20,
+ NAN_SUBNORMAL = 21,
+ NAN_NORMAL = 22,
+ NAN_INFINITY = 23,
+ NAN_NAN = 24,
+ };
+
+ private enum OPERAND
+ {
+ OPERAND_ZERO = 0,
+ OPERAND_SUBNORMAL = 1,
+ OPERAND_NORMAL = 2,
+ OPERAND_INFINITY = 3,
+ OPERAND_NAN = 4,
+ };
+
+ /*
+ ** Following was already defined in NMGLOBAL.H
+ **
+ */
+ private const int INTERNAL_FPF_PRECISION = 4;
+
+ /*
+ ** TYPEDEFS
+ */
+
+ private class InternalFPF
+ {
+ public InternalFPF()
+ {
+ type = IFPF.IFPF_IS_ZERO; sign = (byte)0;
+ exp = (short)0; mantissa = new char[INTERNAL_FPF_PRECISION];
+ }
+ public IFPF type; /* Indicates, NORMAL, SUBNORMAL, etc. */
+ public byte sign; /* Mantissa sign */
+ public short exp; /* Signed exponent...no bias */
+ public char[] mantissa; // [INTERNAL_FPF_PRECISION]
+ };
+
+ /*
+ ** emfloat.c
+ ** Source for emulated floating-point routines.
+ ** BYTEmark (tm)
+ ** BYTE's Native Mode Benchmarks
+ ** Rick Grehan, BYTE Magazine.
+ **
+ ** Created:
+ ** Last update: 3/95
+ **
+ ** DISCLAIMER
+ ** The source, executable, and documentation files that comprise
+ ** the BYTEmark benchmarks are made available on an "as is" basis.
+ ** This means that we at BYTE Magazine have made every reasonable
+ ** effort to verify that the there are no errors in the source and
+ ** executable code. We cannot, however, guarantee that the programs
+ ** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+ ** no claims in regard to the fitness of the source code, executable
+ ** code, and documentation of the BYTEmark.
+ ** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+ ** of McGraw-Hill cannot be held responsible for any damages resulting
+ ** from the use of this code or the results obtained from using
+ ** this code.
+ */
+
+ /*
+ ** Floating-point emulator.
+ ** These routines are only "sort of" IEEE-compliant. All work is
+ ** done using an internal representation. Also, the routines do
+ ** not check for many of the exceptions that might occur.
+ ** Still, the external formats produced are IEEE-compatible,
+ ** with the restriction that they presume a low-endian machine
+ ** (though the endianism will not effect the performance).
+ **
+ ** Some code here was based on work done by Steve Snelgrove of
+ ** Orem, UT. Other code comes from routines presented in
+ ** the long-ago book: "Microprocessor Programming for
+ ** Computer Hobbyists" by Neill Graham.
+ */
+
+ /*****************************
+ ** FLOATING-POINT EMULATION **
+ *****************************/
+
+ /**************
+ ** DoEmFloat **
+ ***************
+ ** Perform the floating-point emulation routines portion of the
+ ** CPU benchmark. Returns the operations per second.
+ */
+ public override double Run()
+ {
+ InternalFPF[] abase; /* Base of A array */
+ InternalFPF[] bbase; /* Base of B array */
+ InternalFPF[] cbase; /* Base of C array */
+ long accumtime; /* Accumulated time in ticks */
+ double iterations; /* # of iterations */
+ long tickcount; /* # of ticks */
+ int loops; /* # of loops */
+
+ /*
+ ** Test the emulation routines.
+ */
+
+ abase = new InternalFPF[this.arraysize];
+ bbase = new InternalFPF[this.arraysize];
+ cbase = new InternalFPF[this.arraysize];
+
+ for (int i = 0; i < this.arraysize; i++)
+ {
+ abase[i] = new InternalFPF();
+ bbase[i] = new InternalFPF();
+ cbase[i] = new InternalFPF();
+ }
+
+ /*
+ for (int i = 0; i < this.arraysize; i++)
+ {
+ abase[i].type = IFPF.IFPF_IS_ZERO;
+ abase[i].sign = (byte)0;
+ abase[i].exp = (short)0;
+ abase[i].mantissa = new char[INTERNAL_FPF_PRECISION];
+
+ bbase[i].type = IFPF.IFPF_IS_ZERO;
+ bbase[i].sign = (byte)0;
+ bbase[i].exp = (short)0;
+ bbase[i].mantissa = new char[INTERNAL_FPF_PRECISION];
+
+ cbase[i].type = IFPF.IFPF_IS_ZERO;
+ cbase[i].sign = (byte)0;
+ cbase[i].exp = (short)0;
+ cbase[i].mantissa = new char[INTERNAL_FPF_PRECISION];
+ }
+ */
+
+ /*
+ ** Set up the arrays
+ */
+ SetupCPUEmFloatArrays(abase, bbase, cbase, this.arraysize);
+
+ /*
+ ** See if we need to do self-adjusting code.
+ */
+ if (this.adjust == 0)
+ {
+ this.loops = 0;
+
+ /*
+ ** Do an iteration of the tests. If the elapsed time is
+ ** less than minimum, increase the loop count and try
+ ** again.
+ */
+ for (loops = 1; loops < global.CPUEMFLOATLOOPMAX; loops += loops)
+ {
+ tickcount = DoEmFloatIteration(abase, bbase, cbase,
+ this.arraysize,
+ loops);
+ if (tickcount > global.min_ticks)
+ {
+ this.loops = loops;
+ break;
+ }
+ }
+ }
+
+ /*
+ ** Verify that selft adjustment code worked.
+ */
+ if (this.loops == 0)
+ {
+ throw new Exception("CPU:EMFPU -- CMPUEMFLOATLOOPMAX limit hit\n");
+ }
+
+ /*
+ ** All's well if we get here. Repeatedly perform floating
+ ** tests until the accumulated time is greater than the
+ ** # of seconds requested.
+ ** Each iteration performs arraysize * 3 operations.
+ */
+ accumtime = 0L;
+ iterations = (double)0.0;
+ do
+ {
+ accumtime += DoEmFloatIteration(abase, bbase, cbase,
+ this.arraysize,
+ this.loops);
+ iterations += (double)1.0;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ /*
+ ** Clean up, calculate results, and go home.
+ ** Also, indicate that adjustment is done.
+ */
+
+ if (this.adjust == 0)
+ this.adjust = 1;
+ double emflops = (iterations * (double)this.loops) /
+ (double)ByteMark.TicksToFracSecs(accumtime);
+
+ return (emflops);
+ }
+
+
+
+
+
+
+ /**************************
+ ** SetupCPUEmFloatArrays **
+ ***************************
+ ** Set up the arrays that will be used in the emulated
+ ** floating-point tests.
+ ** This is done by loading abase and bbase elements with
+ ** random numbers. We use our long-to-floating point
+ ** routine to set them up.
+ ** NOTE: We really don't need the pointer to cbase...cbase
+ ** is overwritten in the benchmark.
+ */
+ private static
+ void SetupCPUEmFloatArrays(InternalFPF[] abase,
+ InternalFPF[] bbase,
+ InternalFPF[] cbase,
+ int arraysize)
+ {
+ int i;
+ InternalFPF locFPF1, locFPF2;
+ locFPF1 = new InternalFPF();
+ locFPF2 = new InternalFPF();
+
+ for (i = 0; i < arraysize; i++)
+ {
+ LongToInternalFPF(ByteMark.randwc(50000), locFPF1);
+ LongToInternalFPF(ByteMark.randwc(50000) + 1, locFPF2);
+ DivideInternalFPF(locFPF1, locFPF2, abase[i]);
+ LongToInternalFPF(ByteMark.randwc(50000) + 1, locFPF2);
+ DivideInternalFPF(locFPF1, locFPF2, bbase[i]);
+ }
+ return;
+ }
+
+ /***********************
+ ** DoEmFloatIteration **
+ ************************
+ ** Perform an iteration of the emulated floating-point
+ ** benchmark. Note that "an iteration" can involve multiple
+ ** loops through the benchmark.
+ */
+ private static
+ long DoEmFloatIteration(InternalFPF[] abase,
+ InternalFPF[] bbase,
+ InternalFPF[] cbase,
+ int arraysize, int loops)
+ {
+ long elapsed; /* For the stopwatch */
+ byte[] jtable = new byte[] { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3 };
+ int i;
+
+ /*
+ ** Begin timing
+ */
+ elapsed = ByteMark.StartStopwatch();
+
+ /*
+ ** Each pass through the array performs operations in
+ ** the followingratios:
+ ** 4 adds, 4 subtracts, 5 multiplies, 3 divides
+ ** (adds and subtracts being nearly the same operation)
+ */
+ while (loops-- > 0)
+ {
+ for (i = 0; i < arraysize; i++)
+ switch (jtable[i % 16])
+ {
+ case 0: /* Add */
+ AddSubInternalFPF(0, abase[i],
+ bbase[i],
+ cbase[i]);
+ break;
+ case 1: /* Subtract */
+ AddSubInternalFPF(1, abase[i],
+ bbase[i],
+ cbase[i]);
+ break;
+ case 2: /* Multiply */
+ MultiplyInternalFPF(abase[i],
+ bbase[i],
+ cbase[i]);
+ break;
+ case 3: /* Divide */
+ DivideInternalFPF(abase[i],
+ bbase[i],
+ cbase[i]);
+ break;
+ }
+ }
+
+ return (ByteMark.StopStopwatch(elapsed));
+ }
+
+ /***********************
+ ** SetInternalFPFZero **
+ ************************
+ ** Set an internal floating-point-format number to zero.
+ ** sign determines the sign of the zero.
+ */
+ private static void SetInternalFPFZero(InternalFPF dest,
+ byte sign)
+ {
+ int i; /* Index */
+
+ dest.type = IFPF.IFPF_IS_ZERO;
+ dest.sign = sign;
+ dest.exp = MIN_EXP;
+
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ dest.mantissa[i] = (char)0;
+ return;
+ }
+
+ /***************************
+ ** SetInternalFPFInfinity **
+ ****************************
+ ** Set an internal floating-point-format number to infinity.
+ ** This can happen if the exponent exceeds MAX_EXP.
+ ** As above, sign picks the sign of infinity.
+ */
+ private static void SetInternalFPFInfinity(InternalFPF dest,
+ byte sign)
+ {
+ int i; /* Index */
+
+ dest.type = IFPF.IFPF_IS_INFINITY;
+ dest.sign = sign;
+ dest.exp = MIN_EXP;
+
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ dest.mantissa[i] = (char)0;
+ return;
+ }
+
+ /**********************
+ ** SetInternalFPFNaN **
+ ***********************
+ ** Set an internal floating-point-format number to Nan
+ ** (not a number). Note that we "emulate" an 80x87 as far
+ ** as the mantissa bits go.
+ */
+ private static void SetInternalFPFNaN(InternalFPF dest)
+ {
+ int i; /* Index */
+
+ dest.type = IFPF.IFPF_IS_NAN;
+ dest.exp = MAX_EXP;
+ dest.sign = 1;
+
+ dest.mantissa[0] = (char)0x4000;
+ for (i = 1; i < INTERNAL_FPF_PRECISION; i++)
+ dest.mantissa[i] = (char)0;
+
+ return;
+ }
+
+ /*******************
+ ** IsMantissaZero **
+ ********************
+ ** Pass this routine a pointer to an internal floating point format
+ ** number's mantissa. It checks for an all-zero mantissa.
+ ** Returns 0 if it is NOT all zeros, !=0 otherwise.
+ */
+ private static bool IsMantissaZero(char[] mant)
+ {
+ int i; /* Index */
+ int n; /* Return value */
+
+ n = 0;
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ n |= mant[i];
+
+ return (n == 0);
+ }
+
+ /**************
+ ** Add16Bits **
+ ***************
+ ** Add b, c, and carry. Retult in a. New carry in carry.
+ */
+ private static void Add16Bits(ref char carry,
+ out char a,
+ char b,
+ char c)
+ {
+ int accum; /* Accumulator */
+
+ /*
+ ** Do the work in the 32-bit accumulator so we can return
+ ** the carry.
+ */
+ accum = b;
+ accum += c;
+ accum += carry;
+ carry = (char)(((accum & 0x00010000) != 0) ? 1 : 0); /* New carry */
+ a = (char)(accum & 0xFFFF); /* Result is lo 16 bits */
+ return;
+ }
+
+ /**************
+ ** Sub16Bits **
+ ***************
+ ** Additive inverse of above.
+ */
+ private static void Sub16Bits(ref char borrow,
+ out char a,
+ char b,
+ char c)
+ {
+ int accum; /* Accumulator */
+
+ accum = b;
+ accum -= c;
+ accum -= borrow;
+ borrow = (char)(((accum & 0x00010000) != 0) ? 1 : 0); /* New borrow */
+ a = (char)(accum & 0xFFFF);
+ return;
+ }
+
+ /*******************
+ ** ShiftMantLeft1 **
+ ********************
+ ** Shift a vector of 16-bit numbers left 1 bit. Also provides
+ ** a carry bit, which is shifted in at the beginning, and
+ ** shifted out at the end.
+ */
+ private static void ShiftMantLeft1(ref char carry,
+ char[] mantissa)
+ {
+ int i; /* Index */
+ int new_carry;
+ char accum; /* Temporary holding placed */
+
+ for (i = INTERNAL_FPF_PRECISION - 1; i >= 0; i--)
+ {
+ accum = mantissa[i];
+ new_carry = accum & 0x8000; /* Get new carry */
+ accum = unchecked((char)(accum << 1)); /* Do the shift */
+ if (carry != 0)
+ accum |= (char)1; /* Insert previous carry */
+ carry = (char)new_carry;
+ mantissa[i] = accum; /* Return shifted value */
+ }
+ return;
+ }
+
+ /********************
+ ** ShiftMantRight1 **
+ *********************
+ ** Shift a mantissa right by 1 bit. Provides carry, as
+ ** above
+ */
+ private static void ShiftMantRight1(ref char carry,
+ char[] mantissa)
+ {
+ int i; /* Index */
+ int new_carry;
+ char accum;
+
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ {
+ accum = mantissa[i];
+ new_carry = accum & 1; /* Get new carry */
+ accum = (char)(accum >> 1);
+ if (carry != 0)
+ accum |= (char)0x8000;
+ carry = (char)new_carry;
+ mantissa[i] = accum;
+ }
+ return;
+ }
+
+
+ /*****************************
+ ** StickyShiftMantRight **
+ ******************************
+ ** This is a shift right of the mantissa with a "sticky bit".
+ ** I.E., if a carry of 1 is shifted out of the least significant
+ ** bit, the least significant bit is set to 1.
+ */
+ private static void StickyShiftRightMant(InternalFPF ptr,
+ int amount)
+ {
+ int i; /* Index */
+ char carry; /* Self-explanatory */
+
+ if (ptr.type != IFPF.IFPF_IS_ZERO) /* Don't bother shifting a zero */
+ {
+ /*
+ ** If the amount of shifting will shift everyting
+ ** out of existence, then just clear the whole mantissa
+ ** and set the lowmost bit to 1.
+ */
+ if (amount >= INTERNAL_FPF_PRECISION * 16)
+ {
+ for (i = 0; i < INTERNAL_FPF_PRECISION - 1; i++)
+ ptr.mantissa[i] = (char)0;
+ ptr.mantissa[INTERNAL_FPF_PRECISION - 1] = (char)1;
+ }
+ else
+ for (i = 0; i < amount; i++)
+ {
+ carry = (char)0;
+ ShiftMantRight1(ref carry, ptr.mantissa);
+ if (carry != 0)
+ ptr.mantissa[INTERNAL_FPF_PRECISION - 1] |= (char)1;
+ }
+ }
+ return;
+ }
+
+
+ /**************************************************
+ ** POST ARITHMETIC PROCESSING **
+ ** (NORMALIZE, ROUND, OVERFLOW, AND UNDERFLOW) **
+ **************************************************/
+
+ /**************
+ ** normalize **
+ ***************
+ ** Normalize an internal-representation number. Normalization
+ ** discards empty most-significant bits.
+ */
+ private static void normalize(InternalFPF ptr)
+ {
+ char carry;
+
+ /*
+ ** As long as there's a highmost 0 bit, shift the significand
+ ** left 1 bit. Each time you do this, though, you've
+ ** gotta decrement the exponent.
+ */
+ while ((ptr.mantissa[0] & 0x8000) == 0)
+ {
+ carry = (char)0;
+ ShiftMantLeft1(ref carry, ptr.mantissa);
+ ptr.exp--;
+ }
+ return;
+ }
+
+ /****************
+ ** denormalize **
+ *****************
+ ** Denormalize an internal-representation number. This means
+ ** shifting it right until its exponent is equivalent to
+ ** minimum_exponent. (You have to do this often in order
+ ** to perform additions and subtractions).
+ */
+ private static void denormalize(InternalFPF ptr,
+ int minimum_exponent)
+ {
+ int exponent_difference;
+
+ if (IsMantissaZero(ptr.mantissa))
+ {
+ throw new Exception("Error: zero significand in denormalize");
+ }
+
+ exponent_difference = ptr.exp - minimum_exponent;
+ if (exponent_difference < 0)
+ {
+ /*
+ ** The number is subnormal
+ */
+ exponent_difference = -exponent_difference;
+ if (exponent_difference >= (INTERNAL_FPF_PRECISION * 16))
+ {
+ /* Underflow */
+ SetInternalFPFZero(ptr, ptr.sign);
+ }
+ else
+ {
+ ptr.exp += (short)exponent_difference;
+ StickyShiftRightMant(ptr, exponent_difference);
+ }
+ }
+ return;
+ }
+
+
+ /*********************
+ ** RoundInternalFPF **
+ **********************
+ ** Round an internal-representation number.
+ ** The kind of rounding we do here is simplest...referred to as
+ ** "chop". "Extraneous" rightmost bits are simply hacked off.
+ */
+ private static
+ void RoundInternalFPF(InternalFPF ptr)
+ {
+ /* int i; */
+
+ if (ptr.type == IFPF.IFPF_IS_NORMAL ||
+ ptr.type == IFPF.IFPF_IS_SUBNORMAL)
+ {
+ denormalize(ptr, MIN_EXP);
+ if (ptr.type != IFPF.IFPF_IS_ZERO)
+ {
+ /* clear the extraneous bits */
+ ptr.mantissa[3] &= (char)0xfff8;
+ /* for (i=4; i<INTERNAL_FPF_PRECISION; i++)
+ {
+ ptr->mantissa[i] = 0;
+ }
+ */
+ /*
+ ** Check for overflow
+ */
+ if (ptr.exp > MAX_EXP)
+ {
+ SetInternalFPFInfinity(ptr, ptr.sign);
+ }
+ }
+ }
+ return;
+ }
+
+ /*******************************************************
+ ** ARITHMETIC OPERATIONS ON INTERNAL REPRESENTATION **
+ *******************************************************/
+
+ private static void memmove(InternalFPF dest, InternalFPF src)
+ {
+ dest.type = src.type;
+ dest.sign = src.sign;
+ dest.exp = src.exp;
+ for (int i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ {
+ dest.mantissa[i] = src.mantissa[i];
+ }
+ }
+
+ /***************
+ ** choose_nan **
+ ****************
+ ** Called by routines that are forced to perform math on
+ ** a pair of NaN's. This routine "selects" which NaN is
+ ** to be returned.
+ */
+ private static void choose_nan(InternalFPF x,
+ InternalFPF y,
+ InternalFPF z,
+ int intel_flag)
+ {
+ int i;
+
+ /*
+ ** Compare the two mantissas,
+ ** return the larger. Note that we will be emulating
+ ** an 80387 in this operation.
+ */
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ {
+ if (x.mantissa[i] > y.mantissa[i])
+ {
+ memmove(z, x);
+ return;
+ }
+ if (x.mantissa[i] < y.mantissa[i])
+ {
+ memmove(z, y);
+ return;
+ }
+ }
+
+ /*
+ ** They are equal
+ */
+ if (intel_flag == 0)
+ /* if the operation is addition */
+ memmove(z, x);
+ else
+ /* if the operation is multiplication */
+ memmove(z, y);
+ return;
+ }
+
+
+ /**********************
+ ** AddSubInternalFPF **
+ ***********************
+ ** Adding or subtracting internal-representation numbers.
+ ** Internal-representation numbers pointed to by x and y are
+ ** added/subtracted and the result returned in z.
+ */
+ private static void AddSubInternalFPF(byte operation,
+ InternalFPF x,
+ InternalFPF y,
+ InternalFPF z)
+ {
+ int exponent_difference;
+ char borrow;
+ char carry;
+ int i;
+ InternalFPF locx, locy; /* Needed since we alter them */
+ /*
+ ** Following big switch statement handles the
+ ** various combinations of operand types.
+ */
+ int count = (int)IFPF.IFPF_TYPE_COUNT;
+ switch ((STATE)(((int)x.type * count) + (int)y.type))
+ {
+ case STATE.ZERO_ZERO:
+ memmove(z, x);
+ if ((x.sign ^ y.sign ^ operation) != 0)
+ {
+ z.sign = 0; /* positive */
+ }
+ break;
+
+ case STATE.NAN_ZERO:
+ case STATE.NAN_SUBNORMAL:
+ case STATE.NAN_NORMAL:
+ case STATE.NAN_INFINITY:
+ case STATE.SUBNORMAL_ZERO:
+ case STATE.NORMAL_ZERO:
+ case STATE.INFINITY_ZERO:
+ case STATE.INFINITY_SUBNORMAL:
+ case STATE.INFINITY_NORMAL:
+ memmove(z, x);
+ break;
+
+
+ case STATE.ZERO_NAN:
+ case STATE.SUBNORMAL_NAN:
+ case STATE.NORMAL_NAN:
+ case STATE.INFINITY_NAN:
+ memmove(z, y);
+ break;
+
+ case STATE.ZERO_SUBNORMAL:
+ case STATE.ZERO_NORMAL:
+ case STATE.ZERO_INFINITY:
+ case STATE.SUBNORMAL_INFINITY:
+ case STATE.NORMAL_INFINITY:
+ memmove(z, x);
+ z.sign ^= operation;
+ break;
+
+ case STATE.SUBNORMAL_SUBNORMAL:
+ case STATE.SUBNORMAL_NORMAL:
+ case STATE.NORMAL_SUBNORMAL:
+ case STATE.NORMAL_NORMAL:
+ /*
+ ** Copy x and y to locals, since we may have
+ ** to alter them.
+ */
+ locx = new InternalFPF();
+ locy = new InternalFPF();
+ memmove(locx, x);
+ memmove(locy, y);
+
+ /* compute sum/difference */
+ exponent_difference = locx.exp - locy.exp;
+ if (exponent_difference == 0)
+ {
+ /*
+ ** locx.exp == locy.exp
+ ** so, no shifting required
+ */
+ if (locx.type == IFPF.IFPF_IS_SUBNORMAL ||
+ locy.type == IFPF.IFPF_IS_SUBNORMAL)
+ z.type = IFPF.IFPF_IS_SUBNORMAL;
+ else
+ z.type = IFPF.IFPF_IS_NORMAL;
+
+ /*
+ ** Assume that locx.mantissa > locy.mantissa
+ */
+ z.sign = locx.sign;
+ z.exp = locx.exp;
+ }
+ else
+ if (exponent_difference > 0)
+ {
+ /*
+ ** locx.exp > locy.exp
+ */
+ StickyShiftRightMant(locy,
+ exponent_difference);
+ z.type = locx.type;
+ z.sign = locx.sign;
+ z.exp = locx.exp;
+ }
+ else /* if (exponent_difference < 0) */
+ {
+ /*
+ ** locx.exp < locy.exp
+ */
+ StickyShiftRightMant(locx,
+ -exponent_difference);
+ z.type = locy.type;
+ z.sign = (byte)(locy.sign ^ operation);
+ z.exp = locy.exp;
+ }
+
+ if ((locx.sign ^ locy.sign ^ operation) != 0)
+ {
+ /*
+ ** Signs are different, subtract mantissas
+ */
+ borrow = (char)0;
+ for (i = (INTERNAL_FPF_PRECISION - 1); i >= 0; i--)
+ Sub16Bits(ref borrow,
+ out z.mantissa[i],
+ locx.mantissa[i],
+ locy.mantissa[i]);
+
+ if (borrow != 0)
+ {
+ /* The y->mantissa was larger than the
+ ** x->mantissa leaving a negative
+ ** result. Change the result back to
+ ** an unsigned number and flip the
+ ** sign flag.
+ */
+ z.sign = (byte)(locy.sign ^ operation);
+ borrow = (char)0;
+ for (i = (INTERNAL_FPF_PRECISION - 1); i >= 0; i--)
+ {
+ Sub16Bits(ref borrow,
+ out z.mantissa[i],
+ (char)0,
+ z.mantissa[i]);
+ }
+ }
+ else
+ {
+ /* The assumption made above
+ ** (i.e. x->mantissa >= y->mantissa)
+ ** was correct. Therefore, do nothing.
+ ** z->sign = x->sign;
+ */
+ }
+
+ if (IsMantissaZero(z.mantissa))
+ {
+ z.type = IFPF.IFPF_IS_ZERO;
+ z.sign = 0; /* positive */
+ }
+ else
+ if (locx.type == IFPF.IFPF_IS_NORMAL ||
+ locy.type == IFPF.IFPF_IS_NORMAL)
+ {
+ normalize(z);
+ }
+ }
+ else
+ {
+ /* signs are the same, add mantissas */
+ carry = (char)0;
+ for (i = (INTERNAL_FPF_PRECISION - 1); i >= 0; i--)
+ {
+ Add16Bits(ref carry,
+ out z.mantissa[i],
+ locx.mantissa[i],
+ locy.mantissa[i]);
+ }
+
+ if (carry != 0)
+ {
+ z.exp++;
+ carry = (char)0;
+ ShiftMantRight1(ref carry, z.mantissa);
+ z.mantissa[0] |= (char)0x8000;
+ z.type = IFPF.IFPF_IS_NORMAL;
+ }
+ else
+ if ((z.mantissa[0] & 0x8000) != 0)
+ z.type = IFPF.IFPF_IS_NORMAL;
+ }
+ break;
+
+ case STATE.INFINITY_INFINITY:
+ SetInternalFPFNaN(z);
+ break;
+
+ case STATE.NAN_NAN:
+ choose_nan(x, y, z, 1);
+ break;
+ }
+
+ /*
+ ** All the math is done; time to round.
+ */
+ RoundInternalFPF(z);
+ return;
+ }
+
+
+ /************************
+ ** MultiplyInternalFPF **
+ *************************
+ ** Two internal-representation numbers x and y are multiplied; the
+ ** result is returned in z.
+ */
+ private static void MultiplyInternalFPF(
+ InternalFPF x,
+ InternalFPF y,
+ InternalFPF z)
+ {
+ int i;
+ int j;
+ char carry;
+ char[] extra_bits = new char[INTERNAL_FPF_PRECISION];
+ InternalFPF locy; /* Needed since this will be altered */
+ /*
+ ** As in the preceding function, this large switch
+ ** statement selects among the many combinations
+ ** of operands.
+ */
+ int count = (int)IFPF.IFPF_TYPE_COUNT;
+ switch ((STATE)(((int)x.type * count) + (int)y.type))
+ {
+ case STATE.INFINITY_SUBNORMAL:
+ case STATE.INFINITY_NORMAL:
+ case STATE.INFINITY_INFINITY:
+ case STATE.ZERO_ZERO:
+ case STATE.ZERO_SUBNORMAL:
+ case STATE.ZERO_NORMAL:
+ memmove(z, x);
+ z.sign ^= y.sign;
+ break;
+
+ case STATE.SUBNORMAL_INFINITY:
+ case STATE.NORMAL_INFINITY:
+ case STATE.SUBNORMAL_ZERO:
+ case STATE.NORMAL_ZERO:
+ memmove(z, y);
+ z.sign ^= x.sign;
+ break;
+
+ case STATE.ZERO_INFINITY:
+ case STATE.INFINITY_ZERO:
+ SetInternalFPFNaN(z);
+ break;
+
+ case STATE.NAN_ZERO:
+ case STATE.NAN_SUBNORMAL:
+ case STATE.NAN_NORMAL:
+ case STATE.NAN_INFINITY:
+ memmove(z, x);
+ break;
+
+ case STATE.ZERO_NAN:
+ case STATE.SUBNORMAL_NAN:
+ case STATE.NORMAL_NAN:
+ case STATE.INFINITY_NAN:
+ memmove(z, y);
+ break;
+
+
+ case STATE.SUBNORMAL_SUBNORMAL:
+ case STATE.SUBNORMAL_NORMAL:
+ case STATE.NORMAL_SUBNORMAL:
+ case STATE.NORMAL_NORMAL:
+ /*
+ ** Make a local copy of the y number, since we will be
+ ** altering it in the process of multiplying.
+ */
+ locy = new InternalFPF();
+ memmove(locy, y);
+
+ /*
+ ** Check for unnormal zero arguments
+ */
+ if (IsMantissaZero(x.mantissa) || IsMantissaZero(y.mantissa))
+ {
+ SetInternalFPFInfinity(z, 0);
+ }
+
+ /*
+ ** Initialize the result
+ */
+ if (x.type == IFPF.IFPF_IS_SUBNORMAL ||
+ y.type == IFPF.IFPF_IS_SUBNORMAL)
+ z.type = IFPF.IFPF_IS_SUBNORMAL;
+ else
+ z.type = IFPF.IFPF_IS_NORMAL;
+
+ z.sign = (byte)(x.sign ^ y.sign);
+ z.exp = (short)(x.exp + y.exp);
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ {
+ z.mantissa[i] = (char)0;
+ extra_bits[i] = (char)0;
+ }
+
+ for (i = 0; i < (INTERNAL_FPF_PRECISION * 16); i++)
+ {
+ /*
+ ** Get rightmost bit of the multiplier
+ */
+ carry = (char)0;
+ ShiftMantRight1(ref carry, locy.mantissa);
+ if (carry != 0)
+ {
+ /*
+ ** Add the multiplicand to the product
+ */
+ carry = (char)0;
+ for (j = (INTERNAL_FPF_PRECISION - 1); j >= 0; j--)
+ Add16Bits(ref carry,
+ out z.mantissa[j],
+ z.mantissa[j],
+ x.mantissa[j]);
+ }
+ else
+ {
+ carry = (char)0;
+ }
+
+ /*
+ ** Shift the product right. Overflow bits get
+ ** shifted into extra_bits. We'll use it later
+ ** to help with the "sticky" bit.
+ */
+ ShiftMantRight1(ref carry, z.mantissa);
+ ShiftMantRight1(ref carry, extra_bits);
+ }
+
+ /*
+ ** Normalize
+ ** Note that we use a "special" normalization routine
+ ** because we need to use the extra bits. (These are
+ ** bits that may have been shifted off the bottom that
+ ** we want to reclaim...if we can.
+ */
+ while ((z.mantissa[0] & 0x8000) == 0)
+ {
+ carry = (char)0;
+ ShiftMantLeft1(ref carry, extra_bits);
+ ShiftMantLeft1(ref carry, z.mantissa);
+ z.exp--;
+ }
+
+ /*
+ ** Set the sticky bit if any bits set in extra bits.
+ */
+ if (IsMantissaZero(extra_bits))
+ {
+ z.mantissa[INTERNAL_FPF_PRECISION - 1] |= (char)1;
+ }
+ break;
+
+ case STATE.NAN_NAN:
+ choose_nan(x, y, z, 0);
+ break;
+ }
+
+ /*
+ ** All math done...do rounding.
+ */
+ RoundInternalFPF(z);
+ return;
+ }
+
+
+ /**********************
+ ** DivideInternalFPF **
+ ***********************
+ ** Divide internal FPF number x by y. Return result in z.
+ */
+ private static void DivideInternalFPF(
+ InternalFPF x,
+ InternalFPF y,
+ InternalFPF z)
+ {
+ int i;
+ int j;
+ char carry;
+ char[] extra_bits = new char[INTERNAL_FPF_PRECISION];
+ InternalFPF locx; /* Local for x number */
+
+ /*
+ ** As with preceding function, the following switch
+ ** statement selects among the various possible
+ ** operands.
+ */
+ int count = (int)IFPF.IFPF_TYPE_COUNT;
+ switch ((STATE)(((int)x.type * count) + (int)y.type))
+ {
+ case STATE.ZERO_ZERO:
+ case STATE.INFINITY_INFINITY:
+ SetInternalFPFNaN(z);
+ break;
+
+ case STATE.ZERO_SUBNORMAL:
+ case STATE.ZERO_NORMAL:
+ if (IsMantissaZero(y.mantissa))
+ {
+ SetInternalFPFNaN(z);
+ break;
+ }
+ goto case STATE.ZERO_INFINITY;
+
+ case STATE.ZERO_INFINITY:
+ case STATE.SUBNORMAL_INFINITY:
+ case STATE.NORMAL_INFINITY:
+ SetInternalFPFZero(z, (byte)(x.sign ^ y.sign));
+ break;
+
+ case STATE.SUBNORMAL_ZERO:
+ case STATE.NORMAL_ZERO:
+ if (IsMantissaZero(x.mantissa))
+ {
+ SetInternalFPFNaN(z);
+ break;
+ }
+ goto case STATE.INFINITY_ZERO;
+
+ case STATE.INFINITY_ZERO:
+ case STATE.INFINITY_SUBNORMAL:
+ case STATE.INFINITY_NORMAL:
+ SetInternalFPFInfinity(z, 0);
+ z.sign = (byte)(x.sign ^ y.sign);
+ break;
+
+ case STATE.NAN_ZERO:
+ case STATE.NAN_SUBNORMAL:
+ case STATE.NAN_NORMAL:
+ case STATE.NAN_INFINITY:
+ memmove(z, x);
+ break;
+
+ case STATE.ZERO_NAN:
+ case STATE.SUBNORMAL_NAN:
+ case STATE.NORMAL_NAN:
+ case STATE.INFINITY_NAN:
+ memmove(z, y);
+ break;
+
+ case STATE.SUBNORMAL_SUBNORMAL:
+ case STATE.NORMAL_SUBNORMAL:
+ case STATE.SUBNORMAL_NORMAL:
+ case STATE.NORMAL_NORMAL:
+ /*
+ ** Make local copy of x number, since we'll be
+ ** altering it in the process of dividing.
+ */
+
+ locx = new InternalFPF();
+ memmove(locx, x);
+
+ /*
+ ** Check for unnormal zero arguments
+ */
+ if (IsMantissaZero(locx.mantissa))
+ {
+ if (IsMantissaZero(y.mantissa))
+ SetInternalFPFNaN(z);
+ else
+ SetInternalFPFZero(z, 0);
+ break;
+ }
+ if (IsMantissaZero(y.mantissa))
+ {
+ SetInternalFPFInfinity(z, 0);
+ break;
+ }
+
+ /*
+ ** Initialize the result
+ */
+ z.type = x.type;
+ z.sign = (byte)(x.sign ^ y.sign);
+ z.exp = (short)(x.exp - y.exp +
+ ((INTERNAL_FPF_PRECISION * 16 * 2)));
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ {
+ z.mantissa[i] = (char)0;
+ extra_bits[i] = (char)0;
+ }
+
+ while ((z.mantissa[0] & 0x8000) == 0)
+ {
+ carry = (char)0;
+ ShiftMantLeft1(ref carry, locx.mantissa);
+ ShiftMantLeft1(ref carry, extra_bits);
+
+ /*
+ ** Time to subtract yet?
+ */
+ if (carry == 0)
+ for (j = 0; j < INTERNAL_FPF_PRECISION; j++)
+ {
+ if (y.mantissa[j] > extra_bits[j])
+ {
+ carry = (char)0;
+ goto no_subtract;
+ }
+ if (y.mantissa[j] < extra_bits[j])
+ break;
+ }
+ /*
+ ** Divisor (y) <= dividend (x), subtract
+ */
+ carry = (char)0;
+ for (j = (INTERNAL_FPF_PRECISION - 1); j >= 0; j--)
+ Sub16Bits(ref carry,
+ out extra_bits[j],
+ extra_bits[j],
+ y.mantissa[j]);
+ carry = (char)1; /* 1 shifted into quotient */
+ no_subtract:
+ ShiftMantLeft1(ref carry, z.mantissa);
+ z.exp--;
+ }
+ break;
+
+ case STATE.NAN_NAN:
+ choose_nan(x, y, z, 0);
+ break;
+ }
+
+ /*
+ ** Math complete...do rounding
+ */
+ RoundInternalFPF(z);
+ }
+
+ /**********************
+ ** LongToInternalFPF **
+ ***********************
+ ** Convert a signed long integer into an internal FPF number.
+ */
+ private static void LongToInternalFPF(
+ int mylong,
+ InternalFPF dest)
+ {
+ int i; /* Index */
+ char myword; /* Used to hold converted stuff */
+ /*
+ ** Save the sign and get the absolute value. This will help us
+ ** with 64-bit machines, since we use only the lower 32
+ ** bits just in case.
+ */
+ if (mylong < 0)
+ {
+ dest.sign = 1;
+ mylong = 0 - mylong;
+ }
+ else
+ dest.sign = 0;
+ /*
+ ** Prepare the destination floating point number
+ */
+ dest.type = IFPF.IFPF_IS_NORMAL;
+ for (i = 0; i < INTERNAL_FPF_PRECISION; i++)
+ dest.mantissa[i] = (char)0;
+
+ /*
+ ** See if we've got a zero. If so, make the resultant FP
+ ** number a true zero and go home.
+ */
+ if (mylong == 0)
+ {
+ dest.type = IFPF.IFPF_IS_ZERO;
+ dest.exp = 0;
+ return;
+ }
+
+ /*
+ ** Not a true zero. Set the exponent to 32 (internal FPFs have
+ ** no bias) and load the low and high words into their proper
+ ** locations in the mantissa. Then normalize. The action of
+ ** normalizing slides the mantissa bits into place and sets
+ ** up the exponent properly.
+ */
+ dest.exp = 32;
+ myword = (char)((mylong >> 16) & 0xFFFFL);
+ dest.mantissa[0] = myword;
+ myword = (char)(mylong & 0xFFFFL);
+ dest.mantissa[1] = myword;
+ normalize(dest);
+ return;
+ }
+
+ /************************
+ ** InternalFPFToString **
+ *************************
+ ** FOR DEBUG PURPOSES
+ ** This routine converts an internal floating point representation
+ ** number to a string. Used in debugging the package.
+ ** Returns length of converted number.
+ ** NOTE: dest must point to a buffer big enough to hold the
+ ** result. Also, this routine does append a null (an effect
+ ** of using the sprintf() function). It also returns
+ ** a length count.
+ ** NOTE: This routine returns 5 significant digits. Thats
+ ** about all I feel safe with, given the method of
+ ** conversion. It should be more than enough for programmers
+ ** to determine whether the package is properly ported.
+ */
+ private static int InternalFPFToString(
+ out string dest,
+ InternalFPF src)
+ {
+ InternalFPF locFPFNum; /* Local for src (will be altered) */
+ InternalFPF IFPF10; /* Floating-point 10 */
+ InternalFPF IFPFComp; /* For doing comparisons */
+ int msign; /* Holding for mantissa sign */
+ int expcount; /* Exponent counter */
+ int ccount; /* Character counter */
+ int i, j, k; /* Index */
+ char carryaccum; /* Carry accumulator */
+ char mycarry; /* Local for carry */
+
+ locFPFNum = new InternalFPF();
+ IFPF10 = new InternalFPF();
+ IFPFComp = new InternalFPF();
+ dest = "";
+ /*
+ ** Check first for the simple things...Nan, Infinity, Zero.
+ ** If found, copy the proper string in and go home.
+ */
+ switch (src.type)
+ {
+ case IFPF.IFPF_IS_NAN:
+ dest = "NaN";
+ return (3);
+
+ case IFPF.IFPF_IS_INFINITY:
+ if (src.sign == 0)
+ dest = "+Inf";
+ else
+ dest = "-Inf";
+ return (4);
+
+ case IFPF.IFPF_IS_ZERO:
+ if (src.sign == 0)
+ dest = "+0";
+ else
+ dest = "-0";
+ return (2);
+ }
+
+ /*
+ ** Move the internal number into our local holding area, since
+ ** we'll be altering it to print it out.
+ */
+ memmove(locFPFNum, src);
+
+ /*
+ ** Set up a floating-point 10...which we'll use a lot in a minute.
+ */
+ LongToInternalFPF(10, IFPF10);
+
+ /*
+ ** Save the mantissa sign and make it positive.
+ */
+ msign = src.sign;
+ src.sign = 0;
+
+ expcount = 0; /* Init exponent counter */
+
+ /*
+ ** See if the number is less than 10. If so, multiply
+ ** the number repeatedly by 10 until it's not. For each
+ ** multiplication, decrement a counter so we can keep track
+ ** of the exponent.
+ */
+ while (true)
+ {
+ AddSubInternalFPF(1, locFPFNum, IFPF10, IFPFComp);
+ if (IFPFComp.sign == 0)
+ break;
+ MultiplyInternalFPF(locFPFNum, IFPF10, IFPFComp);
+ expcount--;
+ memmove(locFPFNum, IFPFComp);
+ }
+
+ /*
+ ** Do the reverse of the above. As long as the number is
+ ** greater than or equal to 10, divide it by 10. Increment the
+ ** exponent counter for each multiplication.
+ */
+ while (true)
+ {
+ AddSubInternalFPF(1, locFPFNum, IFPF10, IFPFComp);
+ if (IFPFComp.sign != 0)
+ break;
+ DivideInternalFPF(locFPFNum, IFPF10, IFPFComp);
+ expcount++;
+ memmove(locFPFNum, IFPFComp);
+ }
+
+ /*
+ ** About time to start storing things. First, store the
+ ** mantissa sign.
+ */
+ ccount = 1; /* Init character counter */
+ if (msign == 0)
+ dest += "+";
+ else
+ dest += "-";
+
+ /*
+ ** At this point we know that the number is in the range
+ ** 10 > n >=1. We need to "strip digits" out of the
+ ** mantissa. We do this by treating the mantissa as
+ ** an integer and multiplying by 10. (Not a floating-point
+ ** 10, but an integer 10. Since this is debug code and we
+ ** could care less about speed, we'll do it the stupid
+ ** way and simply add the number to itself 10 times.
+ ** Anything that makes it to the left of the implied binary point
+ ** gets stripped off and emitted. We'll do this for
+ ** 5 significant digits (which should be enough to
+ ** verify things).
+ */
+ /*
+ ** Re-position radix point
+ */
+ carryaccum = (char)0;
+ while (locFPFNum.exp > 0)
+ {
+ mycarry = (char)0;
+ ShiftMantLeft1(ref mycarry, locFPFNum.mantissa);
+ carryaccum = (char)(carryaccum << 1);
+ if (mycarry != 0)
+ carryaccum++;
+ locFPFNum.exp--;
+ }
+
+ while (locFPFNum.exp < 0)
+ {
+ mycarry = (char)0;
+ ShiftMantRight1(ref mycarry, locFPFNum.mantissa);
+ locFPFNum.exp++;
+ }
+
+ for (i = 0; i < 6; i++)
+ if (i == 1)
+ { /* Emit decimal point */
+ dest += ".";
+ ccount++;
+ }
+ else
+ { /* Emit a digit */
+ string s = "0"; // ((char)('0'+carryaccum)); // never gets called.
+ dest += s;
+ ccount++;
+
+ carryaccum = (char)0;
+ memmove(IFPF10, locFPFNum);
+
+ /* Do multiply via repeated adds */
+ for (j = 0; j < 9; j++)
+ {
+ mycarry = (char)0;
+ for (k = (INTERNAL_FPF_PRECISION - 1); k >= 0; k--)
+ Add16Bits(ref mycarry, out IFPFComp.mantissa[k],
+ locFPFNum.mantissa[k],
+ IFPF10.mantissa[k]);
+ carryaccum += (char)(mycarry != 0 ? 1 : 0);
+ memmove(locFPFNum, IFPFComp);
+ }
+ }
+
+ /*
+ ** Now move the 'E', the exponent sign, and the exponent
+ ** into the string.
+ */
+ dest += "E";
+ dest += expcount.ToString();
+
+ /*
+ ** All done, go home.
+ */
+ return (dest.Length);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/fourier.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/fourier.cs
new file mode 100644
index 0000000000..e2e0a5d609
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/fourier.cs
@@ -0,0 +1,230 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+using System;
+
+public class Fourier : FourierStruct
+{
+ public override string Name()
+ {
+ return "FOURIER";
+ }
+
+ /*
+ ** Perform the transcendental/trigonometric portion of the
+ ** benchmark. This benchmark calculates the first n
+ ** fourier coefficients of the function (x+1)^x defined
+ ** on the interval 0,2.
+ */
+ public override double Run()
+ {
+ double[] abase; /* Base of A[] coefficients array */
+ double[] bbase; /* Base of B[] coefficients array */
+ long accumtime; /* Accumulated time in ticks */
+ double iterations; /* # of iterations */
+
+ /*
+ ** See if we need to do self-adjustment code.
+ */
+ if (this.adjust == 0)
+ {
+ this.arraysize = 100; /* Start at 100 elements */
+ while (true)
+ {
+ abase = new double[this.arraysize];
+ bbase = new double[this.arraysize];
+ /*
+ ** Do an iteration of the tests. If the elapsed time is
+ ** less than or equal to the permitted minimum, re-allocate
+ ** larger arrays and try again.
+ */
+ if (DoFPUTransIteration(abase, bbase, this.arraysize) > global.min_ticks) break;
+ this.arraysize += 50;
+ }
+ }
+ else
+ {
+ /*
+ ** Don't need self-adjustment. Just allocate the
+ ** arrays, and go.
+ */
+ abase = new double[this.arraysize];
+ bbase = new double[this.arraysize];
+ }
+
+ accumtime = 0L;
+ iterations = 0.0;
+ do
+ {
+ accumtime += DoFPUTransIteration(abase, bbase, this.arraysize);
+ iterations += (double)this.arraysize * (double)2.0 - (double)1.0;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ if (this.adjust == 0)
+ this.adjust = 1;
+
+ return iterations / (double)ByteMark.TicksToFracSecs(accumtime);
+ }
+
+ /*
+ ** Perform an iteration of the FPU Transcendental/trigonometric
+ ** benchmark. Here, an iteration consists of calculating the
+ ** first n fourier coefficients of the function (x+1)^x on
+ ** the interval 0,2. n is given by arraysize.
+ ** NOTE: The # of integration steps is fixed at
+ ** 200.
+ */
+ private static long DoFPUTransIteration(double[] abase, double[] bbase, int arraysize)
+ {
+ double omega; /* Fundamental frequency */
+ int i; /* Index */
+ long elapsed; /* Elapsed time */
+
+ elapsed = ByteMark.StartStopwatch();
+
+ /*
+ ** Calculate the fourier series. Begin by
+ ** calculating A[0].
+ */
+
+ abase[0] = TrapezoidIntegrate(0.0, 2.0, 200, 0.0, 0) / 2.0;
+
+ /*
+ ** Calculate the fundamental frequency.
+ ** ( 2 * pi ) / period...and since the period
+ ** is 2, omega is simply pi.
+ */
+ omega = 3.1415926535897921;
+
+ for (i = 1; i < arraysize; i++)
+ {
+ /*
+ ** Calculate A[i] terms. Note, once again, that we
+ ** can ignore the 2/period term outside the integral
+ ** since the period is 2 and the term cancels itself
+ ** out.
+ */
+ abase[i] = TrapezoidIntegrate(0.0, 2.0, 200, omega * (double)i, 1);
+
+ bbase[i] = TrapezoidIntegrate(0.0, 2.0, 200, omega * (double)i, 2);
+ }
+ /*
+ ** All done, stop the stopwatch
+ */
+ return (ByteMark.StopStopwatch(elapsed));
+ }
+
+ /*
+ ** Perform a simple trapezoid integration on the
+ ** function (x+1)**x.
+ ** x0,x1 set the lower and upper bounds of the
+ ** integration.
+ ** nsteps indicates # of trapezoidal sections
+ ** omegan is the fundamental frequency times
+ ** the series member #
+ ** select = 0 for the A[0] term, 1 for cosine terms, and
+ ** 2 for sine terms.
+ ** Returns the value.
+ */
+ private static double TrapezoidIntegrate(double x0, double x1, int nsteps, double omegan, int select)
+ {
+ double x; /* Independent variable */
+ double dx; /* Stepsize */
+ double rvalue; /* Return value */
+
+ /*
+ ** Initialize independent variable
+ */
+ x = x0;
+
+ /*
+ ** Calculate stepsize
+ */
+ dx = (x1 - x0) / (double)nsteps;
+
+ /*
+ ** Initialize the return value.
+ */
+ rvalue = thefunction(x0, omegan, select) / (double)2.0;
+
+ /*
+ ** Compute the other terms of the integral.
+ */
+ if (nsteps != 1)
+ {
+ --nsteps; /* Already done 1 step */
+ while (--nsteps != 0)
+ {
+ x += dx;
+ rvalue += thefunction(x, omegan, select);
+ }
+ }
+ /*
+ ** Finish computation
+ */
+ rvalue = (rvalue + thefunction(x1, omegan, select) / (double)2.0) * dx;
+
+ return (rvalue);
+ }
+
+ /*
+ ** This routine selects the function to be used
+ ** in the Trapezoid integration.
+ ** x is the independent variable
+ ** omegan is omega * n
+ ** select chooses which of the sine/cosine functions
+ ** are used. note the special case for select=0.
+ */
+ private static double thefunction(double x, double omegan, int select)
+ {
+ /*
+ ** Use select to pick which function we call.
+ */
+ switch (select)
+ {
+ case 0: return Math.Pow(x + (double)1.0, x);
+ case 1: return Math.Pow(x + (double)1.0, x) * Math.Cos(omegan * x);
+ case 2: return Math.Pow(x + (double)1.0, x) * Math.Sin(omegan * x);
+ }
+
+ /*
+ ** We should never reach this point, but the following
+ ** keeps compilers from issuing a warning message.
+ */
+ return (0.0);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/idea.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/idea.cs
new file mode 100644
index 0000000000..732a8f0ec9
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/idea.cs
@@ -0,0 +1,451 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/********************
+** IDEA Encryption **
+*********************
+** IDEA - International Data Encryption Algorithm.
+** Based on code presented in Applied Cryptography by Bruce Schneier.
+** Which was based on code developed by Xuejia Lai and James L. Massey.
+** Other modifications made by Colin Plumb.
+**
+*/
+
+/***********
+** DoIDEA **
+************
+** Perform IDEA encryption. Note that we time encryption & decryption
+** time as being a single loop.
+*/
+
+using System;
+
+public class IDEAEncryption : IDEAStruct
+{
+ public override string Name()
+ {
+ return "IDEA";
+ }
+
+ public override double Run()
+ {
+ int i;
+ char[] Z = new char[global.KEYLEN];
+ char[] DK = new char[global.KEYLEN];
+ char[] userkey = new char[8];
+ long accumtime;
+ double iterations;
+ byte[] plain1; /* First plaintext buffer */
+ byte[] crypt1; /* Encryption buffer */
+ byte[] plain2; /* Second plaintext buffer */
+
+ /*
+ ** Re-init random-number generator.
+ */
+ ByteMark.randnum(3);
+
+ /*
+ ** Build an encryption/decryption key
+ */
+ for (i = 0; i < 8; i++)
+ userkey[i] = (char)(ByteMark.abs_randwc(60000) & 0xFFFF);
+ for (i = 0; i < global.KEYLEN; i++)
+ Z[i] = (char)0;
+
+ /*
+ ** Compute encryption/decryption subkeys
+ */
+ en_key_idea(userkey, Z);
+ de_key_idea(Z, DK);
+
+ /*
+ ** Allocate memory for buffers. We'll make 3, called plain1,
+ ** crypt1, and plain2. It works like this:
+ ** plain1 >>encrypt>> crypt1 >>decrypt>> plain2.
+ ** So, plain1 and plain2 should match.
+ ** Also, fill up plain1 with sample text.
+ */
+ plain1 = new byte[this.arraysize];
+ crypt1 = new byte[this.arraysize];
+ plain2 = new byte[this.arraysize];
+
+ /*
+ ** Note that we build the "plaintext" by simply loading
+ ** the array up with random numbers.
+ */
+ for (i = 0; i < this.arraysize; i++)
+ plain1[i] = (byte)(ByteMark.abs_randwc(255) & 0xFF);
+
+ /*
+ ** See if we need to perform self adjustment loop.
+ */
+ if (this.adjust == 0)
+ {
+ /*
+ ** Do self-adjustment. This involves initializing the
+ ** # of loops and increasing the loop count until we
+ ** get a number of loops that we can use.
+ */
+ for (this.loops = 100;
+ this.loops < global.MAXIDEALOOPS;
+ this.loops += 10)
+ if (DoIDEAIteration(plain1, crypt1, plain2,
+ this.arraysize,
+ this.loops,
+ Z, DK) > global.min_ticks)
+ break;
+ }
+
+ /*
+ ** All's well if we get here. Do the test.
+ */
+ accumtime = 0;
+ iterations = (double)0.0;
+
+ do
+ {
+ accumtime += DoIDEAIteration(plain1, crypt1, plain2,
+ this.arraysize,
+ this.loops, Z, DK);
+ iterations += (double)this.loops;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ /*
+ ** Clean up, calculate results, and go home. Be sure to
+ ** show that we don't have to rerun adjustment code.
+ */
+
+ if (this.adjust == 0)
+ this.adjust = 1;
+
+ return (iterations / ByteMark.TicksToFracSecs(accumtime));
+ }
+
+ /********************
+ ** DoIDEAIteration **
+ *********************
+ ** Execute a single iteration of the IDEA encryption algorithm.
+ ** Actually, a single iteration is one encryption and one
+ ** decryption.
+ */
+ private static long DoIDEAIteration(byte[] plain1,
+ byte[] crypt1,
+ byte[] plain2,
+ int arraysize,
+ int nloops,
+ char[] Z,
+ char[] DK)
+ {
+ int i;
+ int j;
+ long elapsed;
+
+ /*
+ ** Start the stopwatch.
+ */
+ elapsed = ByteMark.StartStopwatch();
+
+ /*
+ ** Do everything for nloops.
+ */
+
+ for (i = 0; i < nloops; i++)
+ {
+ for (j = 0; j < arraysize; j += 8)
+ cipher_idea(plain1, crypt1, j, Z); /* Encrypt */
+
+ for (j = 0; j < arraysize; j += 8)
+ cipher_idea(crypt1, plain2, j, DK); /* Decrypt */
+ }
+
+ // Validate output
+ for (j = 0; j < arraysize; j++)
+ if (plain1[j] != plain2[j])
+ {
+ string error = String.Format("IDEA: error at index {0} ({1} <> {2})!", j, (int)plain1[j], (int)plain2[j]);
+ throw new Exception(error);
+ }
+
+ /*
+ ** Get elapsed time.
+ */
+ return (ByteMark.StopStopwatch(elapsed));
+ }
+
+ /********
+ ** mul **
+ *********
+ ** Performs multiplication, modulo (2**16)+1. This code is structured
+ ** on the assumption that untaken branches are cheaper than taken
+ ** branches, and that the compiler doesn't schedule branches.
+ */
+ private static char mul(char a, char b)
+ {
+ int p;
+ if (a != 0)
+ {
+ if (b != 0)
+ {
+ p = unchecked((int)(a * b));
+ b = low16(p);
+ a = unchecked((char)(p >> 16));
+ return unchecked((char)(b - a + (b < a ? 1 : 0)));
+ }
+ else
+ return unchecked((char)(1 - a));
+ }
+ else
+ return unchecked((char)(1 - b));
+ }
+
+ /********
+ ** inv **
+ *********
+ ** Compute multiplicative inverse of x, modulo (2**16)+1
+ ** using Euclid's GCD algorithm. It is unrolled twice
+ ** to avoid swapping the meaning of the registers. And
+ ** some subtracts are changed to adds.
+ */
+ private static char inv(char x)
+ {
+ char t0, t1;
+ char q, y;
+
+ if (x <= 1)
+ return (x); /* 0 and 1 are self-inverse */
+
+ t1 = (char)(0x10001 / x);
+ y = (char)(0x10001 % x);
+
+ if (y == 1)
+ return (low16(1 - t1));
+
+ t0 = (char)1;
+
+ do
+ {
+ q = (char)(x / y);
+ x = (char)(x % y);
+ t0 += (char)(q * t1);
+ if (x == 1)
+ return (t0);
+ q = (char)(y / x);
+ y = (char)(y % x);
+ t1 += (char)(q * t0);
+ } while (y != 1);
+ return (low16(1 - t1));
+ }
+
+ /****************
+ ** en_key_idea **
+ *****************
+ ** Compute IDEA encryption subkeys Z
+ */
+ private static void en_key_idea(char[] userkey, char[] Z)
+ {
+ int i, j;
+
+ // NOTE: The temp variables (tmp,idx) were not in original C code.
+ // It may affect numbers a bit.
+ int tmp = 0;
+ int idx = 0;
+
+ /*
+ ** shifts
+ */
+ for (j = 0; j < 8; j++)
+ Z[j + idx] = userkey[tmp++];
+ for (i = 0; j < global.KEYLEN; j++)
+ {
+ i++;
+ Z[i + 7 + idx] = unchecked((char)((Z[(i & 7) + idx] << 9) | (Z[((i + 1) & 7) + idx] >> 7)));
+ idx += (i & 8);
+ i &= 7;
+ }
+ return;
+ }
+
+ /****************
+ ** de_key_idea **
+ *****************
+ ** Compute IDEA decryption subkeys DK from encryption
+ ** subkeys Z.
+ */
+ private static void de_key_idea(char[] Z, char[] DK)
+ {
+ char[] TT = new char[global.KEYLEN];
+ int j;
+ char t1, t2, t3;
+
+ short p = (short)global.KEYLEN;
+
+ // NOTE: Another local variable was needed here but was not in original C.
+ // May affect benchmark numbers.
+ int tmpZ = 0;
+
+ t1 = inv(Z[tmpZ++]);
+ t2 = unchecked((char)(-Z[tmpZ++]));
+ t3 = unchecked((char)(-Z[tmpZ++]));
+ TT[--p] = inv(Z[tmpZ++]);
+ TT[--p] = t3;
+ TT[--p] = t2;
+ TT[--p] = t1;
+
+ for (j = 1; j < global.ROUNDS; j++)
+ {
+ t1 = Z[tmpZ++];
+ TT[--p] = Z[tmpZ++];
+ TT[--p] = t1;
+ t1 = inv(Z[tmpZ++]);
+ t2 = unchecked((char)(-Z[tmpZ++]));
+ t3 = unchecked((char)(-Z[tmpZ++]));
+ TT[--p] = inv(Z[tmpZ++]);
+ TT[--p] = t2;
+ TT[--p] = t3;
+ TT[--p] = t1;
+ }
+
+ t1 = Z[tmpZ++];
+ TT[--p] = Z[tmpZ++];
+ TT[--p] = t1;
+ t1 = inv(Z[tmpZ++]);
+ t2 = unchecked((char)(-Z[tmpZ++]));
+ t3 = unchecked((char)(-Z[tmpZ++]));
+ TT[--p] = inv(Z[tmpZ++]);
+ TT[--p] = t3;
+ TT[--p] = t2;
+ TT[--p] = t1;
+
+ /*
+ ** Copy and destroy temp copy
+ */
+ for (j = 0, p = 0; j < global.KEYLEN; j++)
+ {
+ DK[j] = TT[p];
+ TT[p++] = (char)0;
+ }
+
+ return;
+ }
+
+ /*
+ ** MUL(x,y)
+ ** This #define creates a macro that computes x=x*y modulo 0x10001.
+ ** Requires temps t16 and t32. Also requires y to be strictly 16
+ ** bits. Here, I am using the simplest form. May not be the
+ ** fastest. -- RG
+ */
+ /* #define MUL(x,y) (x=mul(low16(x),y)) */
+
+ /****************
+ ** cipher_idea **
+ *****************
+ ** IDEA encryption/decryption algorithm.
+ */
+
+ // NOTE: args in and out were renamed because in/out are reserved words
+ // in cool.
+
+ private static void cipher_idea(byte[] xin, byte[] xout, int offset, char[] Z)
+ {
+ char x1, x2, x3, x4, t1, t2;
+ int r = global.ROUNDS;
+
+ // NOTE: More local variables (AND AN ARG) were required by this
+ // function. The original C code did not need/have these.
+ int offset2 = offset;
+ int idx = 0;
+
+ // NOTE: Because of big endian (and lack of pointers) I had to
+ // force two bytes into the chars instead of how original
+ // c code did it.
+ unchecked
+ {
+ x1 = (char)((xin[offset]) | (xin[offset + 1] << 8));
+ x2 = (char)((xin[offset + 2]) | (xin[offset + 3] << 8));
+ x3 = (char)((xin[offset + 4]) | (xin[offset + 5] << 8));
+ x4 = (char)((xin[offset + 6]) | (xin[offset + 7] << 8));
+
+ do
+ {
+ MUL(ref x1, Z[idx++]);
+ x2 += Z[idx++];
+ x3 += Z[idx++];
+ MUL(ref x4, Z[idx++]);
+
+ t2 = (char)(x1 ^ x3);
+ MUL(ref t2, Z[idx++]);
+ t1 = (char)(t2 + (x2 ^ x4));
+ MUL(ref t1, Z[idx++]);
+ t2 = (char)(t1 + t2);
+
+ x1 ^= t1;
+ x4 ^= t2;
+
+ t2 ^= x2;
+ x2 = (char)(x3 ^ t1);
+ x3 = t2;
+ } while ((--r) != 0);
+
+ MUL(ref x1, Z[idx++]);
+ xout[offset2] = (byte)(x1 & 0x00ff);
+ xout[offset2 + 1] = (byte)((x1 >> 8) & 0x00ff);
+ xout[offset2 + 2] = (byte)((x3 + Z[idx]) & 0x00ff);
+ xout[offset2 + 3] = (byte)(((x3 + Z[idx++]) >> 8) & 0x00ff);
+ xout[offset2 + 4] = (byte)((x2 + Z[idx]) & 0x00ff);
+ xout[offset2 + 5] = (byte)(((x2 + Z[idx++]) >> 8) & 0x00ff);
+ MUL(ref x4, Z[idx]);
+ xout[offset2 + 6] = (byte)(x4 & 0x00ff);
+ xout[offset2 + 7] = (byte)((x4 >> 8) & 0x00ff);
+ }
+ return;
+ }
+
+ // These were macros in the original C code
+
+ /* #define low16(x) ((x) & 0x0FFFF) */
+ private static char low16(int x)
+ {
+ return (char)((x) & 0x0FFFF);
+ }
+
+ /* #define MUL(x,y) (x=mul(low16(x),y)) */
+ private static void MUL(ref char x, char y)
+ {
+ x = mul(low16(x), y);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/ludecomp.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/ludecomp.cs
new file mode 100644
index 0000000000..d45a51df59
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/ludecomp.cs
@@ -0,0 +1,340 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+using System;
+
+/***********************
+** LU DECOMPOSITION **
+** (Linear Equations) **
+************************
+** These routines come from "Numerical Recipes in Pascal".
+** Note that, as in the assignment algorithm, though we
+** separately define LUARRAYROWS and LUARRAYCOLS, the two
+** must be the same value (this routine depends on a square
+** matrix).
+*/
+
+internal class LUDecomp : LUStruct
+{
+ private const int MAXLUARRAYS = 1000;
+
+ private static double[] s_LUtempvv;
+
+ public override string Name()
+ {
+ return "LU DECOMPOSITION";
+ }
+
+ public override double Run()
+ {
+ double[][] a;
+ double[] b;
+ double[][][] abase = null;
+ double[][] bbase = null;
+ int n;
+ int i;
+ long accumtime;
+ double iterations;
+
+ /*
+ ** Our first step is to build a "solvable" problem. This
+ ** will become the "seed" set that all others will be
+ ** derived from. (I.E., we'll simply copy these arrays
+ ** into the others.
+ */
+ a = new double[global.LUARRAYROWS][];
+ for (int j = 0; j < global.LUARRAYROWS; j++)
+ {
+ a[j] = new double[global.LUARRAYCOLS];
+ }
+ b = new double[global.LUARRAYROWS];
+ n = global.LUARRAYROWS;
+
+ s_LUtempvv = new double[global.LUARRAYROWS];
+
+ build_problem(a, n, b);
+
+ if (this.adjust == 0)
+ {
+ for (i = 1; i <= MAXLUARRAYS; i++)
+ {
+ abase = new double[i + 1][][];
+ for (int j = 0; j < i + 1; j++)
+ {
+ abase[j] = new double[global.LUARRAYROWS][];
+ for (int k = 0; k < global.LUARRAYROWS; k++)
+ {
+ abase[j][k] = new double[global.LUARRAYCOLS];
+ }
+ }
+
+ bbase = new double[i + 1][];
+ for (int j = 0; j < i + 1; j++)
+ {
+ bbase[j] = new double[global.LUARRAYROWS];
+ }
+
+ if (DoLUIteration(a, b, abase, bbase, i) > global.min_ticks)
+ {
+ this.numarrays = i;
+ break;
+ }
+ }
+
+ if (this.numarrays == 0)
+ {
+ throw new Exception("FPU:LU -- Array limit reached");
+ }
+ }
+ else
+ {
+ abase = new double[this.numarrays][][];
+ for (int j = 0; j < this.numarrays; j++)
+ {
+ abase[j] = new double[global.LUARRAYROWS][];
+ for (int k = 0; k < global.LUARRAYROWS; k++)
+ {
+ abase[j][k] = new double[global.LUARRAYCOLS];
+ }
+ }
+ bbase = new double[this.numarrays][];
+ for (int j = 0; j < this.numarrays; j++)
+ {
+ bbase[j] = new double[global.LUARRAYROWS];
+ }
+ }
+
+ accumtime = 0;
+ iterations = 0.0;
+
+ do
+ {
+ accumtime += DoLUIteration(a, b, abase, bbase, this.numarrays);
+ iterations += (double)this.numarrays;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ if (this.adjust == 0) this.adjust = 1;
+
+ return iterations / ByteMark.TicksToFracSecs(accumtime);
+ }
+
+ private static long DoLUIteration(double[][] a, double[] b, double[][][] abase, double[][] bbase, int numarrays)
+ {
+ double[][] locabase;
+ double[] locbbase;
+ long elapsed;
+ int k, j, i;
+
+ for (j = 0; j < numarrays; j++)
+ {
+ locabase = abase[j];
+ locbbase = bbase[j];
+ for (i = 0; i < global.LUARRAYROWS; i++)
+ for (k = 0; k < global.LUARRAYCOLS; k++)
+ locabase[i][k] = a[i][k];
+ for (i = 0; i < global.LUARRAYROWS; i++)
+ locbbase[i] = b[i];
+ }
+
+ elapsed = ByteMark.StartStopwatch();
+
+ for (i = 0; i < numarrays; i++)
+ {
+ locabase = abase[i];
+ locbbase = bbase[i];
+
+ lusolve(locabase, global.LUARRAYROWS, locbbase);
+ }
+
+ return (ByteMark.StopStopwatch(elapsed));
+ }
+
+ private static void build_problem(double[][] a, int n, double[] b)
+ {
+ int i, j, k, k1;
+ double rcon;
+
+ ByteMark.randnum(13);
+
+ for (i = 0; i < n; i++)
+ {
+ b[i] = (double)(ByteMark.abs_randwc(100) + 1);
+ for (j = 0; j < n; j++)
+ if (i == j)
+ a[i][j] = (double)(ByteMark.abs_randwc(1000) + 1);
+ else
+ a[i][j] = (double)0.0;
+ }
+
+ for (i = 0; i < 8 * n; i++)
+ {
+ k = ByteMark.abs_randwc(n);
+ k1 = ByteMark.abs_randwc(n);
+ if (k != k1)
+ {
+ if (k < k1) rcon = 1.0;
+ else rcon = -1.0;
+ for (j = 0; j < n; j++)
+ a[k][j] += a[k1][j] * rcon;
+ b[k] += b[k1] * rcon;
+ }
+ }
+ }
+
+ private static int ludcmp(double[][] a, int n, int[] indx, out int d)
+ {
+ double big;
+ double sum;
+ double dum;
+ int i, j, k;
+ int imax = 0;
+ double tiny;
+
+ tiny = 1.0e-20;
+ d = 1;
+
+ for (i = 0; i < n; i++)
+ {
+ big = 0.0;
+ for (j = 0; j < n; j++)
+ if (Math.Abs(a[i][j]) > big)
+ big = Math.Abs(a[i][j]);
+ if (big == 0.0) return 0;
+ s_LUtempvv[i] = 1.0 / big;
+ }
+
+ for (j = 0; j < n; j++)
+ {
+ if (j != 0)
+ for (i = 0; i < j; i++)
+ {
+ sum = a[i][j];
+ if (i != 0)
+ for (k = 0; k < i; k++)
+ sum -= a[i][k] * a[k][j];
+ a[i][j] = sum;
+ }
+ big = 0.0;
+
+ for (i = j; i < n; i++)
+ {
+ sum = a[i][j];
+ if (j != 0)
+ for (k = 0; k < j; k++)
+ sum -= a[i][k] * a[k][j];
+ a[i][j] = sum;
+ dum = s_LUtempvv[i] * Math.Abs(sum);
+ if (dum >= big)
+ {
+ big = dum;
+ imax = i;
+ }
+ }
+
+ if (j != imax)
+ {
+ for (k = 0; k < n; k++)
+ {
+ dum = a[imax][k];
+ a[imax][k] = a[j][k];
+ a[j][k] = dum;
+ }
+ d = -d;
+ dum = s_LUtempvv[imax];
+ s_LUtempvv[imax] = s_LUtempvv[j];
+ s_LUtempvv[j] = dum;
+ }
+
+ indx[j] = imax;
+ if (a[j][j] == 0.0)
+ a[j][j] = tiny;
+ if (j != (n - 1))
+ {
+ dum = 1.0 / a[j][j];
+ for (i = j + 1; i < n; i++)
+ a[i][j] = a[i][j] * dum;
+ }
+ }
+
+ return 1;
+ }
+
+ private static void lubksb(double[][] a, int n, int[] indx, double[] b)
+ {
+ int i, j;
+ int ip;
+ int ii;
+ double sum;
+
+ ii = -1;
+
+ for (i = 0; i < n; i++)
+ {
+ ip = indx[i];
+ sum = b[ip];
+ b[ip] = b[i];
+ if (ii != -1)
+ for (j = ii; j < i; j++)
+ sum = sum - a[i][j] * b[j];
+ else
+ if (sum != (double)0.0)
+ ii = i;
+ b[i] = sum;
+ }
+
+ for (i = (n - 1); i >= 0; i--)
+ {
+ sum = b[i];
+ if (i != (n - 1))
+ for (j = (i + 1); j < n; j++)
+ sum = sum - a[i][j] * b[j];
+ b[i] = sum / a[i][i];
+ }
+ }
+
+ private static int lusolve(double[][] a, int n, double[] b)
+ {
+ int[] indx = new int[global.LUARRAYROWS];
+ int d;
+
+ if (ludcmp(a, n, indx, out d) == 0) return 0;
+
+ lubksb(a, n, indx, b);
+
+ return 1;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/neural-dat.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/neural-dat.cs
new file mode 100644
index 0000000000..6e3ab36b94
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/neural-dat.cs
@@ -0,0 +1,231 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+// Captures contents of NNET.DAT as a string
+// to simplfy testing in CoreCLR.
+
+internal class NeuralData
+{
+ public static string Input =
+ "5 7 8 \n"
+ + "26 \n"
+ + "0 0 1 0 0 \n"
+ + "0 1 0 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 1 1 1 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 0 0 0 0 0 1 \n"
+ + "1 1 1 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 1 1 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 1 1 1 0 \n"
+ + "0 1 0 0 0 0 1 0 \n"
+ + "0 1 1 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 1 1 0 \n"
+ + "0 1 0 0 0 0 1 1 \n"
+ + "1 1 1 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 1 1 1 0 \n"
+ + "0 1 0 0 0 1 0 0 \n"
+ + "1 1 1 1 1 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 1 1 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 1 1 1 1 \n"
+ + "0 1 0 0 0 1 0 1 \n"
+ + "1 1 1 1 1 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 1 1 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "0 1 0 0 0 1 1 0 \n"
+ + "0 1 1 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 1 1 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 1 1 0 \n"
+ + "0 1 0 0 0 1 1 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 1 1 1 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 0 0 1 0 0 0 \n"
+ + "0 1 1 1 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 1 1 1 0 \n"
+ + "0 1 0 0 1 0 0 1 \n"
+ + "0 0 0 0 1 \n"
+ + "0 0 0 0 1 \n"
+ + "0 0 0 0 1 \n"
+ + "0 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 1 1 0 \n"
+ + "0 1 0 0 1 0 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 1 0 \n"
+ + "1 0 1 0 0 \n"
+ + "1 1 0 0 0 \n"
+ + "1 0 1 0 0 \n"
+ + "1 0 0 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 0 0 1 0 1 1 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 1 1 1 1 \n"
+ + "0 1 0 0 1 1 0 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 1 0 1 1 \n"
+ + "1 0 1 0 1 \n"
+ + "1 0 1 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 0 0 1 1 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 1 0 0 1 \n"
+ + "1 0 1 0 1 \n"
+ + "1 0 1 0 1 \n"
+ + "1 0 1 0 1 \n"
+ + "1 0 0 1 1 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 0 0 1 1 1 0 \n"
+ + "0 1 1 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 1 1 0 \n"
+ + "0 1 0 0 1 1 1 1 \n"
+ + "1 1 1 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 1 1 1 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "0 1 0 1 0 0 0 0 \n"
+ + "0 1 1 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 1 0 1 \n"
+ + "1 0 0 1 1 \n"
+ + "0 1 1 1 1 \n"
+ + "0 1 0 1 0 0 0 1 \n"
+ + "1 1 1 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 1 1 1 0 \n"
+ + "1 0 1 0 0 \n"
+ + "1 0 0 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 0 1 0 0 1 0 \n"
+ + "0 1 1 1 1 \n"
+ + "1 0 0 0 0 \n"
+ + "1 0 0 0 0 \n"
+ + "0 1 1 1 0 \n"
+ + "0 0 0 0 1 \n"
+ + "0 0 0 0 1 \n"
+ + "1 1 1 1 0 \n"
+ + "0 1 0 1 0 0 1 1 \n"
+ + "1 1 1 1 1 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 1 0 1 0 1 0 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 1 1 0 \n"
+ + "0 1 0 1 0 1 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 0 1 0 \n"
+ + "0 1 0 1 0 \n"
+ + "0 1 0 1 0 \n"
+ + "0 1 0 1 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 1 0 1 0 1 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 0 0 1 \n"
+ + "1 0 1 0 1 \n"
+ + "1 0 1 0 1 \n"
+ + "1 0 1 0 1 \n"
+ + "0 1 0 1 0 \n"
+ + "0 1 0 1 0 1 1 1 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 0 1 0 \n"
+ + "0 1 0 1 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 1 0 1 0 \n"
+ + "0 1 0 1 0 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 0 1 1 0 0 0 \n"
+ + "1 0 0 0 1 \n"
+ + "0 1 0 1 0 \n"
+ + "0 1 0 1 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 1 0 1 1 0 0 1 \n"
+ + "1 1 1 1 1 \n"
+ + "0 0 0 1 0 \n"
+ + "0 0 0 1 0 \n"
+ + "0 0 1 0 0 \n"
+ + "0 1 0 0 0 \n"
+ + "0 1 0 0 0 \n"
+ + "1 1 1 1 1 \n"
+ + "0 1 0 1 1 0 1 0 \n"
+ + " \n";
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/neural.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/neural.cs
new file mode 100644
index 0000000000..9e842c3910
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/neural.cs
@@ -0,0 +1,883 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/********************************
+** BACK PROPAGATION NEURAL NET **
+*********************************
+** This code is a modified version of the code
+** that was submitted to BYTE Magazine by
+** Maureen Caudill. It accomanied an article
+** that I CANNOT NOW RECALL.
+** The author's original heading/comment was
+** as follows:
+**
+** Backpropagation Network
+** Written by Maureen Caudill
+** in Think C 4.0 on a Macintosh
+**
+** (c) Maureen Caudill 1988-1991
+** This network will accept 5x7 input patterns
+** and produce 8 bit output patterns.
+** The source code may be copied or modified without restriction,
+** but no fee may be charged for its use.
+**
+** ++++++++++++++
+** I have modified the code so that it will work
+** on systems other than a Macintosh -- RG
+*/
+
+/***********
+** DoNNet **
+************
+** Perform the neural net benchmark.
+** Note that this benchmark is one of the few that
+** requires an input file. That file is "NNET.DAT" and
+** should be on the local directory (from which the
+** benchmark program in launched).
+*/
+
+using System;
+using System.IO;
+
+public class Neural : NNetStruct
+{
+ public override string Name()
+ {
+ return "NEURAL NET(rectangle)";
+ }
+
+ /*
+ ** DEFINES
+ */
+ public static int T = 1; /* TRUE */
+ public static int F = 0; /* FALSE */
+ public static int ERR = -1;
+ public static int MAXPATS = 10; /* max number of patterns in data file */
+ public static int IN_X_SIZE = 5; /* number of neurodes/row of input layer */
+ public static int IN_Y_SIZE = 7; /* number of neurodes/col of input layer */
+ public static int IN_SIZE = 35; /* equals IN_X_SIZE*IN_Y_SIZE */
+ public static int MID_SIZE = 8; /* number of neurodes in middle layer */
+ public static int OUT_SIZE = 8; /* number of neurodes in output layer */
+ public static double MARGIN = 0.1; /* how near to 1,0 do we have to come to stop? */
+ public static double BETA = 0.09; /* beta learning constant */
+ public static double ALPHA = 0.09; /* momentum term constant */
+ public static double STOP = 0.1; /* when worst_error less than STOP, training is done */
+
+ /*
+ ** MAXNNETLOOPS
+ **
+ ** This constant sets the max number of loops through the neural
+ ** net that the system will attempt before giving up. This
+ ** is not a critical constant. You can alter it if your system
+ ** has sufficient horsepower.
+ */
+ public static int MAXNNETLOOPS = 50000;
+
+
+ /*
+ ** GLOBALS
+ */
+ public static double[,] mid_wts = new double[MID_SIZE, IN_SIZE]; /* middle layer weights */
+ public static double[,] out_wts = new double[OUT_SIZE, MID_SIZE];
+ public static double[] mid_out = new double[MID_SIZE];
+ public static double[] out_out = new double[OUT_SIZE];
+ public static double[] mid_error = new double[MID_SIZE];
+ public static double[] out_error = new double[OUT_SIZE];
+ public static double[,] mid_wt_change = new double[MID_SIZE, IN_SIZE];
+ public static double[,] out_wt_change = new double[OUT_SIZE, MID_SIZE];
+ public static double[,] in_pats = new double[MAXPATS, IN_SIZE];
+ public static double[,] out_pats = new double[MAXPATS, OUT_SIZE];
+ public static double[] tot_out_error = new double[MAXPATS];
+ public static double[,] out_wt_cum_change = new double[OUT_SIZE, MID_SIZE];
+ public static double[,] mid_wt_cum_change = new double[MID_SIZE, IN_SIZE];
+ public static double worst_error = 0.0; /* worst error each pass through the data */
+ public static double average_error = 0.0; /* average error each pass through the data */
+ public static double[] avg_out_error = new double[MAXPATS];
+
+ public static int iteration_count = 0; /* number of passes thru network so far */
+ public static int numpats = 0; /* number of patterns in data file */
+ public static int numpasses = 0; /* number of training passes through data file */
+ public static int learned = 0; /* flag--if TRUE, network has learned all patterns */
+
+ /*
+ ** The Neural Net test requires an input data file.
+ ** The name is specified here.
+ */
+ public static string inpath = "NNET.DAT";
+
+ public override
+ double Run()
+ {
+ return DoNNET(this);
+ }
+
+ /*********************
+ ** read_data_file() **
+ **********************
+ ** Read in the input data file and store the patterns in
+ ** in_pats and out_pats.
+ ** The format for the data file is as follows:
+ **
+ ** line# data expected
+ ** ----- ------------------------------
+ ** 1 In-X-size,in-y-size,out-size
+ ** 2 number of patterns in file
+ ** 3 1st X row of 1st input pattern
+ ** 4.. following rows of 1st input pattern pattern
+ ** in-x+2 y-out pattern
+ ** 1st X row of 2nd pattern
+ ** etc.
+ **
+ ** Each row of data is separated by commas or spaces.
+ ** The data is expected to be ascii text corresponding to
+ ** either a +1 or a 0.
+ **
+ ** Sample input for a 1-pattern file (The comments to the
+ ** right may NOT be in the file unless more sophisticated
+ ** parsing of the input is done.):
+ **
+ ** 5,7,8 input is 5x7 grid, output is 8 bits
+ ** 1 one pattern in file
+ ** 0,1,1,1,0 beginning of pattern for "O"
+ ** 1,0,0,0,1
+ ** 1,0,0,0,1
+ ** 1,0,0,0,1
+ ** 1,0,0,0,1
+ ** 1,0,0,0,0
+ ** 0,1,1,1,0
+ ** 0,1,0,0,1,1,1,1 ASCII code for "O" -- 0100 1111
+ **
+ ** Clearly, this simple scheme can be expanded or enhanced
+ ** any way you like.
+ **
+ ** Returns -1 if any file error occurred, otherwise 0.
+ **/
+ private
+ void read_data_file()
+ {
+ int xinsize = 0, yinsize = 0, youtsize = 0;
+ int patt = 0, element = 0, i = 0, row = 0;
+ int vals_read = 0;
+ int val1 = 0, val2 = 0, val3 = 0, val4 = 0, val5 = 0, val6 = 0, val7 = 0, val8 = 0;
+ Object[] results = new Object[8];
+
+ string input = NeuralData.Input;
+
+ StringReader infile = new StringReader(input);
+
+ vals_read = Utility.fscanf(infile, "%d %d %d", results);
+ xinsize = (int)results[0];
+ yinsize = (int)results[1];
+ youtsize = (int)results[2];
+
+ if (vals_read != 3)
+ {
+ throw new Exception("NNET: error reading input");
+ }
+ vals_read = Utility.fscanf(infile, "%d", results);
+ numpats = (int)results[0];
+ if (vals_read != 1)
+ {
+ throw new Exception("NNET: error reading input");
+ }
+ if (numpats > MAXPATS)
+ numpats = MAXPATS;
+
+ for (patt = 0; patt < numpats; patt++)
+ {
+ element = 0;
+ for (row = 0; row < yinsize; row++)
+ {
+ vals_read = Utility.fscanf(infile, "%d %d %d %d %d", results);
+ val1 = (int)results[0];
+ val2 = (int)results[1];
+ val3 = (int)results[2];
+ val4 = (int)results[3];
+ val5 = (int)results[4];
+ if (vals_read != 5)
+ {
+ throw new Exception("NNET: error reading input");
+ }
+ element = row * xinsize;
+
+ in_pats[patt, element] = (double)val1; element++;
+ in_pats[patt, element] = (double)val2; element++;
+ in_pats[patt, element] = (double)val3; element++;
+ in_pats[patt, element] = (double)val4; element++;
+ in_pats[patt, element] = (double)val5; element++;
+ }
+ for (i = 0; i < IN_SIZE; i++)
+ {
+ if (in_pats[patt, i] >= 0.9)
+ in_pats[patt, i] = 0.9;
+ if (in_pats[patt, i] <= 0.1)
+ in_pats[patt, i] = 0.1;
+ }
+ element = 0;
+ vals_read = Utility.fscanf(infile, "%d %d %d %d %d %d %d %d", results);
+ val1 = (int)results[0];
+ val2 = (int)results[1];
+ val3 = (int)results[2];
+ val4 = (int)results[3];
+ val5 = (int)results[4];
+ val6 = (int)results[5];
+ val7 = (int)results[6];
+ val8 = (int)results[7];
+
+ out_pats[patt, element] = (double)val1; element++;
+ out_pats[patt, element] = (double)val2; element++;
+ out_pats[patt, element] = (double)val3; element++;
+ out_pats[patt, element] = (double)val4; element++;
+ out_pats[patt, element] = (double)val5; element++;
+ out_pats[patt, element] = (double)val6; element++;
+ out_pats[patt, element] = (double)val7; element++;
+ out_pats[patt, element] = (double)val8; element++;
+ }
+ }
+
+
+ private
+ double DoNNET(NNetStruct locnnetstruct)
+ {
+ // string errorcontext = "CPU:NNET";
+ // int systemerror = 0;
+ long accumtime = 0;
+ double iterations = 0.0;
+
+ /*
+ ** Init random number generator.
+ ** NOTE: It is important that the random number generator
+ ** be re-initialized for every pass through this test.
+ ** The NNET algorithm uses the random number generator
+ ** to initialize the net. Results are sensitive to
+ ** the initial neural net state.
+ */
+ ByteMark.randnum(3);
+
+ /*
+ ** Read in the input and output patterns. We'll do this
+ ** only once here at the beginning. These values don't
+ ** change once loaded.
+ */
+ read_data_file();
+
+ /*
+ ** See if we need to perform self adjustment loop.
+ */
+ if (locnnetstruct.adjust == 0)
+ {
+ /*
+ ** Do self-adjustment. This involves initializing the
+ ** # of loops and increasing the loop count until we
+ ** get a number of loops that we can use.
+ */
+ for (locnnetstruct.loops = 1;
+ locnnetstruct.loops < MAXNNETLOOPS;
+ locnnetstruct.loops++)
+ {
+ ByteMark.randnum(3);
+ if (DoNNetIteration(locnnetstruct.loops) > global.min_ticks)
+ break;
+ }
+ }
+
+ /*
+ ** All's well if we get here. Do the test.
+ */
+ accumtime = 0L;
+ iterations = (double)0.0;
+
+ do
+ {
+ ByteMark.randnum(3); /* Gotta do this for Neural Net */
+ accumtime += DoNNetIteration(locnnetstruct.loops);
+ iterations += (double)locnnetstruct.loops;
+ } while (ByteMark.TicksToSecs(accumtime) < locnnetstruct.request_secs);
+
+ /*
+ ** Clean up, calculate results, and go home. Be sure to
+ ** show that we don't have to rerun adjustment code.
+ */
+ locnnetstruct.iterspersec = iterations / ByteMark.TicksToFracSecs(accumtime);
+
+ if (locnnetstruct.adjust == 0)
+ locnnetstruct.adjust = 1;
+
+
+ return locnnetstruct.iterspersec;
+ }
+
+ /********************
+ ** DoNNetIteration **
+ *********************
+ ** Do a single iteration of the neural net benchmark.
+ ** By iteration, we mean a "learning" pass.
+ */
+ public static long DoNNetIteration(long nloops)
+ {
+ long elapsed; /* Elapsed time */
+ int patt;
+
+ /*
+ ** Run nloops learning cycles. Notice that, counted with
+ ** the learning cycle is the weight randomization and
+ ** zeroing of changes. This should reduce clock jitter,
+ ** since we don't have to stop and start the clock for
+ ** each iteration.
+ */
+ elapsed = ByteMark.StartStopwatch();
+ while (nloops-- != 0)
+ {
+ randomize_wts();
+ zero_changes();
+ iteration_count = 1;
+ learned = F;
+ numpasses = 0;
+ while (learned == F)
+ {
+ for (patt = 0; patt < numpats; patt++)
+ {
+ worst_error = 0.0; /* reset this every pass through data */
+ move_wt_changes(); /* move last pass's wt changes to momentum array */
+ do_forward_pass(patt);
+ do_back_pass(patt);
+ iteration_count++;
+ }
+ numpasses++;
+ learned = check_out_error();
+ }
+ }
+ return (ByteMark.StopStopwatch(elapsed));
+ }
+
+ /*************************
+ ** do_mid_forward(patt) **
+ **************************
+ ** Process the middle layer's forward pass
+ ** The activation of middle layer's neurode is the weighted
+ ** sum of the inputs from the input pattern, with sigmoid
+ ** function applied to the inputs.
+ **/
+ public static void do_mid_forward(int patt)
+ {
+ double sum;
+ int neurode, i;
+
+ for (neurode = 0; neurode < MID_SIZE; neurode++)
+ {
+ sum = 0.0;
+ for (i = 0; i < IN_SIZE; i++)
+ { /* compute weighted sum of input signals */
+ sum += mid_wts[neurode, i] * in_pats[patt, i];
+ }
+ /*
+ ** apply sigmoid function f(x) = 1/(1+exp(-x)) to weighted sum
+ */
+ sum = 1.0 / (1.0 + Math.Exp(-sum));
+ mid_out[neurode] = sum;
+ }
+ return;
+ }
+
+ /*********************
+ ** do_out_forward() **
+ **********************
+ ** process the forward pass through the output layer
+ ** The activation of the output layer is the weighted sum of
+ ** the inputs (outputs from middle layer), modified by the
+ ** sigmoid function.
+ **/
+ public static void do_out_forward()
+ {
+ double sum;
+ int neurode, i;
+
+ for (neurode = 0; neurode < OUT_SIZE; neurode++)
+ {
+ sum = 0.0;
+ for (i = 0; i < MID_SIZE; i++)
+ { /*
+ ** compute weighted sum of input signals
+ ** from middle layer
+ */
+ sum += out_wts[neurode, i] * mid_out[i];
+ }
+ /*
+ ** Apply f(x) = 1/(1+Math.Exp(-x)) to weighted input
+ */
+ sum = 1.0 / (1.0 + Math.Exp(-sum));
+ out_out[neurode] = sum;
+ }
+ return;
+ }
+
+ /*************************
+ ** display_output(patt) **
+ **************************
+ ** Display the actual output vs. the desired output of the
+ ** network.
+ ** Once the training is complete, and the "learned" flag set
+ ** to TRUE, then display_output sends its output to both
+ ** the screen and to a text output file.
+ **
+ ** NOTE: This routine has been disabled in the benchmark
+ ** version. -- RG
+ **/
+ /*
+ public static void display_output(int patt)
+ {
+ int i;
+
+ fprintf(outfile,"\n Iteration # %d",iteration_count);
+ fprintf(outfile,"\n Desired Output: ");
+
+ for (i=0; i<OUT_SIZE; i++)
+ {
+ fprintf(outfile,"%6.3f ",out_pats[patt][i]);
+ }
+ fprintf(outfile,"\n Actual Output: ");
+
+ for (i=0; i<OUT_SIZE; i++)
+ {
+ fprintf(outfile,"%6.3f ",out_out[i]);
+ }
+ fprintf(outfile,"\n");
+ return;
+ }
+ */
+
+ /**********************
+ ** do_forward_pass() **
+ ***********************
+ ** control function for the forward pass through the network
+ ** NOTE: I have disabled the call to display_output() in
+ ** the benchmark version -- RG.
+ **/
+ public static void do_forward_pass(int patt)
+ {
+ do_mid_forward(patt); /* process forward pass, middle layer */
+ do_out_forward(); /* process forward pass, output layer */
+ /* display_output(patt); ** display results of forward pass */
+ return;
+ }
+
+ /***********************
+ ** do_out_error(patt) **
+ ************************
+ ** Compute the error for the output layer neurodes.
+ ** This is simply Desired - Actual.
+ **/
+ public static void do_out_error(int patt)
+ {
+ int neurode;
+ double error, tot_error, sum;
+
+ tot_error = 0.0;
+ sum = 0.0;
+ for (neurode = 0; neurode < OUT_SIZE; neurode++)
+ {
+ out_error[neurode] = out_pats[patt, neurode] - out_out[neurode];
+ /*
+ ** while we're here, also compute magnitude
+ ** of total error and worst error in this pass.
+ ** We use these to decide if we are done yet.
+ */
+ error = out_error[neurode];
+ if (error < 0.0)
+ {
+ sum += -error;
+ if (-error > tot_error)
+ tot_error = -error; /* worst error this pattern */
+ }
+ else
+ {
+ sum += error;
+ if (error > tot_error)
+ tot_error = error; /* worst error this pattern */
+ }
+ }
+ avg_out_error[patt] = sum / OUT_SIZE;
+ tot_out_error[patt] = tot_error;
+ return;
+ }
+
+ /***********************
+ ** worst_pass_error() **
+ ************************
+ ** Find the worst and average error in the pass and save it
+ **/
+ public static void worst_pass_error()
+ {
+ double error, sum;
+
+ int i;
+
+ error = 0.0;
+ sum = 0.0;
+ for (i = 0; i < numpats; i++)
+ {
+ if (tot_out_error[i] > error) error = tot_out_error[i];
+ sum += avg_out_error[i];
+ }
+ worst_error = error;
+ average_error = sum / numpats;
+ return;
+ }
+
+ /*******************
+ ** do_mid_error() **
+ ********************
+ ** Compute the error for the middle layer neurodes
+ ** This is based on the output errors computed above.
+ ** Note that the derivative of the sigmoid f(x) is
+ ** f'(x) = f(x)(1 - f(x))
+ ** Recall that f(x) is merely the output of the middle
+ ** layer neurode on the forward pass.
+ **/
+ public static void do_mid_error()
+ {
+ double sum;
+ int neurode, i;
+
+ for (neurode = 0; neurode < MID_SIZE; neurode++)
+ {
+ sum = 0.0;
+ for (i = 0; i < OUT_SIZE; i++)
+ sum += out_wts[i, neurode] * out_error[i];
+
+ /*
+ ** apply the derivative of the sigmoid here
+ ** Because of the choice of sigmoid f(I), the derivative
+ ** of the sigmoid is f'(I) = f(I)(1 - f(I))
+ */
+ mid_error[neurode] = mid_out[neurode] * (1 - mid_out[neurode]) * sum;
+ }
+ return;
+ }
+
+ /*********************
+ ** adjust_out_wts() **
+ **********************
+ ** Adjust the weights of the output layer. The error for
+ ** the output layer has been previously propagated back to
+ ** the middle layer.
+ ** Use the Delta Rule with momentum term to adjust the weights.
+ **/
+ public static void adjust_out_wts()
+ {
+ int weight, neurode;
+ double learn, delta, alph;
+
+ learn = BETA;
+ alph = ALPHA;
+ for (neurode = 0; neurode < OUT_SIZE; neurode++)
+ {
+ for (weight = 0; weight < MID_SIZE; weight++)
+ {
+ /* standard delta rule */
+ delta = learn * out_error[neurode] * mid_out[weight];
+
+ /* now the momentum term */
+ delta += alph * out_wt_change[neurode, weight];
+ out_wts[neurode, weight] += delta;
+
+ /* keep track of this pass's cum wt changes for next pass's momentum */
+ out_wt_cum_change[neurode, weight] += delta;
+ }
+ }
+ return;
+ }
+
+ /*************************
+ ** adjust_mid_wts(patt) **
+ **************************
+ ** Adjust the middle layer weights using the previously computed
+ ** errors.
+ ** We use the Generalized Delta Rule with momentum term
+ **/
+ public static void adjust_mid_wts(int patt)
+ {
+ int weight, neurode;
+ double learn, alph, delta;
+
+ learn = BETA;
+ alph = ALPHA;
+ for (neurode = 0; neurode < MID_SIZE; neurode++)
+ {
+ for (weight = 0; weight < IN_SIZE; weight++)
+ {
+ /* first the basic delta rule */
+ delta = learn * mid_error[neurode] * in_pats[patt, weight];
+
+ /* with the momentum term */
+ delta += alph * mid_wt_change[neurode, weight];
+ mid_wts[neurode, weight] += delta;
+
+ /* keep track of this pass's cum wt changes for next pass's momentum */
+ mid_wt_cum_change[neurode, weight] += delta;
+ }
+ }
+ return;
+ }
+
+ /*******************
+ ** do_back_pass() **
+ ********************
+ ** Process the backward propagation of error through network.
+ **/
+ public static void do_back_pass(int patt)
+ {
+ do_out_error(patt);
+ do_mid_error();
+ adjust_out_wts();
+ adjust_mid_wts(patt);
+
+ return;
+ }
+
+
+ /**********************
+ ** move_wt_changes() **
+ ***********************
+ ** Move the weight changes accumulated last pass into the wt-change
+ ** array for use by the momentum term in this pass. Also zero out
+ ** the accumulating arrays after the move.
+ **/
+ public static void move_wt_changes()
+ {
+ int i, j;
+
+ for (i = 0; i < MID_SIZE; i++)
+ for (j = 0; j < IN_SIZE; j++)
+ {
+ mid_wt_change[i, j] = mid_wt_cum_change[i, j];
+ /*
+ ** Zero it out for next pass accumulation.
+ */
+ mid_wt_cum_change[i, j] = 0.0;
+ }
+
+ for (i = 0; i < OUT_SIZE; i++)
+ for (j = 0; j < MID_SIZE; j++)
+ {
+ out_wt_change[i, j] = out_wt_cum_change[i, j];
+ out_wt_cum_change[i, j] = 0.0;
+ }
+
+ return;
+ }
+
+ /**********************
+ ** check_out_error() **
+ ***********************
+ ** Check to see if the error in the output layer is below
+ ** MARGIN*OUT_SIZE for all output patterns. If so, then
+ ** assume the network has learned acceptably well. This
+ ** is simply an arbitrary measure of how well the network
+ ** has learned -- many other standards are possible.
+ **/
+ public static int check_out_error()
+ {
+ int result, i, error;
+
+ result = T;
+ error = F;
+ worst_pass_error(); /* identify the worst error in this pass */
+
+ /*
+ #if DEBUG
+ Console.WriteLine("\n Iteration # {0}",iteration_count);
+ #endif
+ */
+ for (i = 0; i < numpats; i++)
+ {
+ /* printf("\n Error pattern %d: Worst: %8.3f; Average: %8.3f",
+ i+1,tot_out_error[i], avg_out_error[i]);
+ fprintf(outfile,
+ "\n Error pattern %d: Worst: %8.3f; Average: %8.3f",
+ i+1,tot_out_error[i]);
+ */
+
+ if (worst_error >= STOP) result = F;
+ if (tot_out_error[i] >= 16.0) error = T;
+ }
+
+ if (error == T) result = ERR;
+
+
+#if DEBUG
+ /* printf("\n Error this pass thru data: Worst: %8.3f; Average: %8.3f",
+ worst_error,average_error);
+ */
+ /* fprintf(outfile,
+ "\n Error this pass thru data: Worst: %8.3f; Average: %8.3f",
+ worst_error, average_error); */
+#endif
+
+ return (result);
+ }
+
+
+ /*******************
+ ** zero_changes() **
+ ********************
+ ** Zero out all the wt change arrays
+ **/
+ public static void zero_changes()
+ {
+ int i, j;
+
+ for (i = 0; i < MID_SIZE; i++)
+ {
+ for (j = 0; j < IN_SIZE; j++)
+ {
+ mid_wt_change[i, j] = 0.0;
+ mid_wt_cum_change[i, j] = 0.0;
+ }
+ }
+
+ for (i = 0; i < OUT_SIZE; i++)
+ {
+ for (j = 0; j < MID_SIZE; j++)
+ {
+ out_wt_change[i, j] = 0.0;
+ out_wt_cum_change[i, j] = 0.0;
+ }
+ }
+ return;
+ }
+
+
+ /********************
+ ** randomize_wts() **
+ *********************
+ ** Intialize the weights in the middle and output layers to
+ ** random values between -0.25..+0.25
+ ** Function rand() returns a value between 0 and 32767.
+ **
+ ** NOTE: Had to make alterations to how the random numbers were
+ ** created. -- RG.
+ **/
+ public static void randomize_wts()
+ {
+ int neurode, i;
+ double value;
+
+ /*
+ ** Following not used int benchmark version -- RG
+ **
+ ** printf("\n Please enter a random number seed (1..32767): ");
+ ** scanf("%d", &i);
+ ** srand(i);
+ */
+
+ for (neurode = 0; neurode < MID_SIZE; neurode++)
+ {
+ for (i = 0; i < IN_SIZE; i++)
+ {
+ value = (double)ByteMark.abs_randwc(100000);
+ value = value / (double)100000.0 - (double)0.5;
+ mid_wts[neurode, i] = value / 2;
+ }
+ }
+ for (neurode = 0; neurode < OUT_SIZE; neurode++)
+ {
+ for (i = 0; i < MID_SIZE; i++)
+ {
+ value = (double)ByteMark.abs_randwc(100000);
+ value = value / (double)10000.0 - (double)0.5;
+ out_wts[neurode, i] = value / 2;
+ }
+ }
+ return;
+ }
+
+ /**********************
+ ** display_mid_wts() **
+ ***********************
+ ** Display the weights on the middle layer neurodes
+ ** NOTE: This routine is not used in the benchmark
+ ** test -- RG
+ **/
+ /* static void display_mid_wts()
+ {
+ int neurode, weight, row, col;
+
+ fprintf(outfile,"\n Weights of Middle Layer neurodes:");
+
+ for (neurode=0; neurode<MID_SIZE; neurode++)
+ {
+ fprintf(outfile,"\n Mid Neurode # %d",neurode);
+ for (row=0; row<IN_Y_SIZE; row++)
+ {
+ fprintf(outfile,"\n ");
+ for (col=0; col<IN_X_SIZE; col++)
+ {
+ weight = IN_X_SIZE * row + col;
+ fprintf(outfile," %8.3f ", mid_wts[neurode,weight]);
+ }
+ }
+ }
+ return;
+ }
+ */
+ /**********************
+ ** display_out_wts() **
+ ***********************
+ ** Display the weights on the output layer neurodes
+ ** NOTE: This code is not used in the benchmark
+ ** test -- RG
+ */
+ /* void display_out_wts()
+ {
+ int neurode, weight;
+
+ fprintf(outfile,"\n Weights of Output Layer neurodes:");
+
+ for (neurode=0; neurode<OUT_SIZE; neurode++)
+ {
+ fprintf(outfile,"\n Out Neurode # %d \n",neurode);
+ for (weight=0; weight<MID_SIZE; weight++)
+ {
+ fprintf(outfile," %8.3f ", out_wts[neurode,weight]);
+ }
+ }
+ return;
+ }
+ */
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/neuraljagged.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/neuraljagged.cs
new file mode 100644
index 0000000000..d9dd199c98
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/neuraljagged.cs
@@ -0,0 +1,882 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/********************************
+** BACK PROPAGATION NEURAL NET **
+*********************************
+** This code is a modified version of the code
+** that was submitted to BYTE Magazine by
+** Maureen Caudill. It accomanied an article
+** that I CANNOT NOW RECALL.
+** The author's original heading/comment was
+** as follows:
+**
+** Backpropagation Network
+** Written by Maureen Caudill
+** in Think C 4.0 on a Macintosh
+**
+** (c) Maureen Caudill 1988-1991
+** This network will accept 5x7 input patterns
+** and produce 8 bit output patterns.
+** The source code may be copied or modified without restriction,
+** but no fee may be charged for its use.
+**
+** ++++++++++++++
+** I have modified the code so that it will work
+** on systems other than a Macintosh -- RG
+*/
+
+/***********
+** DoNNet **
+************
+** Perform the neural net benchmark.
+** Note that this benchmark is one of the few that
+** requires an input file. That file is "NNET.DAT" and
+** should be on the local directory (from which the
+** benchmark program in launched).
+*/
+
+using System;
+using System.IO;
+
+public class NeuralJagged : NNetStruct
+{
+ public override string Name()
+ {
+ return "NEURAL NET(jagged)";
+ }
+
+ /*
+ ** DEFINES
+ */
+ public static int T = 1; /* TRUE */
+ public static int F = 0; /* FALSE */
+ public static int ERR = -1;
+ public static int MAXPATS = 10; /* max number of patterns in data file */
+ public static int IN_X_SIZE = 5; /* number of neurodes/row of input layer */
+ public static int IN_Y_SIZE = 7; /* number of neurodes/col of input layer */
+ public static int IN_SIZE = 35; /* equals IN_X_SIZE*IN_Y_SIZE */
+ public static int MID_SIZE = 8; /* number of neurodes in middle layer */
+ public static int OUT_SIZE = 8; /* number of neurodes in output layer */
+ public static double MARGIN = 0.1; /* how near to 1,0 do we have to come to stop? */
+ public static double BETA = 0.09; /* beta learning constant */
+ public static double ALPHA = 0.09; /* momentum term constant */
+ public static double STOP = 0.1; /* when worst_error less than STOP, training is done */
+
+ /*
+ ** MAXNNETLOOPS
+ **
+ ** This constant sets the max number of loops through the neural
+ ** net that the system will attempt before giving up. This
+ ** is not a critical constant. You can alter it if your system
+ ** has sufficient horsepower.
+ */
+ public static int MAXNNETLOOPS = 50000;
+
+
+ /*
+ ** GLOBALS
+
+
+ */
+ public static double[][] mid_wts = new double[MID_SIZE][];
+ public static double[][] out_wts = new double[OUT_SIZE][];
+ public static double[] mid_out = new double[MID_SIZE];
+ public static double[] out_out = new double[OUT_SIZE];
+ public static double[] mid_error = new double[MID_SIZE];
+ public static double[] out_error = new double[OUT_SIZE];
+ public static double[][] mid_wt_change = new double[MID_SIZE][];
+ public static double[][] out_wt_change = new double[OUT_SIZE][];
+ public static double[][] in_pats = new double[MAXPATS][];
+ public static double[][] out_pats = new double[MAXPATS][];
+ public static double[] tot_out_error = new double[MAXPATS];
+ public static double[][] out_wt_cum_change = new double[OUT_SIZE][];
+ public static double[][] mid_wt_cum_change = new double[MID_SIZE][];
+
+ public static double worst_error = 0.0; /* worst error each pass through the data */
+ public static double average_error = 0.0; /* average error each pass through the data */
+ public static double[] avg_out_error = new double[MAXPATS];
+ public static int iteration_count = 0; /* number of passes thru network so far */
+ public static int numpats = 0; /* number of patterns in data file */
+ public static int numpasses = 0; /* number of training passes through data file */
+ public static int learned = 0; /* flag--if TRUE, network has learned all patterns */
+
+ /*
+ ** The Neural Net test requires an input data file.
+ ** The name is specified here.
+ */
+ public static string inpath = "NNET.DAT";
+
+
+ public static void Init()
+ {
+ for (int i = 0; i < MID_SIZE; i++)
+ {
+ mid_wts[i] = new double[IN_SIZE];
+ mid_wt_cum_change[i] = new double[IN_SIZE];
+ mid_wt_change[i] = new double[IN_SIZE];
+ }
+ for (int i = 0; i < OUT_SIZE; i++)
+ {
+ out_wt_change[i] = new double[MID_SIZE];
+ out_wts[i] = new double[MID_SIZE];
+ out_wt_cum_change[i] = new double[MID_SIZE];
+ }
+
+ for (int i = 0; i < MAXPATS; i++)
+ {
+ in_pats[i] = new double[IN_SIZE];
+ out_pats[i] = new double[OUT_SIZE];
+ }
+ }
+
+ public override
+ double Run()
+ {
+ Init();
+ return DoNNET(this);
+ }
+
+ /*********************
+ ** read_data_file() **
+ **********************
+ ** Read in the input data file and store the patterns in
+ ** in_pats and out_pats.
+ ** The format for the data file is as follows:
+ **
+ ** line# data expected
+ ** ----- ------------------------------
+ ** 1 In-X-size,in-y-size,out-size
+ ** 2 number of patterns in file
+ ** 3 1st X row of 1st input pattern
+ ** 4.. following rows of 1st input pattern pattern
+ ** in-x+2 y-out pattern
+ ** 1st X row of 2nd pattern
+ ** etc.
+ **
+ ** Each row of data is separated by commas or spaces.
+ ** The data is expected to be ascii text corresponding to
+ ** either a +1 or a 0.
+ **
+ ** Sample input for a 1-pattern file (The comments to the
+ ** right may NOT be in the file unless more sophisticated
+ ** parsing of the input is done.):
+ **
+ ** 5,7,8 input is 5x7 grid, output is 8 bits
+ ** 1 one pattern in file
+ ** 0,1,1,1,0 beginning of pattern for "O"
+ ** 1,0,0,0,1
+ ** 1,0,0,0,1
+ ** 1,0,0,0,1
+ ** 1,0,0,0,1
+ ** 1,0,0,0,0
+ ** 0,1,1,1,0
+ ** 0,1,0,0,1,1,1,1 ASCII code for "O" -- 0100 1111
+ **
+ ** Clearly, this simple scheme can be expanded or enhanced
+ ** any way you like.
+ **
+ ** Returns -1 if any file error occurred, otherwise 0.
+ **/
+ private
+ void read_data_file()
+ {
+ int xinsize = 0, yinsize = 0, youtsize = 0;
+ int patt = 0, element = 0, i = 0, row = 0;
+ int vals_read = 0;
+ int val1 = 0, val2 = 0, val3 = 0, val4 = 0, val5 = 0, val6 = 0, val7 = 0, val8 = 0;
+ Object[] results = new Object[8];
+ string input = NeuralData.Input;
+ StringReader infile = new StringReader(input);
+
+ vals_read = Utility.fscanf(infile, "%d %d %d", results);
+ xinsize = (int)results[0];
+ yinsize = (int)results[1];
+ youtsize = (int)results[2];
+
+ if (vals_read != 3)
+ {
+ throw new Exception("NNET: error reading input");
+ }
+ vals_read = Utility.fscanf(infile, "%d", results);
+ numpats = (int)results[0];
+ if (vals_read != 1)
+ {
+ throw new Exception("NNET: error reading input");
+ }
+ if (numpats > MAXPATS)
+ numpats = MAXPATS;
+
+ for (patt = 0; patt < numpats; patt++)
+ {
+ element = 0;
+ for (row = 0; row < yinsize; row++)
+ {
+ vals_read = Utility.fscanf(infile, "%d %d %d %d %d", results);
+ val1 = (int)results[0];
+ val2 = (int)results[1];
+ val3 = (int)results[2];
+ val4 = (int)results[3];
+ val5 = (int)results[4];
+ if (vals_read != 5)
+ {
+ throw new Exception("NNET: error reading input");
+ }
+ element = row * xinsize;
+
+ in_pats[patt][element] = (double)val1; element++;
+ in_pats[patt][element] = (double)val2; element++;
+ in_pats[patt][element] = (double)val3; element++;
+ in_pats[patt][element] = (double)val4; element++;
+ in_pats[patt][element] = (double)val5; element++;
+ }
+ for (i = 0; i < IN_SIZE; i++)
+ {
+ if (in_pats[patt][i] >= 0.9)
+ in_pats[patt][i] = 0.9;
+ if (in_pats[patt][i] <= 0.1)
+ in_pats[patt][i] = 0.1;
+ }
+ element = 0;
+ vals_read = Utility.fscanf(infile, "%d %d %d %d %d %d %d %d", results);
+ val1 = (int)results[0];
+ val2 = (int)results[1];
+ val3 = (int)results[2];
+ val4 = (int)results[3];
+ val5 = (int)results[4];
+ val6 = (int)results[5];
+ val7 = (int)results[6];
+ val8 = (int)results[7];
+
+ out_pats[patt][element] = (double)val1; element++;
+ out_pats[patt][element] = (double)val2; element++;
+ out_pats[patt][element] = (double)val3; element++;
+ out_pats[patt][element] = (double)val4; element++;
+ out_pats[patt][element] = (double)val5; element++;
+ out_pats[patt][element] = (double)val6; element++;
+ out_pats[patt][element] = (double)val7; element++;
+ out_pats[patt][element] = (double)val8; element++;
+ }
+ }
+
+ private
+ double DoNNET(NNetStruct locnnetstruct)
+ {
+ // string errorcontext = "CPU:NNET";
+ // int systemerror = 0;
+ long accumtime = 0;
+ double iterations = 0.0;
+
+ /*
+ ** Init random number generator.
+ ** NOTE: It is important that the random number generator
+ ** be re-initialized for every pass through this test.
+ ** The NNET algorithm uses the random number generator
+ ** to initialize the net. Results are sensitive to
+ ** the initial neural net state.
+ */
+ ByteMark.randnum(3);
+
+ /*
+ ** Read in the input and output patterns. We'll do this
+ ** only once here at the beginning. These values don't
+ ** change once loaded.
+ */
+ read_data_file();
+
+ /*
+ ** See if we need to perform self adjustment loop.
+ */
+ if (locnnetstruct.adjust == 0)
+ {
+ /*
+ ** Do self-adjustment. This involves initializing the
+ ** # of loops and increasing the loop count until we
+ ** get a number of loops that we can use.
+ */
+ for (locnnetstruct.loops = 1;
+ locnnetstruct.loops < MAXNNETLOOPS;
+ locnnetstruct.loops++)
+ {
+ ByteMark.randnum(3);
+ if (DoNNetIteration(locnnetstruct.loops) > global.min_ticks)
+ break;
+ }
+ }
+
+ /*
+ ** All's well if we get here. Do the test.
+ */
+ accumtime = 0L;
+ iterations = (double)0.0;
+
+ do
+ {
+ ByteMark.randnum(3); /* Gotta do this for Neural Net */
+ accumtime += DoNNetIteration(locnnetstruct.loops);
+ iterations += (double)locnnetstruct.loops;
+ } while (ByteMark.TicksToSecs(accumtime) < locnnetstruct.request_secs);
+
+ /*
+ ** Clean up, calculate results, and go home. Be sure to
+ ** show that we don't have to rerun adjustment code.
+ */
+ locnnetstruct.iterspersec = iterations / ByteMark.TicksToFracSecs(accumtime);
+
+ if (locnnetstruct.adjust == 0)
+ locnnetstruct.adjust = 1;
+
+ return locnnetstruct.iterspersec;
+ }
+
+ /********************
+ ** DoNNetIteration **
+ *********************
+ ** Do a single iteration of the neural net benchmark.
+ ** By iteration, we mean a "learning" pass.
+ */
+ public static long DoNNetIteration(long nloops)
+ {
+ long elapsed; /* Elapsed time */
+ int patt;
+
+ /*
+ ** Run nloops learning cycles. Notice that, counted with
+ ** the learning cycle is the weight randomization and
+ ** zeroing of changes. This should reduce clock jitter,
+ ** since we don't have to stop and start the clock for
+ ** each iteration.
+ */
+ elapsed = ByteMark.StartStopwatch();
+ while (nloops-- != 0)
+ {
+ randomize_wts();
+ zero_changes();
+ iteration_count = 1;
+ learned = F;
+ numpasses = 0;
+ while (learned == F)
+ {
+ for (patt = 0; patt < numpats; patt++)
+ {
+ worst_error = 0.0; /* reset this every pass through data */
+ move_wt_changes(); /* move last pass's wt changes to momentum array */
+ do_forward_pass(patt);
+ do_back_pass(patt);
+ iteration_count++;
+ }
+ numpasses++;
+ learned = check_out_error();
+ }
+ }
+
+ return (ByteMark.StopStopwatch(elapsed));
+ }
+
+ /*************************
+ ** do_mid_forward(patt) **
+ **************************
+ ** Process the middle layer's forward pass
+ ** The activation of middle layer's neurode is the weighted
+ ** sum of the inputs from the input pattern, with sigmoid
+ ** function applied to the inputs.
+ **/
+ public static void do_mid_forward(int patt)
+ {
+ double sum;
+ int neurode, i;
+
+ for (neurode = 0; neurode < MID_SIZE; neurode++)
+ {
+ sum = 0.0;
+ for (i = 0; i < IN_SIZE; i++)
+ { /* compute weighted sum of input signals */
+ sum += mid_wts[neurode][i] * in_pats[patt][i];
+ }
+ /*
+ ** apply sigmoid function f(x) = 1/(1+exp(-x)) to weighted sum
+ */
+ sum = 1.0 / (1.0 + Math.Exp(-sum));
+ mid_out[neurode] = sum;
+ }
+ return;
+ }
+
+ /*********************
+ ** do_out_forward() **
+ **********************
+ ** process the forward pass through the output layer
+ ** The activation of the output layer is the weighted sum of
+ ** the inputs (outputs from middle layer), modified by the
+ ** sigmoid function.
+ **/
+ public static void do_out_forward()
+ {
+ double sum;
+ int neurode, i;
+
+ for (neurode = 0; neurode < OUT_SIZE; neurode++)
+ {
+ sum = 0.0;
+ for (i = 0; i < MID_SIZE; i++)
+ { /*
+ ** compute weighted sum of input signals
+ ** from middle layer
+ */
+ sum += out_wts[neurode][i] * mid_out[i];
+ }
+ /*
+ ** Apply f(x) = 1/(1+Math.Exp(-x)) to weighted input
+ */
+ sum = 1.0 / (1.0 + Math.Exp(-sum));
+ out_out[neurode] = sum;
+ }
+ return;
+ }
+
+ /*************************
+ ** display_output(patt) **
+ **************************
+ ** Display the actual output vs. the desired output of the
+ ** network.
+ ** Once the training is complete, and the "learned" flag set
+ ** to TRUE, then display_output sends its output to both
+ ** the screen and to a text output file.
+ **
+ ** NOTE: This routine has been disabled in the benchmark
+ ** version. -- RG
+ **/
+ /*
+ public static void display_output(int patt)
+ {
+ int i;
+
+ fprintf(outfile,"\n Iteration # %d",iteration_count);
+ fprintf(outfile,"\n Desired Output: ");
+
+ for (i=0; i<OUT_SIZE; i++)
+ {
+ fprintf(outfile,"%6.3f ",out_pats[patt][i]);
+ }
+ fprintf(outfile,"\n Actual Output: ");
+
+ for (i=0; i<OUT_SIZE; i++)
+ {
+ fprintf(outfile,"%6.3f ",out_out[i]);
+ }
+ fprintf(outfile,"\n");
+ return;
+ }
+ */
+
+ /**********************
+ ** do_forward_pass() **
+ ***********************
+ ** control function for the forward pass through the network
+ ** NOTE: I have disabled the call to display_output() in
+ ** the benchmark version -- RG.
+ **/
+ public static void do_forward_pass(int patt)
+ {
+ do_mid_forward(patt); /* process forward pass, middle layer */
+ do_out_forward(); /* process forward pass, output layer */
+ /* display_output(patt); ** display results of forward pass */
+ return;
+ }
+
+ /***********************
+ ** do_out_error(patt) **
+ ************************
+ ** Compute the error for the output layer neurodes.
+ ** This is simply Desired - Actual.
+ **/
+ public static void do_out_error(int patt)
+ {
+ int neurode;
+ double error, tot_error, sum;
+
+ tot_error = 0.0;
+ sum = 0.0;
+ for (neurode = 0; neurode < OUT_SIZE; neurode++)
+ {
+ out_error[neurode] = out_pats[patt][neurode] - out_out[neurode];
+ /*
+ ** while we're here, also compute magnitude
+ ** of total error and worst error in this pass.
+ ** We use these to decide if we are done yet.
+ */
+ error = out_error[neurode];
+ if (error < 0.0)
+ {
+ sum += -error;
+ if (-error > tot_error)
+ tot_error = -error; /* worst error this pattern */
+ }
+ else
+ {
+ sum += error;
+ if (error > tot_error)
+ tot_error = error; /* worst error this pattern */
+ }
+ }
+ avg_out_error[patt] = sum / OUT_SIZE;
+ tot_out_error[patt] = tot_error;
+ return;
+ }
+
+ /***********************
+ ** worst_pass_error() **
+ ************************
+ ** Find the worst and average error in the pass and save it
+ **/
+ public static void worst_pass_error()
+ {
+ double error, sum;
+
+ int i;
+
+ error = 0.0;
+ sum = 0.0;
+ for (i = 0; i < numpats; i++)
+ {
+ if (tot_out_error[i] > error) error = tot_out_error[i];
+ sum += avg_out_error[i];
+ }
+ worst_error = error;
+ average_error = sum / numpats;
+ return;
+ }
+
+ /*******************
+ ** do_mid_error() **
+ ********************
+ ** Compute the error for the middle layer neurodes
+ ** This is based on the output errors computed above.
+ ** Note that the derivative of the sigmoid f(x) is
+ ** f'(x) = f(x)(1 - f(x))
+ ** Recall that f(x) is merely the output of the middle
+ ** layer neurode on the forward pass.
+ **/
+ public static void do_mid_error()
+ {
+ double sum;
+ int neurode, i;
+
+ for (neurode = 0; neurode < MID_SIZE; neurode++)
+ {
+ sum = 0.0;
+ for (i = 0; i < OUT_SIZE; i++)
+ sum += out_wts[i][neurode] * out_error[i];
+
+ /*
+ ** apply the derivative of the sigmoid here
+ ** Because of the choice of sigmoid f(I), the derivative
+ ** of the sigmoid is f'(I) = f(I)(1 - f(I))
+ */
+ mid_error[neurode] = mid_out[neurode] * (1 - mid_out[neurode]) * sum;
+ }
+ return;
+ }
+
+ /*********************
+ ** adjust_out_wts() **
+ **********************
+ ** Adjust the weights of the output layer. The error for
+ ** the output layer has been previously propagated back to
+ ** the middle layer.
+ ** Use the Delta Rule with momentum term to adjust the weights.
+ **/
+ public static void adjust_out_wts()
+ {
+ int weight, neurode;
+ double learn, delta, alph;
+
+ learn = BETA;
+ alph = ALPHA;
+ for (neurode = 0; neurode < OUT_SIZE; neurode++)
+ {
+ for (weight = 0; weight < MID_SIZE; weight++)
+ {
+ /* standard delta rule */
+ delta = learn * out_error[neurode] * mid_out[weight];
+
+ /* now the momentum term */
+ delta += alph * out_wt_change[neurode][weight];
+ out_wts[neurode][weight] += delta;
+
+ /* keep track of this pass's cum wt changes for next pass's momentum */
+ out_wt_cum_change[neurode][weight] += delta;
+ }
+ }
+ return;
+ }
+
+ /*************************
+ ** adjust_mid_wts(patt) **
+ **************************
+ ** Adjust the middle layer weights using the previously computed
+ ** errors.
+ ** We use the Generalized Delta Rule with momentum term
+ **/
+ public static void adjust_mid_wts(int patt)
+ {
+ int weight, neurode;
+ double learn, alph, delta;
+
+ learn = BETA;
+ alph = ALPHA;
+ for (neurode = 0; neurode < MID_SIZE; neurode++)
+ {
+ for (weight = 0; weight < IN_SIZE; weight++)
+ {
+ /* first the basic delta rule */
+ delta = learn * mid_error[neurode] * in_pats[patt][weight];
+
+ /* with the momentum term */
+ delta += alph * mid_wt_change[neurode][weight];
+ mid_wts[neurode][weight] += delta;
+
+ /* keep track of this pass's cum wt changes for next pass's momentum */
+ mid_wt_cum_change[neurode][weight] += delta;
+ }
+ }
+ return;
+ }
+
+ /*******************
+ ** do_back_pass() **
+ ********************
+ ** Process the backward propagation of error through network.
+ **/
+ public static void do_back_pass(int patt)
+ {
+ do_out_error(patt);
+ do_mid_error();
+ adjust_out_wts();
+ adjust_mid_wts(patt);
+
+ return;
+ }
+
+
+ /**********************
+ ** move_wt_changes() **
+ ***********************
+ ** Move the weight changes accumulated last pass into the wt-change
+ ** array for use by the momentum term in this pass. Also zero out
+ ** the accumulating arrays after the move.
+ **/
+ public static void move_wt_changes()
+ {
+ int i, j;
+
+ for (i = 0; i < MID_SIZE; i++)
+ for (j = 0; j < IN_SIZE; j++)
+ {
+ mid_wt_change[i][j] = mid_wt_cum_change[i][j];
+ /*
+ ** Zero it out for next pass accumulation.
+ */
+ mid_wt_cum_change[i][j] = 0.0;
+ }
+
+ for (i = 0; i < OUT_SIZE; i++)
+ for (j = 0; j < MID_SIZE; j++)
+ {
+ out_wt_change[i][j] = out_wt_cum_change[i][j];
+ out_wt_cum_change[i][j] = 0.0;
+ }
+
+ return;
+ }
+
+ /**********************
+ ** check_out_error() **
+ ***********************
+ ** Check to see if the error in the output layer is below
+ ** MARGIN*OUT_SIZE for all output patterns. If so, then
+ ** assume the network has learned acceptably well. This
+ ** is simply an arbitrary measure of how well the network
+ ** has learned -- many other standards are possible.
+ **/
+ public static int check_out_error()
+ {
+ int result, i, error;
+
+ result = T;
+ error = F;
+ worst_pass_error(); /* identify the worst error in this pass */
+
+ for (i = 0; i < numpats; i++)
+ {
+ if (worst_error >= STOP) result = F;
+ if (tot_out_error[i] >= 16.0) error = T;
+ }
+
+ if (error == T) result = ERR;
+
+ return (result);
+ }
+
+ /*******************
+ ** zero_changes() **
+ ********************
+ ** Zero out all the wt change arrays
+ **/
+ public static void zero_changes()
+ {
+ int i, j;
+
+ for (i = 0; i < MID_SIZE; i++)
+ {
+ for (j = 0; j < IN_SIZE; j++)
+ {
+ mid_wt_change[i][j] = 0.0;
+ mid_wt_cum_change[i][j] = 0.0;
+ }
+ }
+
+ for (i = 0; i < OUT_SIZE; i++)
+ {
+ for (j = 0; j < MID_SIZE; j++)
+ {
+ out_wt_change[i][j] = 0.0;
+ out_wt_cum_change[i][j] = 0.0;
+ }
+ }
+ return;
+ }
+
+ /********************
+ ** randomize_wts() **
+ *********************
+ ** Intialize the weights in the middle and output layers to
+ ** random values between -0.25..+0.25
+ ** Function rand() returns a value between 0 and 32767.
+ **
+ ** NOTE: Had to make alterations to how the random numbers were
+ ** created. -- RG.
+ **/
+ public static void randomize_wts()
+ {
+ int neurode, i;
+ double value;
+
+ /*
+ ** Following not used int benchmark version -- RG
+ **
+ ** printf("\n Please enter a random number seed (1..32767): ");
+ ** scanf("%d", &i);
+ ** srand(i);
+ */
+
+ for (neurode = 0; neurode < MID_SIZE; neurode++)
+ {
+ for (i = 0; i < IN_SIZE; i++)
+ {
+ value = (double)ByteMark.abs_randwc(100000);
+ value = value / (double)100000.0 - (double)0.5;
+ mid_wts[neurode][i] = value / 2;
+ }
+ }
+ for (neurode = 0; neurode < OUT_SIZE; neurode++)
+ {
+ for (i = 0; i < MID_SIZE; i++)
+ {
+ value = (double)ByteMark.abs_randwc(100000);
+ value = value / (double)10000.0 - (double)0.5;
+ out_wts[neurode][i] = value / 2;
+ }
+ }
+ return;
+ }
+
+ /**********************
+ ** display_mid_wts() **
+ ***********************
+ ** Display the weights on the middle layer neurodes
+ ** NOTE: This routine is not used in the benchmark
+ ** test -- RG
+ **/
+ /* static void display_mid_wts()
+ {
+ int neurode, weight, row, col;
+
+ fprintf(outfile,"\n Weights of Middle Layer neurodes:");
+
+ for (neurode=0; neurode<MID_SIZE; neurode++)
+ {
+ fprintf(outfile,"\n Mid Neurode # %d",neurode);
+ for (row=0; row<IN_Y_SIZE; row++)
+ {
+ fprintf(outfile,"\n ");
+ for (col=0; col<IN_X_SIZE; col++)
+ {
+ weight = IN_X_SIZE * row + col;
+ fprintf(outfile," %8.3f ", mid_wts[neurode,weight]);
+ }
+ }
+ }
+ return;
+ }
+ */
+ /**********************
+ ** display_out_wts() **
+ ***********************
+ ** Display the weights on the output layer neurodes
+ ** NOTE: This code is not used in the benchmark
+ ** test -- RG
+ */
+ /* void display_out_wts()
+ {
+ int neurode, weight;
+
+ fprintf(outfile,"\n Weights of Output Layer neurodes:");
+
+ for (neurode=0; neurode<OUT_SIZE; neurode++)
+ {
+ fprintf(outfile,"\n Out Neurode # %d \n",neurode);
+ for (weight=0; weight<MID_SIZE; weight++)
+ {
+ fprintf(outfile," %8.3f ", out_wts[neurode,weight]);
+ }
+ }
+ return;
+ }
+ */
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/nnet.dat b/tests/src/JIT/Performance/CodeQuality/Bytemark/nnet.dat
new file mode 100644
index 0000000000..5711730d93
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/nnet.dat
@@ -0,0 +1,210 @@
+5 7 8
+26
+0 0 1 0 0
+0 1 0 1 0
+1 0 0 0 1
+1 0 0 0 1
+1 1 1 1 1
+1 0 0 0 1
+1 0 0 0 1
+0 1 0 0 0 0 0 1
+1 1 1 1 0
+1 0 0 0 1
+1 0 0 0 1
+1 1 1 1 0
+1 0 0 0 1
+1 0 0 0 1
+1 1 1 1 0
+0 1 0 0 0 0 1 0
+0 1 1 1 0
+1 0 0 0 1
+1 0 0 0 0
+1 0 0 0 0
+1 0 0 0 0
+1 0 0 0 1
+0 1 1 1 0
+0 1 0 0 0 0 1 1
+1 1 1 1 0
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 1 1 1 0
+0 1 0 0 0 1 0 0
+1 1 1 1 1
+1 0 0 0 0
+1 0 0 0 0
+1 1 1 0 0
+1 0 0 0 0
+1 0 0 0 0
+1 1 1 1 1
+0 1 0 0 0 1 0 1
+1 1 1 1 1
+1 0 0 0 0
+1 0 0 0 0
+1 1 1 0 0
+1 0 0 0 0
+1 0 0 0 0
+1 0 0 0 0
+0 1 0 0 0 1 1 0
+0 1 1 1 0
+1 0 0 0 1
+1 0 0 0 0
+1 0 0 0 0
+1 0 0 1 1
+1 0 0 0 1
+0 1 1 1 0
+0 1 0 0 0 1 1 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 1 1 1 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+0 1 0 0 1 0 0 0
+0 1 1 1 0
+0 0 1 0 0
+0 0 1 0 0
+0 0 1 0 0
+0 0 1 0 0
+0 0 1 0 0
+0 1 1 1 0
+0 1 0 0 1 0 0 1
+0 0 0 0 1
+0 0 0 0 1
+0 0 0 0 1
+0 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+0 1 1 1 0
+0 1 0 0 1 0 1 0
+1 0 0 0 1
+1 0 0 1 0
+1 0 1 0 0
+1 1 0 0 0
+1 0 1 0 0
+1 0 0 1 0
+1 0 0 0 1
+0 1 0 0 1 0 1 1
+1 0 0 0 0
+1 0 0 0 0
+1 0 0 0 0
+1 0 0 0 0
+1 0 0 0 0
+1 0 0 0 0
+1 1 1 1 1
+0 1 0 0 1 1 0 0
+1 0 0 0 1
+1 1 0 1 1
+1 0 1 0 1
+1 0 1 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+0 1 0 0 1 1 0 1
+1 0 0 0 1
+1 1 0 0 1
+1 0 1 0 1
+1 0 1 0 1
+1 0 1 0 1
+1 0 0 1 1
+1 0 0 0 1
+0 1 0 0 1 1 1 0
+0 1 1 1 0
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+0 1 1 1 0
+0 1 0 0 1 1 1 1
+1 1 1 1 0
+1 0 0 0 1
+1 0 0 0 1
+1 1 1 1 0
+1 0 0 0 0
+1 0 0 0 0
+1 0 0 0 0
+0 1 0 1 0 0 0 0
+0 1 1 1 0
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 1 0 1
+1 0 0 1 1
+0 1 1 1 1
+0 1 0 1 0 0 0 1
+1 1 1 1 0
+1 0 0 0 1
+1 0 0 0 1
+1 1 1 1 0
+1 0 1 0 0
+1 0 0 1 0
+1 0 0 0 1
+0 1 0 1 0 0 1 0
+0 1 1 1 1
+1 0 0 0 0
+1 0 0 0 0
+0 1 1 1 0
+0 0 0 0 1
+0 0 0 0 1
+1 1 1 1 0
+0 1 0 1 0 0 1 1
+1 1 1 1 1
+0 0 1 0 0
+0 0 1 0 0
+0 0 1 0 0
+0 0 1 0 0
+0 0 1 0 0
+0 0 1 0 0
+0 1 0 1 0 1 0 0
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+0 1 1 1 0
+0 1 0 1 0 1 0 1
+1 0 0 0 1
+1 0 0 0 1
+0 1 0 1 0
+0 1 0 1 0
+0 1 0 1 0
+0 1 0 1 0
+0 0 1 0 0
+0 1 0 1 0 1 1 0
+1 0 0 0 1
+1 0 0 0 1
+1 0 0 0 1
+1 0 1 0 1
+1 0 1 0 1
+1 0 1 0 1
+0 1 0 1 0
+0 1 0 1 0 1 1 1
+1 0 0 0 1
+0 1 0 1 0
+0 1 0 1 0
+0 0 1 0 0
+0 1 0 1 0
+0 1 0 1 0
+1 0 0 0 1
+0 1 0 1 1 0 0 0
+1 0 0 0 1
+0 1 0 1 0
+0 1 0 1 0
+0 0 1 0 0
+0 0 1 0 0
+0 0 1 0 0
+0 0 1 0 0
+0 1 0 1 1 0 0 1
+1 1 1 1 1
+0 0 0 1 0
+0 0 0 1 0
+0 0 1 0 0
+0 1 0 0 0
+0 1 0 0 0
+1 1 1 1 1
+0 1 0 1 1 0 1 0
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/numericsort.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/numericsort.cs
new file mode 100644
index 0000000000..44da6e3a71
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/numericsort.cs
@@ -0,0 +1,539 @@
+// 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.
+/*
+** Copyright (c) Microsoft. All rights reserved.
+** Licensed under the MIT license.
+** See LICENSE file in the project root for full license information.
+**
+** This program was translated to C# and adapted for xunit-performance.
+** New variants of several tests were added to compare class versus
+** struct and to compare jagged arrays vs multi-dimensional arrays.
+*/
+
+/*
+** BYTEmark (tm)
+** BYTE Magazine's Native Mode benchmarks
+** Rick Grehan, BYTE Magazine
+**
+** Create:
+** Revision: 3/95
+**
+** DISCLAIMER
+** The source, executable, and documentation files that comprise
+** the BYTEmark benchmarks are made available on an "as is" basis.
+** This means that we at BYTE Magazine have made every reasonable
+** effort to verify that the there are no errors in the source and
+** executable code. We cannot, however, guarantee that the programs
+** are error-free. Consequently, McGraw-HIll and BYTE Magazine make
+** no claims in regard to the fitness of the source code, executable
+** code, and documentation of the BYTEmark.
+**
+** Furthermore, BYTE Magazine, McGraw-Hill, and all employees
+** of McGraw-Hill cannot be held responsible for any damages resulting
+** from the use of this code or the results obtained from using
+** this code.
+*/
+
+/**************
+** DoNumSort **
+***************
+** This routine performs the CPU numeric sort test.
+** NOTE: Last version incorrectly stated that the routine
+** returned result in # of longword sorted per second.
+** Not so; the routine returns # of iterations per sec.
+*/
+
+using System;
+
+// #define DEBUG
+
+public class NumericSortJagged : SortStruct
+{
+ public override string Name()
+ {
+ return "NUMERIC SORT(jagged)";
+ }
+
+ public override double Run()
+ {
+ /*
+ ** Set the error context string.
+ */
+ int[][] arraybase; /* Base pointers of array */
+ long accumtime; /* Accumulated time */
+ double iterations; /* Iteration counter */
+
+ /*
+ ** See if we need to do self adjustment code.
+ */
+ if (this.adjust == 0)
+ {
+ /*
+ ** Self-adjustment code. The system begins by sorting 1
+ ** array. If it does that in no time, then two arrays
+ ** are built and sorted. This process continues until
+ ** enough arrays are built to handle the tolerance.
+ */
+ this.numarrays = 1;
+ while (true)
+ {
+ /*
+ ** Allocate space for arrays
+ */
+ arraybase = new int[this.numarrays][];
+ for (int i = 0; i < this.numarrays; i++)
+ arraybase[i] = new int[this.arraysize];
+
+ /*
+ ** Do an iteration of the numeric sort. If the
+ ** elapsed time is less than or equal to the permitted
+ ** minimum, then allocate for more arrays and
+ ** try again.
+ */
+
+ if (DoNumSortIteration(arraybase,
+ this.arraysize,
+ this.numarrays) > global.min_ticks)
+ break; /* We're ok...exit */
+ if (this.numarrays++ > global.NUMNUMARRAYS)
+ {
+ throw new Exception("CPU:NSORT -- NUMNUMARRAYS hit.");
+ }
+ }
+ }
+ else
+ {
+ /*
+ ** Allocate space for arrays
+ */
+ arraybase = new int[this.numarrays][];
+ for (int i = 0; i < this.numarrays; i++)
+ arraybase[i] = new int[this.arraysize];
+ }
+
+ /*
+ ** All's well if we get here. Repeatedly perform sorts until the
+ ** accumulated elapsed time is greater than # of seconds requested.
+ */
+ accumtime = 0L;
+ iterations = (double)0.0;
+
+ do
+ {
+ accumtime += DoNumSortIteration(arraybase,
+ this.arraysize,
+ this.numarrays);
+ iterations += (double)1.0;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ if (this.adjust == 0)
+ this.adjust = 1;
+
+ return (iterations * (double)this.numarrays / ByteMark.TicksToFracSecs(accumtime));
+ }
+
+ /***********************
+ ** DoNumSortIteration **
+ ************************
+ ** This routine executes one iteration of the numeric
+ ** sort benchmark. It returns the number of ticks
+ ** elapsed for the iteration.
+ */
+
+ // JTR: The last 2 parms are no longer needed as they
+ // can be inferred from the arraybase. <shrug>
+ private static int DoNumSortIteration(int[][] arraybase, int arraysize, int numarrays)
+ {
+ long elapsed; /* Elapsed ticks */
+ int i;
+ /*
+ ** Load up the array with random numbers
+ */
+ LoadNumArrayWithRand(arraybase, arraysize, numarrays);
+
+ /*
+ ** Start the stopwatch
+ */
+ elapsed = ByteMark.StartStopwatch();
+
+ /*
+ ** Execute a heap of heapsorts
+ */
+ for (i = 0; i < numarrays; i++)
+ {
+ // NumHeapSort(arraybase+i*arraysize,0L,arraysize-1L);
+ NumHeapSort(arraybase[i], 0, arraysize - 1);
+ }
+
+ /*
+ ** Get elapsed time
+ */
+ elapsed = ByteMark.StopStopwatch(elapsed);
+#if DEBUG
+ {
+ for (i = 0; i < arraysize - 1; i++)
+ { /*
+ ** Compare to check for proper
+ ** sort.
+ */
+ if (arraybase[0][i + 1] < arraybase[0][i])
+ {
+ Console.Write("Sort Error\n");
+ break;
+ }
+ }
+ }
+#endif
+
+ return ((int)elapsed);
+ }
+
+ /*************************
+ ** LoadNumArrayWithRand **
+ **************************
+ ** Load up an array with random longs.
+ */
+ private static void LoadNumArrayWithRand(int[][] array, /* Pointer to arrays */
+ int arraysize,
+ int numarrays) /* # of elements in array */
+ {
+ int i; /* Used for index */
+
+ /*
+ ** Initialize the random number generator
+ */
+ ByteMark.randnum(13);
+
+ /*
+ ** Load up first array with randoms
+ */
+ for (i = 0; i < arraysize; i++)
+ array[0][i] = ByteMark.randnum(0);
+
+ /*
+ ** Now, if there's more than one array to load, copy the
+ ** first into each of the others.
+ */
+ for (i = 1; i < numarrays; i++)
+ {
+ // the old code didn't do a memcpy, so I'm not doing
+ // an Array.Copy()
+ for (int j = 0; j < arraysize; j++)
+ array[i][j] = array[0][j];
+ }
+
+ return;
+ }
+
+ /****************
+ ** NumHeapSort **
+ *****************
+ ** Pass this routine a pointer to an array of long
+ ** integers. Also pass in minimum and maximum offsets.
+ ** This routine performs a heap sort on that array.
+ */
+ private static void NumHeapSort(int[] array,
+ int bottom, /* Lower bound */
+ int top) /* Upper bound */
+ {
+ int temp; /* Used to exchange elements */
+ int i; /* Loop index */
+
+ /*
+ ** First, build a heap in the array
+ */
+ for (i = (top / 2); i > 0; --i)
+ NumSift(array, i, top);
+
+ /*
+ ** Repeatedly extract maximum from heap and place it at the
+ ** end of the array. When we get done, we'll have a sorted
+ ** array.
+ */
+ for (i = top; i > 0; --i)
+ {
+ NumSift(array, bottom, i);
+ temp = array[0]; /* Perform exchange */
+ array[0] = array[i];
+ array[i] = temp;
+ }
+ return;
+ }
+
+ /************
+ ** NumSift **
+ *************
+ ** Peforms the sift operation on a numeric array,
+ ** constructing a heap in the array.
+ */
+ private static void NumSift(int[] array, /* Array of numbers */
+ int i, /* Minimum of array */
+ int j) /* Maximum of array */
+ {
+ int k;
+ int temp; /* Used for exchange */
+
+ while ((i + i) <= j)
+ {
+ k = i + i;
+ if (k < j)
+ if (array[k] < array[k + 1])
+ ++k;
+ if (array[i] < array[k])
+ {
+ temp = array[k];
+ array[k] = array[i];
+ array[i] = temp;
+ i = k;
+ }
+ else
+ i = j + 1;
+ }
+ return;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+// New class
+///////////////////////////////////////////////////////////////////////////////////////
+public class NumericSortRect : SortStruct
+{
+ public override string Name()
+ {
+ return "NUMERIC SORT(rectangle)";
+ }
+
+ public override double Run()
+ {
+ /*
+ ** Set the error context string.
+ */
+ int[,] arraybase; /* Base pointers of array */
+ long accumtime; /* Accumulated time */
+ double iterations; /* Iteration counter */
+
+ /*
+ ** See if we need to do self adjustment code.
+ */
+ if (this.adjust == 0)
+ {
+ /*
+ ** Self-adjustment code. The system begins by sorting 1
+ ** array. If it does that in no time, then two arrays
+ ** are built and sorted. This process continues until
+ ** enough arrays are built to handle the tolerance.
+ */
+ this.numarrays = 1;
+ while (true)
+ {
+ /*
+ ** Allocate space for arrays
+ */
+ arraybase = new int[this.numarrays, this.arraysize];
+
+ /*
+ ** Do an iteration of the numeric sort. If the
+ ** elapsed time is less than or equal to the permitted
+ ** minimum, then allocate for more arrays and
+ ** try again.
+ */
+ if (DoNumSortIteration(arraybase,
+ this.arraysize,
+ this.numarrays) > global.min_ticks)
+ break; /* We're ok...exit */
+ if (this.numarrays++ > global.NUMNUMARRAYS)
+ {
+ throw new Exception("CPU:NSORT -- NUMNUMARRAYS hit.");
+ }
+ }
+ }
+ else
+ {
+ /*
+ ** Allocate space for arrays
+ */
+ arraybase = new int[this.numarrays, this.arraysize];
+ }
+
+ /*
+ ** All's well if we get here. Repeatedly perform sorts until the
+ ** accumulated elapsed time is greater than # of seconds requested.
+ */
+ accumtime = 0L;
+ iterations = (double)0.0;
+
+ do
+ {
+ accumtime += DoNumSortIteration(arraybase,
+ this.arraysize,
+ this.numarrays);
+ iterations += (double)1.0;
+ } while (ByteMark.TicksToSecs(accumtime) < this.request_secs);
+
+ if (this.adjust == 0)
+ this.adjust = 1;
+
+ return (iterations * (double)this.numarrays / ByteMark.TicksToFracSecs(accumtime));
+ }
+
+ /***********************
+ ** DoNumSortIteration **
+ ************************
+ ** This routine executes one iteration of the numeric
+ ** sort benchmark. It returns the number of ticks
+ ** elapsed for the iteration.
+ */
+
+ // JTR: The last 2 parms are no longer needed as they
+ // can be inferred from the arraybase. <shrug>
+ private static int DoNumSortIteration(int[,] arraybase, int arraysize, int numarrays)
+ {
+ long elapsed; /* Elapsed ticks */
+ int i;
+ /*
+ ** Load up the array with random numbers
+ */
+ LoadNumArrayWithRand(arraybase, arraysize, numarrays);
+
+ /*
+ ** Start the stopwatch
+ */
+ elapsed = ByteMark.StartStopwatch();
+
+ /*
+ ** Execute a heap of heapsorts
+ */
+ for (i = 0; i < numarrays; i++)
+ {
+ // NumHeapSort(arraybase+i*arraysize,0L,arraysize-1L);
+ NumHeapSort(arraybase, i, arraysize - 1);
+ }
+
+ /*
+ ** Get elapsed time
+ */
+ elapsed = ByteMark.StopStopwatch(elapsed);
+#if DEBUG
+ {
+ for (i = 0; i < arraysize - 1; i++)
+ { /*
+ ** Compare to check for proper
+ ** sort.
+ */
+ if (arraybase[0, i + 1] < arraybase[0, i])
+ {
+ Console.Write("size: {0}, count: {1}, total: {2}\n", arraysize, numarrays, arraybase.Length);
+ Console.Write("Sort Error at index {0}\n", i);
+ break;
+ }
+ }
+ }
+#endif
+
+ return ((int)elapsed);
+ }
+
+ /*************************
+ ** LoadNumArrayWithRand **
+ **************************
+ ** Load up an array with random longs.
+ */
+ private static void LoadNumArrayWithRand(int[,] array, /* Pointer to arrays */
+ int arraysize,
+ int numarrays) /* # of elements in array */
+ {
+ int i; /* Used for index */
+
+ /*
+ ** Initialize the random number generator
+ */
+ ByteMark.randnum(13);
+
+ /*
+ ** Load up first array with randoms
+ */
+ for (i = 0; i < arraysize; i++)
+ array[0, i] = ByteMark.randnum(0);
+
+ /*
+ ** Now, if there's more than one array to load, copy the
+ ** first into each of the others.
+ */
+ while (--numarrays > 0)
+ {
+ for (int j = 0; j < arraysize; j++, i++)
+ array[numarrays, j] = array[0, j];
+ }
+
+ return;
+ }
+
+ /****************
+ ** NumHeapSort **
+ *****************
+ ** Pass this routine a pointer to an array of long
+ ** integers. Also pass in minimum and maximum offsets.
+ ** This routine performs a heap sort on that array.
+ */
+ private static void NumHeapSort(int[,] array,
+ int row, /* which row */
+ int top) /* Upper bound */
+ {
+ int temp; /* Used to exchange elements */
+ int i; /* Loop index */
+
+ /*
+ ** First, build a heap in the array
+ */
+ for (i = (top / 2); i > 0; --i)
+ NumSift(array, row, i, top);
+
+ /*
+ ** Repeatedly extract maximum from heap and place it at the
+ ** end of the array. When we get done, we'll have a sorted
+ ** array.
+ */
+ for (i = top; i > 0; --i)
+ {
+ NumSift(array, row, 0, i);
+ temp = array[row, 0]; /* Perform exchange */
+ array[row, 0] = array[row, i];
+ array[row, i] = temp;
+ }
+ return;
+ }
+
+ /************
+ ** NumSift **
+ *************
+ ** Peforms the sift operation on a numeric array,
+ ** constructing a heap in the array.
+ */
+ private static void NumSift(int[,] array, /* Array of numbers */
+ int row,
+ int i, /* Minimum of array */
+ int j) /* Maximum of array */
+ {
+ int k;
+ int temp; /* Used for exchange */
+
+ while ((i + i) <= j)
+ {
+ k = i + i;
+ if (k < j)
+ if (array[row, k] < array[row, k + 1])
+ ++k;
+ if (array[row, i] < array[row, k])
+ {
+ temp = array[row, k];
+ array[row, k] = array[row, i];
+ array[row, i] = temp;
+ i = k;
+ }
+ else
+ i = j + 1;
+ }
+ return;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Bytemark/utility.cs b/tests/src/JIT/Performance/CodeQuality/Bytemark/utility.cs
new file mode 100644
index 0000000000..c0bdbb656f
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Bytemark/utility.cs
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Text;
+using System.IO;
+
+public class Utility
+{
+ static public int sscanf(String stream, String format, Object[] results)
+ {
+ int fieldsRead = 0;
+ int resultsIndex = 0;
+ int formatIndex = 0;
+ char fieldType = '\0';
+ char charRead = '\0';
+ bool readingField = false;
+ bool eatWhiteSpace = false;
+ StringReader srStream = new StringReader(stream);
+
+ while (formatIndex < format.Length)
+ {
+ if (Char.IsWhiteSpace((char)format[formatIndex]))
+ {
+ eatWhiteSpace = true;
+ formatIndex++;
+ continue;
+ }
+ while (eatWhiteSpace)
+ {
+ if (!Char.IsWhiteSpace((char)srStream.Peek()))
+ {
+ eatWhiteSpace = false;
+ break;
+ }
+ srStream.Read();
+ }
+ if ('%' == format[formatIndex]) //If we found a scan field type
+ {
+ StringBuilder sb = new StringBuilder();
+ ++formatIndex;
+ fieldType = format[formatIndex++];
+ readingField = true;
+ charRead = (char)srStream.Read();
+
+ while (readingField)
+ {
+ if (-1 == (short)charRead)
+ {
+ readingField = false;
+ }
+
+ sb.Append(charRead);
+
+ int intCharRead = srStream.Peek();
+ unchecked
+ {
+ charRead = (char)intCharRead;
+ }
+ if (Char.IsWhiteSpace(charRead) || ('c' == fieldType) || (-1 == intCharRead))
+ {
+ readingField = false;
+ fieldsRead++;
+
+ switch (fieldType)
+ {
+ case 'c':
+ results[resultsIndex++] = sb.ToString()[0];
+ break;
+ case 'd':
+ case 'i':
+ int parsedInt;
+ parsedInt = int.Parse(sb.ToString());
+ results[resultsIndex++] = parsedInt;
+ break;
+ case 'f':
+ double parsedDouble;
+ parsedDouble = double.Parse(sb.ToString());
+ results[resultsIndex++] = parsedDouble;
+ break;
+ case 's':
+ results[resultsIndex++] = sb.ToString();
+ break;
+ }
+ continue;
+ }
+ charRead = (char)srStream.Read();
+ }
+ }
+ }
+
+ return fieldsRead;
+ }
+
+ static public int fscanf(TextReader stream, String format, Object[] results)
+ {
+ String s = stream.ReadLine();
+ if (null == s)
+ return 0;
+ return sscanf(s, format, results);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/FractalPerf/FractalPerf.cs b/tests/src/JIT/Performance/CodeQuality/FractalPerf/FractalPerf.cs
new file mode 100644
index 0000000000..cbaad45df5
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/FractalPerf/FractalPerf.cs
@@ -0,0 +1,177 @@
+// 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.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+namespace FractalPerf
+{
+ struct complex
+ {
+ public complex(double a, double b) { r = a; i = b; }
+ public double r;
+ public double i;
+
+ public complex square() {
+ return new complex(r * r - i * i, 2.0 * r * i);
+ }
+
+ public double sqabs() {
+ return r * r + i * i;
+ }
+
+ public override string ToString() {
+ return String.Format("[{0} + {1}i]", r, i);
+ }
+
+ public static complex operator +(complex a, complex b) {
+ return new complex(a.r + b.r, a.i + b.i);
+ }
+ }
+
+ public abstract class Fractal
+ {
+ protected double XB, YB, XE, YE, XS, YS;
+ const double resolution = 375.0;
+
+ public Fractal(double xbeg, double ybeg, double xend, double yend) {
+ XB = Math.Min(xbeg, xend);
+ YB = Math.Min(ybeg, yend);
+ XE = Math.Max(xbeg, xend);
+ YE = Math.Max(ybeg, yend);
+ XS = (xend - xbeg) / resolution;
+ YS = (yend - ybeg) / resolution;
+ }
+
+ public abstract double Render();
+
+ public static double Clamp(double val, double lo, double hi) {
+ return Math.Min(Math.Max(val, lo), hi);
+ }
+ }
+
+ public class Mandelbrot : Fractal
+ {
+ public Mandelbrot() : base(-2.0, -1.5, 1.0, 1.5) { }
+
+ public override double Render() {
+ double limit = 4.0;
+ double result = 0.0;
+
+ for (double y = YB; y < YE; y += YS) {
+ for (double x = YB; x < YE; x += XS) {
+ complex num = new complex(x, y);
+ complex accum = num;
+ int iters;
+ for (iters = 0; iters < 1000; iters++) {
+ accum = accum.square();
+ accum += num;
+ if (accum.sqabs() > limit)
+ break;
+ }
+ result += iters;
+ }
+ }
+ return result;
+ }
+ }
+
+ public class Julia : Fractal
+ {
+ private double Real;
+ double Imaginary;
+ public Julia(double real, double imaginary)
+ : base(-2.0, -1.5, 1.0, 1.5) {
+ Real = real;
+ Imaginary = imaginary;
+ }
+
+ public override double Render() {
+ double limit = 4.0;
+ double result = 0.0;
+
+ // set the Julia Set constant
+ complex seed = new complex(Real, Imaginary);
+ // run through every point on the screen, setting
+ // m and n to the coordinates
+ for (double m = XB; m < XE; m += XS) {
+ for (double n = YB; n < YE; n += YS) {
+ // the initial z value is the current pixel,
+ // so x and y have to be set to m and n
+ complex accum = new complex(m, n);
+ // perform the iteration
+ int num;
+ for (num = 0; num < 1000; num++) {
+ // exit the loop if the number becomes too big
+ if (accum.sqabs() > limit)
+ break;
+ // use the formula
+ accum = accum.square() + seed;
+ }
+ // determine the color using the number of
+ // iterations it took for the number to become too big
+ // char color = num % number_of_colors;
+ // plot the point
+ result += num;
+ }
+ }
+ return result;
+ }
+ }
+
+ public class Launch
+ {
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 5;
+#endif
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static bool Bench()
+ {
+ Mandelbrot m = new Mandelbrot();
+ Julia j = new Julia(-0.62, 0.41);
+ double mResult = m.Render();
+ double jResult = j.Render();
+
+ return true;
+ }
+
+ [Benchmark]
+ public static void Test() {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ for (int i = 0; i < Iterations; i++) {
+ Bench();
+ }
+ }
+ }
+ }
+
+ static bool TestBase() {
+ bool result = true;
+ for (int i = 0; i < Iterations; i++) {
+ result &= Bench();
+ }
+ return result;
+ }
+
+ public static int Main() {
+ bool result = TestBase();
+ return (result ? 100 : -1);
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/FractalPerf/FractalPerf.csproj b/tests/src/JIT/Performance/CodeQuality/FractalPerf/FractalPerf.csproj
new file mode 100644
index 0000000000..d5ad1554b5
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/FractalPerf/FractalPerf.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="FractalPerf.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/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..54a8a77e03
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsByte.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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..a3e1203570
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsChar.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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..beb3776b17
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsDouble.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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..bb859c09c5
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsFloat.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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..112d35c9c5
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsInt.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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..62499dc019
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsLong.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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..52538e0fed
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsSByte.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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..0013834c8c
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsShort.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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..5b5005edfb
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsString.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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..1775d19d1a
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUInt.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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..81e10be633
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsULong.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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..fb88ffb4d2
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/ConstantArgsUShort.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <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>
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.cs
new file mode 100644
index 0000000000..9b689ce376
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.cs
@@ -0,0 +1,75 @@
+// 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 NoThrowInline
+{
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 100000000;
+#endif
+
+ static void ThrowIfNull(string s)
+ {
+ if (s == null)
+ ThrowArgumentNullException();
+ }
+
+ static void ThrowArgumentNullException()
+ {
+ throw new ArgumentNullException();
+ }
+
+ //
+ // We expect ThrowArgumentNullException to not be inlined into Bench, the throw code is pretty
+ // large and throws are extremly slow. However, we need to be careful not to degrade the
+ // non-exception path performance by preserving registers across the call. For this the compiler
+ // will have to understand that ThrowArgumentNullException never returns and omit the register
+ // preservation code.
+ //
+ // For example, the Bench method below has 4 arguments (all passed in registers on x64) and fairly
+ // typical argument validation code. If the compiler does not inline ThrowArgumentNullException
+ // and does not make use of the "no return" information then all 4 register arguments will have
+ // to be spilled and then reloaded. That would add 8 unnecessary memory accesses.
+ //
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int Bench(string a, string b, string c, string d)
+ {
+ ThrowIfNull(a);
+ ThrowIfNull(b);
+ ThrowIfNull(c);
+ ThrowIfNull(d);
+
+ return a.Length + b.Length + c.Length + d.Length;
+ }
+
+ [Benchmark]
+ public static void Test()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Bench("a", "bc", "def", "ghij");
+ }
+ }
+ }
+
+ public static int Main()
+ {
+ return (Bench("a", "bc", "def", "ghij") == 10) ? 100 : -1;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.csproj b/tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.csproj
new file mode 100644
index 0000000000..75f6176581
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Inlining/NoThrowInline.csproj
@@ -0,0 +1,45 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="NoThrowInline.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/Linq/Linq.cs b/tests/src/JIT/Performance/CodeQuality/Linq/Linq.cs
new file mode 100644
index 0000000000..58ea46a0c9
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Linq/Linq.cs
@@ -0,0 +1,595 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using Microsoft.Xunit.Performance;
+using System.Collections.Generic;
+using System.Linq;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class Product
+{
+ public int ProductID { get; set; }
+ public string ProductName { get; set; }
+ public string Category { get; set; }
+ public decimal UnitPrice { get; set; }
+ public int UnitsInStock { get; set; }
+
+ private static List<Product> s_productList;
+
+ public static List<Product> GetProductList()
+ {
+ if (s_productList == null)
+ CreateLists();
+
+ return s_productList;
+ }
+
+ private static void CreateLists()
+ {
+ s_productList =
+ new List<Product> {
+ new Product { ProductID = 1, ProductName = "Chai", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 39 },
+ new Product { ProductID = 2, ProductName = "Chang", Category = "Beverages", UnitPrice = 19.0000M, UnitsInStock = 17 },
+ new Product { ProductID = 3, ProductName = "Aniseed Syrup", Category = "Condiments", UnitPrice = 10.0000M, UnitsInStock = 13 },
+ new Product { ProductID = 4, ProductName = "Chef Anton's Cajun Seasoning", Category = "Condiments", UnitPrice = 22.0000M, UnitsInStock = 53 },
+ new Product { ProductID = 5, ProductName = "Chef Anton's Gumbo Mix", Category = "Condiments", UnitPrice = 21.3500M, UnitsInStock = 0 },
+ new Product { ProductID = 6, ProductName = "Grandma's Boysenberry Spread", Category = "Condiments", UnitPrice = 25.0000M, UnitsInStock = 120 },
+ new Product { ProductID = 7, ProductName = "Uncle Bob's Organic Dried Pears", Category = "Produce", UnitPrice = 30.0000M, UnitsInStock = 15 },
+ new Product { ProductID = 8, ProductName = "Northwoods Cranberry Sauce", Category = "Condiments", UnitPrice = 40.0000M, UnitsInStock = 6 },
+ new Product { ProductID = 9, ProductName = "Mishi Kobe Niku", Category = "Meat/Poultry", UnitPrice = 97.0000M, UnitsInStock = 29 },
+ new Product { ProductID = 10, ProductName = "Ikura", Category = "Seafood", UnitPrice = 31.0000M, UnitsInStock = 31 },
+ new Product { ProductID = 11, ProductName = "Queso Cabrales", Category = "Dairy Products", UnitPrice = 21.0000M, UnitsInStock = 22 },
+ new Product { ProductID = 12, ProductName = "Queso Manchego La Pastora", Category = "Dairy Products", UnitPrice = 38.0000M, UnitsInStock = 86 },
+ new Product { ProductID = 13, ProductName = "Konbu", Category = "Seafood", UnitPrice = 6.0000M, UnitsInStock = 24 },
+ new Product { ProductID = 14, ProductName = "Tofu", Category = "Produce", UnitPrice = 23.2500M, UnitsInStock = 35 },
+ new Product { ProductID = 15, ProductName = "Genen Shouyu", Category = "Condiments", UnitPrice = 15.5000M, UnitsInStock = 39 },
+ new Product { ProductID = 16, ProductName = "Pavlova", Category = "Confections", UnitPrice = 17.4500M, UnitsInStock = 29 },
+ new Product { ProductID = 17, ProductName = "Alice Mutton", Category = "Meat/Poultry", UnitPrice = 39.0000M, UnitsInStock = 0 },
+ new Product { ProductID = 18, ProductName = "Carnarvon Tigers", Category = "Seafood", UnitPrice = 62.5000M, UnitsInStock = 42 },
+ new Product { ProductID = 19, ProductName = "Teatime Chocolate Biscuits", Category = "Confections", UnitPrice = 9.2000M, UnitsInStock = 25 },
+ new Product { ProductID = 20, ProductName = "Sir Rodney's Marmalade", Category = "Confections", UnitPrice = 81.0000M, UnitsInStock = 40 },
+ new Product { ProductID = 21, ProductName = "Sir Rodney's Scones", Category = "Confections", UnitPrice = 10.0000M, UnitsInStock = 3 },
+ new Product { ProductID = 22, ProductName = "Gustaf's Kn\u00E4ckebr\u00F6d", Category = "Grains/Cereals", UnitPrice = 21.0000M, UnitsInStock = 104 },
+ new Product { ProductID = 23, ProductName = "Tunnbr\u00F6d", Category = "Grains/Cereals", UnitPrice = 9.0000M, UnitsInStock = 61 },
+ new Product { ProductID = 24, ProductName = "Guaran\u00E1 Fant\u00E1stica", Category = "Beverages", UnitPrice = 4.5000M, UnitsInStock = 20 },
+ new Product { ProductID = 25, ProductName = "NuNuCa Nu\u00DF-Nougat-Creme", Category = "Confections", UnitPrice = 14.0000M, UnitsInStock = 76 },
+ new Product { ProductID = 26, ProductName = "Gumb\u00E4r Gummib\u00E4rchen", Category = "Confections", UnitPrice = 31.2300M, UnitsInStock = 15 },
+ new Product { ProductID = 27, ProductName = "Schoggi Schokolade", Category = "Confections", UnitPrice = 43.9000M, UnitsInStock = 49 },
+ new Product { ProductID = 28, ProductName = "R\u00F6ssle Sauerkraut", Category = "Produce", UnitPrice = 45.6000M, UnitsInStock = 26 },
+ new Product { ProductID = 29, ProductName = "Th\u00FCringer Rostbratwurst", Category = "Meat/Poultry", UnitPrice = 123.7900M, UnitsInStock = 0 },
+ new Product { ProductID = 30, ProductName = "Nord-Ost Matjeshering", Category = "Seafood", UnitPrice = 25.8900M, UnitsInStock = 10 },
+ new Product { ProductID = 31, ProductName = "Gorgonzola Telino", Category = "Dairy Products", UnitPrice = 12.5000M, UnitsInStock = 0 },
+ new Product { ProductID = 32, ProductName = "Mascarpone Fabioli", Category = "Dairy Products", UnitPrice = 32.0000M, UnitsInStock = 9 },
+ new Product { ProductID = 33, ProductName = "Geitost", Category = "Dairy Products", UnitPrice = 2.5000M, UnitsInStock = 112 },
+ new Product { ProductID = 34, ProductName = "Sasquatch Ale", Category = "Beverages", UnitPrice = 14.0000M, UnitsInStock = 111 },
+ new Product { ProductID = 35, ProductName = "Steeleye Stout", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 20 },
+ new Product { ProductID = 36, ProductName = "Inlagd Sill", Category = "Seafood", UnitPrice = 19.0000M, UnitsInStock = 112 },
+ new Product { ProductID = 37, ProductName = "Gravad lax", Category = "Seafood", UnitPrice = 26.0000M, UnitsInStock = 11 },
+ new Product { ProductID = 38, ProductName = "C\u00F4te de Blaye", Category = "Beverages", UnitPrice = 263.5000M, UnitsInStock = 17 },
+ new Product { ProductID = 39, ProductName = "Chartreuse verte", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 69 },
+ new Product { ProductID = 40, ProductName = "Boston Crab Meat", Category = "Seafood", UnitPrice = 18.4000M, UnitsInStock = 123 },
+ new Product { ProductID = 41, ProductName = "Jack's New England Clam Chowder", Category = "Seafood", UnitPrice = 9.6500M, UnitsInStock = 85 },
+ new Product { ProductID = 42, ProductName = "Singaporean Hokkien Fried Mee", Category = "Grains/Cereals", UnitPrice = 14.0000M, UnitsInStock = 26 },
+ new Product { ProductID = 43, ProductName = "Ipoh Coffee", Category = "Beverages", UnitPrice = 46.0000M, UnitsInStock = 17 },
+ new Product { ProductID = 44, ProductName = "Gula Malacca", Category = "Condiments", UnitPrice = 19.4500M, UnitsInStock = 27 },
+ new Product { ProductID = 45, ProductName = "Rogede sild", Category = "Seafood", UnitPrice = 9.5000M, UnitsInStock = 5 },
+ new Product { ProductID = 46, ProductName = "Spegesild", Category = "Seafood", UnitPrice = 12.0000M, UnitsInStock = 95 },
+ new Product { ProductID = 47, ProductName = "Zaanse koeken", Category = "Confections", UnitPrice = 9.5000M, UnitsInStock = 36 },
+ new Product { ProductID = 48, ProductName = "Chocolade", Category = "Confections", UnitPrice = 12.7500M, UnitsInStock = 15 },
+ new Product { ProductID = 49, ProductName = "Maxilaku", Category = "Confections", UnitPrice = 20.0000M, UnitsInStock = 10 },
+ new Product { ProductID = 50, ProductName = "Valkoinen suklaa", Category = "Confections", UnitPrice = 16.2500M, UnitsInStock = 65 },
+ new Product { ProductID = 51, ProductName = "Manjimup Dried Apples", Category = "Produce", UnitPrice = 53.0000M, UnitsInStock = 20 },
+ new Product { ProductID = 52, ProductName = "Filo Mix", Category = "Grains/Cereals", UnitPrice = 7.0000M, UnitsInStock = 38 },
+ new Product { ProductID = 53, ProductName = "Perth Pasties", Category = "Meat/Poultry", UnitPrice = 32.8000M, UnitsInStock = 0 },
+ new Product { ProductID = 54, ProductName = "Tourti\u00E8re", Category = "Meat/Poultry", UnitPrice = 7.4500M, UnitsInStock = 21 },
+ new Product { ProductID = 55, ProductName = "P\u00E2t\u00E9 chinois", Category = "Meat/Poultry", UnitPrice = 24.0000M, UnitsInStock = 115 },
+ new Product { ProductID = 56, ProductName = "Gnocchi di nonna Alice", Category = "Grains/Cereals", UnitPrice = 38.0000M, UnitsInStock = 21 },
+ new Product { ProductID = 57, ProductName = "Ravioli Angelo", Category = "Grains/Cereals", UnitPrice = 19.5000M, UnitsInStock = 36 },
+ new Product { ProductID = 58, ProductName = "Escargots de Bourgogne", Category = "Seafood", UnitPrice = 13.2500M, UnitsInStock = 62 },
+ new Product { ProductID = 59, ProductName = "Raclette Courdavault", Category = "Dairy Products", UnitPrice = 55.0000M, UnitsInStock = 79 },
+ new Product { ProductID = 60, ProductName = "Camembert Pierrot", Category = "Dairy Products", UnitPrice = 34.0000M, UnitsInStock = 19 },
+ new Product { ProductID = 61, ProductName = "Sirop d'\u00E9rable", Category = "Condiments", UnitPrice = 28.5000M, UnitsInStock = 113 },
+ new Product { ProductID = 62, ProductName = "Tarte au sucre", Category = "Confections", UnitPrice = 49.3000M, UnitsInStock = 17 },
+ new Product { ProductID = 63, ProductName = "Vegie-spread", Category = "Condiments", UnitPrice = 43.9000M, UnitsInStock = 24 },
+ new Product { ProductID = 64, ProductName = "Wimmers gute Semmelkn\u00F6del", Category = "Grains/Cereals", UnitPrice = 33.2500M, UnitsInStock = 22 },
+ new Product { ProductID = 65, ProductName = "Louisiana Fiery Hot Pepper Sauce", Category = "Condiments", UnitPrice = 21.0500M, UnitsInStock = 76 },
+ new Product { ProductID = 66, ProductName = "Louisiana Hot Spiced Okra", Category = "Condiments", UnitPrice = 17.0000M, UnitsInStock = 4 },
+ new Product { ProductID = 67, ProductName = "Laughing Lumberjack Lager", Category = "Beverages", UnitPrice = 14.0000M, UnitsInStock = 52 },
+ new Product { ProductID = 68, ProductName = "Scottish Longbreads", Category = "Confections", UnitPrice = 12.5000M, UnitsInStock = 6 },
+ new Product { ProductID = 69, ProductName = "Gudbrandsdalsost", Category = "Dairy Products", UnitPrice = 36.0000M, UnitsInStock = 26 },
+ new Product { ProductID = 70, ProductName = "Outback Lager", Category = "Beverages", UnitPrice = 15.0000M, UnitsInStock = 15 },
+ new Product { ProductID = 71, ProductName = "Flotemysost", Category = "Dairy Products", UnitPrice = 21.5000M, UnitsInStock = 26 },
+ new Product { ProductID = 72, ProductName = "Mozzarella di Giovanni", Category = "Dairy Products", UnitPrice = 34.8000M, UnitsInStock = 14 },
+ new Product { ProductID = 73, ProductName = "R\u00F6d Kaviar", Category = "Seafood", UnitPrice = 15.0000M, UnitsInStock = 101 },
+ new Product { ProductID = 74, ProductName = "Longlife Tofu", Category = "Produce", UnitPrice = 10.0000M, UnitsInStock = 4 },
+ new Product { ProductID = 75, ProductName = "Rh\u00F6nbr\u00E4u Klosterbier", Category = "Beverages", UnitPrice = 7.7500M, UnitsInStock = 125 },
+ new Product { ProductID = 76, ProductName = "Lakkalik\u00F6\u00F6ri", Category = "Beverages", UnitPrice = 18.0000M, UnitsInStock = 57 },
+ new Product { ProductID = 77, ProductName = "Original Frankfurter gr\u00FCne So\u00DFe", Category = "Condiments", UnitPrice = 13.0000M, UnitsInStock = 32 }
+ };
+ }
+}
+
+public class LinqBenchmarks
+{
+#if DEBUG
+ public const int IterationsWhere00 = 1;
+ public const int IterationsWhere01 = 1;
+ public const int IterationsCount00 = 1;
+ public const int IterationsOrder00 = 1;
+#else
+ public const int IterationsWhere00 = 1000000;
+ public const int IterationsWhere01 = 250000;
+ public const int IterationsCount00 = 1000000;
+ public const int IterationsOrder00 = 25000;
+#endif
+
+ private static volatile object s_volatileObject;
+
+ private static void Escape(object obj)
+ {
+ s_volatileObject = obj;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private bool Bench()
+ {
+ bool result = true;
+ result &= Where00();
+ result &= Where01();
+ result &= Count00();
+ result &= Order00();
+ return result;
+ }
+
+ #region Where00
+ private bool Where00()
+ {
+ bool result = true;
+ result &= Where00For();
+ result &= Where00LinqMethod();
+ result &= Where00LinqQuery();
+ return result;
+ }
+
+ [Benchmark]
+ private bool Where00LinqQueryX()
+ {
+ bool result = true;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Where00LinqQuery();
+ }
+ }
+ return result;
+ }
+
+ private bool Where00LinqQuery()
+ {
+ List<Product> products = Product.GetProductList();
+ int count = 0;
+ for (int i = 0; i < IterationsWhere00; i++)
+ {
+ var soldOutProducts =
+ from prod in products
+ where prod.UnitsInStock == 0
+ select prod;
+
+ foreach (var product in soldOutProducts)
+ {
+ count++;
+ }
+ }
+
+ return (count == 5 * IterationsWhere00);
+ }
+
+ [Benchmark]
+ private bool Where00LinqMethodX()
+ {
+ bool result = true;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Where00LinqMethod();
+ }
+ }
+
+ return result;
+ }
+
+ private bool Where00LinqMethod()
+ {
+ List<Product> products = Product.GetProductList();
+ int count = 0;
+ for (int i = 0; i < IterationsWhere00; i++)
+ {
+ var soldOutProducts = products.Where(p => p.UnitsInStock == 0);
+
+ foreach (var product in soldOutProducts)
+ {
+ count++;
+ }
+ }
+
+ return (count == 5 * IterationsWhere00);
+ }
+
+ [Benchmark]
+ private bool Where00ForX()
+ {
+ bool result = true;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Where00For();
+ }
+ }
+
+ return result;
+ }
+
+ private bool Where00For()
+ {
+ List<Product> products = Product.GetProductList();
+ int count = 0;
+ for (int i = 0; i < IterationsWhere00; i++)
+ {
+ List<Product> soldOutProducts = new List<Product>();
+
+ foreach (Product p in products)
+ {
+ if (p.UnitsInStock == 0)
+ {
+ soldOutProducts.Add(p);
+ }
+ }
+
+ foreach (var product in soldOutProducts)
+ {
+ count++;
+ }
+ }
+
+ return (count == 5 * IterationsWhere00);
+ }
+ #endregion
+
+ #region Where01
+ private bool Where01()
+ {
+ bool result = true;
+ result &= Where01For();
+ result &= Where01LinqMethod();
+ result &= Where01LinqQuery();
+ return result;
+ }
+
+ [Benchmark]
+ private bool Where01LinqQueryX()
+ {
+ bool result = true;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Where01LinqQuery();
+ }
+ }
+ return result;
+ }
+
+ private bool Where01LinqQuery()
+ {
+ List<Product> products = Product.GetProductList();
+ int count = 0;
+ for (int i = 0; i < IterationsWhere01; i++)
+ {
+ var expensiveInStockProducts =
+ from prod in products
+ where prod.UnitsInStock > 0 && prod.UnitPrice > 60.00M
+ select prod;
+
+ foreach (var product in expensiveInStockProducts)
+ {
+ count++;
+ }
+ }
+
+ return (count == 4 * IterationsWhere01);
+ }
+
+ [Benchmark]
+ private bool Where01LinqMethodX()
+ {
+ bool result = true;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Where01LinqMethod();
+ }
+ }
+
+ return result;
+ }
+
+ private bool Where01LinqMethod()
+ {
+ List<Product> products = Product.GetProductList();
+ int count = 0;
+ for (int i = 0; i < IterationsWhere01; i++)
+ {
+ var soldOutProducts = products.Where(p => p.UnitsInStock > 0 && p.UnitPrice > 60.00M);
+
+ foreach (var product in soldOutProducts)
+ {
+ count++;
+ }
+ }
+
+ return (count == 4 * IterationsWhere01);
+ }
+
+ [Benchmark]
+ private bool Where01LinqMethodNestedX()
+ {
+ bool result = true;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Where01LinqMethodNested();
+ }
+ }
+
+ return result;
+ }
+
+ private bool Where01LinqMethodNested()
+ {
+ List<Product> products = Product.GetProductList();
+ int count = 0;
+ for (int i = 0; i < IterationsWhere01; i++)
+ {
+ var soldOutProducts = products.Where(p => p.UnitsInStock > 0).Where(p => p.UnitPrice > 60.00M);
+
+ foreach (var product in soldOutProducts)
+ {
+ count++;
+ }
+ }
+
+ return (count == 4 * IterationsWhere01);
+ }
+
+ [Benchmark]
+ private bool Where01ForX()
+ {
+ bool result = true;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Where01For();
+ }
+ }
+
+ return result;
+ }
+
+ private bool Where01For()
+ {
+ List<Product> products = Product.GetProductList();
+ int count = 0;
+ for (int i = 0; i < IterationsWhere01; i++)
+ {
+ List<Product> soldOutProducts = new List<Product>();
+
+ foreach (Product p in products)
+ {
+ if (p.UnitsInStock > 0 && p.UnitPrice > 60.00M)
+ {
+ soldOutProducts.Add(p);
+ }
+ }
+
+ foreach (var product in soldOutProducts)
+ {
+ count++;
+ }
+ }
+
+ return (count == 4 * IterationsWhere01);
+ }
+ #endregion
+
+ #region Count00
+ private bool Count00()
+ {
+ bool result = true;
+ result &= Count00For();
+ result &= Count00LinqMethod();
+ return result;
+ }
+
+ [Benchmark]
+ private bool Count00LinqMethodX()
+ {
+ bool result = true;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Count00LinqMethod();
+ }
+ }
+
+ return result;
+ }
+
+ private bool Count00LinqMethod()
+ {
+ List<Product> products = Product.GetProductList();
+ int count = 0;
+ for (int i = 0; i < IterationsCount00; i++)
+ {
+ count += products.Count(p => p.UnitsInStock == 0);
+ }
+
+ return (count == 5 * IterationsCount00);
+ }
+
+ [Benchmark]
+ private bool Count00ForX()
+ {
+ bool result = true;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Count00For();
+ }
+ }
+
+ return result;
+ }
+
+ private bool Count00For()
+ {
+ List<Product> products = Product.GetProductList();
+ int count = 0;
+ for (int i = 0; i < IterationsCount00; i++)
+ {
+ foreach (Product p in products)
+ {
+ if (p.UnitsInStock == 0)
+ {
+ count++;
+ }
+ }
+ }
+
+ return (count == 5 * IterationsCount00);
+ }
+ #endregion
+
+ #region Order00
+ private bool Order00()
+ {
+ bool result = true;
+ result &= Order00Manual();
+ result &= Order00LinqMethod();
+ result &= Order00LinqQuery();
+ return result;
+ }
+
+ [Benchmark]
+ private bool Order00LinqQueryX()
+ {
+ bool result = true;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Order00LinqQuery();
+ }
+ }
+ return result;
+ }
+
+ private bool Order00LinqQuery()
+ {
+ List<Product> products = Product.GetProductList();
+ Product medianPricedProduct = null;
+ for (int i = 0; i < IterationsOrder00; i++)
+ {
+ var productsInPriceOrder = from prod in products orderby prod.UnitPrice descending select prod;
+ int count = productsInPriceOrder.Count();
+ medianPricedProduct = productsInPriceOrder.ElementAt<Product>(count / 2);
+ Escape(medianPricedProduct);
+ }
+
+ return (medianPricedProduct.ProductID == 57);
+ }
+
+ [Benchmark]
+ private bool Order00LinqMethodX()
+ {
+ bool result = true;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Order00LinqMethod();
+ }
+ }
+
+ return result;
+ }
+
+ private bool Order00LinqMethod()
+ {
+ List<Product> products = Product.GetProductList();
+ Product medianPricedProduct = null;
+ for (int i = 0; i < IterationsOrder00; i++)
+ {
+ var productsInPriceOrder = products.OrderByDescending(p => p.UnitPrice);
+ int count = productsInPriceOrder.Count();
+ medianPricedProduct = productsInPriceOrder.ElementAt<Product>(count / 2);
+ Escape(medianPricedProduct);
+ }
+
+ return (medianPricedProduct.ProductID == 57);
+ }
+
+ [Benchmark]
+ private bool Order00ManualX()
+ {
+ bool result = true;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ result &= Order00Manual();
+ }
+ }
+
+ return result;
+ }
+
+ private bool Order00Manual()
+ {
+ List<Product> products = Product.GetProductList();
+ Product medianPricedProduct = null;
+ for (int i = 0; i < IterationsOrder00; i++)
+ {
+ Product[] productsInPriceOrder = products.ToArray<Product>();
+ Array.Sort<Product>(productsInPriceOrder, delegate (Product x, Product y) { return -x.UnitPrice.CompareTo(y.UnitPrice); });
+ int count = productsInPriceOrder.Count();
+ medianPricedProduct = productsInPriceOrder[count / 2];
+ Escape(medianPricedProduct);
+ }
+
+ return (medianPricedProduct.ProductID == 57);
+ }
+ #endregion
+
+ public static int Main()
+ {
+ var tests = new LinqBenchmarks();
+ bool result = tests.Bench();
+ return result ? 100 : -1;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Linq/Linq.csproj b/tests/src/JIT/Performance/CodeQuality/Linq/Linq.csproj
new file mode 100644
index 0000000000..99fa3f03c6
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Linq/Linq.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Linq.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/Math/Functions/Double/AbsDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AbsDouble.cs
new file mode 100644
index 0000000000..6429a39ce4
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AbsDouble.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Abs(double) over 5000 iterations for the domain -1, +1
+
+ private const double absDoubleDelta = 0.0004;
+ private const double absDoubleExpectedResult = 2499.9999999999659;
+
+ [Benchmark]
+ public static void AbsDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ AbsDoubleTest();
+ }
+ }
+ }
+
+ public static void AbsDoubleTest()
+ {
+ var result = 0.0; var value = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += absDoubleDelta;
+ result += Math.Abs(value);
+ }
+
+ var diff = Math.Abs(absDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {absDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AcosDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AcosDouble.cs
new file mode 100644
index 0000000000..3ba2867a8e
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AcosDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Acos(double) over 5000 iterations for the domain -1, +1
+
+ private const double acosDoubleDelta = 0.0004;
+ private const double acosDoubleExpectedResult = 7852.4108380716079;
+
+ [Benchmark]
+ public static void AcosDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ AcosDoubleTest();
+ }
+ }
+ }
+
+ public static void AcosDoubleTest()
+ {
+ var result = 0.0; var value = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += acosDoubleDelta;
+ result += Math.Acos(value);
+ }
+
+ var diff = Math.Abs(acosDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {acosDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AsinDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AsinDouble.cs
new file mode 100644
index 0000000000..030756ce44
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AsinDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Asin(double) over 5000 iterations for the domain -1, +1
+
+ private const double asinDoubleDelta = 0.0004;
+ private const double asinDoubleExpectedResult = 1.5707959028763392;
+
+ [Benchmark]
+ public static void AsinDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ AsinDoubleTest();
+ }
+ }
+ }
+
+ public static void AsinDoubleTest()
+ {
+ var result = 0.0; var value = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += asinDoubleDelta;
+ result += Math.Asin(value);
+ }
+
+ var diff = Math.Abs(asinDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {asinDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/Atan2Double.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/Atan2Double.cs
new file mode 100644
index 0000000000..82831e6412
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/Atan2Double.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Atan2(double, double) over 5000 iterations for the domain y: -1, +1; x: +1, -1
+
+ private const double atan2DoubleDeltaX = -0.0004;
+ private const double atan2DoubleDeltaY = 0.0004;
+ private const double atan2DoubleExpectedResult = 3926.99081698702;
+
+ [Benchmark]
+ public static void Atan2DoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Atan2DoubleTest();
+ }
+ }
+ }
+
+ public static void Atan2DoubleTest()
+ {
+ var result = 0.0; var valueX = 1.0; var valueY = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ valueX += atan2DoubleDeltaX; valueY += atan2DoubleDeltaY;
+ result += Math.Atan2(valueY, valueX);
+ }
+
+ var diff = Math.Abs(atan2DoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {atan2DoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AtanDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AtanDouble.cs
new file mode 100644
index 0000000000..ec2ebe389e
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/AtanDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Atan(double) over 5000 iterations for the domain -1, +1
+
+ private const double atanDoubleDelta = 0.0004;
+ private const double atanDoubleExpectedResult = 0.78539816322061329;
+
+ [Benchmark]
+ public static void AtanDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ AtanDoubleTest();
+ }
+ }
+ }
+
+ public static void AtanDoubleTest()
+ {
+ var result = 0.0; var value = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += atanDoubleDelta;
+ result += Math.Atan(value);
+ }
+
+ var diff = Math.Abs(atanDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {atanDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CeilingDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CeilingDouble.cs
new file mode 100644
index 0000000000..f822aae256
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CeilingDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Ceiling(double) over 5000 iterations for the domain -1, +1
+
+ private const double ceilingDoubleDelta = 0.0004;
+ private const double ceilingDoubleExpectedResult = 2500;
+
+ [Benchmark]
+ public static void CeilingDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ CeilingDoubleTest();
+ }
+ }
+ }
+
+ public static void CeilingDoubleTest()
+ {
+ var result = 0.0; var value = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += ceilingDoubleDelta;
+ result += Math.Ceiling(value);
+ }
+
+ var diff = Math.Abs(ceilingDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {ceilingDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CosDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CosDouble.cs
new file mode 100644
index 0000000000..e95ab5c241
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CosDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Cos(double) over 5000 iterations for the domain 0, PI
+
+ private const double cosDoubleDelta = 0.0006283185307180;
+ private const double cosDoubleExpectedResult = -1.0000000005924159;
+
+ [Benchmark]
+ public static void CosDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ CosDoubleTest();
+ }
+ }
+ }
+
+ public static void CosDoubleTest()
+ {
+ var result = 0.0; var value = 0.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += cosDoubleDelta;
+ result += Math.Cos(value);
+ }
+
+ var diff = Math.Abs(cosDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {cosDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CoshDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CoshDouble.cs
new file mode 100644
index 0000000000..c8b7fb68cc
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/CoshDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Cosh(double) over 5000 iterations for the domain -1, +1
+
+ private const double coshDoubleDelta = 0.0004;
+ private const double coshDoubleExpectedResult = 5876.0060465657216;
+
+ [Benchmark]
+ public static void CoshDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ CoshDoubleTest();
+ }
+ }
+ }
+
+ public static void CoshDoubleTest()
+ {
+ var result = 0.0; var value = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += coshDoubleDelta;
+ result += Math.Cosh(value);
+ }
+
+ var diff = Math.Abs(coshDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {coshDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/ExpDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/ExpDouble.cs
new file mode 100644
index 0000000000..64be83972f
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/ExpDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Exp(double) over 5000 iterations for the domain -1, +1
+
+ private const double expDoubleDelta = 0.0004;
+ private const double expDoubleExpectedResult = 5877.1812477590884;
+
+ [Benchmark]
+ public static void ExpDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ ExpDoubleTest();
+ }
+ }
+ }
+
+ public static void ExpDoubleTest()
+ {
+ var result = 0.0; var value = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += expDoubleDelta;
+ result += Math.Exp(value);
+ }
+
+ var diff = Math.Abs(expDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {expDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/FloorDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/FloorDouble.cs
new file mode 100644
index 0000000000..4d4b4f2f1b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/FloorDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Floor(double) over 5000 iterations for the domain -1, +1
+
+ private const double floorDoubleDelta = 0.0004;
+ private const double floorDoubleExpectedResult = -2500;
+
+ [Benchmark]
+ public static void FloorDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ FloorDoubleTest();
+ }
+ }
+ }
+
+ public static void FloorDoubleTest()
+ {
+ var result = 0.0; var value = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += floorDoubleDelta;
+ result += Math.Floor(value);
+ }
+
+ var diff = Math.Abs(floorDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {floorDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/Log10Double.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/Log10Double.cs
new file mode 100644
index 0000000000..330d8a726b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/Log10Double.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Log10(double) over 5000 iterations for the domain -1, +1
+
+ private const double log10DoubleDelta = 0.0004;
+ private const double log10DoubleExpectedResult = -664.07384902184072;
+
+ [Benchmark]
+ public static void Log10DoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ Log10DoubleTest();
+ }
+ }
+ }
+
+ public static void Log10DoubleTest()
+ {
+ var result = 0.0; var value = 0.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += log10DoubleDelta;
+ result += Math.Log10(value);
+ }
+
+ var diff = Math.Abs(log10DoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {log10DoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/LogDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/LogDouble.cs
new file mode 100644
index 0000000000..bddb84b59c
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/LogDouble.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Log(double) over 5000 iterations for the domain -1, +1
+
+ private const double logDoubleDelta = 0.0004;
+ private const double logDoubleExpectedResult = -1529.0865454048721;
+
+ [Benchmark]
+ public static void LogDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ LogDoubleTest();
+ }
+ }
+ }
+
+ public static void LogDoubleTest()
+ {
+ var result = 0.0; var value = 0.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += logDoubleDelta;
+ result += Math.Log(value);
+ }
+
+ var diff = Math.Abs(logDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {logDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/PowDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/PowDouble.cs
new file mode 100644
index 0000000000..c8248072b7
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/PowDouble.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Pow(double, double) over 5000 iterations for the domain x: +2, +1; y: -2, -1
+
+ private const double powDoubleDeltaX = -0.0004;
+ private const double powDoubleDeltaY = 0.0004;
+ private const double powDoubleExpectedResult = 4659.4627376138733;
+
+ [Benchmark]
+ public static void PowDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ PowDoubleTest();
+ }
+ }
+ }
+
+ public static void PowDoubleTest()
+ {
+ var result = 0.0; var valueX = 2.0; var valueY = -2.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ valueX += powDoubleDeltaX; valueY += powDoubleDeltaY;
+ result += Math.Pow(valueX, valueY);
+ }
+
+ var diff = Math.Abs(powDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {powDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/RoundDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/RoundDouble.cs
new file mode 100644
index 0000000000..9c5dcc9141
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/RoundDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Round(double) over 5000 iterations for the domain -PI/2, +PI/2
+
+ private const double roundDoubleDelta = 0.0006283185307180;
+ private const double roundDoubleExpectedResult = 2;
+
+ [Benchmark]
+ public static void RoundDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ RoundDoubleTest();
+ }
+ }
+ }
+
+ public static void RoundDoubleTest()
+ {
+ var result = 0.0; var value = -1.5707963267948966;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += roundDoubleDelta;
+ result += Math.Round(value);
+ }
+
+ var diff = Math.Abs(roundDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {roundDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SinDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SinDouble.cs
new file mode 100644
index 0000000000..73886aaa3a
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SinDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Sin(double) over 5000 iterations for the domain -PI/2, +PI/2
+
+ private const double sinDoubleDelta = 0.0006283185307180;
+ private const double sinDoubleExpectedResult = 1.0000000005445053;
+
+ [Benchmark]
+ public static void SinDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ SinDoubleTest();
+ }
+ }
+ }
+
+ public static void SinDoubleTest()
+ {
+ var result = 0.0; var value = -1.5707963267948966;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += sinDoubleDelta;
+ result += Math.Sin(value);
+ }
+
+ var diff = Math.Abs(sinDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {sinDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SinhDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SinhDouble.cs
new file mode 100644
index 0000000000..8f79cc9576
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SinhDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Sinh(double) over 5000 iterations for the domain -1, +1
+
+ private const double sinhDoubleDelta = 0.0004;
+ private const double sinhDoubleExpectedResult = 1.17520119337903;
+
+ [Benchmark]
+ public static void SinhDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ SinhDoubleTest();
+ }
+ }
+ }
+
+ public static void SinhDoubleTest()
+ {
+ var result = 0.0; var value = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += sinhDoubleDelta;
+ result += Math.Sinh(value);
+ }
+
+ var diff = Math.Abs(sinhDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {sinhDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SqrtDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SqrtDouble.cs
new file mode 100644
index 0000000000..5d9e554684
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/SqrtDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Sqrt(double) over 5000 iterations for the domain 0, PI
+
+ private const double sqrtDoubleDelta = 0.0006283185307180;
+ private const double sqrtDoubleExpectedResult = 5909.0605337797215;
+
+ [Benchmark]
+ public static void SqrtDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ SqrtDoubleTest();
+ }
+ }
+ }
+
+ public static void SqrtDoubleTest()
+ {
+ var result = 0.0; var value = 0.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += sqrtDoubleDelta;
+ result += Math.Sqrt(value);
+ }
+
+ var diff = Math.Abs(sqrtDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {sqrtDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/TanDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/TanDouble.cs
new file mode 100644
index 0000000000..6988c675dc
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/TanDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Tan(double) over 5000 iterations for the domain -PI/2, +PI/2
+
+ private const double tanDoubleDelta = 0.0004;
+ private const double tanDoubleExpectedResult = 1.5574077243051505;
+
+ [Benchmark]
+ public static void TanDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ TanDoubleTest();
+ }
+ }
+ }
+
+ public static void TanDoubleTest()
+ {
+ var result = 0.0; var value = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += tanDoubleDelta;
+ result += Math.Tan(value);
+ }
+
+ var diff = Math.Abs(tanDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {tanDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/TanhDouble.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/TanhDouble.cs
new file mode 100644
index 0000000000..c4809e53a3
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Double/TanhDouble.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Tanh(double) over 5000 iterations for the domain -1, +1
+
+ private const double tanhDoubleDelta = 0.0004;
+ private const double tanhDoubleExpectedResult = 0.76159415578341827;
+
+ [Benchmark]
+ public static void TanhDoubleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ TanhDoubleTest();
+ }
+ }
+ }
+
+ public static void TanhDoubleTest()
+ {
+ var result = 0.0; var value = -1.0;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += tanhDoubleDelta;
+ result += Math.Tanh(value);
+ }
+
+ var diff = Math.Abs(tanhDoubleExpectedResult - result);
+
+ if (diff > doubleEpsilon)
+ {
+ throw new Exception($"Expected Result {tanhDoubleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Functions.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Functions.cs
new file mode 100644
index 0000000000..8ddc6ad73b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Functions.cs
@@ -0,0 +1,158 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Microsoft.Xunit.Performance;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+namespace Functions
+{
+ public static class Program
+ {
+#if DEBUG
+ private const int defaultIterations = 1;
+#else
+ private const int defaultIterations = 1000;
+#endif
+
+ private static readonly IDictionary<string, Action> TestList = new Dictionary<string, Action>() {
+ ["absdouble"] = MathTests.AbsDoubleTest,
+ ["abssingle"] = MathTests.AbsSingleTest,
+ ["acosdouble"] = MathTests.AcosDoubleTest,
+ ["asindouble"] = MathTests.AsinDoubleTest,
+ ["atandouble"] = MathTests.AtanDoubleTest,
+ ["atan2double"] = MathTests.Atan2DoubleTest,
+ ["ceilingdouble"] = MathTests.CeilingDoubleTest,
+ ["cosdouble"] = MathTests.CosDoubleTest,
+ ["coshdouble"] = MathTests.CoshDoubleTest,
+ ["expdouble"] = MathTests.ExpDoubleTest,
+ ["floordouble"] = MathTests.FloorDoubleTest,
+ ["logdouble"] = MathTests.LogDoubleTest,
+ ["log10double"] = MathTests.Log10DoubleTest,
+ ["powdouble"] = MathTests.PowDoubleTest,
+ ["rounddouble"] = MathTests.RoundDoubleTest,
+ ["sindouble"] = MathTests.SinDoubleTest,
+ ["sinhdouble"] = MathTests.SinhDoubleTest,
+ ["sqrtdouble"] = MathTests.SqrtDoubleTest,
+ ["tandouble"] = MathTests.TanDoubleTest,
+ ["tanhdouble"] = MathTests.TanhDoubleTest
+ };
+
+ private static int Main(string[] args)
+ {
+ var isPassing = true; var iterations = defaultIterations;
+ ICollection<string> testsToRun = new HashSet<string>();
+
+ try
+ {
+ for (int index = 0; index < args.Length; index++)
+ {
+ if (args[index].ToLowerInvariant() == "-bench")
+ {
+ index++;
+
+ if ((index >= args.Length) || !int.TryParse(args[index], out iterations))
+ {
+ iterations = defaultIterations;
+ }
+ }
+ else if (args[index].ToLowerInvariant() == "all")
+ {
+ testsToRun = TestList.Keys;
+ break;
+ }
+ else
+ {
+ var testName = args[index].ToLowerInvariant();
+
+ if (!TestList.ContainsKey(testName))
+ {
+ PrintUsage();
+ break;
+ }
+
+ testsToRun.Add(testName);
+ }
+ }
+
+ if (testsToRun.Count == 0)
+ {
+ testsToRun = TestList.Keys;
+ }
+
+ foreach (var testToRun in testsToRun)
+ {
+ Console.WriteLine($"Running {testToRun} test...");
+ Test(iterations, TestList[testToRun]);
+ }
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine($" Error: {exception.Message}");
+ isPassing = false;
+ }
+
+ return isPassing ? 100 : -1;
+ }
+
+ private static void PrintUsage()
+ {
+ Console.WriteLine(@"Usage:
+Functions [name] [-bench #]
+
+ [name]: The name of the function to test. Defaults to 'all'.
+ all");
+
+ foreach (var testName in TestList.Keys)
+ {
+ Console.WriteLine($" {testName}");
+ }
+
+ Console.WriteLine($@"
+ [-bench #]: The number of iterations. Defaults to {defaultIterations}");
+ }
+
+ private static void Test(int iterations, Action action)
+ {
+ // ****************************************************************
+
+ Console.WriteLine(" Warming up...");
+
+ var startTimestamp = Stopwatch.GetTimestamp();
+
+ action();
+
+ var totalElapsedTime = (Stopwatch.GetTimestamp() - startTimestamp);
+ var totalElapsedTimeInSeconds = (totalElapsedTime / (double)(Stopwatch.Frequency));
+
+ Console.WriteLine($" Total Time: {totalElapsedTimeInSeconds}");
+
+ // ****************************************************************
+
+ Console.WriteLine($" Executing {iterations} iterations...");
+
+ totalElapsedTime = 0L;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ startTimestamp = Stopwatch.GetTimestamp();
+
+ action();
+
+ totalElapsedTime += (Stopwatch.GetTimestamp() - startTimestamp);
+ }
+
+ totalElapsedTimeInSeconds = (totalElapsedTime / (double)(Stopwatch.Frequency));
+
+ Console.WriteLine($" Total Time: {totalElapsedTimeInSeconds} seconds");
+ Console.WriteLine($" Average Time: {totalElapsedTimeInSeconds / iterations} seconds");
+
+ // ****************************************************************
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Functions.csproj b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Functions.csproj
new file mode 100644
index 0000000000..7e7a74e142
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Functions.csproj
@@ -0,0 +1,67 @@
+<?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>{C949CB07-60B2-420A-B3CA-59847ED4700B}</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>
+ </NuGetPackageImportStamp>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Double\AbsDouble.cs" />
+ <Compile Include="Single\AbsSingle.cs" />
+ <Compile Include="Double\AcosDouble.cs" />
+ <Compile Include="Double\AsinDouble.cs" />
+ <Compile Include="Double\AtanDouble.cs" />
+ <Compile Include="Double\Atan2Double.cs" />
+ <Compile Include="Double\CeilingDouble.cs" />
+ <Compile Include="Double\CosDouble.cs" />
+ <Compile Include="Double\CoshDouble.cs" />
+ <Compile Include="Double\ExpDouble.cs" />
+ <Compile Include="Double\FloorDouble.cs" />
+ <Compile Include="Functions.cs" />
+ <Compile Include="Double\LogDouble.cs" />
+ <Compile Include="Double\Log10Double.cs" />
+ <Compile Include="MathTests.cs" />
+ <Compile Include="Double\PowDouble.cs" />
+ <Compile Include="Double\RoundDouble.cs" />
+ <Compile Include="Double\SinDouble.cs" />
+ <Compile Include="Double\SinhDouble.cs" />
+ <Compile Include="Double\SqrtDouble.cs" />
+ <Compile Include="Double\TanDouble.cs" />
+ <Compile Include="Double\TanhDouble.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/Math/Functions/MathTests.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/MathTests.cs
new file mode 100644
index 0000000000..b738c75352
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/MathTests.cs
@@ -0,0 +1,29 @@
+// 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.
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // double has a machine epsilon of approx: 2.22e-16. However, due to floating-point precision
+ // errors, this is too accurate when aggregating values of a set of iterations. Using the
+ // single-precision machine epsilon as our epsilon should be 'good enough' for the purposes
+ // of the perf testing as it ensures we get the expected value and that it is at least as precise
+ // as we would have computed with the single-precision version of the function (without aggregation).
+ private const double doubleEpsilon = 1.19e-07;
+
+ // 5000 iterations is enough to cover the full domain of inputs for certain functions (such
+ // as Cos, which has a domain of 0 to PI) at reasonable intervals (in the case of Cos, the
+ // interval is PI / 5000 which is 0.0006283185307180). It should also give reasonable coverage
+ // for functions which have a larger domain (such as Atan, which covers the full set of real numbers).
+ private const int iterations = 5000;
+
+ // float has a machine epsilon of approx: 1.19e-07. However, due to floating-point precision
+ // errors, this is too accurate when aggregating values of a set of iterations. Using the
+ // half-precision machine epsilon as our epsilon should be 'good enough' for the purposes
+ // of the perf testing as it ensures we get the expected value and that it is at least as precise
+ // as we would have computed with the half-precision version of the function (without aggregation).
+ private const float singleEpsilon = 9.77e-04f;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Math/Functions/Single/AbsSingle.cs b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Single/AbsSingle.cs
new file mode 100644
index 0000000000..6168991297
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Math/Functions/Single/AbsSingle.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Microsoft.Xunit.Performance;
+
+namespace Functions
+{
+ public static partial class MathTests
+ {
+ // Tests Math.Abs(single) over 5000 iterations for the domain -1, +1
+
+ private const float absSingleDelta = 0.0004f;
+ private const float absSingleExpectedResult = 2500.03125f;
+
+ [Benchmark]
+ public static void AbsSingleBenchmark()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ AbsSingleTest();
+ }
+ }
+ }
+
+ public static void AbsSingleTest()
+ {
+ var result = 0.0f; var value = -1.0f;
+
+ for (var iteration = 0; iteration < iterations; iteration++)
+ {
+ value += absSingleDelta;
+ result += Math.Abs(value);
+ }
+
+ var diff = Math.Abs(absSingleExpectedResult - result);
+
+ if (diff > singleEpsilon)
+ {
+ throw new Exception($"Expected Result {absSingleExpectedResult}; Actual Result {result}");
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Roslyn/CscBench.cs b/tests/src/JIT/Performance/CodeQuality/Roslyn/CscBench.cs
new file mode 100644
index 0000000000..e3337d115b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Roslyn/CscBench.cs
@@ -0,0 +1,196 @@
+// 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.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Text;
+using Microsoft.Xunit.Performance;
+using System;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public static class CscBench
+{
+
+#if DEBUG
+ public const int CompileIterations = 1;
+ public const int DataflowIterations = 1;
+#else
+ public const int CompileIterations = 1500;
+ public const int DataflowIterations = 10000;
+#endif
+
+ public static string MscorlibPath;
+
+ static bool FindMscorlib()
+ {
+ string CoreRoot = System.Environment.GetEnvironmentVariable("CORE_ROOT");
+ if (CoreRoot == null) { return false; }
+ // Some CoreCLR packages have System.Private.CoreLib.ni.dll only
+ string nicorlib = Path.Combine(CoreRoot, "System.Private.CoreLib.ni.dll");
+ if(File.Exists(nicorlib))
+ {
+ MscorlibPath = nicorlib;
+ return true;
+ }
+ MscorlibPath = Path.Combine(CoreRoot, "System.Private.CoreLib.dll");
+ return File.Exists(MscorlibPath);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static bool CompileBench()
+ {
+ var expression = "6 * 7";
+ var text = @"public class Calculator { public static object Evaluate() { return $; } }".Replace("$", expression);
+ var tree = SyntaxFactory.ParseSyntaxTree(text);
+ var compilation = CSharpCompilation.Create(
+ "calc.dll",
+ options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
+ syntaxTrees: new[] { tree },
+ references: new[] { MetadataReference.CreateFromFile(MscorlibPath) });
+
+ bool result = true;
+ for (int i = 0; i < CompileIterations; i++)
+ {
+ using (var stream = new MemoryStream())
+ {
+ var emitResult = compilation.Emit(stream);
+ result &= emitResult.Success;
+ }
+ }
+
+ return result;
+ }
+
+ [Benchmark]
+ public static void CompileTest()
+ {
+ if (!FindMscorlib())
+ {
+ throw new Exception("This test requires CORE_ROOT to be set");
+ }
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ CompileBench();
+ }
+ }
+ }
+
+ public static TextSpan GetSpanBetweenMarkers(SyntaxTree tree)
+ {
+ SyntaxTrivia startComment = tree
+ .GetRoot()
+ .DescendantTrivia()
+ .First(syntaxTrivia => syntaxTrivia.ToString().Contains("start"));
+ SyntaxTrivia endComment = tree
+ .GetRoot()
+ .DescendantTrivia()
+ .First(syntaxTrivia => syntaxTrivia.ToString().Contains("end"));
+ TextSpan textSpan = TextSpan.FromBounds(
+ startComment.FullSpan.End,
+ endComment.FullSpan.Start);
+ return textSpan;
+ }
+
+ public static void GetStatementsBetweenMarkers(SyntaxTree tree, out StatementSyntax firstStatement, out StatementSyntax lastStatement)
+ {
+ TextSpan span = GetSpanBetweenMarkers(tree);
+ var statementsInside = tree
+ .GetRoot()
+ .DescendantNodes(span)
+ .OfType<StatementSyntax>()
+ .Where(s => span.Contains(s.Span));
+ firstStatement = statementsInside.First();
+ var first = firstStatement;
+ lastStatement = statementsInside
+ .Where(s => s.Parent == first.Parent)
+ .Last();
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static bool DataflowBench()
+ {
+ var text = @"
+class C {
+ public void F(int x)
+ {
+ int a;
+/*start*/
+ int b;
+ int x, y = 1;
+ { var z = ""a""; }
+/*end*/
+ int c;
+ }
+}";
+ var tree = SyntaxFactory.ParseSyntaxTree(text);
+ var compilation = CSharpCompilation.Create(
+ "calc.dll",
+ options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
+ syntaxTrees: new[] { tree },
+ references: new[] { MetadataReference.CreateFromFile(MscorlibPath) });
+ var semanticModel = compilation.GetSemanticModel(tree);
+
+ bool result = true;
+ for (int i = 0; i < DataflowIterations; i++)
+ {
+ StatementSyntax firstStatement, lastStatement;
+ GetStatementsBetweenMarkers(tree, out firstStatement, out lastStatement);
+ DataFlowAnalysis regionDataFlowAnalysis = semanticModel.AnalyzeDataFlow(firstStatement, lastStatement);
+ string declaredVars = string.Join(",", regionDataFlowAnalysis
+ .VariablesDeclared
+ .Select(symbol => symbol.Name));
+
+ result &= "b,x,y,z".Equals(declaredVars);
+ }
+
+ return result;
+ }
+
+ [Benchmark]
+ public static void DatflowTest()
+ {
+ if (!FindMscorlib())
+ {
+ throw new Exception("This test requires CORE_ROOT to be set");
+ }
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ DataflowBench();
+ }
+ }
+ }
+
+ static bool Bench()
+ {
+ bool result = true;
+ result &= CompileBench();
+ result &= DataflowBench();
+ return result;
+ }
+
+ public static int Main()
+ {
+ bool result = true;
+ if (!FindMscorlib())
+ {
+ Console.WriteLine("This test requires CORE_ROOT to be set");
+ result = false;
+ }
+ else {
+ result = Bench();
+ }
+ return result ? 100 : -1;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Roslyn/CscBench.csproj b/tests/src/JIT/Performance/CodeQuality/Roslyn/CscBench.csproj
new file mode 100644
index 0000000000..b99d74b9bc
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Roslyn/CscBench.csproj
@@ -0,0 +1,44 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ <GCStressIncompatible>true</GCStressIncompatible>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="CscBench.cs" />
+ </ItemGroup>
+ <PropertyGroup>
+ <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark+roslyn\project.json</ProjectJson>
+ <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark+roslyn\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/SIMD/ConsoleMandel/Abstractions.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/Abstractions.cs
new file mode 100644
index 0000000000..8cfc0d1238
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/Abstractions.cs
@@ -0,0 +1,138 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+
+namespace Algorithms
+{
+ // A float implementation of the BCL Complex type that only
+ // contains the bare essentials, plus a couple operations needed
+ // for efficient Mandelbrot calcuation.
+ internal struct ComplexFloat
+ {
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public ComplexFloat(float real, float imaginary)
+ {
+ Real = real; Imaginary = imaginary;
+ }
+
+ public float Real;
+ public float Imaginary;
+
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public ComplexFloat square()
+ {
+ return new ComplexFloat(Real * Real - Imaginary * Imaginary, 2.0f * Real * Imaginary);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public float sqabs()
+ {
+ return Real * Real + Imaginary * Imaginary;
+ }
+
+ public override string ToString()
+ {
+ return String.Format("[{0} + {1}Imaginary]", Real, Imaginary);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static ComplexFloat operator +(ComplexFloat a, ComplexFloat b)
+ {
+ return new ComplexFloat(a.Real + b.Real, a.Imaginary + b.Imaginary);
+ }
+ }
+
+ // A couple extension methods that operate on BCL Complex types to help efficiently calculate
+ // the Mandelbrot set (They're instance methods on the ComplexFloat custom type)
+ public static partial class extensions
+ {
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static double sqabs(this Complex val)
+ {
+ return val.Real * val.Real + val.Imaginary * val.Imaginary;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static Complex square(this Complex val)
+ {
+ return new Complex(val.Real * val.Real - val.Imaginary * val.Imaginary, 2.0 * val.Real * val.Imaginary);
+ }
+ }
+
+ // This is an implementation of ComplexFloat that operates on Vector<float> at a time SIMD types
+ internal struct ComplexVecFloat
+ {
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public ComplexVecFloat(Vector<float> real, Vector<float> imaginary)
+ {
+ Real = real; Imaginary = imaginary;
+ }
+
+ public Vector<float> Real;
+ public Vector<float> Imaginary;
+
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public ComplexVecFloat square()
+ {
+ return new ComplexVecFloat(Real * Real - Imaginary * Imaginary, Real * Imaginary + Real * Imaginary);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public Vector<float> sqabs()
+ {
+ return Real * Real + Imaginary * Imaginary;
+ }
+
+ public override string ToString()
+ {
+ return String.Format("[{0} + {1}Imaginary]", Real, Imaginary);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static ComplexVecFloat operator +(ComplexVecFloat a, ComplexVecFloat b)
+ {
+ return new ComplexVecFloat(a.Real + b.Real, a.Imaginary + b.Imaginary);
+ }
+ }
+
+ // This is an implementation of Complex that operates on Vector<double> at a time SIMD types
+ internal struct ComplexVecDouble
+ {
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public ComplexVecDouble(Vector<double> real, Vector<double> imaginary)
+ {
+ Real = real; Imaginary = imaginary;
+ }
+
+ public Vector<double> Real;
+ public Vector<double> Imaginary;
+
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public ComplexVecDouble square()
+ {
+ return new ComplexVecDouble(Real * Real - Imaginary * Imaginary, Real * Imaginary + Real * Imaginary);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public Vector<double> sqabs()
+ {
+ return Real * Real + Imaginary * Imaginary;
+ }
+
+ public override string ToString()
+ {
+ return String.Format("[{0} + {1}Imaginary]", Real, Imaginary);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static ComplexVecDouble operator +(ComplexVecDouble a, ComplexVecDouble b)
+ {
+ return new ComplexVecDouble(a.Real + b.Real, a.Imaginary + b.Imaginary);
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.cs
new file mode 100644
index 0000000000..ed7f675700
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.cs
@@ -0,0 +1,256 @@
+// 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.Diagnostics;
+using Xunit;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+namespace ConsoleMandel
+{
+ public static class Program
+ {
+ private const int Pass = 100;
+ private const int Fail = -1;
+ private static bool s_silent = false;
+
+ private static void DoNothing(int x, int y, int count) { }
+
+ private static void DrawDot(int x, int y, int count)
+ {
+ if (x == 0)
+ Console.WriteLine();
+ Console.Write((count < 1000) ? ' ' : '*');
+ }
+
+ private static Algorithms.FractalRenderer.Render GetRenderer(Action<int, int, int> draw, int which)
+ {
+ return Algorithms.FractalRenderer.SelectRender(draw, Abort, IsVector(which), IsDouble(which), IsMulti(which), UsesADT(which), !UseIntTypes(which));
+ }
+
+ private static bool Abort() { return false; }
+
+ private static bool UseIntTypes(int num) { return (num & 8) == 0; }
+
+ private static bool IsVector(int num) { return num > 7; }
+
+ private static bool IsDouble(int num) { return (num & 4) != 0; }
+
+ private static bool IsMulti(int num) { return (num & 2) != 0; }
+
+ private static bool UsesADT(int num) { return (num & 1) != 0; }
+
+ private static void PrintDescription(int i)
+ {
+ Console.WriteLine("{0}: {1} {2}-Precision {3}Threaded using {4} and {5} int types", i,
+ IsVector(i) ? "Vector" : "Scalar",
+ IsDouble(i) ? "Double" : "Single",
+ IsMulti(i) ? "Multi" : "Single",
+ UsesADT(i) ? "ADT" : "Raw Values",
+ UseIntTypes(i) ? "using" : "not using any");
+ }
+
+ private static void PrintUsage()
+ {
+ Console.WriteLine("Usage:\n ConsoleMandel [0-23] -[bench #] where # is the number of iterations.");
+ for (int i = 0; i < 24; i++)
+ {
+ PrintDescription(i);
+ }
+ Console.WriteLine("The numeric argument selects the implementation number;");
+ Console.WriteLine("If not specified, all are run.");
+ Console.WriteLine("In non-benchmark mode, dump a text view of the Mandelbrot set.");
+ Console.WriteLine("In benchmark mode, a larger set is computed but nothing is dumped.");
+ }
+
+ private static int Main(string[] args)
+ {
+ try
+ {
+ int which = -1;
+ bool verbose = false;
+ bool bench = false;
+ int iters = 1;
+ int argNum = 0;
+ while (argNum < args.Length)
+ {
+ if (args[argNum].ToUpperInvariant() == "-BENCH")
+ {
+ bench = true;
+ if ((args.Length <= (argNum + 1)) || !Int32.TryParse(args[argNum + 1], out iters))
+ {
+ iters = 5;
+ }
+ argNum++;
+ }
+ else if (args[argNum].ToUpperInvariant() == "-V")
+ {
+ verbose = true;
+ }
+ else if (args[argNum].ToUpperInvariant() == "-S")
+ {
+ s_silent = true;
+ }
+ else if (!Int32.TryParse(args[argNum], out which))
+ {
+ PrintUsage();
+ return Fail;
+ }
+ argNum++;
+ }
+ if (bench)
+ {
+ Bench(iters, which);
+ return Pass;
+ }
+ if (which == -1)
+ {
+ PrintUsage();
+ return Pass;
+ }
+ if (verbose)
+ {
+ PrintDescription(which);
+ }
+ if (IsVector(which))
+ {
+ if (verbose)
+ {
+ Console.WriteLine(" Vector Count is {0}", IsDouble(which) ? System.Numerics.Vector<Double>.Count : System.Numerics.Vector<Single>.Count);
+ Console.WriteLine(" {0} Accelerated.", System.Numerics.Vector.IsHardwareAccelerated ? "IS" : "IS NOT");
+ }
+ }
+ var render = GetRenderer(DrawDot, which);
+ render(-1.5f, .5f, -1f, 1f, 2.0f / 60.0f);
+ return Pass;
+ }
+ catch (System.Exception)
+ {
+ return Fail;
+ }
+ }
+
+ public static void Bench(int iters, int which)
+ {
+ float XC = -1.248f;
+ float YC = -.0362f;
+ float Range = .001f;
+ float xmin = XC - Range;
+ float xmax = XC + Range;
+ float ymin = YC - Range;
+ float ymax = YC + Range;
+ float step = Range / 1000f; // This will render one million pixels
+ float warm = Range / 100f; // To warm up, just render 10000 pixels :-)
+ Algorithms.FractalRenderer.Render[] renderers = new Algorithms.FractalRenderer.Render[24];
+ // Warm up each renderer
+ if (!s_silent)
+ {
+ Console.WriteLine("Warming up...");
+ }
+ Stopwatch timer = new Stopwatch();
+ int firstRenderer = (which == -1) ? 0 : which;
+ int lastRenderer = (which == -1) ? (renderers.Length - 1) : which;
+ for (int i = firstRenderer; i <= lastRenderer; i++)
+ {
+ renderers[i] = GetRenderer(DoNothing, i);
+ timer.Restart();
+ renderers[i](xmin, xmax, ymin, ymax, warm);
+ timer.Stop();
+ if (!s_silent)
+ {
+ Console.WriteLine("{0}{1}{2}{3}{4} Complete [{5} ms]",
+ UseIntTypes(i) ? "IntBV " : "Strict ",
+ IsVector(i) ? "Vector " : "Scalar ",
+ IsDouble(i) ? "Double " : "Single ",
+ UsesADT(i) ? "ADT " : "Raw ",
+ IsMulti(i) ? "Multi " : "Single ",
+ timer.ElapsedMilliseconds);
+ }
+ }
+ if (!s_silent)
+ {
+ Console.WriteLine(" Run Type : Min Max Average Std-Dev");
+ }
+ for (int i = firstRenderer; i <= lastRenderer; i++)
+ {
+ long totalTime = 0;
+ long min = long.MaxValue;
+ long max = long.MinValue;
+ for (int count = 0; count < iters; count++)
+ {
+ timer.Restart();
+ renderers[i](xmin, xmax, ymin, ymax, step);
+ timer.Stop();
+ long time = timer.ElapsedMilliseconds;
+ max = Math.Max(time, max);
+ min = Math.Min(time, min);
+ totalTime += time;
+ }
+ double avg = totalTime / (double)iters;
+ double stdDev = Math.Sqrt(totalTime / (iters - 1.0)) / avg;
+ if (s_silent)
+ {
+ Console.WriteLine("Average: {0,0:0.0}", avg);
+ }
+ else
+ {
+ Console.WriteLine("{0}{1}{2}{3}{4}: {5,8} {6,8} {7,10:0.0} {8,10:P}",
+ UseIntTypes(i) ? "IntBV " : "Strict ",
+ IsVector(i) ? "Vector " : "Scalar ",
+ IsDouble(i) ? "Double " : "Single ",
+ UsesADT(i) ? "ADT " : "Raw ",
+ IsMulti(i) ? "Multi " : "Single ",
+ min, max, avg, stdDev);
+ }
+ }
+ }
+
+ public static void XBench(int iters, int which)
+ {
+ float XC = -1.248f;
+ float YC = -.0362f;
+ float Range = .001f;
+ float xmin = XC - Range;
+ float xmax = XC + Range;
+ float ymin = YC - Range;
+ float ymax = YC + Range;
+ float step = Range / 100f;
+
+ Algorithms.FractalRenderer.Render renderer = GetRenderer(DoNothing, which);
+
+ for (int count = 0; count < iters; count++)
+ {
+ renderer(xmin, xmax, ymin, ymax, step);
+ }
+ }
+
+ [Benchmark]
+ public static void VectorFloatSinglethreadRawNoInt()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ XBench(10, 8);
+ }
+ }
+ }
+
+ [Benchmark]
+ public static void VectorFloatSinglethreadADTNoInt()
+ {
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ XBench(10, 9);
+ }
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.csproj b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.csproj
new file mode 100644
index 0000000000..73a4c99541
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ConsoleMandel.csproj
@@ -0,0 +1,52 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ConsoleMandel.cs" />
+ <Compile Include="Abstractions.cs" />
+ <Compile Include="Interfaces.cs" />
+ <Compile Include="ScalarDouble.cs" />
+ <Compile Include="ScalarFloat.cs" />
+ <Compile Include="VectorDouble.cs" />
+ <Compile Include="VectorDoubleStrict.cs" />
+ <Compile Include="VectorFloat.cs" />
+ <Compile Include="VectorFloatStrict.cs" />
+ <Compile Include="VectorHelpers.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/SIMD/ConsoleMandel/Interfaces.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/Interfaces.cs
new file mode 100644
index 0000000000..dda2690e3d
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/Interfaces.cs
@@ -0,0 +1,145 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+
+namespace Algorithms
+{
+ public abstract class FractalRenderer
+ {
+ public delegate void Render(float xmin, float xmax, float ymin, float ymax, float step);
+
+ private Func<bool> _abort;
+ private Action<int, int, int> _drawPixel;
+ protected const int max_iters = 1000; // Make this higher to see more detail when zoomed in (and slow down rendering a lot)
+
+ protected FractalRenderer(Action<int, int, int> draw, Func<bool> checkAbort)
+ {
+ _drawPixel = draw; _abort = checkAbort;
+ }
+
+ protected Action<int, int, int> DrawPixel { get { return _drawPixel; } }
+
+ public bool Abort { get { return _abort(); } }
+
+ public static Render SelectRender(Action<int, int, int> draw, Func<bool> abort, bool useVectorTypes, bool doublePrecision, bool isMultiThreaded, bool useAbstractDataType, bool dontUseIntTypes = true)
+ {
+ if (useVectorTypes && doublePrecision)
+ {
+ if (dontUseIntTypes)
+ {
+ var r = new VectorDoubleStrictRenderer(draw, abort);
+ if (isMultiThreaded)
+ {
+ if (useAbstractDataType)
+ return r.RenderMultiThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderMultiThreadedNoADT;
+ }
+ else // !isMultiThreaded
+ {
+ if (useAbstractDataType)
+ return r.RenderSingleThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderSingleThreadedNoADT;
+ }
+ }
+ else // !dontUseIntTypes
+ {
+ var r = new VectorDoubleRenderer(draw, abort);
+ if (isMultiThreaded)
+ {
+ if (useAbstractDataType)
+ return r.RenderMultiThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderMultiThreadedNoADT;
+ }
+ else // !isMultiThreaded
+ {
+ if (useAbstractDataType)
+ return r.RenderSingleThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderSingleThreadedNoADT;
+ }
+ }
+ }
+ else if (useVectorTypes && !doublePrecision)
+ {
+ if (dontUseIntTypes)
+ {
+ var r = new VectorFloatStrictRenderer(draw, abort);
+ if (isMultiThreaded)
+ {
+ if (useAbstractDataType)
+ return r.RenderMultiThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderMultiThreadedNoADT;
+ }
+ else // !isMultiThreaded
+ {
+ if (useAbstractDataType)
+ return r.RenderSingleThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderSingleThreadedNoADT;
+ }
+ }
+ else // !dontUseIntTypes
+ {
+ var r = new VectorFloatRenderer(draw, abort);
+ if (isMultiThreaded)
+ {
+ if (useAbstractDataType)
+ return r.RenderMultiThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderMultiThreadedNoADT;
+ }
+ else // !isMultiThreaded
+ {
+ if (useAbstractDataType)
+ return r.RenderSingleThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderSingleThreadedNoADT;
+ }
+ }
+ }
+ else if (!useVectorTypes && doublePrecision)
+ {
+ var r = new ScalarDoubleRenderer(draw, abort);
+ if (isMultiThreaded)
+ {
+ if (useAbstractDataType)
+ return r.RenderMultiThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderMultiThreadedNoADT;
+ }
+ else // !isMultiThreaded
+ {
+ if (useAbstractDataType)
+ return r.RenderSingleThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderSingleThreadedNoADT;
+ }
+ }
+ else // (!useVectorTypes && !doublePrecision)
+ {
+ var r = new ScalarFloatRenderer(draw, abort);
+ if (isMultiThreaded)
+ {
+ if (useAbstractDataType)
+ return r.RenderMultiThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderMultiThreadedNoADT;
+ }
+ else // !isMultiThreaded
+ {
+ if (useAbstractDataType)
+ return r.RenderSingleThreadedWithADT;
+ else // !useAbstractDataType
+ return r.RenderSingleThreadedNoADT;
+ }
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ScalarDouble.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ScalarDouble.cs
new file mode 100644
index 0000000000..e4ef4fbdf2
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ScalarDouble.cs
@@ -0,0 +1,158 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Numerics;
+using System.Threading.Tasks;
+
+namespace Algorithms
+{
+ // This class contains renderers that use scalar doubles
+ internal class ScalarDoubleRenderer : FractalRenderer
+ {
+ public ScalarDoubleRenderer(Action<int, int, int> dp, Func<bool> abortFunc)
+ : base(dp, abortFunc)
+ {
+ }
+
+ protected const double limit = 4.0;
+
+ // Render the fractal using the BCL Complex data type abstraction on a single thread with scalar doubles
+ public void RenderSingleThreadedWithADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
+ {
+ double xmin = (double)xminf;
+ double xmax = (double)xmaxf;
+ double ymin = (double)yminf;
+ double ymax = (double)ymaxf;
+ double step = (double)stepf;
+
+ int yp = 0;
+ for (double y = ymin; y < ymax && !Abort; y += step, yp++)
+ {
+ int xp = 0;
+ for (double x = xmin; x < xmax; x += step, xp++)
+ {
+ Complex num = new Complex(x, y);
+ Complex accum = num;
+ int iters = 0;
+ double sqabs = 0f;
+ do
+ {
+ accum = accum.square();
+ accum += num;
+ iters++;
+ sqabs = accum.sqabs();
+ } while (sqabs < limit && iters < max_iters);
+
+ DrawPixel(xp, yp, iters);
+ }
+ }
+ }
+
+ // Render the fractal with no data type abstraction on a single thread with scalar doubles
+ public void RenderSingleThreadedNoADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
+ {
+ double xmin = (double)xminf;
+ double xmax = (double)xmaxf;
+ double ymin = (double)yminf;
+ double ymax = (double)ymaxf;
+ double step = (double)stepf;
+
+ int yp = 0;
+ for (double y = ymin; y < ymax && !Abort; y += step, yp++)
+ {
+ int xp = 0;
+ for (double x = xmin; x < xmax; x += step, xp++)
+ {
+ double accumx = x;
+ double accumy = y;
+ int iters = 0;
+ double sqabs = 0.0;
+ do
+ {
+ double naccumx = accumx * accumx - accumy * accumy;
+ double naccumy = 2.0 * accumx * accumy;
+ accumx = naccumx + x;
+ accumy = naccumy + y;
+ iters++;
+ sqabs = accumx * accumx + accumy * accumy;
+ } while (sqabs < limit && iters < max_iters);
+
+ DrawPixel(xp, yp, iters);
+ }
+ }
+ }
+
+ // Render the fractal using the BCL Complex data type abstraction on multiple threads with scalar doubles
+ public void RenderMultiThreadedWithADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
+ {
+ double xmin = (double)xminf;
+ double xmax = (double)xmaxf;
+ double ymin = (double)yminf;
+ double ymax = (double)ymaxf;
+ double step = (double)stepf;
+
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5), (yp) =>
+ {
+ if (Abort)
+ return;
+ double y = ymin + step * yp;
+ int xp = 0;
+ for (double x = xmin; x < xmax; x += step, xp++)
+ {
+ Complex num = new Complex(x, y);
+ Complex accum = num;
+ int iters = 0;
+ double sqabs = 0f;
+ do
+ {
+ accum = accum.square();
+ accum += num;
+ iters++;
+ sqabs = accum.sqabs();
+ } while (sqabs < limit && iters < max_iters);
+
+ DrawPixel(xp, yp, iters);
+ }
+ });
+ }
+
+ // Render the fractal with no data type abstraction on multiple threads with scalar doubles
+ public void RenderMultiThreadedNoADT(float xmind, float xmaxd, float ymind, float ymaxd, float stepd)
+ {
+ double xmin = (double)xmind;
+ double xmax = (double)xmaxd;
+ double ymin = (double)ymind;
+ double ymax = (double)ymaxd;
+ double step = (double)stepd;
+
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5), (yp) =>
+ {
+ if (Abort)
+ return;
+ double y = ymin + step * yp;
+ int xp = 0;
+ for (double x = xmin; x < xmax; x += step, xp++)
+ {
+ double accumx = x;
+ double accumy = y;
+ int iters = 0;
+ double sqabs = 0.0;
+ do
+ {
+ double naccumx = accumx * accumx - accumy * accumy;
+ double naccumy = 2.0 * accumx * accumy;
+ accumx = naccumx + x;
+ accumy = naccumy + y;
+ iters++;
+ sqabs = accumx * accumx + accumy * accumy;
+ } while (sqabs < limit && iters < max_iters);
+
+ DrawPixel(xp, yp, iters);
+ }
+ });
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ScalarFloat.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ScalarFloat.cs
new file mode 100644
index 0000000000..a7f17385aa
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/ScalarFloat.cs
@@ -0,0 +1,132 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Threading.Tasks;
+
+namespace Algorithms
+{
+ // This class contains renderers that use scalar floats
+ internal class ScalarFloatRenderer : FractalRenderer
+ {
+ public ScalarFloatRenderer(Action<int, int, int> dp, Func<bool> abortFunc)
+ : base(dp, abortFunc)
+ {
+ }
+
+ protected const float limit = 4.0f;
+
+ // Render the fractal using a Complex data type on a single thread with scalar floats
+ public void RenderSingleThreadedWithADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ int yp = 0;
+ for (float y = ymin; y < ymax && !Abort; y += step, yp++)
+ {
+ int xp = 0;
+ for (float x = xmin; x < xmax; x += step, xp++)
+ {
+ ComplexFloat num = new ComplexFloat(x, y);
+ ComplexFloat accum = num;
+ int iters = 0;
+ float sqabs = 0f;
+ do
+ {
+ accum = accum.square();
+ accum += num;
+ iters++;
+ sqabs = accum.sqabs();
+ } while (sqabs < limit && iters < max_iters);
+
+ DrawPixel(xp, yp, iters);
+ }
+ }
+ }
+
+ // Render the fractal with no data type abstraction on a single thread with scalar floats
+ public void RenderSingleThreadedNoADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ int yp = 0;
+ for (float y = ymin; y < ymax && !Abort; y += step, yp++)
+ {
+ int xp = 0;
+ for (float x = xmin; x < xmax; x += step, xp++)
+ {
+ float accumx = x;
+ float accumy = y;
+ int iters = 0;
+ float sqabs = 0f;
+ do
+ {
+ float naccumx = accumx * accumx - accumy * accumy;
+ float naccumy = 2.0f * accumx * accumy;
+ accumx = naccumx + x;
+ accumy = naccumy + y;
+ iters++;
+ sqabs = accumx * accumx + accumy * accumy;
+ } while (sqabs < limit && iters < max_iters);
+ DrawPixel(xp, yp, iters);
+ }
+ }
+ }
+
+ // Render the fractal using a Complex data type on a single thread with scalar floats
+ public void RenderMultiThreadedWithADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5f), (yp) =>
+ {
+ if (Abort)
+ return;
+ float y = ymin + step * yp;
+ int xp = 0;
+ for (float x = xmin; x < xmax; x += step, xp++)
+ {
+ ComplexFloat num = new ComplexFloat(x, y);
+ ComplexFloat accum = num;
+ int iters = 0;
+ float sqabs = 0f;
+ do
+ {
+ accum = accum.square();
+ accum += num;
+ iters++;
+ sqabs = accum.sqabs();
+ } while (sqabs < limit && iters < max_iters);
+
+ DrawPixel(xp, yp, iters);
+ }
+ });
+ }
+
+ // Render the fractal with no data type abstraction on multiple threads with scalar floats
+ public void RenderMultiThreadedNoADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5f), (yp) =>
+ {
+ if (Abort)
+ return;
+ float y = ymin + step * yp;
+ int xp = 0;
+ for (float x = xmin; x < xmax; x += step, xp++)
+ {
+ float accumx = x;
+ float accumy = y;
+ int iters = 0;
+ float sqabs = 0f;
+ do
+ {
+ float naccumx = accumx * accumx - accumy * accumy;
+ float naccumy = 2.0f * accumx * accumy;
+ accumx = naccumx + x;
+ accumy = naccumy + y;
+ iters++;
+ sqabs = accumx * accumx + accumy * accumy;
+ } while (sqabs < limit && iters < max_iters);
+
+ DrawPixel(xp, yp, iters);
+ }
+ });
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorDouble.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorDouble.cs
new file mode 100644
index 0000000000..0d57e0b4bc
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorDouble.cs
@@ -0,0 +1,212 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Numerics;
+using System.Threading.Tasks;
+
+namespace Algorithms
+{
+ // This contains renderers that only use Vector<double>'s and Vector<long> types.
+ internal class VectorDoubleRenderer : FractalRenderer
+ {
+ private const double limit = 4.0;
+
+ private static Vector<double> s_dummy = Vector<double>.One;
+
+ public VectorDoubleRenderer(Action<int, int, int> dp, Func<bool> abortFunc)
+ : base(dp, abortFunc)
+ {
+ }
+
+ // Render the fractal on a single thread using raw Vector<double> data types
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderSingleThreadedNoADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
+ {
+ double xmin = (double)xminf;
+ double xmax = (double)xmaxf;
+ double ymin = (double)yminf;
+ double ymax = (double)ymaxf;
+ double step = (double)stepf;
+
+ Vector<double> vlimit = new Vector<double>(limit);
+ Vector<double> vinc = new Vector<double>((double)Vector<double>.Count * step);
+ Vector<double> vstep = new Vector<double>(step);
+ Vector<long> vmax_iters = new Vector<long>(max_iters);
+ Vector<double> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ double y = ymin;
+ int yp = 0;
+ for (Vector<double> vy = new Vector<double>(ymin); y <= ymax && !Abort; vy += vstep, y += step, yp++)
+ {
+ int xp = 0;
+ Vector<double> vxmaxd = new Vector<double>(xmax);
+ for (Vector<double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmaxd); vx += vinc, xp += Vector<long>.Count)
+ {
+ Vector<double> accumx = vx;
+ Vector<double> accumy = vy;
+
+ Vector<long> viters = Vector<long>.Zero;
+ Vector<long> increment = Vector<long>.One;
+
+ do
+ {
+ Vector<double> naccumx = accumx * accumx - accumy * accumy;
+ Vector<double> naccumy = accumx * accumy + accumx * accumy;
+ accumx = naccumx + vx;
+ accumy = naccumy + vy;
+ viters += increment;
+ Vector<double> sqabs = accumx * accumx + accumy * accumy;
+ Vector<long> vCond = Vector.LessThanOrEqual(sqabs, vlimit) &
+ Vector.LessThanOrEqual(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<long>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ }
+ }
+
+ // Render the fractal on a single thread using the ComplexVecDouble data type
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderSingleThreadedWithADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
+ {
+ double xmin = (double)xminf;
+ double xmax = (double)xmaxf;
+ double ymin = (double)yminf;
+ double ymax = (double)ymaxf;
+ double step = (double)stepf;
+
+ Vector<double> vlimit = new Vector<double>(limit);
+ Vector<double> vinc = new Vector<double>((double)Vector<double>.Count * step);
+ Vector<double> vstep = new Vector<double>(step);
+ Vector<long> vmax_iters = new Vector<long>(max_iters);
+ Vector<double> vxmax = new Vector<double>(xmax);
+ Vector<double> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ double y = ymin;
+ int yp = 0;
+ for (Vector<double> vy = new Vector<double>(ymin); y <= ymax && !Abort; vy += vstep, y += step, yp++)
+ {
+ int xp = 0;
+ for (Vector<double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<long>.Count)
+ {
+ ComplexVecDouble num = new ComplexVecDouble(vx, vy);
+ ComplexVecDouble accum = num;
+
+ Vector<long> viters = Vector<long>.Zero;
+ Vector<long> increment = Vector<long>.One;
+
+ do
+ {
+ accum = accum.square() + num;
+ viters += increment;
+ Vector<long> vCond = Vector.LessThanOrEqual(accum.sqabs(), vlimit) &
+ Vector.LessThanOrEqual(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<long>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ }
+ }
+
+ // Render the fractal on multiple threads using raw Vector<double> data types
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderMultiThreadedNoADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
+ {
+ double xmin = (double)xminf;
+ double xmax = (double)xmaxf;
+ double ymin = (double)yminf;
+ double ymax = (double)ymaxf;
+ double step = (double)stepf;
+
+ Vector<long> vmax_iters = new Vector<long>(max_iters);
+ Vector<double> vlimit = new Vector<double>(limit);
+ Vector<double> vinc = new Vector<double>((double)Vector<double>.Count * step);
+ Vector<double> vxmax = new Vector<double>(xmax);
+ Vector<double> vstep = new Vector<double>(step);
+ Vector<double> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5), (yp) =>
+ {
+ if (Abort)
+ return;
+
+ Vector<double> vy = new Vector<double>(ymin + step * yp);
+ int xp = 0;
+ for (Vector<double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<long>.Count)
+ {
+ Vector<double> accumx = vx;
+ Vector<double> accumy = vy;
+
+ Vector<long> viters = Vector<long>.Zero;
+ Vector<long> increment = Vector<long>.One;
+
+ do
+ {
+ Vector<double> naccumx = accumx * accumx - accumy * accumy;
+ Vector<double> naccumy = accumx * accumy + accumx * accumy;
+ accumx = naccumx + vx;
+ accumy = naccumy + vy;
+ viters += increment;
+ Vector<double> sqabs = accumx * accumx + accumy * accumy;
+ Vector<long> vCond = Vector.LessThanOrEqual(sqabs, vlimit) &
+ Vector.LessThanOrEqual(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<long>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ });
+ }
+
+ // Render the fractal on multiple threads using the ComplexVecDouble data type
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderMultiThreadedWithADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
+ {
+ double xmin = (double)xminf;
+ double xmax = (double)xmaxf;
+ double ymin = (double)yminf;
+ double ymax = (double)ymaxf;
+ double step = (double)stepf;
+
+ Vector<long> vmax_iters = new Vector<long>(max_iters);
+ Vector<double> vlimit = new Vector<double>(limit);
+ Vector<double> vinc = new Vector<double>((double)Vector<double>.Count * step);
+ Vector<double> vxmax = new Vector<double>(xmax);
+ Vector<double> vstep = new Vector<double>(step);
+ Vector<double> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5), (yp) =>
+ {
+ if (Abort)
+ return;
+
+ Vector<double> vy = new Vector<double>(ymin + step * yp);
+ int xp = 0;
+ for (Vector<double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<long>.Count)
+ {
+ ComplexVecDouble num = new ComplexVecDouble(vx, vy);
+ ComplexVecDouble accum = num;
+
+ Vector<long> viters = Vector<long>.Zero;
+ Vector<long> increment = Vector<long>.One;
+
+ do
+ {
+ accum = accum.square() + num;
+ viters += increment;
+ Vector<long> vCond = Vector.LessThanOrEqual(accum.sqabs(), vlimit) &
+ Vector.LessThanOrEqual(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<long>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ });
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorDoubleStrict.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorDoubleStrict.cs
new file mode 100644
index 0000000000..a6099c7821
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorDoubleStrict.cs
@@ -0,0 +1,215 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Numerics;
+using System.Threading.Tasks;
+
+namespace Algorithms
+{
+ // This contains renderers that only use Vector<double>'s with no Vector<long> types. It's
+ // primarily useful when targeting AVX (not AVX2), because AVX doesn't support 256 bits of
+ // integer values, only floating point values.
+ internal class VectorDoubleStrictRenderer : FractalRenderer
+ {
+ private const double limit = 4.0;
+
+ private static Vector<double> s_dummy;
+
+ static VectorDoubleStrictRenderer()
+ {
+ s_dummy = Vector<double>.One;
+ }
+
+ public VectorDoubleStrictRenderer(Action<int, int, int> dp, Func<bool> abortFunc)
+ : base(dp, abortFunc)
+ {
+ }
+
+ // Render the fractal on multiple threads using the ComplexVecDouble data type
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderMultiThreadedWithADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
+ {
+ double xmin = (double)xminf;
+ double xmax = (double)xmaxf;
+ double ymin = (double)yminf;
+ double ymax = (double)ymaxf;
+ double step = (double)stepf;
+
+ Vector<double> vmax_iters = new Vector<double>((double)max_iters);
+ Vector<double> vlimit = new Vector<double>(limit);
+ Vector<double> vstep = new Vector<double>(step);
+ Vector<double> vinc = new Vector<double>((double)Vector<double>.Count * step);
+ Vector<double> vxmax = new Vector<double>(xmax);
+ Vector<double> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5), (yp) =>
+ {
+ if (Abort)
+ return;
+
+ Vector<double> vy = new Vector<double>(ymin + step * yp);
+ int xp = 0;
+ for (Vector<double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<double>.Count)
+ {
+ ComplexVecDouble num = new ComplexVecDouble(vx, vy);
+ ComplexVecDouble accum = num;
+
+ Vector<double> viters = Vector<double>.Zero;
+ Vector<double> increment = Vector<double>.One;
+ do
+ {
+ accum = accum.square() + num;
+ viters += increment;
+ Vector<double> vCond = Vector.LessThanOrEqual<double>(accum.sqabs(), vlimit) &
+ Vector.LessThanOrEqual<double>(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<double>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ });
+ }
+
+ // Render the fractal on multiple threads using raw Vector<double> data types
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderMultiThreadedNoADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
+ {
+ double xmin = (double)xminf;
+ double xmax = (double)xmaxf;
+ double ymin = (double)yminf;
+ double ymax = (double)ymaxf;
+ double step = (double)stepf;
+
+ Vector<double> vmax_iters = new Vector<double>((double)max_iters);
+ Vector<double> vlimit = new Vector<double>(limit);
+ Vector<double> vstep = new Vector<double>(step);
+ Vector<double> vinc = new Vector<double>((double)Vector<double>.Count * step);
+ Vector<double> vxmax = new Vector<double>(xmax);
+ Vector<double> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5), (yp) =>
+ {
+ if (Abort)
+ return;
+
+ Vector<double> vy = new Vector<double>(ymin + step * yp);
+ int xp = 0;
+ for (Vector<double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<double>.Count)
+ {
+ Vector<double> accumx = vx;
+ Vector<double> accumy = vy;
+
+ Vector<double> viters = Vector<double>.Zero;
+ Vector<double> increment = Vector<double>.One;
+ do
+ {
+ Vector<double> naccumx = accumx * accumx - accumy * accumy;
+ Vector<double> naccumy = accumx * accumy + accumx * accumy;
+ accumx = naccumx + vx;
+ accumy = naccumy + vy;
+ viters += increment;
+ Vector<double> sqabs = accumx * accumx + accumy * accumy;
+ Vector<double> vCond = Vector.LessThanOrEqual<double>(sqabs, vlimit) &
+ Vector.LessThanOrEqual<double>(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<double>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ });
+ }
+
+ // Render the fractal on a single thread using the ComplexVecDouble data type
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderSingleThreadedWithADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
+ {
+ double xmin = (double)xminf;
+ double xmax = (double)xmaxf;
+ double ymin = (double)yminf;
+ double ymax = (double)ymaxf;
+ double step = (double)stepf;
+
+ Vector<double> vmax_iters = new Vector<double>((double)max_iters);
+ Vector<double> vlimit = new Vector<double>(limit);
+ Vector<double> vstep = new Vector<double>(step);
+ Vector<double> vinc = new Vector<double>((double)Vector<double>.Count * step);
+ Vector<double> vxmax = new Vector<double>(xmax);
+ Vector<double> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ double y = ymin;
+ int yp = 0;
+ for (Vector<double> vy = new Vector<double>(ymin); y <= ymax && !Abort; vy += vstep, y += step, yp++)
+ {
+ int xp = 0;
+ for (Vector<double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<double>.Count)
+ {
+ ComplexVecDouble num = new ComplexVecDouble(vx, vy);
+ ComplexVecDouble accum = num;
+
+ Vector<double> viters = Vector<double>.Zero;
+ Vector<double> increment = Vector<double>.One;
+ do
+ {
+ accum = accum.square() + num;
+ viters += increment;
+ Vector<double> vCond = Vector.LessThanOrEqual<double>(accum.sqabs(), vlimit) &
+ Vector.LessThanOrEqual<double>(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<double>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ }
+ }
+
+ // Render the fractal on a single thread using raw Vector<double> data types
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderSingleThreadedNoADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
+ {
+ double xmin = (double)xminf;
+ double xmax = (double)xmaxf;
+ double ymin = (double)yminf;
+ double ymax = (double)ymaxf;
+ double step = (double)stepf;
+
+ Vector<double> vmax_iters = new Vector<double>((double)max_iters);
+ Vector<double> vlimit = new Vector<double>(limit);
+ Vector<double> vstep = new Vector<double>(step);
+ Vector<double> vinc = new Vector<double>((double)Vector<double>.Count * step);
+ Vector<double> vxmax = new Vector<double>(xmax);
+ Vector<double> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ double y = ymin;
+ int yp = 0;
+ for (Vector<double> vy = new Vector<double>(ymin); y <= ymax && !Abort; vy += vstep, y += step, yp++)
+ {
+ int xp = 0;
+ for (Vector<double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<double>.Count)
+ {
+ Vector<double> accumx = vx;
+ Vector<double> accumy = vy;
+
+ Vector<double> viters = Vector<double>.Zero;
+ Vector<double> increment = Vector<double>.One;
+ do
+ {
+ Vector<double> naccumx = accumx * accumx - accumy * accumy;
+ Vector<double> naccumy = accumx * accumy + accumx * accumy;
+ accumx = naccumx + vx;
+ accumy = naccumy + vy;
+ viters += increment;
+ Vector<double> sqabs = accumx * accumx + accumy * accumy;
+ Vector<double> vCond = Vector.LessThanOrEqual<double>(sqabs, vlimit) &
+ Vector.LessThanOrEqual<double>(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<double>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorFloat.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorFloat.cs
new file mode 100644
index 0000000000..418c271fcf
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorFloat.cs
@@ -0,0 +1,214 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Numerics;
+using System.Threading.Tasks;
+
+namespace Algorithms
+{
+ // This class contains renderers that use Vector (SIMD) floats
+ internal class VectorFloatRenderer : FractalRenderer
+ {
+ private const float limit = 4.0f;
+
+ public VectorFloatRenderer(Action<int, int, int> dp, Func<bool> abortFunc)
+ : base(dp, abortFunc)
+ {
+ }
+
+ // Render the fractal on a single thread using the ComplexFloatVec data type
+ // This is the implementation that has the best comments.
+ public void RenderSingleThreadedWithADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ // Initialize a pile of method constant vectors
+ Vector<int> vmax_iters = new Vector<int>(max_iters);
+ Vector<float> vlimit = new Vector<float>(limit);
+ Vector<float> vstep = new Vector<float>(step);
+ Vector<float> vxmax = new Vector<float>(xmax);
+ Vector<float> vinc = new Vector<float>((float)Vector<float>.Count * step);
+ // Use my little helper routine: it's kind of slow, but I find it pleasantly readable.
+ // The alternative would be this:
+ // float[] xmins = new float[Vector<float>.Count];
+ // for (int i = 0; i < xmins.Count; i++)
+ // xmins[i] = xmin + step * i;
+ // Vector<float> vxmin = new Vector<float>(xmins);
+ // Both allocate some memory, this one just does it in a separate routine :-)
+ Vector<float> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ float y = ymin;
+ int yp = 0;
+ for (Vector<float> vy = new Vector<float>(ymin);
+ y <= ymax && !Abort;
+ vy += vstep, y += step, yp++)
+ {
+ int xp = 0;
+ for (Vector<float> vx = vxmin;
+ Vector.LessThanOrEqualAny(vx, vxmax); // Vector.{comparision}Any|All return bools, not masks
+ vx += vinc, xp += Vector<int>.Count)
+ {
+ ComplexVecFloat num = new ComplexVecFloat(vx, vy);
+ ComplexVecFloat accum = num;
+
+ Vector<int> viters = Vector<int>.Zero; // Iteration counts start at all zeros
+ Vector<int> increment = Vector<int>.One; // Increment starts out as all ones
+ do
+ {
+ // This is work that can be vectorized
+ accum = accum.square() + num;
+ // Increment the iteration count Only pixels that haven't already hit the
+ // limit will be incremented because the increment variable gets masked below
+ viters += increment;
+ // Create a mask that correspons to the element-wise logical operation
+ // "accum <= limit && iters <= max_iters" Note that the bitwise and is used,
+ // because the Vector.{comparision} operations return masks, not boolean values
+ Vector<int> vCond = Vector.LessThanOrEqual(accum.sqabs(), vlimit) &
+ Vector.LessThanOrEqual(viters, vmax_iters);
+ // increment becomes zero for the elems that have hit the limit because
+ // vCond is a mask of all zeros or ones, based on the results of the
+ // Vector.{comparison} operations
+ increment = increment & vCond;
+ // Keep going until we have no elements that haven't either hit the value
+ // limit or the iteration count
+ } while (increment != Vector<int>.Zero);
+
+ // This is another little helper I created. It's definitely kind of slow but I
+ // find it pleasantly succinct. It could also be written like this:
+ //
+ // for (int eNum = 0; eNum < Vector<int>.Count; eNum++)
+ // DrawPixel(xp + eNum, yp, viters[eNum]);
+ //
+ // Neither implementation is particularly fast, because pulling individual elements
+ // is a slow operation for vector types.
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, iter));
+ }
+ }
+ }
+
+ // Render the fractal on a single thread using raw Vector<float> data types
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT
+ public void RenderSingleThreadedNoADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ Vector<int> vmax_iters = new Vector<int>(max_iters);
+ Vector<float> vlimit = new Vector<float>(limit);
+ Vector<float> vstep = new Vector<float>(step);
+ Vector<float> vxmax = new Vector<float>(xmax);
+ Vector<float> vinc = new Vector<float>((float)Vector<float>.Count * step);
+ Vector<float> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ float y = ymin;
+ int yp = 0;
+ for (Vector<float> vy = new Vector<float>(ymin); y <= ymax && !Abort; vy += vstep, y += step, yp++)
+ {
+ int xp = 0;
+ for (Vector<float> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<int>.Count)
+ {
+ Vector<float> accumx = vx;
+ Vector<float> accumy = vy;
+
+ Vector<int> viters = Vector<int>.Zero;
+ Vector<int> increment = Vector<int>.One;
+ do
+ {
+ Vector<float> naccumx = accumx * accumx - accumy * accumy;
+ Vector<float> naccumy = accumx * accumy + accumx * accumy;
+ accumx = naccumx + vx;
+ accumy = naccumy + vy;
+ viters += increment;
+ Vector<float> sqabs = accumx * accumx + accumy * accumy;
+ Vector<int> vCond = Vector.LessThanOrEqual(sqabs, vlimit) &
+ Vector.LessThanOrEqual(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<int>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ }
+ }
+
+ // Render the fractal on multiple threads using raw Vector<float> data types
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT
+ public void RenderMultiThreadedNoADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ Vector<int> vmax_iters = new Vector<int>(max_iters);
+ Vector<float> vlimit = new Vector<float>(limit);
+ Vector<float> vstep = new Vector<float>(step);
+ Vector<float> vinc = new Vector<float>((float)Vector<float>.Count * step);
+ Vector<float> vxmax = new Vector<float>(xmax);
+ Vector<float> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5f), (yp) =>
+ {
+ if (Abort)
+ return;
+
+ Vector<float> vy = new Vector<float>(ymin + step * yp);
+ int xp = 0;
+ for (Vector<float> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<int>.Count)
+ {
+ Vector<float> accumx = vx;
+ Vector<float> accumy = vy;
+
+ Vector<int> viters = Vector<int>.Zero;
+ Vector<int> increment = Vector<int>.One;
+ do
+ {
+ Vector<float> naccumx = accumx * accumx - accumy * accumy;
+ Vector<float> XtimesY = accumx * accumy;
+ Vector<float> naccumy = XtimesY + XtimesY;
+ accumx = naccumx + vx;
+ accumy = naccumy + vy;
+ viters += increment;
+ Vector<float> sqabs = accumx * accumx + accumy * accumy;
+ Vector<int> vCond = Vector.LessThanOrEqual(sqabs, vlimit) &
+ Vector.LessThanOrEqual(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<int>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ });
+ }
+
+ // Render the fractal on multiple threads using the ComplexFloatVec data type
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT
+ public void RenderMultiThreadedWithADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ Vector<int> vmax_iters = new Vector<int>(max_iters);
+ Vector<float> vlimit = new Vector<float>(limit);
+ Vector<float> vstep = new Vector<float>(step);
+ Vector<float> vinc = new Vector<float>((float)Vector<float>.Count * step);
+ Vector<float> vxmax = new Vector<float>(xmax);
+ Vector<float> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5f), (yp) =>
+ {
+ if (Abort)
+ return;
+
+ Vector<float> vy = new Vector<float>(ymin + step * yp);
+ int xp = 0;
+ for (Vector<float> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<int>.Count)
+ {
+ ComplexVecFloat num = new ComplexVecFloat(vx, vy);
+ ComplexVecFloat accum = num;
+
+ Vector<int> viters = Vector<int>.Zero;
+ Vector<int> increment = Vector<int>.One;
+ do
+ {
+ accum = accum.square() + num;
+ viters += increment;
+ Vector<int> vCond = Vector.LessThanOrEqual(accum.sqabs(), vlimit) &
+ Vector.LessThanOrEqual(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<int>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, iter));
+ }
+ });
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorFloatStrict.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorFloatStrict.cs
new file mode 100644
index 0000000000..f4b8ccf9a5
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorFloatStrict.cs
@@ -0,0 +1,191 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Numerics;
+using System.Threading.Tasks;
+
+namespace Algorithms
+{
+ // This contains renderers that only use Vector<float>'s with no Vector<int> types. It was
+ // originally focused on targeting AVX (not AVX2), because AVX doesn't support 256 bits of
+ // integer values, only floating point values.
+ internal class VectorFloatStrictRenderer : FractalRenderer
+ {
+ private const float limit = 4.0f;
+
+ private static Vector<float> s_dummy;
+
+ static VectorFloatStrictRenderer()
+ {
+ s_dummy = Vector<float>.One;
+ }
+
+ public VectorFloatStrictRenderer(Action<int, int, int> dp, Func<bool> abortFunc)
+ : base(dp, abortFunc)
+ {
+ }
+
+ // Render the fractal on multiple threads using the ComplexFloatVec data type
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderMultiThreadedWithADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ Vector<float> vmax_iters = new Vector<float>((float)max_iters);
+ Vector<float> vlimit = new Vector<float>(limit);
+ Vector<float> vstep = new Vector<float>(step);
+ Vector<float> vinc = new Vector<float>((float)Vector<float>.Count * step);
+ Vector<float> vxmax = new Vector<float>(xmax);
+ Vector<float> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5f), (yp) =>
+ {
+ if (Abort)
+ return;
+
+ Vector<float> vy = new Vector<float>(ymin + step * yp);
+ int xp = 0;
+ for (Vector<float> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<float>.Count)
+ {
+ ComplexVecFloat num = new ComplexVecFloat(vx, vy);
+ ComplexVecFloat accum = num;
+
+ Vector<float> viters = Vector<float>.Zero;
+ Vector<float> increment = Vector<float>.One;
+ do
+ {
+ accum = accum.square() + num;
+ viters += increment;
+ Vector<float> vCond = Vector.LessThanOrEqual<float>(accum.sqabs(), vlimit) &
+ Vector.LessThanOrEqual<float>(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<float>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ });
+ }
+
+ // Render the fractal on multiple threads using raw Vector<float> data types
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderMultiThreadedNoADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ Vector<float> vmax_iters = new Vector<float>((float)max_iters);
+ Vector<float> vlimit = new Vector<float>(limit);
+ Vector<float> vstep = new Vector<float>(step);
+ Vector<float> vinc = new Vector<float>((float)Vector<float>.Count * step);
+ Vector<float> vxmax = new Vector<float>(xmax);
+ Vector<float> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ Parallel.For(0, (int)(((ymax - ymin) / step) + .5f), (yp) =>
+ {
+ if (Abort)
+ return;
+
+ Vector<float> vy = new Vector<float>(ymin + step * yp);
+ int xp = 0;
+ for (Vector<float> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<float>.Count)
+ {
+ Vector<float> accumx = vx;
+ Vector<float> accumy = vy;
+
+ Vector<float> viters = Vector<float>.Zero;
+ Vector<float> increment = Vector<float>.One;
+ do
+ {
+ Vector<float> naccumx = accumx * accumx - accumy * accumy;
+ Vector<float> naccumy = accumx * accumy + accumx * accumy;
+ accumx = naccumx + vx;
+ accumy = naccumy + vy;
+ viters += increment;
+ Vector<float> sqabs = accumx * accumx + accumy * accumy;
+ Vector<float> vCond = Vector.LessThanOrEqual<float>(sqabs, vlimit) &
+ Vector.LessThanOrEqual<float>(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<float>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ });
+ }
+
+ // Render the fractal on a single thread using the ComplexFloatVec data type
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderSingleThreadedWithADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ Vector<float> vmax_iters = new Vector<float>((float)max_iters);
+ Vector<float> vlimit = new Vector<float>(limit);
+ Vector<float> vstep = new Vector<float>(step);
+ Vector<float> vxmax = new Vector<float>(xmax);
+ Vector<float> vinc = new Vector<float>((float)Vector<float>.Count * step);
+ Vector<float> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ float y = ymin;
+ int yp = 0;
+ for (Vector<float> vy = new Vector<float>(ymin); y <= ymax && !Abort; vy += vstep, y += step, yp++)
+ {
+ int xp = 0;
+ for (Vector<float> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<float>.Count)
+ {
+ ComplexVecFloat num = new ComplexVecFloat(vx, vy);
+ ComplexVecFloat accum = num;
+
+ Vector<float> viters = Vector<float>.Zero;
+ Vector<float> increment = Vector<float>.One;
+ do
+ {
+ accum = accum.square() + num;
+ viters += increment;
+ Vector<float> vCond = Vector.LessThanOrEqual<float>(accum.sqabs(), vlimit) &
+ Vector.LessThanOrEqual<float>(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<float>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ }
+ }
+
+ // Render the fractal on a single thread using raw Vector<float> data types
+ // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
+ public void RenderSingleThreadedNoADT(float xmin, float xmax, float ymin, float ymax, float step)
+ {
+ Vector<float> vmax_iters = new Vector<float>(max_iters);
+ Vector<float> vlimit = new Vector<float>(limit);
+ Vector<float> vstep = new Vector<float>(step);
+ Vector<float> vxmax = new Vector<float>(xmax);
+ Vector<float> vinc = new Vector<float>((float)Vector<float>.Count * step);
+ Vector<float> vxmin = VectorHelper.Create(i => xmin + step * i);
+
+ float y = ymin;
+ int yp = 0;
+ for (Vector<float> vy = new Vector<float>(ymin); y <= ymax && !Abort; vy += vstep, y += step, yp++)
+ {
+ int xp = 0;
+ for (Vector<float> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector<float>.Count)
+ {
+ Vector<float> accumx = vx;
+ Vector<float> accumy = vy;
+
+ Vector<float> viters = Vector<float>.Zero;
+ Vector<float> increment = Vector<float>.One;
+ do
+ {
+ Vector<float> naccumx = accumx * accumx - accumy * accumy;
+ Vector<float> naccumy = accumx * accumy + accumx * accumy;
+ accumx = naccumx + vx;
+ accumy = naccumy + vy;
+ viters += increment;
+ Vector<float> sqabs = accumx * accumx + accumy * accumy;
+ Vector<float> vCond = Vector.LessThanOrEqual<float>(sqabs, vlimit) &
+ Vector.LessThanOrEqual<float>(viters, vmax_iters);
+ increment = increment & vCond;
+ } while (increment != Vector<float>.Zero);
+
+ viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
+ }
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorHelpers.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorHelpers.cs
new file mode 100644
index 0000000000..cba8ce8194
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/ConsoleMandel/VectorHelpers.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+
+namespace Algorithms
+{
+ public static class VectorHelper
+ {
+ // Helper to construct a vector from a lambda that takes an
+ // index. It's not efficient, but it's more succint than the
+ // corresponding for loop. Don't use it on a hot code path
+ // (i.e. inside a loop)
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static Vector<T> Create<T>(Func<int, T> creator) where T : struct
+ {
+ T[] data = new T[Vector<T>.Count];
+ for (int i = 0; i < data.Length; i++)
+ data[i] = creator(i);
+ return new Vector<T>(data);
+ }
+
+ // Helper to invoke a function for each element of the
+ // vector. This is NOT fast. I just like the way it looks
+ // better than a for loop. Don't use it somewhere that
+ // performance truly matters
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static void ForEach<T>(this Vector<T> vec, Action<T, int> op) where T : struct
+ {
+ for (int i = 0; i < Vector<T>.Count; i++)
+ op(vec[i], i);
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Camera.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Camera.cs
new file mode 100644
index 0000000000..7d96ca769e
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Camera.cs
@@ -0,0 +1,25 @@
+// 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.
+//
+
+internal class Camera
+{
+ public Vector Pos;
+ public Vector Forward;
+ public Vector Up;
+ public Vector Right;
+
+ public Camera(Vector pos, Vector forward, Vector up, Vector right) { Pos = pos; Forward = forward; Up = up; Right = right; }
+
+ public static Camera Create(Vector pos, Vector lookAt)
+ {
+ Vector forward = Vector.Norm(Vector.Minus(lookAt, pos));
+ Vector down = new Vector(0, -1, 0);
+ Vector right = Vector.Times(1.5F, Vector.Norm(Vector.Cross(forward, down)));
+ Vector up = Vector.Times(1.5F, Vector.Norm(Vector.Cross(forward, right)));
+
+ return new Camera(pos, forward, up, right);
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Color.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Color.cs
new file mode 100644
index 0000000000..c88b188ec4
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Color.cs
@@ -0,0 +1,143 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Numerics;
+
+public struct Color
+{
+ private Vector3 _simdVector;
+ public float R { get { return _simdVector.X; } }
+ public float G { get { return _simdVector.Y; } }
+ public float B { get { return _simdVector.Z; } }
+
+ public Color(double r, double g, double b)
+ {
+ _simdVector = new Vector3((float)r, (float)g, (float)b);
+ }
+ public Color(string str)
+ {
+ string[] nums = str.Split(',');
+ if (nums.Length != 3) throw new ArgumentException();
+ _simdVector = new Vector3(float.Parse(nums[0]), float.Parse(nums[1]), float.Parse(nums[2]));
+ }
+
+
+ public static Color Times(double n, Color v)
+ {
+ Color result;
+ result._simdVector = (float)n * v._simdVector;
+ return result;
+ }
+ public static Color Times(Color v1, Color v2)
+ {
+ Color result;
+ result._simdVector = v1._simdVector * v2._simdVector;
+ return result;
+ }
+
+ public static Color Plus(Color v1, Color v2)
+ {
+ Color result;
+ result._simdVector = v1._simdVector + v2._simdVector;
+ return result;
+ }
+ public static Color Minus(Color v1, Color v2)
+ {
+ Color result;
+ result._simdVector = v1._simdVector - v2._simdVector;
+ return result;
+ }
+
+ public static Color Background { get { Color result; result._simdVector = Vector3.Zero; return result; } }
+ public static Color DefaultColor { get { Color result; result._simdVector = Vector3.Zero; return result; } }
+
+ public static float Legalize(float d)
+ {
+ return d > 1 ? 1 : d;
+ }
+
+ public static byte ToByte(float c)
+ {
+ return (byte)(255 * Legalize(c));
+ }
+
+ public static Int32 ToInt32(float c)
+ {
+ Int32 r = (Int32)(255 * c);
+ return (r > 255 ? 255 : r);
+ }
+
+ public Int32 ToInt32()
+ {
+ return (ToInt32(B) | ToInt32(G) << 8 | ToInt32(R) << 16 | 255 << 24);
+ }
+
+ public float Brightness()
+ {
+ float r = (float)R / 255.0f;
+ float g = (float)G / 255.0f;
+ float b = (float)B / 255.0f;
+
+ float max, min;
+
+ max = r; min = r;
+
+ if (g > max) max = g;
+ if (b > max) max = b;
+
+ if (g < min) min = g;
+ if (b < min) min = b;
+
+ return (max + min) / 2;
+ }
+
+ public void ChangeHue(float hue)
+ {
+ float H, S, L, Br;
+
+ Br = Brightness();
+ H = hue;
+ S = 0.9F;
+ L = ((Br - 0.5F) * 0.5F) + 0.5F;
+
+ if (L == 0)
+ {
+ _simdVector = Vector3.Zero;
+ }
+ else
+ {
+ if (S == 0)
+ {
+ _simdVector = new Vector3(L);
+ }
+ else
+ {
+ float temp2 = ((L <= 0.5F) ? L * (1.0F + S) : L + S - (L * S));
+ float temp1 = 2.0F * L - temp2;
+
+ float[] t3 = new float[] { H + 1.0F / 3.0F, H, H - 1.0F / 3.0F };
+ float[] clr = new float[] { 0, 0, 0 };
+
+ for (int i = 0; i < 3; i++)
+ {
+ if (t3[i] < 0) t3[i] += 1.0F;
+ if (t3[i] > 1) t3[i] -= 1.0F;
+ if (6.0 * t3[i] < 1.0)
+ clr[i] = temp1 + (temp2 - temp1) * t3[i] * 6.0F;
+ else if (2.0 * t3[i] < 1.0)
+ clr[i] = temp2;
+ else if (3.0 * t3[i] < 2.0)
+ clr[i] = (temp1 + (temp2 - temp1) * ((2.0F / 3.0F) - t3[i]) * 6.0F);
+ else
+ clr[i] = temp1;
+ }
+
+ _simdVector = new Vector3(clr[0], clr[1], clr[2]);
+ }
+ }
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ISect.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ISect.cs
new file mode 100644
index 0000000000..71a8e0a512
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ISect.cs
@@ -0,0 +1,16 @@
+// 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.
+//
+
+internal class ISect
+{
+ public SceneObject Thing;
+ public Ray Ray;
+ public double Dist;
+
+ public ISect(SceneObject thing, Ray ray, double dist) { Thing = thing; Ray = ray; Dist = dist; }
+
+ public static bool IsNull(ISect sect) { return sect == null; }
+ public readonly static ISect Null = null;
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Light.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Light.cs
new file mode 100644
index 0000000000..d8f448f1fa
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Light.cs
@@ -0,0 +1,13 @@
+// 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.
+//
+
+internal class Light
+{
+ public Vector Pos;
+ public Color Color;
+
+ public Light(Vector pos, Color color) { Pos = pos; Color = color; }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ObjectPool.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ObjectPool.cs
new file mode 100644
index 0000000000..29be23238b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ObjectPool.cs
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Collections.Concurrent
+{
+ /// <summary>Provides a thread-safe object pool.</summary>
+ /// <typeparam name="T">Specifies the type of the elements stored in the pool.</typeparam>
+ [DebuggerDisplay("Count={Count}")]
+ [DebuggerTypeProxy(typeof(IProducerConsumerCollection_DebugView<>))]
+ public sealed class ObjectPool<T> : ProducerConsumerCollectionBase<T>
+ {
+ private readonly Func<T> _generator;
+
+ /// <summary>Initializes an instance of the ObjectPool class.</summary>
+ /// <param name="generator">The function used to create items when no items exist in the pool.</param>
+ public ObjectPool(Func<T> generator) : this(generator, new ConcurrentQueue<T>()) { }
+
+ /// <summary>Initializes an instance of the ObjectPool class.</summary>
+ /// <param name="generator">The function used to create items when no items exist in the pool.</param>
+ /// <param name="collection">The collection used to store the elements of the pool.</param>
+ public ObjectPool(Func<T> generator, IProducerConsumerCollection<T> collection)
+ : base(collection)
+ {
+ if (generator == null) throw new ArgumentNullException("generator");
+ _generator = generator;
+ }
+
+ /// <summary>Adds the provided item into the pool.</summary>
+ /// <param name="item">The item to be added.</param>
+ public void PutObject(T item) { base.TryAdd(item); }
+
+ /// <summary>Gets an item from the pool.</summary>
+ /// <returns>The removed or created item.</returns>
+ /// <remarks>If the pool is empty, a new item will be created and returned.</remarks>
+ public T GetObject()
+ {
+ T value;
+ return base.TryTake(out value) ? value : _generator();
+ }
+
+ /// <summary>Clears the object pool, returning all of the data that was in the pool.</summary>
+ /// <returns>An array containing all of the elements in the pool.</returns>
+ public T[] ToArrayAndClear()
+ {
+ var items = new List<T>();
+ T value;
+ while (base.TryTake(out value)) items.Add(value);
+ return items.ToArray();
+ }
+
+ protected override bool TryAdd(T item)
+ {
+ PutObject(item);
+ return true;
+ }
+
+ protected override bool TryTake(out T item)
+ {
+ item = GetObject();
+ return true;
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Plane.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Plane.cs
new file mode 100644
index 0000000000..9504a0b116
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Plane.cs
@@ -0,0 +1,25 @@
+// 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.
+//
+
+internal class Plane : SceneObject
+{
+ public Vector Norm;
+ public double Offset;
+
+ public Plane(Vector norm, double offset, Surface surface) : base(surface) { Norm = norm; Offset = offset; }
+
+ public override ISect Intersect(Ray ray)
+ {
+ double denom = Vector.Dot(Norm, ray.Dir);
+ if (denom > 0) return ISect.Null;
+ return new ISect(this, ray, (Vector.Dot(Norm, ray.Start) + Offset) / (-denom));
+ }
+
+ public override Vector Normal(Vector pos)
+ {
+ return Norm;
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ProducerConsumerCollectionBase.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ProducerConsumerCollectionBase.cs
new file mode 100644
index 0000000000..fee736397d
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/ProducerConsumerCollectionBase.cs
@@ -0,0 +1,107 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Collections.Concurrent
+{
+ /// <summary>Debug view for the IProducerConsumerCollection.</summary>
+ /// <typeparam name="T">Specifies the type of the data being aggregated.</typeparam>
+ internal sealed class IProducerConsumerCollection_DebugView<T>
+ {
+ private IProducerConsumerCollection<T> _collection;
+
+ public IProducerConsumerCollection_DebugView(IProducerConsumerCollection<T> collection)
+ {
+ _collection = collection;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public T[] Values { get { return _collection.ToArray(); } }
+ }
+
+ /// <summary>
+ /// Provides a base implementation for producer-consumer collections that wrap other
+ /// producer-consumer collections.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of elements in the collection.</typeparam>
+ public abstract class ProducerConsumerCollectionBase<T> : IProducerConsumerCollection<T>
+ {
+ private readonly IProducerConsumerCollection<T> _contained;
+
+ /// <summary>Initializes the ProducerConsumerCollectionBase instance.</summary>
+ /// <param name="contained">The collection to be wrapped by this instance.</param>
+ protected ProducerConsumerCollectionBase(IProducerConsumerCollection<T> contained)
+ {
+ if (contained == null) throw new ArgumentNullException("contained");
+ _contained = contained;
+ }
+
+ /// <summary>Gets the contained collection.</summary>
+ protected IProducerConsumerCollection<T> ContainedCollection { get { return _contained; } }
+
+ /// <summary>Attempts to add the specified value to the end of the deque.</summary>
+ /// <param name="item">The item to add.</param>
+ /// <returns>true if the item could be added; otherwise, false.</returns>
+ protected virtual bool TryAdd(T item) { return _contained.TryAdd(item); }
+
+ /// <summary>Attempts to remove and return an item from the collection.</summary>
+ /// <param name="item">
+ /// When this method returns, if the operation was successful, item contains the item removed. If
+ /// no item was available to be removed, the value is unspecified.
+ /// </param>
+ /// <returns>
+ /// true if an element was removed and returned from the collection; otherwise, false.
+ /// </returns>
+ protected virtual bool TryTake(out T item) { return _contained.TryTake(out item); }
+
+ /// <summary>Attempts to add the specified value to the end of the deque.</summary>
+ /// <param name="item">The item to add.</param>
+ /// <returns>true if the item could be added; otherwise, false.</returns>
+ bool IProducerConsumerCollection<T>.TryAdd(T item) { return TryAdd(item); }
+
+ /// <summary>Attempts to remove and return an item from the collection.</summary>
+ /// <param name="item">
+ /// When this method returns, if the operation was successful, item contains the item removed. If
+ /// no item was available to be removed, the value is unspecified.
+ /// </param>
+ /// <returns>
+ /// true if an element was removed and returned from the collection; otherwise, false.
+ /// </returns>
+ bool IProducerConsumerCollection<T>.TryTake(out T item) { return TryTake(out item); }
+
+ /// <summary>Gets the number of elements contained in the collection.</summary>
+ public int Count { get { return _contained.Count; } }
+
+ /// <summary>Creates an array containing the contents of the collection.</summary>
+ /// <returns>The array.</returns>
+ public T[] ToArray() { return _contained.ToArray(); }
+
+ /// <summary>Copies the contents of the collection to an array.</summary>
+ /// <param name="array">The array to which the data should be copied.</param>
+ /// <param name="index">The starting index at which data should be copied.</param>
+ public void CopyTo(T[] array, int index) { _contained.CopyTo(array, index); }
+
+ /// <summary>Copies the contents of the collection to an array.</summary>
+ /// <param name="array">The array to which the data should be copied.</param>
+ /// <param name="index">The starting index at which data should be copied.</param>
+ void ICollection.CopyTo(Array array, int index) { _contained.CopyTo(array, index); }
+
+ /// <summary>Gets an enumerator for the collection.</summary>
+ /// <returns>An enumerator.</returns>
+ public IEnumerator<T> GetEnumerator() { return _contained.GetEnumerator(); }
+
+ /// <summary>Gets an enumerator for the collection.</summary>
+ /// <returns>An enumerator.</returns>
+ IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
+
+ /// <summary>Gets whether the collection is synchronized.</summary>
+ bool ICollection.IsSynchronized { get { return _contained.IsSynchronized; } }
+
+ /// <summary>Gets the synchronization root object for the collection.</summary>
+ object ICollection.SyncRoot { get { return _contained.SyncRoot; } }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Ray.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Ray.cs
new file mode 100644
index 0000000000..a2d91fb07c
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Ray.cs
@@ -0,0 +1,13 @@
+// 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.
+//
+
+internal struct Ray
+{
+ public Vector Start;
+ public Vector Dir;
+
+ public Ray(Vector start, Vector dir) { Start = start; Dir = dir; }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/RayTracer.csproj b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/RayTracer.csproj
new file mode 100644
index 0000000000..00db618453
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/RayTracer.csproj
@@ -0,0 +1,58 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="RayTracerBench.cs" />
+ <Compile Include="Camera.cs" />
+ <Compile Include="Color.cs" />
+ <Compile Include="ISect.cs" />
+ <Compile Include="Light.cs" />
+ <Compile Include="ObjectPool.cs" />
+ <Compile Include="Plane.cs" />
+ <Compile Include="ProducerConsumerCollectionBase.cs" />
+ <Compile Include="Ray.cs" />
+ <Compile Include="Raytracer.cs" />
+ <Compile Include="Scene.cs" />
+ <Compile Include="SceneObject.cs" />
+ <Compile Include="Sphere.cs" />
+ <Compile Include="Surface.cs" />
+ <Compile Include="Surfaces.cs" />
+ <Compile Include="Vector.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/SIMD/RayTracer/RayTracerBench.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/RayTracerBench.cs
new file mode 100644
index 0000000000..064f860611
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/RayTracerBench.cs
@@ -0,0 +1,144 @@
+// 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.
+//
+// Based on the Raytracer example from
+// Samples for Parallel Programming with the .NET Framework
+// https://code.msdn.microsoft.com/windowsdesktop/Samples-for-Parallel-b4b76364
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections.Concurrent;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class RayTracerBench
+{
+#if DEBUG
+
+ private const int RunningTime = 200;
+ private const int Width = 100;
+ private const int Height = 100;
+ private const int Iterations = 1;
+ private const int MaxIterations = 1000;
+
+#else
+
+ private const int RunningTime = 1000;
+ private const int Width = 250;
+ private const int Height = 250;
+ private const int Iterations = 7;
+ private const int MaxIterations = 1000;
+
+#endif
+
+ public RayTracerBench()
+ {
+ _width = Width;
+ _height = Height;
+ _parallel = false;
+ _showThreads = false;
+ _freeBuffers = new ObjectPool<int[]>(() => new int[_width * _height]);
+ }
+
+ private double _framesPerSecond;
+ private bool _parallel;
+ private bool _showThreads;
+ private int _width, _height;
+ private int _degreeOfParallelism = Environment.ProcessorCount;
+ private int _frames;
+ private CancellationTokenSource _cancellation;
+ private ObjectPool<int[]> _freeBuffers;
+
+ private void RenderTest()
+ {
+ _cancellation = new CancellationTokenSource(RunningTime);
+ RenderLoop(MaxIterations);
+ }
+
+ private void RenderBench()
+ {
+ _cancellation = new CancellationTokenSource();
+ RenderLoop(Iterations);
+ }
+
+ private void RenderLoop(int iterations)
+ {
+ // Create a ray tracer, and create a reference to "sphere2" that we are going to bounce
+ var rayTracer = new RayTracer(_width, _height);
+ var scene = rayTracer.DefaultScene;
+ var sphere2 = (Sphere)scene.Things[0]; // The first item is assumed to be our sphere
+ var baseY = sphere2.Radius;
+ sphere2.Center.Y = sphere2.Radius;
+
+ // Timing determines how fast the ball bounces as well as diagnostics frames/second info
+ var renderingTime = new Stopwatch();
+ var totalTime = Stopwatch.StartNew();
+
+ // Keep rendering until the iteration count is hit
+ for (_frames = 0; _frames < iterations; _frames++)
+ {
+ // Or the rendering task has been canceled
+ if (_cancellation.IsCancellationRequested)
+ {
+ break;
+ }
+
+ // Get the next buffer
+ var rgb = _freeBuffers.GetObject();
+
+ // Determine the new position of the sphere based on the current time elapsed
+ double dy2 = 0.8 * Math.Abs(Math.Sin(totalTime.ElapsedMilliseconds * Math.PI / 3000));
+ sphere2.Center.Y = (float)(baseY + dy2);
+
+ // Render the scene
+ renderingTime.Reset();
+ renderingTime.Start();
+ ParallelOptions options = new ParallelOptions
+ {
+ MaxDegreeOfParallelism = _degreeOfParallelism,
+ CancellationToken = _cancellation.Token
+ };
+ if (!_parallel) rayTracer.RenderSequential(scene, rgb);
+ else if (_showThreads) rayTracer.RenderParallelShowingThreads(scene, rgb, options);
+ else rayTracer.RenderParallel(scene, rgb, options);
+ renderingTime.Stop();
+
+ _framesPerSecond = (1000.0 / renderingTime.ElapsedMilliseconds);
+ _freeBuffers.PutObject(rgb);
+ }
+ }
+
+ [Benchmark]
+ public static void Bench()
+ {
+ var m = new RayTracerBench();
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ m.RenderBench();
+ }
+ }
+ }
+
+ public bool Run()
+ {
+ RenderTest();
+ Console.WriteLine("{0} frames, {1} frames/sec",
+ _frames,
+ _framesPerSecond.ToString("F2"));
+ return true;
+ }
+
+ public static int Main(string[] args)
+ {
+ var r = new RayTracerBench();
+ bool result = r.Run();
+ return (result ? 100 : -1);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Raytracer.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Raytracer.cs
new file mode 100644
index 0000000000..c32782ee18
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Raytracer.cs
@@ -0,0 +1,196 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Numerics;
+
+internal sealed class RayTracer
+{
+ private int _screenWidth;
+ private int _screenHeight;
+ private const int MaxDepth = 5;
+
+ public RayTracer(int screenWidth, int screenHeight)
+ {
+ _screenWidth = screenWidth;
+ _screenHeight = screenHeight;
+ }
+
+ internal void RenderSequential(Scene scene, Int32[] rgb)
+ {
+ for (int y = 0; y < _screenHeight; y++)
+ {
+ int stride = y * _screenWidth;
+ Camera camera = scene.Camera;
+ for (int x = 0; x < _screenWidth; x++)
+ {
+ Color color = TraceRay(new Ray(camera.Pos, GetPoint(x, y, camera)), scene, 0);
+ rgb[x + stride] = color.ToInt32();
+ }
+ }
+ }
+
+ internal void RenderParallel(Scene scene, Int32[] rgb, ParallelOptions options)
+ {
+ Parallel.For(0, _screenHeight, options, y =>
+ {
+ int stride = y * _screenWidth;
+ Camera camera = scene.Camera;
+ for (int x = 0; x < _screenWidth; x++)
+ {
+ Color color = TraceRay(new Ray(camera.Pos, GetPoint(x, y, camera)), scene, 0);
+ rgb[x + stride] = color.ToInt32();
+ }
+ });
+ }
+
+ internal void RenderParallelShowingThreads(Scene scene, Int32[] rgb, ParallelOptions options)
+ {
+ int id = 0;
+ Parallel.For<float>(0, _screenHeight, options, () => GetHueShift(Interlocked.Increment(ref id)), (y, state, hue) =>
+ {
+ int stride = y * _screenWidth;
+ Camera camera = scene.Camera;
+ for (int x = 0; x < _screenWidth; x++)
+ {
+ Color color = TraceRay(new Ray(camera.Pos, GetPoint(x, y, camera)), scene, 0);
+ color.ChangeHue(hue);
+ rgb[x + stride] = color.ToInt32();
+ }
+ return hue;
+ },
+ hue => Interlocked.Decrement(ref id));
+ }
+
+ private Dictionary<int, float> _numToHueShiftLookup = new Dictionary<int, float>();
+ private Random _rand = new Random();
+
+ private float GetHueShift(int id)
+ {
+ float shift;
+ lock (_numToHueShiftLookup)
+ {
+ if (!_numToHueShiftLookup.TryGetValue(id, out shift))
+ {
+ shift = (float)_rand.NextDouble();
+ _numToHueShiftLookup.Add(id, shift);
+ }
+ }
+ return shift;
+ }
+
+ internal readonly Scene DefaultScene = CreateDefaultScene();
+
+ private static Scene CreateDefaultScene()
+ {
+ SceneObject[] things = {
+ new Sphere( new Vector(-0.5,1,1.5), 0.5, Surfaces.MatteShiny),
+ new Sphere( new Vector(0,1,-0.25), 1, Surfaces.Shiny),
+ new Plane( new Vector(0,1,0), 0, Surfaces.CheckerBoard)
+ };
+ Light[] lights = {
+ new Light(new Vector(-2,2.5,0),new Color(.5,.45,.41)),
+ new Light(new Vector(2,4.5,2), new Color(.99,.95,.8))
+ };
+ Camera camera = Camera.Create(new Vector(2.75, 2, 3.75), new Vector(-0.6, .5, 0));
+
+ return new Scene(things, lights, camera);
+ }
+
+
+ private ISect MinIntersection(Ray ray, Scene scene)
+ {
+ ISect min = ISect.Null;
+ foreach (SceneObject obj in scene.Things)
+ {
+ ISect isect = obj.Intersect(ray);
+ if (!ISect.IsNull(isect))
+ {
+ if (ISect.IsNull(min) || min.Dist > isect.Dist)
+ {
+ min = isect;
+ }
+ }
+ }
+ return min;
+ }
+
+ private double TestRay(Ray ray, Scene scene)
+ {
+ ISect isect = MinIntersection(ray, scene);
+ if (ISect.IsNull(isect))
+ return 0;
+ return isect.Dist;
+ }
+
+ private Color TraceRay(Ray ray, Scene scene, int depth)
+ {
+ ISect isect = MinIntersection(ray, scene);
+ if (ISect.IsNull(isect))
+ return Color.Background;
+ return Shade(isect, scene, depth);
+ }
+
+ private Color GetNaturalColor(SceneObject thing, Vector pos, Vector norm, Vector rd, Scene scene)
+ {
+ Color ret = new Color(0, 0, 0);
+ foreach (Light light in scene.Lights)
+ {
+ Vector ldis = Vector.Minus(light.Pos, pos);
+ Vector livec = Vector.Norm(ldis);
+ double neatIsect = TestRay(new Ray(pos, livec), scene);
+ bool isInShadow = !((neatIsect > Vector.Mag(ldis)) || (neatIsect == 0));
+ if (!isInShadow)
+ {
+ float illum = Vector.Dot(livec, norm);
+ Color lcolor = illum > 0 ? Color.Times(illum, light.Color) : new Color(0, 0, 0);
+ float specular = Vector.Dot(livec, Vector.Norm(rd));
+ Color scolor = specular > 0 ? Color.Times(Math.Pow(specular, thing.Surface.Roughness), light.Color) : new Color(0, 0, 0);
+ ret = Color.Plus(ret, Color.Plus(Color.Times(thing.Surface.Diffuse(pos), lcolor),
+ Color.Times(thing.Surface.Specular(pos), scolor)));
+ }
+ }
+ return ret;
+ }
+
+ private Color GetReflectionColor(SceneObject thing, Vector pos, Vector norm, Vector rd, Scene scene, int depth)
+ {
+ return Color.Times(thing.Surface.Reflect(pos), TraceRay(new Ray(pos, rd), scene, depth + 1));
+ }
+
+ private Color Shade(ISect isect, Scene scene, int depth)
+ {
+ Vector d = isect.Ray.Dir;
+ Vector pos = Vector.Plus(Vector.Times(isect.Dist, isect.Ray.Dir), isect.Ray.Start);
+ Vector normal = isect.Thing.Normal(pos);
+ Vector reflectDir = Vector.Minus(d, Vector.Times(2 * Vector.Dot(normal, d), normal));
+ Color ret = Color.DefaultColor;
+ ret = Color.Plus(ret, GetNaturalColor(isect.Thing, pos, normal, reflectDir, scene));
+ if (depth >= MaxDepth)
+ {
+ return Color.Plus(ret, new Color(.5, .5, .5));
+ }
+ return Color.Plus(ret, GetReflectionColor(isect.Thing, Vector.Plus(pos, Vector.Times(.001, reflectDir)), normal, reflectDir, scene, depth));
+ }
+
+ private double RecenterX(double x)
+ {
+ return (x - (_screenWidth / 2.0)) / (2.0 * _screenWidth);
+ }
+ private double RecenterY(double y)
+ {
+ return -(y - (_screenHeight / 2.0)) / (2.0 * _screenHeight);
+ }
+
+ private Vector GetPoint(double x, double y, Camera camera)
+ {
+ return Vector.Norm(Vector.Plus(camera.Forward, Vector.Plus(Vector.Times(RecenterX(x), camera.Right),
+ Vector.Times(RecenterY(y), camera.Up))));
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Scene.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Scene.cs
new file mode 100644
index 0000000000..28bf788188
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Scene.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System.Collections.Generic;
+
+internal class Scene
+{
+ public SceneObject[] Things;
+ public Light[] Lights;
+ public Camera Camera;
+
+ public Scene(SceneObject[] things, Light[] lights, Camera camera) { Things = things; Lights = lights; Camera = camera; }
+
+ public IEnumerable<ISect> Intersect(Ray r)
+ {
+ foreach (SceneObject obj in Things)
+ {
+ yield return obj.Intersect(r);
+ }
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/SceneObject.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/SceneObject.cs
new file mode 100644
index 0000000000..8b4adea04f
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/SceneObject.cs
@@ -0,0 +1,14 @@
+// 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.
+//
+
+internal abstract class SceneObject
+{
+ public Surface Surface;
+ public abstract ISect Intersect(Ray ray);
+ public abstract Vector Normal(Vector pos);
+
+ public SceneObject(Surface surface) { Surface = surface; }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Sphere.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Sphere.cs
new file mode 100644
index 0000000000..5a92f9481a
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Sphere.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+
+internal class Sphere : SceneObject
+{
+ public Vector Center;
+ public float Radius;
+
+ public Sphere(Vector center, double radius, Surface surface) : base(surface) { Center = center; Radius = (float)radius; }
+
+ public override ISect Intersect(Ray ray)
+ {
+ Vector eo = Vector.Minus(Center, ray.Start);
+ float v = Vector.Dot(eo, ray.Dir);
+ float dist;
+ if (v < 0)
+ {
+ dist = 0;
+ }
+ else
+ {
+ double disc = Math.Pow(Radius, 2) - (Vector.Dot(eo, eo) - Math.Pow(v, 2));
+ dist = disc < 0 ? 0 : v - (float)Math.Sqrt(disc);
+ }
+ if (dist == 0) return ISect.Null;
+ return new ISect(this, ray, dist);
+ }
+
+ public override Vector Normal(Vector pos)
+ {
+ return Vector.Norm(Vector.Minus(pos, Center));
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Surface.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Surface.cs
new file mode 100644
index 0000000000..c33899edd7
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Surface.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+
+internal class Surface
+{
+ public Func<Vector, Color> Diffuse;
+ public Func<Vector, Color> Specular;
+ public Func<Vector, double> Reflect;
+ public double Roughness;
+
+ public Surface(Func<Vector, Color> Diffuse,
+ Func<Vector, Color> Specular,
+ Func<Vector, double> Reflect,
+ double Roughness)
+ {
+ this.Diffuse = Diffuse;
+ this.Specular = Specular;
+ this.Reflect = Reflect;
+ this.Roughness = Roughness;
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Surfaces.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Surfaces.cs
new file mode 100644
index 0000000000..3342e1b7a6
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Surfaces.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+
+internal static class Surfaces
+{
+ // Only works with X-Z plane.
+ public static readonly Surface CheckerBoard =
+ new Surface(
+ delegate (Vector pos)
+ {
+ return ((Math.Floor(pos.Z) + Math.Floor(pos.X)) % 2 != 0)
+ ? new Color(1, 1, 1)
+ : new Color(0.02, 0.0, 0.14);
+ },
+ delegate (Vector pos) { return new Color(1, 1, 1); },
+ delegate (Vector pos)
+ {
+ return ((Math.Floor(pos.Z) + Math.Floor(pos.X)) % 2 != 0)
+ ? .1
+ : .5;
+ },
+ 150);
+
+
+
+ public static readonly Surface Shiny =
+ new Surface(
+ delegate (Vector pos) { return new Color(1, 1, 1); },
+ delegate (Vector pos) { return new Color(.5, .5, .5); },
+ delegate (Vector pos) { return .7; },
+ 250);
+
+ public static readonly Surface MatteShiny =
+ new Surface(
+ delegate (Vector pos) { return new Color(1, 1, 1); },
+ delegate (Vector pos) { return new Color(.25, .25, .25); },
+ delegate (Vector pos) { return .7; },
+ 250);
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Vector.cs b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Vector.cs
new file mode 100644
index 0000000000..c6ba48312b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SIMD/RayTracer/Vector.cs
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+
+internal struct Vector
+{
+ private Vector3 _simdVector;
+ public float X { get { return _simdVector.X; } }
+ public float Y { get { return _simdVector.Y; } set { _simdVector = new Vector3(_simdVector.X, value, _simdVector.Z); } }
+ public float Z { get { return _simdVector.Z; } }
+
+ public Vector(double x, double y, double z)
+ {
+ _simdVector = new Vector3((float)x, (float)y, (float)z);
+ }
+ public Vector(string str)
+ {
+ string[] nums = str.Split(',');
+ if (nums.Length != 3) throw new ArgumentException();
+ _simdVector = new Vector3(float.Parse(nums[0]), float.Parse(nums[1]), float.Parse(nums[2]));
+ }
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static Vector Times(double n, Vector v)
+ {
+ Vector result;
+ result._simdVector = (float)n * v._simdVector;
+ return result;
+ }
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static Vector Minus(Vector v1, Vector v2)
+ {
+ Vector result;
+ result._simdVector = v1._simdVector - v2._simdVector;
+ return result;
+ }
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static Vector Plus(Vector v1, Vector v2)
+ {
+ Vector result;
+ result._simdVector = v1._simdVector + v2._simdVector;
+ return result;
+ }
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static float Dot(Vector v1, Vector v2)
+ {
+ return Vector3.Dot(v1._simdVector, v2._simdVector);
+ }
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static float Mag(Vector v) { return (float)Math.Sqrt(Dot(v, v)); }
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static Vector Norm(Vector v)
+ {
+ float mag = Mag(v);
+ float div = mag == 0 ? float.PositiveInfinity : 1 / mag;
+ return Times(div, v);
+ }
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static Vector Cross(Vector v1, Vector v2)
+ {
+ return new Vector(((v1.Y * v2.Z) - (v1.Z * v2.Y)),
+ ((v1.Z * v2.X) - (v1.X * v2.Z)),
+ ((v1.X * v2.Y) - (v1.Y * v2.X)));
+ }
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public static bool Equals(Vector v1, Vector v2)
+ {
+ return v1._simdVector.Equals(v2._simdVector);
+ }
+
+ public static Vector Null { get { Vector result; result._simdVector = Vector3.Zero; return result; } }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/SciMark/CommandLine.cs b/tests/src/JIT/Performance/CodeQuality/SciMark/CommandLine.cs
new file mode 100644
index 0000000000..eeb40acfb4
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SciMark/CommandLine.cs
@@ -0,0 +1,106 @@
+// 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.
+/// <license>
+/// This is a port of the SciMark2a Java Benchmark to C# by
+/// Chris Re (cmr28@cornell.edu) and Werner Vogels (vogels@cs.cornell.edu)
+///
+/// For details on the original authors see http://math.nist.gov/scimark2
+///
+/// This software is likely to burn your processor, bitflip your memory chips
+/// anihilate your screen and corrupt all your disks, so you it at your
+/// own risk.
+/// </license>
+
+
+using System;
+
+namespace SciMark2
+{
+ /// <summary>
+ /// SciMark2: A Java numerical benchmark measuring performance
+ /// of computational kernels for FFTs, Monte Carlo simulation,
+ /// sparse matrix computations, Jacobi SOR, and dense LU matrix
+ /// factorizations.
+ /// </summary>
+
+ public class CommandLine
+ {
+ /// <summary>
+ /// Benchmark 5 kernels with individual Mflops.
+ /// "results[0]" has the average Mflop rate.
+ /// </summary>
+ public static int Main(System.String[] args)
+ {
+#if DEBUG
+ double min_time = Constants.RESOLUTION_TINY;
+#else
+ double min_time = Constants.RESOLUTION_DEFAULT;
+#endif
+
+ int FFT_size = Constants.FFT_SIZE;
+ int SOR_size = Constants.SOR_SIZE;
+ int Sparse_size_M = Constants.SPARSE_SIZE_M;
+ int Sparse_size_nz = Constants.SPARSE_SIZE_nz;
+ int LU_size = Constants.LU_SIZE;
+
+ // look for runtime options
+ if (args.Length > 0)
+ {
+ if (args[0].ToUpper().Equals("-h") ||
+ args[0].ToUpper().Equals("-help"))
+ {
+ Console.WriteLine("Usage: [-large] [iterations]");
+ return -1;
+ }
+
+ int current_arg = 0;
+ if (args[current_arg].ToUpper().Equals("-LARGE"))
+ {
+ FFT_size = Constants.LG_FFT_SIZE;
+ SOR_size = Constants.LG_SOR_SIZE;
+ Sparse_size_M = Constants.LG_SPARSE_SIZE_M;
+ Sparse_size_nz = Constants.LG_SPARSE_SIZE_nz;
+ LU_size = Constants.LG_LU_SIZE;
+
+ current_arg++;
+ }
+
+ if (args.Length > current_arg)
+ min_time = Double.Parse(args[current_arg]);
+ }
+ Console.WriteLine("** **");
+ Console.WriteLine("** SciMark2a Numeric Benchmark, see http://math.nist.gov/scimark **");
+ Console.WriteLine("** **");
+
+ // run the benchmark
+ double[] res = new double[6];
+ SciMark2.Random R = new SciMark2.Random(Constants.RANDOM_SEED);
+
+ Console.WriteLine("Mininum running time = {0} seconds", min_time);
+
+ res[1] = kernel.measureFFT(FFT_size, min_time, R);
+
+ res[2] = kernel.measureSOR(SOR_size, min_time, R);
+
+ res[3] = kernel.measureMonteCarlo(min_time, R);
+
+ res[4] = kernel.measureSparseMatmult(Sparse_size_M, Sparse_size_nz, min_time, R);
+
+ res[5] = kernel.measureLU(LU_size, min_time, R);
+
+ res[0] = (res[1] + res[2] + res[3] + res[4] + res[5]) / 5;
+
+ // print out results
+ Console.WriteLine();
+ Console.WriteLine("Composite Score: {0:F2} MFlops", res[0]);
+ Console.WriteLine("FFT : {0} - ({1})", res[1] == 0.0 ? "ERROR, INVALID NUMERICAL RESULT!" : res[1].ToString("F2"), FFT_size);
+ Console.WriteLine("SOR : {1:F2} - ({0}x{0})", SOR_size, res[2]);
+ Console.WriteLine("Monte Carlo : {0:F2}", res[3]);
+ Console.WriteLine("Sparse MatMult : {2:F2} - (N={0}, nz={1})", Sparse_size_M, Sparse_size_nz, res[4]);
+ Console.WriteLine("LU : {1} - ({0}x{0})", LU_size, res[1] == 0.0 ? "ERROR, INVALID NUMERICAL RESULT!" : res[5].ToString("F2"));
+
+ return 100;
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SciMark/Constants.cs b/tests/src/JIT/Performance/CodeQuality/SciMark/Constants.cs
new file mode 100644
index 0000000000..a0baa6fac6
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SciMark/Constants.cs
@@ -0,0 +1,51 @@
+// 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.
+/// <license>
+/// This is a port of the SciMark2a Java Benchmark to C# by
+/// Chris Re (cmr28@cornell.edu) and Werner Vogels (vogels@cs.cornell.edu)
+///
+/// For details on the original authors see http://math.nist.gov/scimark2
+///
+/// This software is likely to burn your processor, bitflip your memory chips
+/// anihilate your screen and corrupt all your disks, so you it at your
+/// own risk.
+/// </license>
+
+
+namespace SciMark2
+{
+ public class Constants
+ {
+ public const double RESOLUTION_DEFAULT = 2.0; /*secs*/
+ public const double RESOLUTION_TINY = 0.02; /*secs*/
+ public const int RANDOM_SEED = 101010;
+
+ // default: small (cache-contained) problem sizes
+ //
+ public const int FFT_SIZE = 1024; // must be a power of two
+ public const int SOR_SIZE = 100; // NxN grid
+ public const int SPARSE_SIZE_M = 1000;
+ public const int SPARSE_SIZE_nz = 5000;
+ public const int LU_SIZE = 100;
+
+ // large (out-of-cache) problem sizes
+ //
+ public const int LG_FFT_SIZE = 1048576; // must be a power of two
+ public const int LG_SOR_SIZE = 1000; // NxN grid
+ public const int LG_SPARSE_SIZE_M = 100000;
+ public const int LG_SPARSE_SIZE_nz = 1000000;
+ public const int LG_LU_SIZE = 1000;
+
+ // tiny problem sizes (used to mainly to preload network classes
+ // for applet, so that network download times
+ // are factored out of benchmark.)
+ //
+ public const int TINY_FFT_SIZE = 16; // must be a power of two
+ public const int TINY_SOR_SIZE = 10; // NxN grid
+ public const int TINY_SPARSE_SIZE_M = 10;
+ public const int TINY_SPARSE_SIZE_N = 10;
+ public const int TINY_SPARSE_SIZE_nz = 50;
+ public const int TINY_LU_SIZE = 10;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SciMark/FFT.cs b/tests/src/JIT/Performance/CodeQuality/SciMark/FFT.cs
new file mode 100644
index 0000000000..824c50f01a
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SciMark/FFT.cs
@@ -0,0 +1,222 @@
+// 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.
+/// <license>
+/// This is a port of the SciMark2a Java Benchmark to C# by
+/// Chris Re (cmr28@cornell.edu) and Werner Vogels (vogels@cs.cornell.edu)
+///
+/// For details on the original authors see http://math.nist.gov/scimark2
+///
+/// This software is likely to burn your processor, bitflip your memory chips
+/// anihilate your screen and corrupt all your disks, so you it at your
+/// own risk.
+/// </license>
+
+
+using System;
+
+namespace SciMark2
+{
+ /// <summary>Computes FFT's of complex, double precision data where n is an integer power of 2.
+ /// This appears to be slower than the Radix2 method,
+ /// but the code is smaller and simpler, and it requires no extra storage.
+ /// </P>
+ /// </summary>
+ ///
+ /// <author>
+ /// Bruce R. Miller bruce.miller@nist.gov,
+ /// Derived from GSL (Gnu Scientific Library),
+ /// GSL's FFT Code by Brian Gough bjg@vvv.lanl.gov
+ /// </author>
+
+ public class FFT
+ {
+ public static double num_flops(int N)
+ {
+ double Nd = (double)N;
+ double logN = (double)log2(N);
+
+ return (5.0 * Nd - 2) * logN + 2 * (Nd + 1);
+ }
+
+
+ /// <summary>
+ /// Compute Fast Fourier Transform of (complex) data, in place.
+ /// </summary>
+ public static void transform(double[] data)
+ {
+ transform_internal(data, -1);
+ }
+
+ /// <summary>
+ /// Compute Inverse Fast Fourier Transform of (complex) data, in place.
+ /// </summary>
+ public static void inverse(double[] data)
+ {
+ transform_internal(data, +1);
+ // Normalize
+ int nd = data.Length;
+ int n = nd / 2;
+ double norm = 1 / ((double)n);
+ for (int i = 0; i < nd; i++)
+ data[i] *= norm;
+ }
+
+ /// <summary>
+ /// Accuracy check on FFT of data. Make a copy of data, Compute the FFT, then
+ /// the inverse and compare to the original. Returns the rms difference.
+ /// </summary>
+ public static double test(double[] data)
+ {
+ int nd = data.Length;
+ // Make duplicate for comparison
+ double[] copy = new double[nd];
+ Array.Copy(data, 0, copy, 0, nd);
+ // Transform & invert
+ transform(data);
+ inverse(data);
+ // Compute RMS difference.
+ double diff = 0.0;
+ for (int i = 0; i < nd; i++)
+ {
+ double d = data[i] - copy[i];
+ diff += d * d;
+ }
+ return Math.Sqrt(diff / nd);
+ }
+
+ /// <summary>
+ /// Make a random array of n (complex) elements.
+ /// </summary>
+ public static double[] makeRandom(int n)
+ {
+ int nd = 2 * n;
+ double[] data = new double[nd];
+ System.Random r = new System.Random();
+ for (int i = 0; i < nd; i++)
+ data[i] = r.NextDouble();
+ return data;
+ }
+
+ protected internal static int log2(int n)
+ {
+ int log = 0;
+ for (int k = 1; k < n; k *= 2, log++)
+ ;
+ if (n != (1 << log))
+ throw new Exception("FFT: Data length is not a power of 2!: " + n);
+ return log;
+ }
+
+ protected internal static void transform_internal(double[] data, int direction)
+ {
+ if (data.Length == 0)
+ return;
+ int n = data.Length / 2;
+ if (n == 1)
+ return;
+ // Identity operation!
+ int logn = log2(n);
+
+ /* bit reverse the input data for decimation in time algorithm */
+ bitreverse(data);
+
+ /* apply fft recursion */
+ /* this loop executed log2(N) times */
+ for (int bit = 0, dual = 1; bit < logn; bit++, dual *= 2)
+ {
+ double w_real = 1.0;
+ double w_imag = 0.0;
+
+ double theta = 2.0 * direction * Math.PI / (2.0 * (double)dual);
+ double s = Math.Sin(theta);
+ double t = Math.Sin(theta / 2.0);
+ double s2 = 2.0 * t * t;
+
+ /* a = 0 */
+ for (int b = 0; b < n; b += 2 * dual)
+ {
+ int i = 2 * b;
+ int j = 2 * (b + dual);
+
+ double wd_real = data[j];
+ double wd_imag = data[j + 1];
+
+ data[j] = data[i] - wd_real;
+ data[j + 1] = data[i + 1] - wd_imag;
+ data[i] += wd_real;
+ data[i + 1] += wd_imag;
+ }
+
+ /* a = 1 .. (dual-1) */
+ for (int a = 1; a < dual; a++)
+ {
+ /* trignometric recurrence for w-> exp(i theta) w */
+ {
+ double tmp_real = w_real - s * w_imag - s2 * w_real;
+ double tmp_imag = w_imag + s * w_real - s2 * w_imag;
+ w_real = tmp_real;
+ w_imag = tmp_imag;
+ }
+ for (int b = 0; b < n; b += 2 * dual)
+ {
+ int i = 2 * (b + a);
+ int j = 2 * (b + a + dual);
+
+ double z1_real = data[j];
+ double z1_imag = data[j + 1];
+
+ double wd_real = w_real * z1_real - w_imag * z1_imag;
+ double wd_imag = w_real * z1_imag + w_imag * z1_real;
+
+ data[j] = data[i] - wd_real;
+ data[j + 1] = data[i + 1] - wd_imag;
+ data[i] += wd_real;
+ data[i + 1] += wd_imag;
+ }
+ }
+ }
+ }
+
+
+ protected internal static void bitreverse(double[] data)
+ {
+ /* This is the Goldrader bit-reversal algorithm */
+ int n = data.Length / 2;
+ int nm1 = n - 1;
+ int i = 0;
+ int j = 0;
+ for (; i < nm1; i++)
+ {
+ //int ii = 2*i;
+ int ii = i << 1;
+
+ //int jj = 2*j;
+ int jj = j << 1;
+
+ //int k = n / 2 ;
+ int k = n >> 1;
+
+ if (i < j)
+ {
+ double tmp_real = data[ii];
+ double tmp_imag = data[ii + 1];
+ data[ii] = data[jj];
+ data[ii + 1] = data[jj + 1];
+ data[jj] = tmp_real;
+ data[jj + 1] = tmp_imag;
+ }
+
+ while (k <= j)
+ {
+ //j = j - k ;
+ j -= k;
+
+ //k = k / 2 ;
+ k >>= 1;
+ }
+ j += k;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SciMark/LU.cs b/tests/src/JIT/Performance/CodeQuality/SciMark/LU.cs
new file mode 100644
index 0000000000..db8d61a1c8
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SciMark/LU.cs
@@ -0,0 +1,271 @@
+// 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.
+/// <license>
+/// This is a port of the SciMark2a Java Benchmark to C# by
+/// Chris Re (cmr28@cornell.edu) and Werner Vogels (vogels@cs.cornell.edu)
+///
+/// For details on the original authors see http://math.nist.gov/scimark2
+///
+/// This software is likely to burn your processor, bitflip your memory chips
+/// anihilate your screen and corrupt all your disks, so you it at your
+/// own risk.
+/// </license>
+
+
+using System;
+
+namespace SciMark2
+{
+ /// <summary>
+ /// LU matrix factorization. (Based on TNT implementation.)
+ /// Decomposes a matrix A into a triangular lower triangular
+ /// factor (L) and an upper triangular factor (U) such that
+ /// A = L*U. By convnetion, the main diagonal of L consists
+ /// of 1's so that L and U can be stored compactly in
+ /// a NxN matrix.
+ /// </summary>
+ public class LU
+ {
+ private double[][] _LU;
+ private int[] _pivot;
+
+ /// <summary>
+ /// Returns a <em>copy</em> of the compact LU factorization.
+ /// (useful mainly for debugging.)
+ /// </summary>
+ ///
+ /// <returns>
+ /// the compact LU factorization. The U factor
+ /// is stored in the upper triangular portion, and the L
+ /// factor is stored in the lower triangular portion.
+ /// The main diagonal of L consists (by convention) of
+ /// ones, and is not explicitly stored.
+ /// </returns>
+ public static double num_flops(int N)
+ {
+ // rougly 2/3*N^3
+
+ double Nd = (double)N;
+
+ return (2.0 * Nd * Nd * Nd / 3.0);
+ }
+
+ protected internal static double[] new_copy(double[] x)
+ {
+ double[] T = new double[x.Length];
+ x.CopyTo(T, 0);
+ return T;
+ }
+
+
+ protected internal static double[][] new_copy(double[][] A)
+ {
+ int M = A.Length;
+ int N = A[0].Length;
+
+ double[][] T = new double[M][];
+ for (int i = 0; i < M; i++)
+ {
+ T[i] = new double[N];
+ }
+
+ for (int i = 0; i < M; i++)
+ {
+ A[i].CopyTo(T[i], 0);
+ }
+
+ return T;
+ }
+
+
+
+ public static int[] new_copy(int[] x)
+ {
+ int[] T = new int[x.Length];
+ x.CopyTo(T, 0);
+ return T;
+ }
+
+ protected internal static void insert_copy(double[][] B, double[][] A)
+ {
+ for (int i = 0; i < A.Length; i++)
+ {
+ A[i].CopyTo(B[i], 0);
+ }
+ }
+
+ /// <summary>
+ /// Initalize LU factorization from matrix.
+ /// </summary>
+ /// <param name="A">
+ /// (in) the matrix to associate with this factorization.
+ ///
+ /// </param>
+ public LU(double[][] A)
+ {
+ _LU = new_copy(A);
+ _pivot = new int[A.Length];
+
+ factor(_LU, _pivot);
+ }
+
+ /// <summary>
+ /// Solve a linear system, with pre-computed factorization.
+ /// </summary>
+ /// <param name="b">
+ /// (in) the right-hand side.
+ /// </param>
+ /// <returns>
+ /// solution vector.
+ /// </returns>
+ public virtual double[] solve(double[] b)
+ {
+ double[] x = new_copy(b);
+
+ solve(_LU, _pivot, x);
+ return x;
+ }
+
+
+ /// <summary>
+ /// LU factorization (in place).
+ /// </summary>
+ /// <param name="A">
+ /// (in/out) On input, the matrix to be factored.
+ /// On output, the compact LU factorization.
+ /// </param>
+ /// <param name="pivot">
+ /// (out) The pivot vector records the
+ /// reordering of the rows of A during factorization.
+ /// </param>
+ /// <returns>
+ /// 0, if OK, nozero value, othewise.
+ /// </returns>
+ public static int factor(double[][] A, int[] pivot)
+ {
+ int N = A.Length;
+ int M = A[0].Length;
+
+ int minMN = Math.Min(M, N);
+
+ for (int j = 0; j < minMN; j++)
+ {
+ // find pivot in column j and test for singularity.
+ int jp = j;
+
+ double t = Math.Abs(A[j][j]);
+ for (int i = j + 1; i < M; i++)
+ {
+ double ab = Math.Abs(A[i][j]);
+ if (ab > t)
+ {
+ jp = i;
+ t = ab;
+ }
+ }
+
+ pivot[j] = jp;
+
+ // jp now has the index of maximum element
+ // of column j, below the diagonal
+ if (A[jp][j] == 0)
+ return 1;
+
+ // factorization failed because of zero pivot
+ if (jp != j)
+ {
+ // swap rows j and jp
+ double[] tA = A[j];
+ A[j] = A[jp];
+ A[jp] = tA;
+ }
+
+ if (j < M - 1)
+ {
+ // compute elements j+1:M of jth column
+ // note A(j,j), was A(jp,p) previously which was
+ // guarranteed not to be zero (Label #1)
+ //
+ double recp = 1.0 / A[j][j];
+
+ for (int k = j + 1; k < M; k++)
+ A[k][j] *= recp;
+ }
+
+ if (j < minMN - 1)
+ {
+ // rank-1 update to trailing submatrix: E = E - x*y;
+ //
+ // E is the region A(j+1:M, j+1:N)
+ // x is the column vector A(j+1:M,j)
+ // y is row vector A(j,j+1:N)
+ for (int ii = j + 1; ii < M; ii++)
+ {
+ double[] Aii = A[ii];
+ double[] Aj = A[j];
+ double AiiJ = Aii[j];
+ for (int jj = j + 1; jj < N; jj++)
+ Aii[jj] -= AiiJ * Aj[jj];
+ }
+ }
+ }
+
+ return 0;
+ }
+
+
+ /// <summary>Solve a linear system, using a prefactored matrix
+ /// in LU form.
+ /// </summary>
+ /// <param name="A">(in) the factored matrix in LU form.
+ /// </param>
+ /// <param name="pivot">(in) the pivot vector which lists
+ /// the reordering used during the factorization
+ /// stage.
+ /// </param>
+ /// <param name="b"> (in/out) On input, the right-hand side.
+ /// On output, the solution vector.
+ ///
+ /// </param>
+ public static void solve(double[][] A, int[] pvt, double[] b)
+ {
+ int M = A.Length;
+ int N = A[0].Length;
+ int ii = 0;
+
+ for (int i = 0; i < M; i++)
+ {
+ int ip = pvt[i];
+ double sum = b[ip];
+
+ b[ip] = b[i];
+ if (ii == 0)
+ {
+ for (int j = ii; j < i; j++)
+ {
+ sum -= A[i][j] * b[j];
+ }
+ }
+ else
+ {
+ if (sum == 0.0)
+ {
+ ii = i;
+ }
+ }
+ b[i] = sum;
+ }
+
+ for (int i = N - 1; i >= 0; i--)
+ {
+ double sum = b[i];
+ for (int j = i + 1; j < N; j++)
+ {
+ sum -= A[i][j] * b[j];
+ }
+ b[i] = sum / A[i][i];
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/src/JIT/Performance/CodeQuality/SciMark/MonteCarlo.cs b/tests/src/JIT/Performance/CodeQuality/SciMark/MonteCarlo.cs
new file mode 100644
index 0000000000..e01d22bd9f
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SciMark/MonteCarlo.cs
@@ -0,0 +1,72 @@
+// 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.
+/// <license>
+/// This is a port of the SciMark2a Java Benchmark to C# by
+/// Chris Re (cmr28@cornell.edu) and Werner Vogels (vogels@cs.cornell.edu)
+///
+/// For details on the original authors see http://math.nist.gov/scimark2
+///
+/// This software is likely to burn your processor, bitflip your memory chips
+/// anihilate your screen and corrupt all your disks, so you it at your
+/// own risk.
+/// </license>
+
+
+using System;
+
+namespace SciMark2
+{
+ /// <summary>Estimate Pi by approximating the area of a circle.
+ /// How: generate N random numbers in the unit square, (0,0) to (1,1)
+ /// and see how are within a radius of 1 or less, i.e.
+ /// <pre>
+ /// sqrt(x^2 + y^2) < r
+ /// </pre>
+ /// since the radius is 1.0, we can square both sides
+ /// and avoid a sqrt() computation:
+ /// <pre>
+ /// x^2 + y^2 <= 1.0
+ /// </pre>
+ /// this area under the curve is (Pi * r^2)/ 4.0,
+ /// and the area of the unit of square is 1.0,
+ /// so Pi can be approximated by
+ /// <pre>
+ /// # points with x^2+y^2 < 1
+ /// Pi =~ -------------------------- * 4.0
+ /// total # points
+ /// </pre>
+ /// </summary>
+
+ public class MonteCarlo
+ {
+ internal const int SEED = 113;
+
+ public static double num_flops(int Num_samples)
+ {
+ // 3 flops in x^2+y^2 and 1 flop in random routine
+
+ return ((double)Num_samples) * 4.0;
+ }
+
+
+
+ public static double integrate(int Num_samples)
+ {
+ SciMark2.Random R = new SciMark2.Random(SEED);
+
+
+ int under_curve = 0;
+ for (int count = 0; count < Num_samples; count++)
+ {
+ double x = R.nextDouble();
+ double y = R.nextDouble();
+
+ if (x * x + y * y <= 1.0)
+ under_curve++;
+ }
+
+ return ((double)under_curve / Num_samples) * 4.0;
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/src/JIT/Performance/CodeQuality/SciMark/Random.cs b/tests/src/JIT/Performance/CodeQuality/SciMark/Random.cs
new file mode 100644
index 0000000000..7c4f618ee3
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SciMark/Random.cs
@@ -0,0 +1,305 @@
+// 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.
+/// <license>
+/// This is a port of the SciMark2a Java Benchmark to C# by
+/// Chris Re (cmr28@cornell.edu) and Werner Vogels (vogels@cs.cornell.edu)
+///
+/// For details on the original authors see http://math.nist.gov/scimark2
+///
+/// This software is likely to burn your processor, bitflip your memory chips
+/// anihilate your screen and corrupt all your disks, so you it at your
+/// own risk.
+/// </license>
+
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace SciMark2
+{
+ /* Random.java based on Java Numerical Toolkit (JNT) Random.UniformSequence
+ class. We do not use Java's own java.util.Random so that we can compare
+ results with equivalent C and Fortran coces.*/
+
+ public class Random
+ {
+ /*------------------------------------------------------------------------------
+ CLASS VARIABLES
+ ------------------------------------------------------------------------------ */
+
+ internal int seed = 0;
+
+ private int[] _m;
+ private int _i = 4;
+ private int _j = 16;
+
+ private const int mdig = 32;
+ private const int one = 1;
+ private int _m1;
+ private int _m2;
+
+ private double _dm1;
+
+ private bool _haveRange = false;
+ private double _left = 0.0;
+ private double _right = 1.0;
+ private double _width = 1.0;
+
+
+ /* ------------------------------------------------------------------------------
+ CONSTRUCTORS
+ ------------------------------------------------------------------------------ */
+
+ /// <summary>
+ /// Initializes a sequence of uniformly distributed quasi random numbers with a
+ /// seed based on the system clock.
+ /// </summary>
+ public Random()
+ {
+ initialize((int)System.DateTime.Now.Ticks);
+ }
+
+ /// <summary>
+ /// Initializes a sequence of uniformly distributed quasi random numbers on a
+ /// given half-open interval [left,right) with a seed based on the system
+ /// clock.
+ /// </summary>
+ /// <param name="<B>left</B>">(double)<BR>
+ /// The left endpoint of the half-open interval [left,right).
+ /// </param>
+ /// <param name="<B>right</B>">(double)<BR>
+ /// The right endpoint of the half-open interval [left,right).
+ /// </param>
+ public Random(double left, double right)
+ {
+ initialize((int)System.DateTime.Now.Ticks);
+ _left = left;
+ _right = right;
+ _width = right - left;
+ _haveRange = true;
+ }
+
+ /// <summary>
+ /// Initializes a sequence of uniformly distributed quasi random numbers with a
+ /// given seed.
+ /// </summary>
+ /// <param name="<B>seed</B>">(int)<BR>
+ /// The seed of the random number generator. Two sequences with the same
+ /// seed will be identical.
+ /// </param>
+ public Random(int seed)
+ {
+ initialize(seed);
+ }
+
+ /// <summary>Initializes a sequence of uniformly distributed quasi random numbers
+ /// with a given seed on a given half-open interval [left,right).
+ /// </summary>
+ /// <param name="<B>seed</B>">(int)<BR>
+ /// The seed of the random number generator. Two sequences with the same
+ /// seed will be identical.
+ /// </param>
+ /// <param name="<B>left</B>">(double)<BR>
+ /// The left endpoint of the half-open interval [left,right).
+ /// </param>
+ /// <param name="<B>right</B>">(double)<BR>
+ /// The right endpoint of the half-open interval [left,right).
+ /// </param>
+ public Random(int seed, double left, double right)
+ {
+ initialize(seed);
+ _left = left;
+ _right = right;
+ _width = right - left;
+ _haveRange = true;
+ }
+
+ /* ------------------------------------------------------------------------------
+ PUBLIC METHODS
+ ------------------------------------------------------------------------------ */
+
+ /// <summary>
+ /// Returns the next random number in the sequence.
+ /// </summary>
+ public double nextDouble()
+ {
+ int k;
+
+ k = _m[_i] - _m[_j];
+ if (k < 0)
+ k += _m1;
+ _m[_j] = k;
+
+ if (_i == 0)
+ _i = 16;
+ else
+ _i--;
+
+ if (_j == 0)
+ _j = 16;
+ else
+ _j--;
+
+ if (_haveRange)
+ return _left + _dm1 * (double)k * _width;
+ else
+ return _dm1 * (double)k;
+ }
+
+ /// <summary>
+ /// Returns the next N random numbers in the sequence, as
+ /// a vector.
+ /// </summary>
+ public void nextDoubles(double[] x)
+ {
+ int N = x.Length;
+ int remainder = N & 3;
+
+ if (_haveRange)
+ {
+ for (int count = 0; count < N; count++)
+ {
+ int k = _m[_i] - _m[_j];
+
+ if (_i == 0)
+ _i = 16;
+ else
+ _i--;
+
+ if (k < 0)
+ k += _m1;
+ _m[_j] = k;
+
+ if (_j == 0)
+ _j = 16;
+ else
+ _j--;
+
+ x[count] = _left + _dm1 * (double)k * _width;
+ }
+ }
+ else
+ {
+ for (int count = 0; count < remainder; count++)
+ {
+ int k = _m[_i] - _m[_j];
+
+ if (_i == 0)
+ _i = 16;
+ else
+ _i--;
+
+ if (k < 0)
+ k += _m1;
+ _m[_j] = k;
+
+ if (_j == 0)
+ _j = 16;
+ else
+ _j--;
+
+
+ x[count] = _dm1 * (double)k;
+ }
+
+ for (int count = remainder; count < N; count += 4)
+ {
+ int k = _m[_i] - _m[_j];
+ if (_i == 0)
+ _i = 16;
+ else
+ _i--;
+ if (k < 0)
+ k += _m1;
+ _m[_j] = k;
+ if (_j == 0)
+ _j = 16;
+ else
+ _j--;
+ x[count] = _dm1 * (double)k;
+
+
+ k = _m[_i] - _m[_j];
+ if (_i == 0)
+ _i = 16;
+ else
+ _i--;
+ if (k < 0)
+ k += _m1;
+ _m[_j] = k;
+ if (_j == 0)
+ _j = 16;
+ else
+ _j--;
+ x[count + 1] = _dm1 * (double)k;
+
+
+ k = _m[_i] - _m[_j];
+ if (_i == 0)
+ _i = 16;
+ else
+ _i--;
+ if (k < 0)
+ k += _m1;
+ _m[_j] = k;
+ if (_j == 0)
+ _j = 16;
+ else
+ _j--;
+ x[count + 2] = _dm1 * (double)k;
+
+
+ k = _m[_i] - _m[_j];
+ if (_i == 0)
+ _i = 16;
+ else
+ _i--;
+ if (k < 0)
+ k += _m1;
+ _m[_j] = k;
+ if (_j == 0)
+ _j = 16;
+ else
+ _j--;
+ x[count + 3] = _dm1 * (double)k;
+ }
+ }
+ }
+
+ /*----------------------------------------------------------------------------
+ PRIVATE METHODS
+ ------------------------------------------------------------------------ */
+
+ private void initialize(int seed)
+ {
+ // First the initialization of the member variables;
+ _m1 = (one << mdig - 2) + ((one << mdig - 2) - one);
+ _m2 = one << mdig / 2;
+ _dm1 = 1.0 / (double)_m1;
+
+ int jseed, k0, k1, j0, j1, iloop;
+
+ this.seed = seed;
+
+ _m = new int[17];
+
+ jseed = System.Math.Min(System.Math.Abs(seed), _m1);
+ if (jseed % 2 == 0)
+ --jseed;
+ k0 = 9069 % _m2;
+ k1 = 9069 / _m2;
+ j0 = jseed % _m2;
+ j1 = jseed / _m2;
+ for (iloop = 0; iloop < 17; ++iloop)
+ {
+ jseed = j0 * k0;
+ j1 = (jseed / _m2 + j0 * k1 + j1 * k0) % (_m2 / 2);
+ j0 = jseed % _m2;
+ _m[iloop] = j0 + _m2 * j1;
+ }
+ _i = 4;
+ _j = 16;
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/SciMark/SOR.cs b/tests/src/JIT/Performance/CodeQuality/SciMark/SOR.cs
new file mode 100644
index 0000000000..5fb8099adc
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SciMark/SOR.cs
@@ -0,0 +1,56 @@
+// 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.
+/// <license>
+/// This is a port of the SciMark2a Java Benchmark to C# by
+/// Chris Re (cmr28@cornell.edu) and Werner Vogels (vogels@cs.cornell.edu)
+///
+/// For details on the original authors see http://math.nist.gov/scimark2
+///
+/// This software is likely to burn your processor, bitflip your memory chips
+/// anihilate your screen and corrupt all your disks, so you it at your
+/// own risk.
+/// </license>
+
+
+using System;
+
+namespace SciMark2
+{
+ public class SOR
+ {
+ public static double num_flops(int M, int N, int num_iterations)
+ {
+ double Md = (double)M;
+ double Nd = (double)N;
+ double num_iterD = (double)num_iterations;
+
+ return (Md - 1) * (Nd - 1) * num_iterD * 6.0;
+ }
+
+ public static void execute(double omega, double[][] G, int num_iterations)
+ {
+ int M = G.Length;
+ int N = G[0].Length;
+
+ double omega_over_four = omega * 0.25;
+ double one_minus_omega = 1.0 - omega;
+
+ // update interior points
+ //
+ int Mm1 = M - 1;
+ int Nm1 = N - 1;
+ for (int p = 0; p < num_iterations; p++)
+ {
+ for (int i = 1; i < Mm1; i++)
+ {
+ double[] Gi = G[i];
+ double[] Gim1 = G[i - 1];
+ double[] Gip1 = G[i + 1];
+ for (int j = 1; j < Nm1; j++)
+ Gi[j] = omega_over_four * (Gim1[j] + Gip1[j] + Gi[j - 1] + Gi[j + 1]) + one_minus_omega * Gi[j];
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/src/JIT/Performance/CodeQuality/SciMark/SciMark.csproj b/tests/src/JIT/Performance/CodeQuality/SciMark/SciMark.csproj
new file mode 100644
index 0000000000..28127efebc
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SciMark/SciMark.csproj
@@ -0,0 +1,53 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ <AssemblyName>SciMark</AssemblyName>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="CommandLine.cs" />
+ <Compile Include="Constants.cs" />
+ <Compile Include="FFT.cs" />
+ <Compile Include="kernel.cs" />
+ <Compile Include="LU.cs" />
+ <Compile Include="MonteCarlo.cs" />
+ <Compile Include="Random.cs" />
+ <Compile Include="SOR.cs" />
+ <Compile Include="SparseCompRow.cs" />
+ <Compile Include="Stopwatch.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/SciMark/SparseCompRow.cs b/tests/src/JIT/Performance/CodeQuality/SciMark/SparseCompRow.cs
new file mode 100644
index 0000000000..34660c5978
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SciMark/SparseCompRow.cs
@@ -0,0 +1,59 @@
+// 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.
+/// <license>
+/// This is a port of the SciMark2a Java Benchmark to C# by
+/// Chris Re (cmr28@cornell.edu) and Werner Vogels (vogels@cs.cornell.edu)
+///
+/// For details on the original authors see http://math.nist.gov/scimark2
+///
+/// This software is likely to burn your processor, bitflip your memory chips
+/// anihilate your screen and corrupt all your disks, so you it at your
+/// own risk.
+/// </license>
+
+
+using System;
+
+namespace SciMark2
+{
+ public class SparseCompRow
+ {
+ // multiple iterations used to make kernel
+ // have roughly same granulairty as other
+ // Scimark kernels
+ public static double num_flops(int N, int nz, int num_iterations)
+ {
+ /* Note that if nz does not divide N evenly, then the
+ actual number of nonzeros used is adjusted slightly.
+ */
+ int actual_nz = (nz / N) * N;
+ return ((double)actual_nz) * 2.0 * ((double)num_iterations);
+ }
+
+ /// <summary>
+ /// computes a matrix-vector multiply with a sparse matrix
+ /// held in compress-row format. If the size of the matrix
+ /// in MxN with nz nonzeros, then the val[] is the nz nonzeros,
+ /// with its ith entry in column col[i]. The integer vector row[]
+ /// is of size M+1 and row[i] points to the begining of the
+ /// ith row in col[].
+ public static void matmult(double[] y, double[] val, int[] row, int[] col, double[] x, int NUM_ITERATIONS)
+ {
+ int M = row.Length - 1;
+
+ for (int reps = 0; reps < NUM_ITERATIONS; reps++)
+ {
+ for (int r = 0; r < M; r++)
+ {
+ double sum = 0.0;
+ int rowR = row[r];
+ int rowRp1 = row[r + 1];
+ for (int i = rowR; i < rowRp1; i++)
+ sum += x[col[i]] * val[i];
+ y[r] = sum;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/src/JIT/Performance/CodeQuality/SciMark/Stopwatch.cs b/tests/src/JIT/Performance/CodeQuality/SciMark/Stopwatch.cs
new file mode 100644
index 0000000000..9acaf9bce1
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SciMark/Stopwatch.cs
@@ -0,0 +1,112 @@
+// 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.
+/// <license>
+/// This is a port of the SciMark2a Java Benchmark to C# by
+/// Chris Re (cmr28@cornell.edu) and Werner Vogels (vogels@cs.cornell.edu)
+///
+/// For details on the original authors see http://math.nist.gov/scimark2
+///
+/// This software is likely to burn your processor, bitflip your memory chips
+/// anihilate your screen and corrupt all your disks, so you it at your
+/// own risk.
+/// </license>
+
+
+using System;
+
+namespace SciMark2
+{
+ /// <summary>
+ /// Provides a stopwatch to measure elapsed time.
+ /// </summary>
+ /// <author>
+ /// Roldan Pozo
+ /// </author>
+ /// <version>
+ /// 14 October 1997, revised 1999-04-24
+ /// </version>
+ ///
+ public class Stopwatch
+ {
+ private bool _running;
+ private double _last_time;
+ private double _total;
+
+ ///
+ /// <summary>R
+ /// eturn system time (in seconds)
+ /// </summary>
+ public static double seconds()
+ {
+ return (System.DateTime.Now.Ticks * 1.0E-7);
+ }
+
+ public virtual void reset()
+ {
+ _running = false;
+ _last_time = 0.0;
+ _total = 0.0;
+ }
+
+ public Stopwatch()
+ {
+ reset();
+ }
+
+ ///
+ /// <summary>
+ /// Start (and reset) timer
+ /// </summary>
+ public virtual void start()
+ {
+ if (!_running)
+ {
+ _running = true;
+ _total = 0.0;
+ _last_time = seconds();
+ }
+ }
+
+ ///
+ /// <summary>
+ /// Resume timing, after stopping. (Does not wipe out accumulated times.)
+ /// </summary>
+ public virtual void resume()
+ {
+ if (!_running)
+ {
+ _last_time = seconds();
+ _running = true;
+ }
+ }
+
+ ///
+ /// <summary>
+ /// Stop timer
+ /// </summary>
+ public virtual double stop()
+ {
+ if (_running)
+ {
+ _total += seconds() - _last_time;
+ _running = false;
+ }
+ return _total;
+ }
+
+ ///
+ /// <summary>
+ /// return the elapsed time (in seconds)
+ /// </summary>
+ public virtual double read()
+ {
+ if (_running)
+ {
+ _total += seconds() - _last_time;
+ _last_time = seconds();
+ }
+ return _total;
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/src/JIT/Performance/CodeQuality/SciMark/kernel.cs b/tests/src/JIT/Performance/CodeQuality/SciMark/kernel.cs
new file mode 100644
index 0000000000..3cba0c16c8
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/SciMark/kernel.cs
@@ -0,0 +1,450 @@
+// 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.
+/// <license>
+/// This is a port of the SciMark2a Java Benchmark to C# by
+/// Chris Re (cmr28@cornell.edu) and Werner Vogels (vogels@cs.cornell.edu)
+///
+/// For details on the original authors see http://math.nist.gov/scimark2
+///
+/// This software is likely to burn your processor, bitflip your memory chips
+/// anihilate your screen and corrupt all your disks, so you it at your
+/// own risk.
+/// </license>
+
+
+using Microsoft.Xunit.Performance;
+using System;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+namespace SciMark2
+{
+ public static class kernel
+ {
+ [Benchmark]
+ public static void benchFFT()
+ {
+ SciMark2.Random R = new SciMark2.Random(Constants.RANDOM_SEED);
+ int N = Constants.FFT_SIZE;
+ long Iterations = 20000;
+
+ double[] x = RandomVector(2 * N, R);
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ innerFFT(x, Iterations);
+ }
+ }
+ validateFFT(N, x);
+ }
+
+ private static void innerFFT(double[] x, long Iterations)
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ FFT.transform(x); // forward transform
+ FFT.inverse(x); // backward transform
+ }
+ }
+
+ private static void validateFFT(int N, double[] x)
+ {
+ const double EPS = 1.0e-10;
+ if (FFT.test(x) / N > EPS)
+ {
+ throw new Exception("FFT failed to validate");
+ }
+ }
+
+ public static double measureFFT(int N, double mintime, Random R)
+ {
+ // initialize FFT data as complex (N real/img pairs)
+ double[] x = RandomVector(2 * N, R);
+
+ long cycles = 1;
+ Stopwatch Q = new Stopwatch();
+ while (true)
+ {
+ Q.start();
+ innerFFT(x, cycles);
+ Q.stop();
+ if (Q.read() >= mintime)
+ break;
+
+ cycles *= 2;
+ }
+
+ validateFFT(N, x);
+
+ // approx Mflops
+ return FFT.num_flops(N) * cycles / Q.read() * 1.0e-6;
+ }
+
+ [Benchmark]
+ public static void benchSOR()
+ {
+ int N = Constants.SOR_SIZE;
+ SciMark2.Random R = new SciMark2.Random(Constants.RANDOM_SEED);
+ int Iterations = 20000;
+ double[][] G = RandomMatrix(N, N, R);
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ SOR.execute(1.25, G, Iterations);
+ }
+ }
+ }
+
+ public static double measureSOR(int N, double min_time, Random R)
+ {
+ double[][] G = RandomMatrix(N, N, R);
+ Stopwatch Q = new Stopwatch();
+ int cycles = 1;
+ while (true)
+ {
+ Q.start();
+ SOR.execute(1.25, G, cycles);
+ Q.stop();
+ if (Q.read() >= min_time)
+ break;
+
+ cycles *= 2;
+ }
+
+ // approx Mflops
+ return SOR.num_flops(N, N, cycles) / Q.read() * 1.0e-6;
+ }
+
+ [Benchmark]
+ public static void benchMonteCarlo()
+ {
+ SciMark2.Random R = new SciMark2.Random(Constants.RANDOM_SEED);
+ int Iterations = 40000000;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ MonteCarlo.integrate(Iterations);
+ }
+ }
+ }
+
+ public static double measureMonteCarlo(double min_time, Random R)
+ {
+ Stopwatch Q = new Stopwatch();
+
+ int cycles = 1;
+ while (true)
+ {
+ Q.start();
+ MonteCarlo.integrate(cycles);
+ Q.stop();
+ if (Q.read() >= min_time)
+ break;
+
+ cycles *= 2;
+ }
+
+ // approx Mflops
+ return MonteCarlo.num_flops(cycles) / Q.read() * 1.0e-6;
+ }
+
+ [Benchmark]
+ public static void benchSparseMult()
+ {
+ int N = Constants.SPARSE_SIZE_M;
+ int nz = Constants.SPARSE_SIZE_nz;
+ int Iterations = 100000;
+ SciMark2.Random R = new SciMark2.Random(Constants.RANDOM_SEED);
+
+ double[] x = RandomVector(N, R);
+ double[] y = new double[N];
+ int nr = nz / N; // average number of nonzeros per row
+ int anz = nr * N; // _actual_ number of nonzeros
+ double[] val = RandomVector(anz, R);
+ int[] col = new int[anz];
+ int[] row = new int[N + 1];
+
+ row[0] = 0;
+ for (int r = 0; r < N; r++)
+ {
+ // initialize elements for row r
+
+ int rowr = row[r];
+ row[r + 1] = rowr + nr;
+ int step = r / nr;
+ if (step < 1)
+ step = 1;
+ // take at least unit steps
+
+ for (int i = 0; i < nr; i++)
+ col[rowr + i] = i * step;
+ }
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ SparseCompRow.matmult(y, val, row, col, x, Iterations);
+ }
+ }
+ }
+
+ public static double measureSparseMatmult(int N, int nz, double min_time, Random R)
+ {
+ // initialize vector multipliers and storage for result
+ // y = A*y;
+
+ double[] x = RandomVector(N, R);
+ double[] y = new double[N];
+
+ // initialize square sparse matrix
+ //
+ // for this test, we create a sparse matrix wit M/nz nonzeros
+ // per row, with spaced-out evenly between the begining of the
+ // row to the main diagonal. Thus, the resulting pattern looks
+ // like
+ // +-----------------+
+ // +* +
+ // +*** +
+ // +* * * +
+ // +** * * +
+ // +** * * +
+ // +* * * * +
+ // +* * * * +
+ // +* * * * +
+ // +-----------------+
+ //
+ // (as best reproducible with integer artihmetic)
+ // Note that the first nr rows will have elements past
+ // the diagonal.
+
+ int nr = nz / N; // average number of nonzeros per row
+ int anz = nr * N; // _actual_ number of nonzeros
+
+
+ double[] val = RandomVector(anz, R);
+ int[] col = new int[anz];
+ int[] row = new int[N + 1];
+
+ row[0] = 0;
+ for (int r = 0; r < N; r++)
+ {
+ // initialize elements for row r
+
+ int rowr = row[r];
+ row[r + 1] = rowr + nr;
+ int step = r / nr;
+ if (step < 1)
+ step = 1;
+ // take at least unit steps
+
+ for (int i = 0; i < nr; i++)
+ col[rowr + i] = i * step;
+ }
+
+ Stopwatch Q = new Stopwatch();
+
+ int cycles = 1;
+ while (true)
+ {
+ Q.start();
+ SparseCompRow.matmult(y, val, row, col, x, cycles);
+ Q.stop();
+ if (Q.read() >= min_time)
+ break;
+
+ cycles *= 2;
+ }
+
+ // approx Mflops
+ return SparseCompRow.num_flops(N, nz, cycles) / Q.read() * 1.0e-6;
+ }
+
+ [Benchmark]
+ public static void benchmarkLU()
+ {
+ int N = Constants.LU_SIZE;
+ SciMark2.Random R = new SciMark2.Random(Constants.RANDOM_SEED);
+ int Iterations = 2000;
+
+ double[][] A = RandomMatrix(N, N, R);
+ double[][] lu = new double[N][];
+ for (int i = 0; i < N; i++)
+ {
+ lu[i] = new double[N];
+ }
+ int[] pivot = new int[N];
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ CopyMatrix(lu, A);
+ LU.factor(lu, pivot);
+ }
+ }
+ }
+
+ validateLU(N, R, lu, A, pivot);
+ }
+
+ public static void validateLU(int N, SciMark2.Random R, double[][] lu, double[][] A, int[] pivot)
+ {
+ // verify that LU is correct
+ double[] b = RandomVector(N, R);
+ double[] x = NewVectorCopy(b);
+
+ LU.solve(lu, pivot, x);
+
+ const double EPS = 1.0e-12;
+ if (normabs(b, matvec(A, x)) / N > EPS)
+ {
+ throw new Exception("LU failed to validate");
+ }
+ }
+ public static double measureLU(int N, double min_time, Random R)
+ {
+ // compute approx Mlfops, or O if LU yields large errors
+
+ double[][] A = RandomMatrix(N, N, R);
+ double[][] lu = new double[N][];
+ for (int i = 0; i < N; i++)
+ {
+ lu[i] = new double[N];
+ }
+ int[] pivot = new int[N];
+
+ Stopwatch Q = new Stopwatch();
+
+ int cycles = 1;
+ while (true)
+ {
+ Q.start();
+ for (int i = 0; i < cycles; i++)
+ {
+ CopyMatrix(lu, A);
+ LU.factor(lu, pivot);
+ }
+ Q.stop();
+ if (Q.read() >= min_time)
+ break;
+
+ cycles *= 2;
+ }
+
+ validateLU(N, R, lu, A, pivot);
+
+ return LU.num_flops(N) * cycles / Q.read() * 1.0e-6;
+ }
+
+ private static double[] NewVectorCopy(double[] x)
+ {
+ int N = x.Length;
+
+ double[] y = new double[N];
+ for (int i = 0; i < N; i++)
+ y[i] = x[i];
+
+ return y;
+ }
+
+ private static void CopyVector(double[] B, double[] A)
+ {
+ int N = A.Length;
+
+ for (int i = 0; i < N; i++)
+ B[i] = A[i];
+ }
+
+ private static double normabs(double[] x, double[] y)
+ {
+ int N = x.Length;
+ double sum = 0.0;
+
+ for (int i = 0; i < N; i++)
+ sum += System.Math.Abs(x[i] - y[i]);
+
+ return sum;
+ }
+
+ private static void CopyMatrix(double[][] B, double[][] A)
+ {
+ int M = A.Length;
+ int N = A[0].Length;
+
+ int remainder = N & 3; // N mod 4;
+
+ for (int i = 0; i < M; i++)
+ {
+ double[] Bi = B[i];
+ double[] Ai = A[i];
+ for (int j = 0; j < remainder; j++)
+ Bi[j] = Ai[j];
+ for (int j = remainder; j < N; j += 4)
+ {
+ Bi[j] = Ai[j];
+ Bi[j + 1] = Ai[j + 1];
+ Bi[j + 2] = Ai[j + 2];
+ Bi[j + 3] = Ai[j + 3];
+ }
+ }
+ }
+
+ private static double[][] RandomMatrix(int M, int N, Random R)
+ {
+ double[][] A = new double[M][];
+ for (int i = 0; i < M; i++)
+ {
+ A[i] = new double[N];
+ }
+
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < N; j++)
+ A[i][j] = R.nextDouble();
+ return A;
+ }
+
+ private static double[] RandomVector(int N, Random R)
+ {
+ double[] A = new double[N];
+
+ for (int i = 0; i < N; i++)
+ A[i] = R.nextDouble();
+ return A;
+ }
+
+ private static double[] matvec(double[][] A, double[] x)
+ {
+ int N = x.Length;
+ double[] y = new double[N];
+
+ matvec(A, x, y);
+
+ return y;
+ }
+
+ private static void matvec(double[][] A, double[] x, double[] y)
+ {
+ int M = A.Length;
+ int N = A[0].Length;
+
+ for (int i = 0; i < M; i++)
+ {
+ double sum = 0.0;
+ double[] Ai = A[i];
+ for (int j = 0; j < N; j++)
+ sum += Ai[j] * x[j];
+
+ y[i] = sum;
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.cs b/tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.cs
new file mode 100644
index 0000000000..b0ed00d40b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.cs
@@ -0,0 +1,201 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Json;
+using System.Text;
+using Newtonsoft.Json.Bson;
+using Microsoft.Xunit.Performance;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class JsonBenchmarks
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+ public const int JsonNetIterations = 1;
+#else
+ public const int Iterations = 30000;
+ public const int JsonNetIterations = 90000;
+#endif
+
+ const string DataContractXml = @"<JsonBenchmarks.TestObject xmlns=""http://schemas.datacontract.org/2004/07/"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""><Id>33</Id><Name>SqMtx</Name><Results xmlns:a=""http://schemas.microsoft.com/2003/10/Serialization/Arrays""><a:double>101.3</a:double><a:double>99.8</a:double><a:double>99.6</a:double><a:double>100.4</a:double></Results><WhenRun>2015-01-01T00:00:00-08:00</WhenRun></JsonBenchmarks.TestObject>";
+
+ const string DataContractJson = @"{""Id"":33,""Name"":""SqMtx"",""Results"":[101.3,99.8,99.6,100.4],""WhenRun"":""\/Date(1420099200000-0800)\/""}";
+
+ const string JsonNetJson = @"{""Id"":33,""Name"":""SqMtx"",""Results"":[101.3,99.8,99.6,100.4],""WhenRun"":""2015-01-01T00:00:00-08:00""}";
+
+ byte[] JsonNetBinary = new byte[] { 0x68, 0x00, 0x00, 0x00, 0x10, 0x49, 0x64, 0x00, 0x21, 0x00, 0x00, 0x00, 0x02, 0x4E, 0x61, 0x6D, 0x65, 0x00, 0x06, 0x00, 0x00, 0x00, 0x53, 0x71, 0x4D, 0x74, 0x78, 0x00, 0x04, 0x52, 0x65, 0x73, 0x75, 0x6C, 0x74, 0x73, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x30, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x53, 0x59, 0x40, 0x01, 0x31, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0xF3, 0x58, 0x40, 0x01, 0x32, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x58, 0x40, 0x01, 0x33, 0x00, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x19, 0x59, 0x40, 0x00, 0x09, 0x57, 0x68, 0x65, 0x6E, 0x52, 0x75, 0x6E, 0x00, 0x00, 0x24, 0x82, 0xA4, 0x4A, 0x01, 0x00, 0x00, 0x00 };
+
+ static volatile object VolatileObject;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Escape(object obj) {
+ VolatileObject = obj;
+ }
+
+ [DataContract]
+ public class TestObject
+ {
+ [DataMember]
+ public int Id { get; set; }
+
+ [DataMember]
+ public string Name { get; set; }
+
+ [DataMember]
+ public double[] Results { get; set; }
+
+ [DataMember]
+ public DateTime WhenRun { get; set; }
+
+ public static TestObject Expected()
+ {
+ TestObject t = new TestObject();
+ t.Id = 33;
+ t.Name = "SqMtx";
+ t.Results = new double[] { 101.3, 99.8, 99.6, 100.4 };
+ t.WhenRun = DateTime.Parse("Jan 1, 2015 8:00 GMT");
+ return t;
+ }
+ }
+
+ private bool Deserialize()
+ {
+ bool result = true;
+ DeserializeObject();
+ return result;
+ }
+
+ private void DeserializeObject()
+ {
+ DeserializeDataContractBench();
+ DeserializeDataContractJsonBench();
+ DeserializeJsonNetBinaryBench();
+ DeserializeJsonNetBench();
+ }
+
+ [Benchmark]
+ private void DeserializeDataContract()
+ {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ DeserializeDataContractBench();
+ }
+ }
+ }
+
+ private void DeserializeDataContractBench() {
+ DataContractSerializer ds = new DataContractSerializer(typeof(TestObject));
+ MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(DataContractXml));
+ DeserializeDataContractBenchInner(ds, ms);
+ }
+
+ private void DeserializeDataContractBenchInner(DataContractSerializer ds, MemoryStream ms)
+ {
+ TestObject t;
+ for (int i = 0; i < Iterations; i++)
+ {
+ t = (TestObject)ds.ReadObject(ms);
+ Escape(t.Name);
+ ms.Seek(0, SeekOrigin.Begin);
+ }
+ }
+
+ [Benchmark]
+ private void DeserializeDataContractJson()
+ {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ DeserializeDataContractJsonBench();
+ }
+ }
+ }
+
+ private void DeserializeDataContractJsonBench()
+ {
+ DataContractJsonSerializer ds = new DataContractJsonSerializer(typeof(TestObject));
+ MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(DataContractJson));
+ DeserializeDataContractJsonBenchInner(ds, ms);
+ }
+
+ private void DeserializeDataContractJsonBenchInner(DataContractJsonSerializer ds, MemoryStream ms)
+ {
+ TestObject t;
+ for (int i = 0; i < Iterations; i++)
+ {
+ t = (TestObject) ds.ReadObject(ms);
+ Escape(t.Name);
+ ms.Seek(0, SeekOrigin.Begin);
+ }
+ }
+
+ [Benchmark]
+ private void DeserializeJsonNetBinary()
+ {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ DeserializeJsonNetBinaryBench();
+ }
+ }
+ }
+
+ private void DeserializeJsonNetBinaryBench()
+ {
+ DeserializeJsonNetBinaryBenchInner();
+ }
+
+ private void DeserializeJsonNetBinaryBenchInner()
+ {
+ Newtonsoft.Json.JsonSerializer ds = new Newtonsoft.Json.JsonSerializer();
+ TestObject t;
+ Type ty = typeof(TestObject);
+ for (int i = 0; i < JsonNetIterations; i++)
+ {
+ BsonReader br = new BsonReader(new MemoryStream(JsonNetBinary));
+ t = (TestObject) ds.Deserialize(br, ty);
+ Escape(t.Name);
+ }
+ }
+
+ [Benchmark]
+ private void DeserializeJsonNet()
+ {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ DeserializeJsonNetBench();
+ }
+ }
+ }
+
+ private void DeserializeJsonNetBench()
+ {
+ DeserializeJsonNetBenchInner();
+ }
+
+ private void DeserializeJsonNetBenchInner()
+ {
+ Newtonsoft.Json.JsonSerializer ds = new Newtonsoft.Json.JsonSerializer();
+ TestObject t;
+ Type ty = typeof(TestObject);
+ for (int i = 0; i < JsonNetIterations; i++)
+ {
+ StringReader sr = new StringReader(JsonNetJson);
+ t = (TestObject)ds.Deserialize(sr, ty);
+ Escape(t.Name);
+ }
+ }
+
+ public static int Main() {
+ var tests = new JsonBenchmarks();
+ bool result = tests.Deserialize();
+ return result ? 100 : -1;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.csproj b/tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.csproj
new file mode 100644
index 0000000000..8f95407729
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Serialization/Deserialize.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Deserialize.cs" />
+ </ItemGroup>
+ <PropertyGroup>
+ <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark+serialize\project.json</ProjectJson>
+ <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark+serialize\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/Serialization/Serialize.cs b/tests/src/JIT/Performance/CodeQuality/Serialization/Serialize.cs
new file mode 100644
index 0000000000..905cf56584
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Serialization/Serialize.cs
@@ -0,0 +1,188 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Json;
+using Newtonsoft.Json.Bson;
+using Microsoft.Xunit.Performance;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+public class JsonBenchmarks
+{
+
+#if DEBUG
+ public const int Iterations = 1;
+#else
+ public const int Iterations = 75000;
+#endif
+
+ static volatile object VolatileObject;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Escape(object obj) {
+ VolatileObject = obj;
+ }
+
+ [DataContract]
+ public class TestObject
+ {
+ [DataMember]
+ public int Id { get; set; }
+
+ [DataMember]
+ public string Name { get; set; }
+
+ [DataMember]
+ public double[] Results { get; set; }
+
+ [DataMember]
+ public DateTime WhenRun { get; set; }
+
+ public static TestObject New()
+ {
+ TestObject t = new TestObject();
+ t.Id = 33;
+ t.Name = "SqMtx";
+ t.Results = new double[] { 101.3, 99.8, 99.6, 100.4 };
+ t.WhenRun = DateTime.Parse("Jan 1, 2015 8:00 GMT");
+ return t;
+ }
+ }
+
+ private bool Serialize()
+ {
+ bool result = true;
+ SerializeObject();
+ return result;
+ }
+
+ private void SerializeObject()
+ {
+ SerializeDataContractBench();
+ SerializeDataContractJsonBench();
+ SerializeJsonNetBinaryBench();
+ SerializeJsonNetBench();
+ }
+
+ [Benchmark]
+ private void SerializeDataContract()
+ {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ SerializeDataContractBench();
+ }
+ }
+ }
+
+ private void SerializeDataContractBench() {
+ TestObject t = TestObject.New();
+ MemoryStream ms = new MemoryStream();
+ SerializeDataContractBenchInner(t, ms);
+ }
+
+ private void SerializeDataContractBenchInner(object o, MemoryStream ms)
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ var s = new DataContractSerializer(o.GetType());
+ s.WriteObject(ms, o);
+ Escape(ms);
+ ms.Flush();
+ }
+ }
+
+ [Benchmark]
+ private void SerializeDataContractJson()
+ {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ SerializeDataContractJsonBench();
+ }
+ }
+ }
+
+ private void SerializeDataContractJsonBench()
+ {
+ TestObject t = TestObject.New();
+ MemoryStream ms = new MemoryStream();
+ SerializeDataContractJsonBenchInner(t, ms);
+ }
+
+ private void SerializeDataContractJsonBenchInner(object o, MemoryStream ms)
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ var s = new DataContractJsonSerializer(o.GetType());
+ s.WriteObject(ms, o);
+ Escape(ms);
+ ms.Flush();
+ }
+ }
+
+ [Benchmark]
+ private void SerializeJsonNetBinary()
+ {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ SerializeJsonNetBinaryBench();
+ }
+ }
+ }
+
+ private void SerializeJsonNetBinaryBench()
+ {
+ TestObject t = TestObject.New();
+ MemoryStream ms = new MemoryStream();
+ SerializeJsonNetBinaryBenchInner(t, ms);
+ }
+
+ private void SerializeJsonNetBinaryBenchInner(object o, MemoryStream ms)
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ var s = new Newtonsoft.Json.JsonSerializer();
+ var w = new BsonWriter(ms);
+ s.Serialize(w, o);
+ Escape(w);
+ w.Flush();
+ }
+ }
+
+ [Benchmark]
+ private void SerializeJsonNet()
+ {
+ foreach (var iteration in Benchmark.Iterations) {
+ using (iteration.StartMeasurement()) {
+ SerializeJsonNetBench();
+ }
+ }
+ }
+
+ private void SerializeJsonNetBench()
+ {
+ TestObject t = TestObject.New();
+ SerializeJsonNetBenchInner(t);
+ }
+
+ private void SerializeJsonNetBenchInner(object o)
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ var s = Newtonsoft.Json.JsonConvert.SerializeObject(o);
+ Escape(s);
+ }
+ }
+
+ public static int Main() {
+ var tests = new JsonBenchmarks();
+ bool result = tests.Serialize();
+ return result ? 100 : -1;
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/Serialization/Serialize.csproj b/tests/src/JIT/Performance/CodeQuality/Serialization/Serialize.csproj
new file mode 100644
index 0000000000..60df05075b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/Serialization/Serialize.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Serialize.cs" />
+ </ItemGroup>
+ <PropertyGroup>
+ <ProjectJson>$(JitPackagesConfigFileDirectory)benchmark+serialize\project.json</ProjectJson>
+ <ProjectLockJson>$(JitPackagesConfigFileDirectory)benchmark+serialize\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/V8/Crypto/Crypto.cs b/tests/src/JIT/Performance/CodeQuality/V8/Crypto/Crypto.cs
new file mode 100644
index 0000000000..23eab8db5b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/V8/Crypto/Crypto.cs
@@ -0,0 +1,2111 @@
+// 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.
+/*
+ * Copyright (c) 2003-2005 Tom Wu
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following condition applies:
+ *
+ * All redistributions must retain an intact copy of this copyright notice
+ * and disclaimer.
+ */
+
+// Comment this out to use a fixed random number seed.
+
+// #define USE_RANDOM_SEED
+
+// The code has been adapted for use as a benchmark by Microsoft.
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+namespace Crypto
+{
+ public class Support
+ {
+ private const string INPUT = "The quick brown fox jumped over the extremely lazy frogs!";
+
+ public static int Main(String[] args)
+ {
+ int n = 1;
+
+ if (args.Length > 0)
+ {
+ n = Int32.Parse(args[0]);
+ }
+
+ bool verbose = false;
+
+ if (args.Length > 1)
+ {
+ switch (args[1])
+ {
+ case "verbose":
+ verbose = true;
+ break;
+ default:
+ Console.WriteLine("Bad arg: '{0}'.\n", args[1]);
+ return -1;
+ }
+ }
+
+ Measure(n, verbose);
+
+ bool result = s_TEXT.Equals(INPUT);
+
+ return (result ? 100 : -1);
+ }
+
+ [Benchmark]
+ public static void Bench()
+ {
+ const int Iterations = 10;
+ const int n = 8;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ Measure(n, false);
+ }
+ }
+ }
+ }
+
+ public static void Measure(int n, bool verbose)
+ {
+ DateTime start = DateTime.Now;
+ Setup();
+ for (int i = 0; i < n; i++)
+ {
+ runEncrypt(verbose);
+ runDecrypt(verbose);
+ }
+ DateTime end = DateTime.Now;
+ TimeSpan dur = end - start;
+ if (verbose)
+ {
+ Console.WriteLine("Doing {0} iters of Crytpo takes {1} ms; {2} usec/iter.",
+ n, dur.TotalMilliseconds, dur.TotalMilliseconds * 1000 / n);
+ }
+ }
+
+ private static RSAKey s_RSA;
+ private static String s_TEXT;
+
+ private static void Setup()
+ {
+ String nValue = "a5261939975948bb7a58dffe5ff54e65f0498f9175f5a09288810b8975871e99af3b5dd94057b0fc07535f5f97444504fa35169d461d0d30cf0192e307727c065168c788771c561a9400fb49175e9e6aa4e23fe11af69e9412dd23b0cb6684c4c2429bce139e848ab26d0829073351f4acd36074eafd036a5eb83359d2a698d3";
+ String eValue = "10001";
+ String dValue = "8e9912f6d3645894e8d38cb58c0db81ff516cf4c7e5a14c7f1eddb1459d2cded4d8d293fc97aee6aefb861859c8b6a3d1dfe710463e1f9ddc72048c09751971c4a580aa51eb523357a3cc48d31cfad1d4a165066ed92d4748fb6571211da5cb14bc11b6e2df7c1a559e6d5ac1cd5c94703a22891464fba23d0d965086277a161";
+ String pValue = "d090ce58a92c75233a6486cb0a9209bf3583b64f540c76f5294bb97d285eed33aec220bde14b2417951178ac152ceab6da7090905b478195498b352048f15e7d";
+ String qValue = "cab575dc652bb66df15a0359609d51d1db184750c00c6698b90ef3465c99655103edbf0d54c56aec0ce3c4d22592338092a126a0cc49f65a4a30d222b411e58f";
+ String dmp1Value = "1a24bca8e273df2f0e47c199bbf678604e7df7215480c77c8db39f49b000ce2cf7500038acfff5433b7d582a01f1826e6f4d42e1c57f5e1fef7b12aabc59fd25";
+ String dmq1Value = "3d06982efbbe47339e1f6d36b1216b8a741d410b0c662f54f7118b27b9a4ec9d914337eb39841d8666f3034408cf94f5b62f11c402fc994fe15a05493150d9fd";
+ String coeffValue = "3a3e731acd8960b7ff9eb81a7ff93bd1cfa74cbd56987db58b4594fb09c09084db1734c8143f98b602b981aaa9243ca28deb69b5b280ee8dcee0fd2625e53250";
+
+ BigInteger.setupEngine(new BigInteger.AMSig(BigInteger.am3), 28);
+
+ s_RSA = new RSAKey();
+ s_RSA.setPublic(nValue, eValue);
+ s_RSA.setPrivateEx(nValue, eValue, dValue, pValue, qValue, dmp1Value, dmq1Value, coeffValue);
+
+ s_TEXT = INPUT;
+ }
+
+ public static void runEncrypt(bool verbose)
+ {
+ var res = s_RSA.encrypt(s_TEXT);
+ if (verbose) Console.WriteLine("encrypt '{0}' is '{1}'", s_TEXT, res);
+ s_TEXT = res;
+ }
+ public static void runDecrypt(bool verbose)
+ {
+ var res = s_RSA.decrypt(s_TEXT);
+ if (verbose) Console.WriteLine("decrypt '{0}' is '{1}'", s_TEXT, res);
+ s_TEXT = res;
+ }
+ }
+
+ internal class ListX<T> : List<T>
+ {
+ public ListX() : base() { }
+ public ListX(int cap) : base(cap) { }
+
+ public new T this[int index]
+ {
+ get { return base[index]; }
+ set
+ {
+ if (index < Count)
+ {
+ base[index] = value;
+ }
+ else
+ {
+ for (int j = Count; j < index; j++)
+ {
+ base.Add(default(T));
+ }
+ base.Add(value);
+ }
+ }
+ }
+ }
+
+ // Basic JavaScript BN library - subset useful for RSA encryption.
+
+ internal class BigInteger
+ {
+ private ListX<int> _array;
+ private int _t;
+ private int _s;
+
+ // Bits per digit
+ private static int s_dbits;
+ private static int s_BI_DB;
+ private static int s_BI_DM;
+ private static int s_BI_DV;
+
+ private static int s_BI_FP;
+ private static ulong s_BI_FV;
+ private static int s_BI_F1;
+ private static int s_BI_F2;
+
+ // JavaScript engine analysis
+ private const long canary = 0xdeadbeefcafe;
+ private const bool j_lm = ((canary & 0xffffff) == 0xefcafe);
+
+ // (public) Constructor
+ public BigInteger(int a, int b, SecureRandom c)
+ {
+ _array = new ListX<int>();
+ this.fromNumber(a, b, c);
+ }
+
+ public BigInteger()
+ {
+ _array = new ListX<int>();
+ }
+
+ public BigInteger(String a)
+ {
+ _array = new ListX<int>();
+ this.fromString(a, 256);
+ }
+ public BigInteger(byte[] ba)
+ {
+ _array = new ListX<int>();
+ this.fromByteArray(ba);
+ }
+ public BigInteger(String a, int b)
+ {
+ _array = new ListX<int>();
+ this.fromString(a, b);
+ }
+
+ // return new, unset BigInteger
+ private static BigInteger nbi() { return new BigInteger(); }
+
+ public delegate int AMSig(BigInteger bi, int i, int x, BigInteger w, int j, int c, int n);
+
+ private static AMSig s_am;
+
+ // am: Compute w_j += (x*this_i), propagate carries,
+ // c is initial carry, returns final carry.
+ // c < 3*dvalue, x < 2*dvalue, this_i < dvalue
+ // We need to select the fastest one that works in this environment.
+
+ // These appear to be unused
+#if false
+ // am1: use a single mult and divide to get the high bits,
+ // max digit bits should be 26 because
+ // max internal value = 2*dvalue^2-2*dvalue (< 2^53)
+ function am1(i,x,w,j,c,n) {
+ var this_array = this.array;
+ var w_array = w.array;
+ while(--n >= 0) {
+ var v = x*this_array[i++]+w_array[j]+c;
+ c = Math.floor(v/0x4000000);
+ w_array[j++] = v&0x3ffffff;
+ }
+ return c;
+ }
+
+ // am2 avoids a big mult-and-extract completely.
+ // Max digit bits should be <= 30 because we do bitwise ops
+ // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
+ function am2(i,x,w,j,c,n) {
+ var this_array = this.array;
+ var w_array = w.array;
+ var xl = x&0x7fff, xh = x>>15;
+ while(--n >= 0) {
+ var l = this_array[i]&0x7fff;
+ var h = this_array[i++]>>15;
+ var m = xh*l+h*xl;
+ l = xl*l+((m&0x7fff)<<15)+w_array[j]+(c&0x3fffffff);
+ c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
+ w_array[j++] = l&0x3fffffff;
+ }
+ return c;
+ }
+#endif
+
+ // Alternately, set max digit bits to 28 since some
+ // browsers slow down when dealing with 32-bit numbers.
+ public static int am3(BigInteger bi, int i, int x, BigInteger w, int j, int c, int n)
+ {
+ var this_array = bi._array;
+ var w_array = w._array;
+
+ var xl = x & 0x3fff; var xh = x >> 14;
+ while (--n >= 0)
+ {
+ var l = this_array[i] & 0x3fff;
+ var h = this_array[i++] >> 14;
+ var m = xh * l + h * xl;
+ l = xl * l + ((m & 0x3fff) << 14) + w_array[j] + c;
+ c = (l >> 28) + (m >> 14) + xh * h;
+ w_array[j++] = l & 0xfffffff;
+ }
+ return c;
+ }
+
+
+#if false
+ // This is tailored to VMs with 2-bit tagging. It makes sure
+ // that all the computations stay within the 29 bits available.
+ function am4(i,x,w,j,c,n) {
+ var this_array = this.array;
+ var w_array = w.array;
+
+ var xl = x&0x1fff, xh = x>>13;
+ while(--n >= 0) {
+ var l = this_array[i]&0x1fff;
+ var h = this_array[i++]>>13;
+ var m = xh*l+h*xl;
+ l = xl*l+((m&0x1fff)<<13)+w_array[j]+c;
+ c = (l>>26)+(m>>13)+xh*h;
+ w_array[j++] = l&0x3ffffff;
+ }
+ return c;
+ }
+#endif
+
+ // Digit conversions
+ private const String BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
+ private static int[] s_BI_RC;
+
+ // am3/28 is best for SM, Rhino, but am4/26 is best for v8.
+ // Kestrel (Opera 9.5) gets its best result with am4/26.
+ // IE7 does 9% better with am3/28 than with am4/26.
+ // Firefox (SM) gets 10% faster with am3/28 than with am4/26.
+
+
+ public static void setupEngine(AMSig fn, int bits)
+ {
+ BigInteger.s_am = fn;
+ s_dbits = bits;
+
+ s_BI_DB = s_dbits;
+ s_BI_DM = ((((int)1) << (int)s_dbits) - 1);
+ s_BI_DV = (((int)1) << (int)s_dbits);
+
+ s_BI_FP = 52;
+ // The RHS had been Math.Pow(2,BI_FP);
+ s_BI_FV = (((ulong)1) << (int)s_BI_FP);
+ s_BI_F1 = s_BI_FP - s_dbits;
+ s_BI_F2 = 2 * s_dbits - s_BI_FP;
+
+ s_BI_RC = new int[256];
+
+ // char rr = "0".charCodeAt(0);
+ char rr = '0';
+ for (int vv = 0; vv <= 9; ++vv) s_BI_RC[rr++] = vv;
+ // rr = 'a".charCodeAt(0);
+ rr = 'a';
+ for (int vv = 10; vv < 36; ++vv) s_BI_RC[rr++] = vv;
+ // rr = "A".charCodeAt(0);
+ rr = 'A';
+ for (int vv = 10; vv < 36; ++vv) s_BI_RC[rr++] = vv;
+ }
+
+ private static char int2char(int n) { return BI_RM[(int)n]; }
+ private static int intAt(String s, int i)
+ {
+ // int c = (int)BI_RC[s[(int)i]];
+ // return (c==null)?-1:c;
+ if (i > s_BI_RC.Length) return -1;
+ else return (int)s_BI_RC[s[(int)i]];
+ }
+
+ // (protected) copy this to r
+ private void copyTo(BigInteger r)
+ {
+ var this_array = _array;
+ var r_array = r._array;
+
+ for (var i = _t - 1; i >= 0; --i) r_array[i] = this_array[i];
+ r._t = _t;
+ r._s = _s;
+ }
+
+ // (protected) set from integer value x, -DV <= x < DV
+ private void fromInt(int x)
+ {
+ var this_array = _array;
+ _t = 1;
+ _s = (x < 0) ? -1 : 0;
+ if (this_array.Count == 0)
+ {
+ if (x > 0)
+ this_array.Add(x);
+ else if (x < -1)
+ this_array.Add(x + s_BI_DV);
+ else
+ _t = 0;
+ }
+ else
+ {
+ if (x > 0) this_array[0] = (int)x;
+ else if (x < -1) this_array[0] = (int)(x + s_BI_DV);
+ else _t = 0;
+ }
+ }
+
+ // return bigint initialized to value
+ private static BigInteger nbv(int i) { var r = nbi(); r.fromInt(i); return r; }
+
+ // (protected) set from string and radix
+ private void fromString(String s, int b)
+ {
+ var this_array = _array;
+ int k;
+ if (b == 16) k = 4;
+ else if (b == 8) k = 3;
+ else if (b == 256) k = 8; // byte array
+ else if (b == 2) k = 1;
+ else if (b == 32) k = 5;
+ else if (b == 4) k = 2;
+ else { this.fromRadix(s, b); return; }
+ _t = 0;
+ _s = 0;
+ int i = s.Length; bool mi = false; var sh = 0;
+ while (--i >= 0)
+ {
+ int x = (k == 8) ? (s[i] & 0xff) : intAt(s, (int)i);
+ if (x < 0)
+ {
+ if (s[i] == '-') mi = true;
+ continue;
+ }
+ mi = false;
+ if (sh == 0)
+ this_array[_t++] = (int)x;
+ else if (sh + k > s_BI_DB)
+ {
+ this_array[_t - 1] |= ((int)x & ((((int)1) << (s_BI_DB - sh)) - 1)) << sh;
+ this_array[_t++] = ((int)x >> (s_BI_DB - sh));
+ }
+ else
+ this_array[_t - 1] |= ((int)x) << sh;
+ sh += (int)k;
+ if (sh >= s_BI_DB) sh -= s_BI_DB;
+ }
+ if (k == 8 && (s[0] & 0x80) != 0)
+ {
+ _s = -1;
+ if (sh > 0) this_array[_t - 1] |= ((((int)1) << (s_BI_DB - sh)) - 1) << sh;
+ }
+ this.clamp();
+ if (mi) BigInteger.ZERO.subTo(this, this);
+ }
+
+ private void fromByteArray(byte[] ba)
+ {
+ var this_array = _array;
+ _t = 0;
+ _s = 0;
+ int i = ba.Length; bool mi = false; var sh = 0;
+ while (--i >= 0)
+ {
+ int x = ba[i] & 0xff;
+ mi = false;
+ if (sh == 0)
+ this_array[_t++] = (int)x;
+ else if (sh + 8 > s_BI_DB)
+ {
+ this_array[_t - 1] |= ((int)x & ((((int)1) << (s_BI_DB - sh)) - 1)) << sh;
+ this_array[_t++] = ((int)x >> (s_BI_DB - sh));
+ }
+ else
+ this_array[_t - 1] |= ((int)x) << sh;
+ sh += 8;
+ if (sh >= s_BI_DB) sh -= s_BI_DB;
+ }
+ if ((ba[0] & 0x80) != 0)
+ {
+ _s = -1;
+ if (sh > 0) this_array[_t - 1] |= ((((int)1) << (s_BI_DB - sh)) - 1) << sh;
+ }
+ this.clamp();
+ if (mi) BigInteger.ZERO.subTo(this, this);
+ }
+
+ // (protected) clamp off excess high words
+ private void clamp()
+ {
+ var this_array = _array;
+ var c = _s & s_BI_DM;
+ while (_t > 0 && this_array[_t - 1] == c) --_t;
+ }
+
+ // (public) return string representation in given radix
+ public String toString(int b)
+ {
+ var this_array = _array;
+ if (_s < 0) return "-" + this.negate().toString(b);
+ int k;
+ if (b == 16) k = 4;
+ else if (b == 8) k = 3;
+ else if (b == 2) k = 1;
+ else if (b == 32) k = 5;
+ else if (b == 4) k = 2;
+ else return this.toRadix(b);
+ int km = ((int)1 << k) - 1;
+ int d; bool m = false; var r = ""; int i = (int)_t;
+ int p = (s_BI_DB - (i * s_BI_DB) % k);
+ if (i-- > 0)
+ {
+ if (p < s_BI_DB && (d = this_array[i] >> p) > 0) { m = true; r = new String(int2char(d), 1); }
+ while (i >= 0)
+ {
+ if (p < k)
+ {
+ d = (this_array[i] & ((((int)1) << p) - 1)) << (k - p);
+ d |= this_array[--i] >> (p += (int)(s_BI_DB - k));
+ }
+ else
+ {
+ d = (this_array[i] >> (p -= k)) & km;
+ if (p <= 0) { p += (int)s_BI_DB; --i; }
+ }
+ if (d > 0) m = true;
+ if (m) r += int2char(d);
+ }
+ }
+ return m ? r : "0";
+ }
+
+ // (public) -this
+ public BigInteger negate() { var r = nbi(); BigInteger.ZERO.subTo(this, r); return r; }
+
+ // (public) |this|
+ public BigInteger abs() { return (_s < 0) ? this.negate() : this; }
+
+ // (public) return + if this > a, - if this < a, 0 if equal
+ public int compareTo(BigInteger a)
+ {
+ var this_array = _array;
+ var a_array = a._array;
+
+ var r = _s - a._s;
+ if (r != 0) return r;
+ int i = (int)_t;
+ r = i - (int)a._t;
+ if (r != 0) return r;
+ while (--i >= 0) if ((r = (int)(this_array[i] - a_array[i])) != 0) return r;
+ return 0;
+ }
+
+ // returns bit length of the integer x
+ public int nbits(int x)
+ {
+ int r = 1;
+ int t;
+ if ((t = x >> 16) != 0) { x = t; r += 16; }
+ if ((t = x >> 8) != 0) { x = t; r += 8; }
+ if ((t = x >> 4) != 0) { x = t; r += 4; }
+ if ((t = x >> 2) != 0) { x = t; r += 2; }
+ if ((t = x >> 1) != 0) { x = t; r += 1; }
+ return r;
+ }
+
+ // (public) return the number of bits in "this"
+ public int bitLength()
+ {
+ var this_array = _array;
+ if (_t <= 0) return 0;
+ return ((int)s_BI_DB) * (_t - 1) + nbits(this_array[_t - 1] ^ (int)(_s & s_BI_DM));
+ }
+
+ // (protected) r = this << n*DB
+ private void dLShiftTo(int n, BigInteger r)
+ {
+ var this_array = _array;
+ var r_array = r._array;
+ for (int i = (int)_t - 1; i >= 0; --i) r_array[i + n] = this_array[i];
+ for (int i = (int)n - 1; i >= 0; --i) r_array[i] = 0;
+ r._t = _t + (int)n;
+ r._s = _s;
+ }
+
+ // (protected) r = this >> n*DB
+ private void dRShiftTo(int n, BigInteger r)
+ {
+ var this_array = _array;
+ var r_array = r._array;
+ for (var i = n; i < _t; ++i) r_array[i - n] = this_array[i];
+ r._t = (int)Math.Max(_t - n, 0);
+ r._s = _s;
+ }
+
+ // (protected) r = this << n
+ private void lShiftTo(int n, BigInteger r)
+ {
+ var this_array = _array;
+ var r_array = r._array;
+ int bs = (int)(n % s_BI_DB);
+ int cbs = (int)(s_BI_DB - bs);
+ var bm = ((int)1 << cbs) - 1;
+ int ds = n / s_BI_DB; int c = ((int)_s << bs) & s_BI_DM;
+ for (int i = (int)_t - 1; i >= 0; --i)
+ {
+ r_array[i + ds + 1] = (this_array[i] >> cbs) | c;
+ c = (this_array[i] & bm) << bs;
+#if TRACING
+ Console.WriteLine(" i = {0}, this_array[i] = {3}, r_array[i + ds + 1] = {1}; c = {2}.", i, r_array[i + ds + 1], c, this_array[i]);
+#endif
+ }
+ for (int i = (int)ds - 1; i >= 0; --i) r_array[i] = 0;
+ r_array[ds] = c;
+ r._t = _t + (int)ds + 1;
+ r._s = _s;
+ r.clamp();
+ }
+
+ // (protected) r = this >> n
+ private void rShiftTo(int n, BigInteger r)
+ {
+ var this_array = _array;
+ var r_array = r._array;
+ r._s = _s;
+ var ds = n / s_BI_DB;
+ if (ds >= _t) { r._t = 0; return; }
+ int bs = (int)(n % s_BI_DB);
+ int cbs = (int)(s_BI_DB - bs);
+ int bm = ((int)1 << bs) - 1;
+ r_array[0] = this_array[ds] >> bs;
+ for (int i = ds + 1; i < _t; ++i)
+ {
+ r_array[i - ds - 1] |= (this_array[i] & bm) << cbs;
+ r_array[i - ds] = this_array[i] >> bs;
+ }
+ if (bs > 0) r_array[(int)_t - ds - 1] |= ((int)_s & bm) << cbs;
+ r._t = _t - (int)ds;
+ r.clamp();
+ }
+
+ // (protected) r = this - a
+ private void subTo(BigInteger a, BigInteger r)
+ {
+ var this_array = _array;
+ var r_array = r._array;
+ var a_array = a._array;
+ int i = 0; int c = 0; var m = Math.Min(a._t, _t);
+ while (i < m)
+ {
+ c += (int)this_array[i] - (int)a_array[i];
+ r_array[i++] = (int)c & s_BI_DM;
+ c >>= (int)s_BI_DB;
+ }
+ if (a._t < _t)
+ {
+ c -= a._s;
+ while (i < _t)
+ {
+ c += (int)this_array[i];
+ r_array[i++] = (int)c & s_BI_DM;
+ c >>= (int)s_BI_DB;
+ }
+ c += _s;
+ }
+ else
+ {
+ c += _s;
+ while (i < a._t)
+ {
+ c -= (int)a_array[i];
+ r_array[i++] = (int)c & s_BI_DM;
+ c >>= (int)s_BI_DB;
+ }
+ c -= a._s;
+ }
+ r._s = (c < 0) ? -1 : 0;
+ if (c < -1) r_array[i++] = (int)((int)s_BI_DV + c);
+ else if (c > 0) r_array[i++] = (int)c;
+ r._t = i;
+ r.clamp();
+ }
+
+ // (protected) r = this * a, r != this,a (HAC 14.12)
+ // "this" should be the larger one if appropriate.
+ private void multiplyTo(BigInteger a, BigInteger r)
+ {
+ var this_array = _array;
+ var r_array = r._array;
+ var x = this.abs(); var y = a.abs();
+ var y_array = y._array;
+
+ int i = (int)x._t;
+ r._t = (int)i + y._t;
+ while (--i >= 0) r_array[i] = 0;
+ for (i = 0; i < y._t; ++i) r_array[i + (int)x._t] = s_am(x, 0, y_array[i], r, (int)i, 0, (int)x._t);
+ r._s = 0;
+ r.clamp();
+ if (_s != a._s) BigInteger.ZERO.subTo(r, r);
+ }
+
+ // (protected) r = this^2, r != this (HAC 14.16)
+ private void squareTo(BigInteger r)
+ {
+ var x = this.abs();
+ var x_array = x._array;
+ var r_array = r._array;
+
+ int i = (int)(2 * x._t);
+ r._t = (int)i;
+ while (--i >= 0) r_array[i] = 0;
+ for (i = 0; i < x._t - 1; ++i)
+ {
+ var c = s_am(x, (int)i, x_array[i], r, (int)(2 * i), 0, 1);
+ if ((r_array[(int)i + x._t] += s_am(x, (int)(i + 1), 2 * x_array[i], r, (int)(2 * i + 1), c, (int)x._t - i - 1)) >= s_BI_DV)
+ {
+ r_array[(int)i + x._t] -= s_BI_DV;
+ r_array[(int)i + x._t + 1] = 1;
+ }
+ }
+ if (r._t > 0) r_array[r._t - 1] += s_am(x, (int)i, x_array[i], r, (int)(2 * i), 0, 1);
+ r._s = 0;
+ r.clamp();
+ }
+
+ // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
+ // r != q, this != m. q or r may be null.
+ private void divRemTo(BigInteger m, BigInteger q, BigInteger r)
+ {
+#if TRACING
+ this.PrintArray("this");
+#endif
+ var pm = m.abs();
+ if (pm._t <= 0) return;
+ var pt = this.abs();
+#if TRACING
+ pt.PrintArray("pt");
+#endif
+ if (pt._t < pm._t)
+ {
+ if (q != null) q.fromInt(0);
+ if (r != null) this.copyTo(r);
+ return;
+ }
+ if (r == null) r = nbi();
+ var y = nbi(); var ts = _s; var ms = m._s;
+ var pm_array = pm._array;
+ int nsh = s_BI_DB - (int)nbits(pm_array[pm._t - 1]); // normalize modulus
+ if (nsh > 0) { pm.lShiftTo(nsh, y); pt.lShiftTo(nsh, r); }
+ else { pm.copyTo(y); pt.copyTo(r); }
+ int ys = y._t;
+
+ var y_array = y._array;
+ double y0 = (double)y_array[ys - 1];
+ if (y0 == 0) return;
+ double yt = (y0 * (double)((int)1 << s_BI_F1) + ((ys > 1) ? y_array[ys - 2] >> s_BI_F2 : 0));
+ double d1 = ((double)s_BI_FV) / yt;
+ double d2 = ((double)(1 << s_BI_F1)) / yt;
+ var e = 1 << s_BI_F2;
+ int i = (int)r._t; int j = i - (int)ys; var t = (q == null) ? nbi() : q;
+ y.dLShiftTo(j, t);
+
+#if TRACING
+ Console.WriteLine("y is");
+ for (int kk = 0; kk < y.array.Count; kk++)
+ Console.WriteLine("{0}", y.array[kk]);
+#endif
+
+ var r_array = r._array;
+ if (r.compareTo(t) >= 0)
+ {
+ r_array[r._t++] = 1;
+ r.subTo(t, r);
+ }
+ BigInteger.ONE.dLShiftTo((int)ys, t);
+ t.subTo(y, y); // "negative" y so we can replace sub with am later
+ while (y._t < ys) y_array[y._t++] = 0;
+ while (--j >= 0)
+ {
+ // Estimate quotient digit
+ int qd = (r_array[--i] == y0) ? s_BI_DM :
+ (int)Math.Floor((double)r_array[i] * d1 + ((double)(r_array[i - 1] + e)) * d2);
+ if ((r_array[i] += s_am(y, 0, qd, r, (int)j, 0, (int)ys)) < qd)
+ { // Try it out
+ y.dLShiftTo(j, t);
+ r.subTo(t, r);
+ while (r_array[i] < --qd) r.subTo(t, r);
+ }
+ }
+ if (q != null)
+ {
+ r.dRShiftTo((int)ys, q);
+ if (ts != ms) BigInteger.ZERO.subTo(q, q);
+ }
+ r._t = (int)ys;
+ r.clamp();
+ if (nsh > 0) r.rShiftTo(nsh, r); // Denormalize remainder
+ if (ts < 0) BigInteger.ZERO.subTo(r, r);
+ }
+
+ // (public) this mod a
+ public BigInteger mod(BigInteger a)
+ {
+ var r = nbi();
+ this.abs().divRemTo(a, null, r);
+ if (_s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r, r);
+ return r;
+ }
+
+ // Modular reduction using "classic" algorithm
+ public class ClassicReducer : Reducer
+ {
+ private BigInteger _m;
+
+ public ClassicReducer(BigInteger m) { _m = m; }
+
+ public void reduce(BigInteger x) { x.divRemTo(_m, null, x); }
+
+ public override BigInteger convert(BigInteger x)
+ {
+ if (x._s < 0 || x.compareTo(_m) >= 0) return x.mod(_m);
+ else return x;
+ }
+
+ public override BigInteger revert(BigInteger x) { return x; }
+ public override void mulTo(BigInteger x, BigInteger y, BigInteger r) { x.multiplyTo(y, r); this.reduce(r); }
+ public override void sqrTo(BigInteger x, BigInteger r) { x.squareTo(r); this.reduce(r); }
+ }
+
+ // (protected) return "-1/this % 2^DB"; useful for Mont. reduction
+ // justification:
+ // xy == 1 (mod m)
+ // xy = 1+km
+ // xy(2-xy) = (1+km)(1-km)
+ // x[y(2-xy)] = 1-k^2m^2
+ // x[y(2-xy)] == 1 (mod m^2)
+ // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
+ // should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
+ // JS multiply "overflows" differently from C/C++, so care is needed here.
+ private int invDigit()
+ {
+ var this_array = _array;
+ if (_t < 1) return 0;
+ int x = (int)this_array[0];
+ if ((x & 1) == 0) return 0;
+ int y = x & 3; // y == 1/x mod 2^2
+ y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
+ y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
+ y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
+ // last step - calculate inverse mod DV directly;
+ // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
+ y = (y * (2 - x * y % (int)s_BI_DV)) % (int)s_BI_DV; // y == 1/x mod 2^dbits
+ // we really want the negative inverse, and -DV < y < DV
+ return (y > 0) ? (int)s_BI_DV - y : -y;
+ }
+
+ public abstract class Reducer
+ {
+ abstract public BigInteger convert(BigInteger x);
+ abstract public BigInteger revert(BigInteger x);
+ // DELETEME
+ // abstract public void reduce(BigInteger x);
+ abstract public void sqrTo(BigInteger x, BigInteger r);
+ abstract public void mulTo(BigInteger x, BigInteger y, BigInteger r);
+ };
+
+ private class MontgomeryReducer : Reducer
+ {
+ private BigInteger _m;
+ private int _mp;
+ private int _mpl;
+ private int _mph;
+ private int _um;
+ private int _mt2;
+
+ public MontgomeryReducer(BigInteger m)
+ {
+ _m = m;
+ _mp = m.invDigit();
+ _mpl = _mp & 0x7fff;
+ _mph = _mp >> 15;
+ _um = (1 << (s_BI_DB - 15)) - 1;
+ _mt2 = 2 * m._t;
+ }
+
+ // xR mod m
+ public override BigInteger convert(BigInteger x)
+ {
+ var r = nbi();
+ x.abs().dLShiftTo(_m._t, r);
+ r.divRemTo(_m, null, r);
+ if (x._s < 0 && r.compareTo(BigInteger.ZERO) > 0) _m.subTo(r, r);
+ return r;
+ }
+
+ public override BigInteger revert(BigInteger x)
+ {
+ var r = nbi();
+ x.copyTo(r);
+ this.reduce(r);
+ return r;
+ }
+
+ // x = x/R mod m (HAC 14.32)
+ public void reduce(BigInteger x)
+ {
+ var x_array = x._array;
+ while (x._t <= _mt2) // pad x so am has enough room later
+ x_array[x._t++] = 0;
+ for (var i = 0; i < _m._t; ++i)
+ {
+ // faster way of calculating u0 = x[i]*mp mod DV
+ var j = x_array[i] & 0x7fff;
+ var u0 = (j * _mpl + (((j * _mph + (x_array[i] >> 15) * _mpl) & _um) << 15)) & s_BI_DM;
+ // use am to combine the multiply-shift-add into one call
+ j = i + _m._t;
+ x_array[j] += s_am(_m, 0, u0, x, i, 0, _m._t);
+ // propagate carry
+ while (x_array[j] >= s_BI_DV) { x_array[j] -= s_BI_DV; x_array[++j]++; }
+ }
+ x.clamp();
+ x.dRShiftTo(_m._t, x);
+ if (x.compareTo(_m) >= 0) x.subTo(_m, x);
+ }
+
+ // r = "x^2/R mod m"; x != r
+ public override void sqrTo(BigInteger x, BigInteger r) { x.squareTo(r); this.reduce(r); }
+
+ // r = "xy/R mod m"; x,y != r
+ public override void mulTo(BigInteger x, BigInteger y, BigInteger r)
+ {
+ x.multiplyTo(y, r); this.reduce(r);
+ }
+ }
+
+
+ // (protected) true iff this is even
+ private bool isEven()
+ {
+ var this_array = _array;
+ return ((_t > 0) ? (int)(this_array[0] & 1) : _s) == 0;
+ }
+
+ // (protected) this^e, e < 2^32, doing sqr and mul with "z" (HAC 14.79)
+ private BigInteger exp(uint e, Reducer z)
+ {
+ if (e > 0xffffffff || e < 1) return BigInteger.ONE;
+ var r = nbi(); var r2 = nbi(); var g = z.convert(this); int i = (int)nbits((int)e) - 1;
+ g.copyTo(r);
+ while (--i >= 0)
+ {
+ z.sqrTo(r, r2);
+ if ((e & (1 << i)) > 0) z.mulTo(r2, g, r);
+ else { var t = r; r = r2; r2 = t; }
+ }
+ return z.revert(r);
+ }
+
+ // (public) this^e % m, 0 <= e < 2^32
+ public BigInteger modPowInt(uint e, BigInteger m)
+ {
+ Reducer z;
+ if (e < 256 || m.isEven()) z = new ClassicReducer(m); else z = new MontgomeryReducer(m);
+ return this.exp(e, z);
+ }
+
+ // "constants"
+ public static BigInteger ZERO = nbv(0);
+ public static BigInteger ONE = nbv(1);
+
+ // Copyright (c) 2005 Tom Wu
+ // All Rights Reserved.
+ // See "LICENSE" for details.
+
+ // Extended JavaScript BN functions, required for RSA private ops.
+
+ // (public)
+ public BigInteger clone() { var r = nbi(); this.copyTo(r); return r; }
+
+ // (public) return value as integer
+ public int intValue()
+ {
+ var this_array = _array;
+ if (_s < 0)
+ {
+ if (_t == 1) return (int)this_array[0] - (int)s_BI_DV;
+ else if (_t == 0) return -1;
+ }
+ else if (_t == 1) return (int)this_array[0];
+ else if (_t == 0) return 0;
+ // assumes 16 < DB < 32
+ // return ((this_array[1]&((1<<(32-BI_DB))-1))<<BI_DB)|this_array[0];
+ var x = (this_array[1] & ((1 << (32 - s_BI_DB)) - 1));
+ return (int)((int)(x << s_BI_DB) | this_array[0]);
+ }
+
+ // (public) return value as byte
+ public byte byteValue()
+ {
+ var this_array = _array;
+ return (_t == 0) ? (byte)_s : (byte)((this_array[0] << 24) >> 24);
+ }
+
+ // (public) return value as short (assumes DB>=16)
+ public ushort shortValue()
+ {
+ var this_array = _array;
+ return (_t == 0) ? (ushort)_s : (ushort)((this_array[0] << 16) >> 16);
+ }
+
+ private static double s_LN2 = Math.Log(2.0);
+
+ // (protected) return x s.t. r^x < DV
+ private int chunkSize(int r) { return (int)Math.Floor(s_LN2 * (double)s_BI_DB / Math.Log(r)); }
+
+ // (public) 0 if this == 0, 1 if this > 0
+ public int signum()
+ {
+ var this_array = _array;
+ if (_s < 0) return -1;
+ else if (_t <= 0 || (_t == 1 && this_array[0] <= 0)) return 0;
+ else return 1;
+ }
+
+ private static String s_sdigits = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+ private static String IntToString(int i, int radix)
+ {
+ if (radix == 10)
+ {
+ return i.ToString();
+ }
+ else if (radix == 16)
+ {
+ return i.ToString("X");
+ }
+ else
+ {
+ bool neg = false;
+ if (i < 0)
+ {
+ neg = true; i = -i;
+ }
+ String res = "";
+ while (i != 0)
+ {
+ int digit = i % radix;
+ res = s_sdigits.Substring(digit, 1) + res;
+ i = i / radix;
+ }
+ if (neg) res = "-" + res;
+ return res;
+ }
+ }
+
+ // (protected) convert to radix string
+ public String toRadix(int b)
+ {
+ // if (b == null) b = 10;
+ if (this.signum() == 0 || b < 2 || b > 36) return "0";
+ var cs = this.chunkSize(b);
+ var a = (int)Math.Pow((double)b, (double)cs);
+ Console.WriteLine("a = {0}.", a);
+ var d = nbv(a); var y = nbi(); var z = nbi(); var r = "";
+ Console.WriteLine("d.intValue = {0}.", d.intValue());
+ this.divRemTo(d, y, z);
+ Console.WriteLine("y.signum = {0}", y.signum());
+ Console.WriteLine("z.intValue = " + z.intValue());
+ while (y.signum() > 0)
+ {
+ r = IntToString(a + z.intValue(), (int)b).Substring(1) + r;
+ y.divRemTo(d, y, z);
+ Console.WriteLine("y.signum = {0}", y.signum());
+ Console.WriteLine("z.intValue = " + z.intValue());
+ }
+ return IntToString(z.intValue(), (int)b) + r;
+ }
+
+ private static int IntPow(int n, int p)
+ {
+ int res = 1;
+ for (int k = 1; k < p; k++)
+ {
+ res *= n;
+ }
+ return res;
+ }
+
+ // (protected) convert from radix string
+ private void fromRadix(String s, int b)
+ {
+ this.fromInt(0);
+ var cs = this.chunkSize(b);
+ var d = IntPow(b, cs); bool mi = false; int j = 0; int w = 0;
+ for (int i = 0; i < s.Length; ++i)
+ {
+ int x = intAt(s, i);
+ if (x < 0)
+ {
+ if (s[(int)i] == '-' && this.signum() == 0) mi = true;
+ continue;
+ }
+ w = b * w + (int)x;
+ if (++j >= cs)
+ {
+ this.dMultiply(d);
+ this.dAddOffset(w, 0);
+ j = 0;
+ w = 0;
+ }
+ }
+ if (j > 0)
+ {
+ this.dMultiply(IntPow(b, j));
+ this.dAddOffset(w, 0);
+ }
+ if (mi) BigInteger.ZERO.subTo(this, this);
+ }
+
+ // (protected) alternate constructor
+ private void fromNumber(int a, int b, SecureRandom c)
+ {
+ if (a < 2) this.fromInt(1);
+ else
+ {
+ this.fromNumber(a, c);
+ if (!this.testBit(a - 1)) // force MSB set
+ this.bitwiseTo(BigInteger.ONE.shiftLeft((int)a - 1), op_or, this);
+ if (this.isEven()) this.dAddOffset(1, 0); // force odd
+ while (!this.isProbablePrime(b))
+ {
+ this.dAddOffset(2, 0);
+ if (this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft((int)a - 1), this);
+ }
+ }
+ }
+
+ private void fromNumber(int a, SecureRandom b)
+ {
+ // new BigInteger(int,RNG)
+ byte[] x = new byte[(a >> 3) + 1];
+ int t = (int)a & 7;
+ b.nextBytes(x);
+ if (t > 0)
+ x[0] &= (byte)((1 << (int)t) - 1);
+ else
+ x[0] = 0;
+ this.fromByteArray(x);
+ }
+
+ // (public) convert to bigendian byte array
+ public byte[] toByteArray()
+ {
+ var this_array = _array;
+ int i = (int)_t; var r = new ListX<byte>();
+ r[0] = (byte)_s;
+ int p = (int)s_BI_DB - (i * (int)s_BI_DB) % 8;
+ int d; int k = 0;
+ if (i-- > 0)
+ {
+ if (p < s_BI_DB && (d = this_array[i] >> p) != (_s & s_BI_DM) >> p)
+ r[k++] = (byte)(d | ((int)_s << (int)(s_BI_DB - p)));
+ while (i >= 0)
+ {
+ if (p < 8)
+ {
+ d = (this_array[i] & (((int)1 << p) - 1)) << (8 - p);
+ d |= this_array[--i] >> (p += s_BI_DB - 8);
+ }
+ else
+ {
+ d = (this_array[i] >> (p -= 8)) & 0xff;
+ if (p <= 0) { p += s_BI_DB; --i; }
+ }
+ if ((d & 0x80) != 0) d = (int)((int)d | -256);
+ if (k == 0 && (_s & 0x80) != (d & 0x80)) ++k;
+ if (k > 0 || d != _s) r[k++] = (byte)d;
+ }
+ }
+ return r.ToArray();
+ }
+
+ public bool Equals(BigInteger a) { return (this.compareTo(a) == 0); }
+ public BigInteger min(BigInteger a) { return (this.compareTo(a) < 0) ? this : a; }
+ public BigInteger max(BigInteger a) { return (this.compareTo(a) > 0) ? this : a; }
+
+ // (protected) r = this op a (bitwise)
+ public delegate int BinOpInt(int x1, int x2);
+
+ private void bitwiseTo(BigInteger a, BinOpInt op, BigInteger r)
+ {
+ var this_array = _array;
+ var a_array = a._array;
+ var r_array = r._array;
+ var m = Math.Min(a._t, _t);
+ for (int i = 0; i < m; ++i) r_array[i] = op(this_array[i], a_array[i]);
+ int f;
+ if (a._t < _t)
+ {
+ f = (int)a._s & s_BI_DM;
+ for (int i = m; i < _t; ++i) r_array[i] = op(this_array[i], f);
+ r._t = _t;
+ }
+ else
+ {
+ f = (int)_s & s_BI_DM;
+ for (int i = m; i < a._t; ++i) r_array[i] = op(f, a_array[i]);
+ r._t = a._t;
+ }
+ r._s = (int)op((int)_s, (int)a._s);
+ r.clamp();
+ }
+
+ // (public) this & a
+ private static int op_and(int x, int y) { return x & y; }
+ public BigInteger and(BigInteger a) { var r = nbi(); this.bitwiseTo(a, op_and, r); return r; }
+
+ // (public) this | a
+ private static int op_or(int x, int y) { return x | y; }
+ public BigInteger or(BigInteger a) { var r = nbi(); this.bitwiseTo(a, op_or, r); return r; }
+
+ // (public) this ^ a
+ private static int op_xor(int x, int y) { return x ^ y; }
+ public BigInteger xor(BigInteger a) { var r = nbi(); this.bitwiseTo(a, op_xor, r); return r; }
+
+ // (public) this & ~a
+ private static int op_andnot(int x, int y) { return x & ~y; }
+ public BigInteger andNot(BigInteger a) { var r = nbi(); this.bitwiseTo(a, op_andnot, r); return r; }
+
+ // (public) ~this
+ public BigInteger not()
+ {
+ var this_array = _array;
+ var r = nbi();
+ var r_array = r._array;
+
+ for (var i = 0; i < _t; ++i) r_array[i] = s_BI_DM & ~this_array[i];
+ r._t = _t;
+ r._s = ~_s;
+ return r;
+ }
+
+ // (public) this << n
+ public BigInteger shiftLeft(int n)
+ {
+ var r = nbi();
+ if (n < 0) this.rShiftTo(-n, r); else this.lShiftTo(n, r);
+ return r;
+ }
+
+ // (public) this >> n
+ public BigInteger shiftRight(int n)
+ {
+ var r = nbi();
+ if (n < 0) this.lShiftTo(-n, r); else this.rShiftTo(n, r);
+ return r;
+ }
+
+ // return index of lowest 1-bit in x, x < 2^31 (-1 for no set bits)
+ public static int lbit(int x)
+ {
+ if (x == 0) return -1;
+ int r = 0;
+ if ((x & 0xffff) == 0) { x >>= 16; r += 16; }
+ if ((x & 0xff) == 0) { x >>= 8; r += 8; }
+ if ((x & 0xf) == 0) { x >>= 4; r += 4; }
+ if ((x & 3) == 0) { x >>= 2; r += 2; }
+ if ((x & 1) == 0) ++r;
+ return r;
+ }
+
+ // (public) returns index of lowest 1-bit (or -1 if none)
+ public int getLowestSetBit()
+ {
+ var this_array = _array;
+ for (var i = 0; i < _t; ++i)
+ if (this_array[i] != 0) return i * s_BI_DB + lbit(this_array[i]);
+ if (_s < 0) return (int)_t * s_BI_DB;
+ return -1;
+ }
+
+ // return number of 1 bits in x
+ private static int cbit(int x)
+ {
+ int r = 0;
+ while (x != 0) { x &= x - 1; ++r; }
+ return r;
+ }
+
+ // (public) return number of set bits
+ public int bitCount()
+ {
+ int r = 0;
+ int x = (int)_s & s_BI_DM;
+ for (int i = 0; i < _t; ++i) r += cbit(_array[i] ^ x);
+ return r;
+ }
+
+ // (public) true iff nth bit is set
+ public bool testBit(int n)
+ {
+ var this_array = _array;
+ int j = n / (int)s_BI_DB;
+ if (j >= _t) return (_s != 0);
+ return ((this_array[j] & ((int)1 << (int)(n % s_BI_DB))) != 0);
+ }
+
+ // (protected) this op (1<<n)
+ private BigInteger changeBit(int n, BinOpInt op)
+ {
+ var r = ONE.shiftLeft((int)n);
+ this.bitwiseTo(r, op, r);
+ return r;
+ }
+
+ // (public) this | (1<<n)
+ public BigInteger setBit(int n) { return this.changeBit(n, op_or); }
+
+ // (public) this & ~(1<<n)
+ public BigInteger clearBit(int n) { return this.changeBit(n, op_andnot); }
+
+ // (public) this ^ (1<<n)
+ public BigInteger flipBit(int n) { return this.changeBit(n, op_xor); }
+
+ // (protected) r = this + a
+ private void addTo(BigInteger a, BigInteger r)
+ {
+ var this_array = _array;
+ var a_array = a._array;
+ var r_array = r._array;
+ int i = 0; int c = 0; int m = Math.Min(a._t, _t);
+ while (i < m)
+ {
+ c += this_array[i] + a_array[i];
+ r_array[i++] = c & s_BI_DM;
+ c >>= s_BI_DB;
+ }
+ if (a._t < _t)
+ {
+ c += (int)a._s;
+ while (i < _t)
+ {
+ c += this_array[i];
+ r_array[i++] = c & s_BI_DM;
+ c >>= s_BI_DB;
+ }
+ c += (int)_s;
+ }
+ else
+ {
+ c += (int)_s;
+ while (i < a._t)
+ {
+ c += a_array[i];
+ r_array[i++] = c & s_BI_DM;
+ c >>= s_BI_DB;
+ }
+ c += (int)a._s;
+ }
+ r._s = (c < 0) ? -1 : 0;
+ if (c > 0) r_array[i++] = c;
+ else if (c < -1) r_array[i++] = s_BI_DV + c;
+ r._t = i;
+ r.clamp();
+ }
+
+ // (public) this + a
+ public BigInteger add(BigInteger a) { var r = nbi(); this.addTo(a, r); return r; }
+
+ // (public) this - a
+ public BigInteger subtract(BigInteger a) { var r = nbi(); this.subTo(a, r); return r; }
+
+ // (public) this * a
+ public BigInteger multiply(BigInteger a) { var r = nbi(); this.multiplyTo(a, r); return r; }
+
+ // (public) this / a
+ public BigInteger divide(BigInteger a) { var r = nbi(); this.divRemTo(a, r, null); return r; }
+
+ // (public) this % a
+ public BigInteger remainder(BigInteger a) { var r = nbi(); this.divRemTo(a, null, r); return r; }
+
+ public struct BigIntPair
+ {
+ public BigInteger p1;
+ public BigInteger p2;
+ public BigIntPair(BigInteger p1, BigInteger p2) { this.p1 = p1; this.p2 = p2; }
+ }
+ // (public) [this/a,this%a]
+ public BigIntPair divideAndRemainder(BigInteger a)
+ {
+ var q = nbi(); var r = nbi();
+ this.divRemTo(a, q, r);
+ return new BigIntPair(q, r);
+ }
+
+ // (protected) this *= n, this >= 0, 1 < n < DV
+ private void dMultiply(int n)
+ {
+ var this_array = _array;
+ this_array[_t] = s_am(this, 0, n - 1, this, 0, 0, _t);
+ ++_t;
+ this.clamp();
+ }
+
+ // (protected) this += n << w words, this >= 0
+ private void dAddOffset(int n, int w)
+ {
+ var this_array = _array;
+ while (_t <= w) this_array[_t++] = 0;
+ this_array[w] += n;
+ while (this_array[w] >= s_BI_DV)
+ {
+ this_array[w] -= s_BI_DV;
+ if (++w >= _t) this_array[_t++] = 0;
+ ++this_array[w];
+ }
+ }
+
+ private class NullReducer : Reducer
+ {
+ public NullReducer() { }
+
+
+ public override BigInteger convert(BigInteger x) { return x; }
+ public override BigInteger revert(BigInteger x) { return x; }
+ public override void mulTo(BigInteger x, BigInteger y, BigInteger r) { x.multiplyTo(y, r); }
+ public override void sqrTo(BigInteger x, BigInteger r) { x.squareTo(r); }
+ }
+
+ // (public) this^e
+ // public BigInteger pow(BigInteger e) { return this.exp(e,new NullReducer()); }
+
+ // (protected) r = lower n words of "this * a", a.t <= n
+ // "this" should be the larger one if appropriate.
+ private void multiplyLowerTo(BigInteger a, int n, BigInteger r)
+ {
+ var r_array = r._array;
+ var a_array = a._array;
+ var i = Math.Min(_t + a._t, n);
+ r._s = 0; // assumes a,this >= 0
+ r._t = i;
+ while (i > 0) r_array[--i] = 0;
+ for (int j = r._t - _t; i < j; ++i) r_array[i + _t] = s_am(this, 0, a_array[i], r, i, 0, _t);
+ for (int j = Math.Min(a._t, n); i < j; ++i) s_am(this, 0, a_array[i], r, i, 0, n - i);
+ r.clamp();
+ }
+
+ // (protected) r = "this * a" without lower n words, n > 0
+ // "this" should be the larger one if appropriate.
+ public void multiplyUpperTo(BigInteger a, int n, BigInteger r)
+ {
+ var r_array = r._array;
+ var a_array = a._array;
+ --n;
+ int i = r._t = _t + a._t - n;
+ r._s = 0; // assumes a,this >= 0
+ while (--i >= 0) r_array[i] = 0;
+ for (i = Math.Max(n - _t, 0); i < a._t; ++i)
+ r_array[_t + i - n] = s_am(this, n - i, a_array[i], r, 0, 0, _t + i - n);
+ r.clamp();
+ r.dRShiftTo(1, r);
+ }
+
+ // Barrett modular reduction
+ public class BarrettReducer : Reducer
+ {
+ private BigInteger _r2;
+ private BigInteger _q3;
+ private BigInteger _mu;
+ private BigInteger _m;
+
+ public BarrettReducer(BigInteger m)
+ {
+ // setup Barrett
+ _r2 = nbi();
+ _q3 = nbi();
+ BigInteger.ONE.dLShiftTo(2 * m._t, _r2);
+ _mu = _r2.divide(m);
+ _m = m;
+ }
+
+ public override BigInteger convert(BigInteger x)
+ {
+ if (x._s < 0 || x._t > 2 * _m._t) return x.mod(_m);
+ else if (x.compareTo(_m) < 0) return x;
+ else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
+ }
+
+ public override BigInteger revert(BigInteger x) { return x; }
+
+ // x = x mod m (HAC 14.42)
+ public void reduce(BigInteger x)
+ {
+ x.dRShiftTo(_m._t - 1, _r2);
+ if (x._t > _m._t + 1) { x._t = _m._t + 1; x.clamp(); }
+ _mu.multiplyUpperTo(_r2, _m._t + 1, _q3);
+ _m.multiplyLowerTo(_q3, _m._t + 1, _r2);
+ while (x.compareTo(_r2) < 0) x.dAddOffset(1, _m._t + 1);
+ x.subTo(_r2, x);
+ while (x.compareTo(_m) >= 0) x.subTo(_m, x);
+ }
+
+ // r = x^2 mod m; x != r
+ public override void sqrTo(BigInteger x, BigInteger r) { x.squareTo(r); this.reduce(r); }
+
+ // r = x*y mod m; x,y != r
+ public override void mulTo(BigInteger x, BigInteger y, BigInteger r) { x.multiplyTo(y, r); this.reduce(r); }
+ }
+
+ // (public) this^e % m (HAC 14.85)
+ public BigInteger modPow(BigInteger e, BigInteger m)
+ {
+ var e_array = e._array;
+ var i = e.bitLength(); int k; BigInteger r = nbv(1); Reducer z;
+ if (i <= 0) return r;
+ else if (i < 18) k = 1;
+ else if (i < 48) k = 3;
+ else if (i < 144) k = 4;
+ else if (i < 768) k = 5;
+ else k = 6;
+ if (i < 8)
+ z = new ClassicReducer(m);
+ else if (m.isEven())
+ z = new BarrettReducer(m);
+ else
+ z = new MontgomeryReducer(m);
+
+ // precomputation
+ var g = new ListX<BigInteger>();
+ int n = 3;
+ int k1 = k - 1;
+ int km = (1 << k) - 1;
+ g[1] = z.convert(this);
+ if (k > 1)
+ {
+ var g2 = nbi();
+ z.sqrTo(g[1], g2);
+ while (n <= km)
+ {
+ g[n] = nbi();
+ z.mulTo(g2, g[n - 2], g[n]);
+ n += 2;
+ }
+ }
+
+ int j = e._t - 1; int w; bool is1 = true; BigInteger r2 = nbi(); BigInteger t;
+ i = nbits(e_array[j]) - 1;
+ while (j >= 0)
+ {
+ if (i >= k1) w = (e_array[j] >> (i - k1)) & km;
+ else
+ {
+ w = (e_array[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
+ if (j > 0) w |= e_array[j - 1] >> (s_BI_DB + i - k1);
+ }
+
+ n = k;
+ while ((w & 1) == 0) { w >>= 1; --n; }
+ if ((i -= n) < 0) { i += s_BI_DB; --j; }
+ if (is1)
+ { // ret == 1, don't bother squaring or multiplying it
+ g[w].copyTo(r);
+ is1 = false;
+ }
+ else
+ {
+ while (n > 1) { z.sqrTo(r, r2); z.sqrTo(r2, r); n -= 2; }
+ if (n > 0) z.sqrTo(r, r2); else { t = r; r = r2; r2 = t; }
+ z.mulTo(r2, g[w], r);
+ }
+
+ while (j >= 0 && (e_array[j] & (1 << i)) == 0)
+ {
+ z.sqrTo(r, r2); t = r; r = r2; r2 = t;
+ if (--i < 0) { i = s_BI_DB - 1; --j; }
+ }
+ }
+ return z.revert(r);
+ }
+
+ // (public) gcd(this,a) (HAC 14.54)
+ public BigInteger gcd(BigInteger a)
+ {
+ var x = (_s < 0) ? this.negate() : this.clone();
+ var y = (a._s < 0) ? a.negate() : a.clone();
+ if (x.compareTo(y) < 0) { var t = x; x = y; y = t; }
+ var i = x.getLowestSetBit(); var g = y.getLowestSetBit();
+ if (g < 0) return x;
+ if (i < g) g = i;
+ if (g > 0)
+ {
+ x.rShiftTo(g, x);
+ y.rShiftTo(g, y);
+ }
+ while (x.signum() > 0)
+ {
+ if ((i = x.getLowestSetBit()) > 0) x.rShiftTo(i, x);
+ if ((i = y.getLowestSetBit()) > 0) y.rShiftTo(i, y);
+ if (x.compareTo(y) >= 0)
+ {
+ x.subTo(y, x);
+ x.rShiftTo(1, x);
+ }
+ else
+ {
+ y.subTo(x, y);
+ y.rShiftTo(1, y);
+ }
+ }
+ if (g > 0) y.lShiftTo(g, y);
+ return y;
+ }
+
+ // (protected) this % n, n < 2^26
+ private int modInt(int n)
+ {
+ var this_array = _array;
+ if (n <= 0) return 0;
+ var d = s_BI_DV % n; int r = (_s < 0) ? n - 1 : 0;
+ if (_t > 0)
+ if (d == 0) r = this_array[0] % n;
+ else for (var i = _t - 1; i >= 0; --i) r = (d * r + this_array[i]) % n;
+ return r;
+ }
+
+ // (public) 1/this % m (HAC 14.61)
+ public BigInteger modInverse(BigInteger m)
+ {
+ var ac = m.isEven();
+ if ((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
+ var u = m.clone(); var v = this.clone();
+ var a = nbv(1); var b = nbv(0); var c = nbv(0); var d = nbv(1);
+ while (u.signum() != 0)
+ {
+ while (u.isEven())
+ {
+ u.rShiftTo(1, u);
+ if (ac)
+ {
+ if (!a.isEven() || !b.isEven()) { a.addTo(this, a); b.subTo(m, b); }
+ a.rShiftTo(1, a);
+ }
+ else if (!b.isEven()) b.subTo(m, b);
+ b.rShiftTo(1, b);
+ }
+ while (v.isEven())
+ {
+ v.rShiftTo(1, v);
+ if (ac)
+ {
+ if (!c.isEven() || !d.isEven()) { c.addTo(this, c); d.subTo(m, d); }
+ c.rShiftTo(1, c);
+ }
+ else if (!d.isEven()) d.subTo(m, d);
+ d.rShiftTo(1, d);
+ }
+ if (u.compareTo(v) >= 0)
+ {
+ u.subTo(v, u);
+ if (ac) a.subTo(c, a);
+ b.subTo(d, b);
+ }
+ else
+ {
+ v.subTo(u, v);
+ if (ac) c.subTo(a, c);
+ d.subTo(b, d);
+ }
+ }
+ if (v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
+ if (d.compareTo(m) >= 0) return d.subtract(m);
+ if (d.signum() < 0) d.addTo(m, d); else return d;
+ if (d.signum() < 0) return d.add(m); else return d;
+ }
+
+ private static int[] s_lowprimes = new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509 };
+ private static int s_lplim = (1 << 26) / s_lowprimes[s_lowprimes.Length - 1];
+
+ // (public) test primality with certainty >= 1-.5^t
+ public bool isProbablePrime(int t)
+ {
+ int i; var x = this.abs();
+ var x_array = x._array;
+ if (x._t == 1 && x_array[0] <= s_lowprimes[s_lowprimes.Length - 1])
+ {
+ for (i = 0; i < s_lowprimes.Length; ++i)
+ if (x_array[0] == s_lowprimes[i]) return true;
+ return false;
+ }
+ if (x.isEven()) return false;
+ i = 1;
+ while (i < s_lowprimes.Length)
+ {
+ var m = s_lowprimes[i]; var j = i + 1;
+ while (j < s_lowprimes.Length && m < s_lplim) m *= s_lowprimes[j++];
+ m = x.modInt(m);
+ while (i < j) if (m % s_lowprimes[i++] == 0) return false;
+ }
+ return x.millerRabin(t);
+ }
+
+ // (protected) true if probably prime (HAC 4.24, Miller-Rabin)
+ private bool millerRabin(int t)
+ {
+ var n1 = this.subtract(BigInteger.ONE);
+ var k = n1.getLowestSetBit();
+ if (k <= 0) return false;
+ var r = n1.shiftRight(k);
+ t = (t + 1) >> 1;
+ if (t > s_lowprimes.Length) t = s_lowprimes.Length;
+ var a = nbi();
+ for (var i = 0; i < t; ++i)
+ {
+ a.fromInt(s_lowprimes[i]);
+ var y = a.modPow(r, this);
+ if (y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0)
+ {
+ var j = 1;
+ while (j++ < k && y.compareTo(n1) != 0)
+ {
+ y = y.modPowInt(2, this);
+ if (y.compareTo(BigInteger.ONE) == 0) return false;
+ }
+ if (y.compareTo(n1) != 0) return false;
+ }
+ }
+ return true;
+ }
+
+ public void PrintArray(String nm)
+ {
+ for (int kk = 0; kk < _array.Count; kk++) Console.WriteLine(" {0}.array[{1}] = {2}", nm, kk, _array[kk]);
+ }
+
+ // BigInteger interfaces not implemented in jsbn:
+
+ // BigInteger(int signum, byte[] magnitude)
+ // double doubleValue()
+ // float floatValue()
+ // int hashCode()
+ // long longValue()
+ // static BigInteger valueOf(long val)
+ // prng4.js - uses Arcfour as a PRNG
+ }
+
+ internal abstract class RNG
+ {
+ abstract public void init(int[] key);
+ abstract public int next();
+ }
+
+ internal class Arcfour : RNG
+ {
+ private int _i;
+ private int _j;
+ private int[] _S;
+
+ public Arcfour()
+ {
+ _i = 0;
+ _j = 0;
+ _S = new int[256];
+ }
+
+ // Initialize arcfour context from key, an array of ints, each from [0..255]
+ public override void init(int[] key)
+ {
+ for (int i = 0; i < 256; ++i)
+ _S[i] = i;
+ int j = 0;
+ for (int i = 0; i < 256; ++i)
+ {
+ j = (j + _S[i] + key[i % key.Length]) & 255;
+ int t = _S[i];
+ _S[i] = _S[j];
+ _S[j] = t;
+ }
+ _i = 0;
+ _j = 0;
+ }
+
+ public override int next()
+ {
+ _i = (_i + 1) & 255;
+ _j = (_j + _S[_i]) & 255;
+ int t = _S[_i];
+ _S[_i] = _S[_j];
+ _S[_j] = t;
+ return _S[(t + _S[_i]) & 255];
+ }
+ }
+
+ internal class SecureRandom
+ {
+ // Pool size must be a multiple of 4 and greater than 32.
+ // An array of bytes the size of the pool will be passed to init()
+ private const int rng_psize = 256;
+
+ // Random number generator - requires a PRNG backend, e.g. prng4.js
+
+ // For best results, put code like
+ // <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
+ // in your main HTML document.
+
+ private RNG _rng_state;
+ private int[] _rng_pool;
+ private int _rng_pptr;
+
+ public SecureRandom()
+ {
+ _rng_pool = new int[rng_psize];
+ _rng_pptr = 0;
+#if USE_RANDOM_SEED
+ Random rnd = new Random();
+#endif
+ while (_rng_pptr < rng_psize)
+ { // extract some randomness from Math.random()
+#if USE_RANDOM_SEED
+ int t = (int)Math.Floor(65536.0 * rnd.NextDouble());
+#else
+ int t = 1000;
+#endif
+ _rng_pool[_rng_pptr++] = (int)((uint)t >> 8);
+ _rng_pool[_rng_pptr++] = t & 255;
+ }
+ _rng_pptr = 0;
+ rng_seed_time();
+ }
+
+ // Mix in a 32-bit integer into the pool
+ private void rng_seed_int(int x)
+ {
+ _rng_pool[_rng_pptr++] ^= x & 255;
+ _rng_pool[_rng_pptr++] ^= (x >> 8) & 255;
+ _rng_pool[_rng_pptr++] ^= (x >> 16) & 255;
+ _rng_pool[_rng_pptr++] ^= (x >> 24) & 255;
+ if (_rng_pptr >= rng_psize) _rng_pptr -= rng_psize;
+ }
+
+ // Mix in the current time (w/milliseconds) into the pool
+ private void rng_seed_time()
+ {
+#if USE_RANDOM_SEED
+ rng_seed_int((int)(new DateTime().Ticks));
+#endif
+ }
+
+
+ // Plug in your RNG constructor here
+ private RNG prng_newstate()
+ {
+ return new Arcfour();
+ }
+
+ private byte rng_get_byte()
+ {
+ if (_rng_state == null)
+ {
+ rng_seed_time();
+ _rng_state = prng_newstate();
+ _rng_state.init(_rng_pool);
+ for (_rng_pptr = 0; _rng_pptr < _rng_pool.Length; ++_rng_pptr)
+ _rng_pool[_rng_pptr] = 0;
+ _rng_pptr = 0;
+ //rng_pool = null;
+ }
+ // TODO: allow reseeding after first request
+ return (byte)_rng_state.next();
+ }
+
+ public void nextBytes(byte[] ba)
+ {
+ for (int i = 0; i < ba.Length; ++i) ba[i] = rng_get_byte();
+ }
+ }
+
+ internal class RSAKey
+ {
+ private BigInteger _n;
+ private int _e;
+ private BigInteger _d;
+ private BigInteger _p;
+ private BigInteger _q;
+ private BigInteger _dmp1;
+ private BigInteger _dmq1;
+ private BigInteger _coeff;
+
+ // "empty" RSA key constructor
+ public RSAKey()
+ {
+ _n = null;
+ _e = 0;
+ _d = null;
+ _p = null;
+ _q = null;
+ _dmp1 = null;
+ _dmq1 = null;
+ _coeff = null;
+ }
+
+ // convert a (hex) string to a bignum object
+ private static BigInteger parseBigInt(String str, int r)
+ {
+ return new BigInteger(str, r);
+ }
+
+ private static String linebrk(String s, int n)
+ {
+ var ret = "";
+ var i = 0;
+ while (i + n < s.Length)
+ {
+ ret += s.Substring(i, i + n) + "\n";
+ i += n;
+ }
+ return ret + s.Substring(i, s.Length);
+ }
+
+ private static String byte2Hex(byte b)
+ {
+ if (b < 0x10)
+ return "0" + b.ToString("X");
+ else
+ return b.ToString("X");
+ }
+
+ // PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
+ private static BigInteger pkcs1pad2(String s, int n)
+ {
+ if (n < s.Length + 11)
+ {
+ throw new ArgumentException("Message too long for RSA");
+ }
+ var ba = new byte[n];
+ var i = s.Length - 1;
+ while (i >= 0 && n > 0) ba[--n] = (byte)s[i--];
+ ba[--n] = 0;
+ var rng = new SecureRandom();
+ byte[] x = new byte[1];
+ while (n > 2)
+ { // random non-zero pad
+ x[0] = 0;
+ while (x[0] == 0) rng.nextBytes(x);
+ ba[--n] = x[0];
+ }
+ ba[--n] = 2;
+ ba[--n] = 0;
+ // for (int k = 0; k < ba.Length; k++) Console.WriteLine("ba[{0}] = {1}", k, (int)ba[k]);
+ return new BigInteger(ba);
+ }
+
+ // Set the public key fields N and e from hex strings
+ public void setPublic(String N, String E)
+ {
+ if (N != null && E != null && N.Length > 0 && E.Length > 0)
+ {
+ _n = parseBigInt(N, 16);
+ _e = Int32.Parse(E, NumberStyles.HexNumber);
+ }
+ else
+ throw new ArgumentException("Invalid RSA public key");
+ }
+
+ // Perform raw public operation on "x": return x^e (mod n)
+ private BigInteger doPublic(BigInteger x)
+ {
+ return x.modPowInt((uint)_e, _n);
+ }
+
+ // Return the PKCS#1 RSA encryption of "text" as an even-length hex string
+ public String encrypt(String text)
+ {
+ var m = pkcs1pad2(text, (_n.bitLength() + 7) >> 3);
+#if TRACING
+ m.PrintArray("m");
+ Console.WriteLine(m.toString(10));
+#endif
+ if (m == null) return null;
+ var c = this.doPublic(m);
+ if (c == null) return null;
+ var h = c.toString(16);
+ if ((h.Length & 1) == 0) return h; else return "0" + h;
+ }
+
+ // Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
+ //function RSAEncryptB64(text) {
+ // var h = this.encrypt(text);
+ // if(h) return hex2b64(h); else return null;
+ //}
+
+ // Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
+ private String pkcs1unpad2(BigInteger d, int n)
+ {
+ var b = d.toByteArray();
+ var i = 0;
+ while (i < b.Length && b[i] == 0) ++i;
+ if (b.Length - i != n - 1 || b[i] != 2)
+ return null;
+ ++i;
+ while (b[i] != 0)
+ if (++i >= b.Length) return null;
+ var ret = "";
+ char[] oneChar = new char[1];
+ while (++i < b.Length)
+ {
+ oneChar[0] = (char)b[i];
+ ret += new String(oneChar);
+ }
+ return ret;
+ }
+
+ // Set the private key fields N, e, and d from hex strings
+ private void setPrivate(String N, String E, String D)
+ {
+ if (N != null && E != null && N.Length > 0 && E.Length > 0)
+ {
+ _n = parseBigInt(N, 16);
+ _e = Int32.Parse(E, NumberStyles.HexNumber);
+ _d = parseBigInt(D, 16);
+ }
+ else
+ throw new ArgumentException("Invalid RSA private key");
+ }
+
+ // Set the private key fields N, e, d and CRT params from hex strings
+ public void setPrivateEx(String N,
+ String E,
+ String D,
+ String P,
+ String Q,
+ String DP,
+ String DQ,
+ String C)
+ {
+ if (N != null && E != null && N.Length > 0 && E.Length > 0)
+ {
+ _n = parseBigInt(N, 16);
+ _e = Int32.Parse(E, NumberStyles.HexNumber);
+ _d = parseBigInt(D, 16);
+ _p = parseBigInt(P, 16);
+ _q = parseBigInt(Q, 16);
+ _dmp1 = parseBigInt(DP, 16);
+ _dmq1 = parseBigInt(DQ, 16);
+ _coeff = parseBigInt(C, 16);
+ }
+ else
+ throw new ArgumentException("Invalid RSA private key");
+ }
+
+ // Generate a new random private key B bits long, using public expt E
+ private void generate(int B, String E)
+ {
+ var rng = new SecureRandom();
+ var qs = B >> 1;
+ _e = Int32.Parse(E, NumberStyles.HexNumber);
+ var ee = new BigInteger(E, 16);
+ for (; ;)
+ {
+ for (; ;)
+ {
+ _p = new BigInteger(B - qs, 1, rng);
+ if (_p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && _p.isProbablePrime(10)) break;
+ }
+ for (; ;)
+ {
+ _q = new BigInteger(qs, 1, rng);
+ if (_q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && _q.isProbablePrime(10)) break;
+ }
+ if (_p.compareTo(_q) <= 0)
+ {
+ var t = _p;
+ _p = _q;
+ _q = t;
+ }
+ var p1 = _p.subtract(BigInteger.ONE);
+ var q1 = _q.subtract(BigInteger.ONE);
+ var phi = p1.multiply(q1);
+ if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0)
+ {
+ _n = _p.multiply(_q);
+ _d = ee.modInverse(phi);
+ _dmp1 = _d.mod(p1);
+ _dmq1 = _d.mod(q1);
+ _coeff = _q.modInverse(_p);
+ break;
+ }
+ }
+ }
+
+ // Perform raw private operation on "x": return x^d (mod n)
+ private BigInteger doPrivate(BigInteger x)
+ {
+ if (_p == null || _q == null)
+ return x.modPow(_d, _n);
+
+ // TODO: re-calculate any missing CRT params
+ var xp = x.mod(_p).modPow(_dmp1, _p);
+ var xq = x.mod(_q).modPow(_dmq1, _q);
+
+ while (xp.compareTo(xq) < 0)
+ xp = xp.add(_p);
+ return xp.subtract(xq).multiply(_coeff).mod(_p).multiply(_q).add(xq);
+ }
+
+ // Return the PKCS#1 RSA decryption of "ctext".
+ // "ctext" is an even-length hex string and the output is a plain string.
+ public String decrypt(String ctext)
+ {
+ var c = parseBigInt(ctext, 16);
+ var m = this.doPrivate(c);
+ if (m == null) return null;
+ return pkcs1unpad2(m, (_n.bitLength() + 7) >> 3);
+ }
+ }
+}
+
diff --git a/tests/src/JIT/Performance/CodeQuality/V8/Crypto/Crypto.csproj b/tests/src/JIT/Performance/CodeQuality/V8/Crypto/Crypto.csproj
new file mode 100644
index 0000000000..112d7b5a9e
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/V8/Crypto/Crypto.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Crypto.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/V8/DeltaBlue/DeltaBlue.cs b/tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.cs
new file mode 100644
index 0000000000..ee14b8b1b1
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.cs
@@ -0,0 +1,1068 @@
+// 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.
+/*
+ This is a Java implemention of the DeltaBlue algorithm described in:
+ "The DeltaBlue Algorithm: An Incremental Constraint Hierarchy Solver"
+ by Bjorn N. Freeman-Benson and John Maloney
+ January 1990 Communications of the ACM,
+ also available as University of Washington TR 89-08-06.
+
+ This implementation by Mario Wolczko, Sun Microsystems, Sep 1996,
+ based on the Smalltalk implementation by John Maloney.
+
+*/
+
+// The code has been adapted for use as a C# benchmark by Microsoft.
+
+#define USE_STACK
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Collections;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+/*
+Strengths are used to measure the relative importance of constraints.
+New strengths may be inserted in the strength hierarchy without
+disrupting current constraints. Strengths cannot be created outside
+this class, so pointer comparison can be used for value comparison.
+*/
+
+internal class Strength
+{
+ private int _strengthValue;
+ private String _name;
+
+ private Strength(int strengthValue, String name)
+ {
+ _strengthValue = strengthValue;
+ _name = name;
+ }
+
+ public static Boolean stronger(Strength s1, Strength s2)
+ {
+ return s1._strengthValue < s2._strengthValue;
+ }
+
+ public static Boolean weaker(Strength s1, Strength s2)
+ {
+ return s1._strengthValue > s2._strengthValue;
+ }
+
+ public static Strength weakestOf(Strength s1, Strength s2)
+ {
+ return weaker(s1, s2) ? s1 : s2;
+ }
+
+ public static Strength strongest(Strength s1, Strength s2)
+ {
+ return stronger(s1, s2) ? s1 : s2;
+ }
+
+ // for iteration
+ public Strength nextWeaker()
+ {
+ switch (_strengthValue)
+ {
+ case 0: return weakest;
+ case 1: return weakDefault;
+ case 2: return normal;
+ case 3: return strongDefault;
+ case 4: return preferred;
+ case 5: return strongPreferred;
+
+ case 6:
+ default:
+ Console.Error.WriteLine("Invalid call to nextStrength()!");
+ //System.exit(1);
+ return null;
+ }
+ }
+
+ // Strength constants
+ public static Strength required = new Strength(0, "required");
+ public static Strength strongPreferred = new Strength(1, "strongPreferred");
+ public static Strength preferred = new Strength(2, "preferred");
+ public static Strength strongDefault = new Strength(3, "strongDefault");
+ public static Strength normal = new Strength(4, "normal");
+ public static Strength weakDefault = new Strength(5, "weakDefault");
+ public static Strength weakest = new Strength(6, "weakest");
+
+ public void print()
+ {
+ Console.Write("strength[" + _strengthValue + "]");
+ }
+}
+
+
+
+
+//------------------------------ variables ------------------------------
+
+// I represent a constrained variable. In addition to my value, I
+// maintain the structure of the constraint graph, the current
+// dataflow graph, and various parameters of interest to the DeltaBlue
+// incremental constraint solver.
+
+internal class Variable
+{
+ public int value; // my value; changed by constraints
+ public ArrayList constraints; // normal constraints that reference me
+ public Constraint determinedBy; // the constraint that currently determines
+ // my value (or null if there isn't one)
+ public int mark; // used by the planner to mark constraints
+ public Strength walkStrength; // my walkabout strength
+ public Boolean stay; // true if I am a planning-time constant
+ public String name; // a symbolic name for reporting purposes
+
+
+ private Variable(String name, int initialValue, Strength walkStrength,
+ int nconstraints)
+ {
+ value = initialValue;
+ constraints = new ArrayList(nconstraints);
+ determinedBy = null;
+ mark = 0;
+ this.walkStrength = walkStrength;
+ stay = true;
+ this.name = name;
+ }
+
+ public Variable(String name, int value) : this(name, value, Strength.weakest, 2)
+ {
+ }
+
+ public Variable(String name) : this(name, 0, Strength.weakest, 2)
+ {
+ }
+
+ public void print()
+ {
+ Console.Write(name + "(");
+ walkStrength.print();
+ Console.Write("," + value + ")");
+ }
+
+ // Add the given constraint to the set of all constraints that refer to me.
+ public void addConstraint(Constraint c)
+ {
+ constraints.Add(c);
+ }
+
+ // Remove all traces of c from this variable.
+ public void removeConstraint(Constraint c)
+ {
+ constraints.Remove(c);
+ if (determinedBy == c) determinedBy = null;
+ }
+
+ // Attempt to assign the given value to me using the given strength.
+ public void setValue(int value, Strength strength)
+ {
+ EditConstraint e = new EditConstraint(this, strength);
+ if (e.isSatisfied())
+ {
+ this.value = value;
+ deltablue.planner.propagateFrom(this);
+ }
+ e.destroyConstraint();
+ }
+}
+
+
+
+
+//------------------------ constraints ------------------------------------
+
+// I am an abstract class representing a system-maintainable
+// relationship (or "constraint") between a set of variables. I supply
+// a strength instance variable; concrete subclasses provide a means
+// of storing the constrained variables and other information required
+// to represent a constraint.
+
+internal abstract class Constraint
+{
+ public Strength strength; // the strength of this constraint
+
+ public Constraint() { } // this has to be here because of
+ // Java's constructor idiocy.
+
+ public Constraint(Strength strength)
+ {
+ this.strength = strength;
+ }
+
+ // Answer true if this constraint is satisfied in the current solution.
+ public abstract Boolean isSatisfied();
+
+ // Record the fact that I am unsatisfied.
+ public abstract void markUnsatisfied();
+
+ // Normal constraints are not input constraints. An input constraint
+ // is one that depends on external state, such as the mouse, the
+ // keyboard, a clock, or some arbitrary piece of imperative code.
+ public virtual Boolean isInput() { return false; }
+
+ // Activate this constraint and attempt to satisfy it.
+ public void addConstraint()
+ {
+ addToGraph();
+ deltablue.planner.incrementalAdd(this);
+ }
+
+ // Deactivate this constraint, remove it from the constraint graph,
+ // possibly causing other constraints to be satisfied, and destroy
+ // it.
+ public void destroyConstraint()
+ {
+ if (isSatisfied()) deltablue.planner.incrementalRemove(this);
+ else
+ removeFromGraph();
+ }
+
+ // Add myself to the constraint graph.
+ public abstract void addToGraph();
+
+ // Remove myself from the constraint graph.
+ public abstract void removeFromGraph();
+
+ // Decide if I can be satisfied and record that decision. The output
+ // of the choosen method must not have the given mark and must have
+ // a walkabout strength less than that of this constraint.
+ public abstract void chooseMethod(int mark);
+
+ // Set the mark of all input from the given mark.
+ public abstract void markInputs(int mark);
+
+ // Assume that I am satisfied. Answer true if all my current inputs
+ // are known. A variable is known if either a) it is 'stay' (i.e. it
+ // is a constant at plan execution time), b) it has the given mark
+ // (indicating that it has been computed by a constraint appearing
+ // earlier in the plan), or c) it is not determined by any
+ // constraint.
+ public abstract Boolean inputsKnown(int mark);
+
+ // Answer my current output variable. Raise an error if I am not
+ // currently satisfied.
+ public abstract Variable output();
+
+ // Attempt to find a way to enforce this constraint. If successful,
+ // record the solution, perhaps modifying the current dataflow
+ // graph. Answer the constraint that this constraint overrides, if
+ // there is one, or nil, if there isn't.
+ // Assume: I am not already satisfied.
+ //
+ public Constraint satisfy(int mark)
+ {
+ chooseMethod(mark);
+ if (!isSatisfied())
+ {
+ if (strength == Strength.required)
+ {
+ deltablue.error("Could not satisfy a required constraint");
+ }
+ return null;
+ }
+ // constraint can be satisfied
+ // mark inputs to allow cycle detection in addPropagate
+ markInputs(mark);
+ Variable outvar = output();
+ Constraint overridden = outvar.determinedBy;
+ if (overridden != null) overridden.markUnsatisfied();
+ outvar.determinedBy = this;
+ if (!deltablue.planner.addPropagate(this, mark))
+ {
+ Console.WriteLine("Cycle encountered");
+ return null;
+ }
+ outvar.mark = mark;
+ return overridden;
+ }
+
+ // Enforce this constraint. Assume that it is satisfied.
+ public abstract void execute();
+
+ // Calculate the walkabout strength, the stay flag, and, if it is
+ // 'stay', the value for the current output of this
+ // constraint. Assume this constraint is satisfied.
+ public abstract void recalculate();
+
+ public abstract void printInputs();
+
+ public void printOutput() { output().print(); }
+
+ public void print()
+ {
+ if (!isSatisfied())
+ {
+ Console.Write("Unsatisfied");
+ }
+ else
+ {
+ Console.Write("Satisfied(");
+ printInputs();
+ Console.Write(" -> ");
+ printOutput();
+ Console.Write(")");
+ }
+ Console.Write("\n");
+ }
+}
+
+
+
+//-------------unary constraints-------------------------------------------
+
+// I am an abstract superclass for constraints having a single
+// possible output variable.
+//
+internal abstract class UnaryConstraint : Constraint
+{
+ public Variable myOutput; // possible output variable
+ public Boolean satisfied; // true if I am currently satisfied
+
+ public UnaryConstraint(Variable v, Strength strength) : base(strength)
+
+ {
+ myOutput = v;
+ satisfied = false;
+ addConstraint();
+ }
+
+ // Answer true if this constraint is satisfied in the current solution.
+ public override Boolean isSatisfied() { return satisfied; }
+
+ // Record the fact that I am unsatisfied.
+ public override void markUnsatisfied() { satisfied = false; }
+
+ // Answer my current output variable.
+ public override Variable output() { return myOutput; }
+
+ // Add myself to the constraint graph.
+ public override void addToGraph()
+ {
+ myOutput.addConstraint(this);
+ satisfied = false;
+ }
+
+ // Remove myself from the constraint graph.
+ public override void removeFromGraph()
+ {
+ if (myOutput != null) myOutput.removeConstraint(this);
+ satisfied = false;
+ }
+
+ // Decide if I can be satisfied and record that decision.
+ public override void chooseMethod(int mark)
+ {
+ satisfied = myOutput.mark != mark
+ && Strength.stronger(strength, myOutput.walkStrength);
+ }
+
+ public override void markInputs(int mark) { } // I have no inputs
+
+ public override Boolean inputsKnown(int mark) { return true; }
+
+ // Calculate the walkabout strength, the stay flag, and, if it is
+ // 'stay', the value for the current output of this
+ // constraint. Assume this constraint is satisfied."
+ public override void recalculate()
+ {
+ myOutput.walkStrength = strength;
+ myOutput.stay = !isInput();
+ if (myOutput.stay) execute(); // stay optimization
+ }
+
+ public override void printInputs() { } // I have no inputs
+}
+
+
+// I am a unary input constraint used to mark a variable that the
+// client wishes to change.
+//
+internal class EditConstraint : UnaryConstraint
+{
+ public EditConstraint(Variable v, Strength str) : base(v, str) { }
+
+ // I indicate that a variable is to be changed by imperative code.
+ public override Boolean isInput() { return true; }
+
+ public override void execute() { } // Edit constraints do nothing.
+}
+
+// I mark variables that should, with some level of preference, stay
+// the same. I have one method with zero inputs and one output, which
+// does nothing. Planners may exploit the fact that, if I am
+// satisfied, my output will not change during plan execution. This is
+// called "stay optimization".
+//
+internal class StayConstraint : UnaryConstraint
+{
+ // Install a stay constraint with the given strength on the given variable.
+ public StayConstraint(Variable v, Strength str) : base(v, str) { }
+
+ public override void execute() { } // Stay constraints do nothing.
+}
+
+
+
+
+//-------------binary constraints-------------------------------------------
+
+
+// I am an abstract superclass for constraints having two possible
+// output variables.
+//
+internal abstract class BinaryConstraint : Constraint
+{
+ public Variable v1, v2; // possible output variables
+ public sbyte direction; // one of the following...
+ public static sbyte backward = -1; // v1 is output
+ public static sbyte nodirection = 0; // not satisfied
+ public static sbyte forward = 1; // v2 is output
+
+ public BinaryConstraint() { } // this has to be here because of
+ // Java's constructor idiocy.
+
+ public BinaryConstraint(Variable var1, Variable var2, Strength strength)
+ : base(strength)
+ {
+ v1 = var1;
+ v2 = var2;
+ direction = nodirection;
+ addConstraint();
+ }
+
+ // Answer true if this constraint is satisfied in the current solution.
+ public override Boolean isSatisfied() { return direction != nodirection; }
+
+ // Add myself to the constraint graph.
+ public override void addToGraph()
+ {
+ v1.addConstraint(this);
+ v2.addConstraint(this);
+ direction = nodirection;
+ }
+
+ // Remove myself from the constraint graph.
+ public override void removeFromGraph()
+ {
+ if (v1 != null) v1.removeConstraint(this);
+ if (v2 != null) v2.removeConstraint(this);
+ direction = nodirection;
+ }
+
+ // Decide if I can be satisfied and which way I should flow based on
+ // the relative strength of the variables I relate, and record that
+ // decision.
+ //
+ public override void chooseMethod(int mark)
+ {
+ if (v1.mark == mark)
+ direction =
+ v2.mark != mark && Strength.stronger(strength, v2.walkStrength)
+ ? forward : nodirection;
+
+ if (v2.mark == mark)
+ direction =
+ v1.mark != mark && Strength.stronger(strength, v1.walkStrength)
+ ? backward : nodirection;
+
+ // If we get here, neither variable is marked, so we have a choice.
+ if (Strength.weaker(v1.walkStrength, v2.walkStrength))
+ direction =
+ Strength.stronger(strength, v1.walkStrength) ? backward : nodirection;
+ else
+ direction =
+ Strength.stronger(strength, v2.walkStrength) ? forward : nodirection;
+ }
+
+ // Record the fact that I am unsatisfied.
+ public override void markUnsatisfied() { direction = nodirection; }
+
+ // Mark the input variable with the given mark.
+ public override void markInputs(int mark)
+ {
+ input().mark = mark;
+ }
+
+ public override Boolean inputsKnown(int mark)
+ {
+ Variable i = input();
+ return i.mark == mark || i.stay || i.determinedBy == null;
+ }
+
+ // Answer my current output variable.
+ public override Variable output() { return direction == forward ? v2 : v1; }
+
+ // Answer my current input variable
+ public Variable input() { return direction == forward ? v1 : v2; }
+
+ // Calculate the walkabout strength, the stay flag, and, if it is
+ // 'stay', the value for the current output of this
+ // constraint. Assume this constraint is satisfied.
+ //
+ public override void recalculate()
+ {
+ Variable invar = input(), outvar = output();
+ outvar.walkStrength = Strength.weakestOf(strength, invar.walkStrength);
+ outvar.stay = invar.stay;
+ if (outvar.stay) execute();
+ }
+
+ public override void printInputs()
+ {
+ input().print();
+ }
+}
+
+
+// I constrain two variables to have the same value: "v1 = v2".
+//
+internal class EqualityConstraint : BinaryConstraint
+{
+ // Install a constraint with the given strength equating the given variables.
+ public EqualityConstraint(Variable var1, Variable var2, Strength strength)
+ : base(var1, var2, strength)
+
+ {
+ }
+
+ // Enforce this constraint. Assume that it is satisfied.
+ public override void execute()
+ {
+ output().value = input().value;
+ }
+}
+
+
+// I relate two variables by the linear scaling relationship: "v2 =
+// (v1 * scale) + offset". Either v1 or v2 may be changed to maintain
+// this relationship but the scale factor and offset are considered
+// read-only.
+//
+internal class ScaleConstraint : BinaryConstraint
+{
+ public Variable scale; // scale factor input variable
+ public Variable offset; // offset input variable
+
+ // Install a scale constraint with the given strength on the given variables.
+ public ScaleConstraint(Variable src, Variable scale, Variable offset,
+ Variable dest, Strength strength)
+ {
+ // Curse this wretched language for insisting that constructor invocation
+ // must be the first thing in a method...
+ // ..because of that, we must copy the code from the inherited
+ // constructors.
+ this.strength = strength;
+ v1 = src;
+ v2 = dest;
+ direction = nodirection;
+ this.scale = scale;
+ this.offset = offset;
+ addConstraint();
+ }
+
+ // Add myself to the constraint graph.
+ public override void addToGraph()
+ {
+ base.addToGraph();
+ scale.addConstraint(this);
+ offset.addConstraint(this);
+ }
+
+ // Remove myself from the constraint graph.
+ public override void removeFromGraph()
+ {
+ base.removeFromGraph();
+ if (scale != null) scale.removeConstraint(this);
+ if (offset != null) offset.removeConstraint(this);
+ }
+
+ // Mark the inputs from the given mark.
+ public override void markInputs(int mark)
+ {
+ base.markInputs(mark);
+ scale.mark = offset.mark = mark;
+ }
+
+ // Enforce this constraint. Assume that it is satisfied.
+ public override void execute()
+ {
+ if (direction == forward)
+ v2.value = v1.value * scale.value + offset.value;
+ else
+ v1.value = (v2.value - offset.value) / scale.value;
+ }
+
+ // Calculate the walkabout strength, the stay flag, and, if it is
+ // 'stay', the value for the current output of this
+ // constraint. Assume this constraint is satisfied.
+ public override void recalculate()
+ {
+ Variable invar = input(), outvar = output();
+ outvar.walkStrength = Strength.weakestOf(strength, invar.walkStrength);
+ outvar.stay = invar.stay && scale.stay && offset.stay;
+ if (outvar.stay) execute(); // stay optimization
+ }
+}
+
+
+// ------------------------------------------------------------
+
+
+// A Plan is an ordered list of constraints to be executed in sequence
+// to resatisfy all currently satisfiable constraints in the face of
+// one or more changing inputs.
+
+internal class Plan
+{
+ private ArrayList _v;
+
+ public Plan() { _v = new ArrayList(); }
+
+ public void addConstraint(Constraint c) { _v.Add(c); }
+
+ public int size() { return _v.Count; }
+
+ public Constraint constraintAt(int index)
+ {
+ return (Constraint)_v[index];
+ }
+
+ public void execute()
+ {
+ for (int i = 0; i < size(); ++i)
+ {
+ Constraint c = (Constraint)constraintAt(i);
+ c.execute();
+ }
+ }
+}
+
+
+// ------------------------------------------------------------
+
+// The deltablue planner
+
+internal class Planner
+{
+ private int _currentMark = 0;
+
+ // Select a previously unused mark value.
+ private int newMark() { return ++_currentMark; }
+
+ public Planner()
+ {
+ _currentMark = 0;
+ }
+
+ // Attempt to satisfy the given constraint and, if successful,
+ // incrementally update the dataflow graph. Details: If satifying
+ // the constraint is successful, it may override a weaker constraint
+ // on its output. The algorithm attempts to resatisfy that
+ // constraint using some other method. This process is repeated
+ // until either a) it reaches a variable that was not previously
+ // determined by any constraint or b) it reaches a constraint that
+ // is too weak to be satisfied using any of its methods. The
+ // variables of constraints that have been processed are marked with
+ // a unique mark value so that we know where we've been. This allows
+ // the algorithm to avoid getting into an infinite loop even if the
+ // constraint graph has an inadvertent cycle.
+ //
+ public void incrementalAdd(Constraint c)
+ {
+ int mark = newMark();
+ Constraint overridden = c.satisfy(mark);
+ while (overridden != null)
+ {
+ overridden = overridden.satisfy(mark);
+ }
+ }
+
+
+ // Entry point for retracting a constraint. Remove the given
+ // constraint and incrementally update the dataflow graph.
+ // Details: Retracting the given constraint may allow some currently
+ // unsatisfiable downstream constraint to be satisfied. We therefore collect
+ // a list of unsatisfied downstream constraints and attempt to
+ // satisfy each one in turn. This list is traversed by constraint
+ // strength, strongest first, as a heuristic for avoiding
+ // unnecessarily adding and then overriding weak constraints.
+ // Assume: c is satisfied.
+ //
+ public void incrementalRemove(Constraint c)
+ {
+ Variable outvar = c.output();
+ c.markUnsatisfied();
+ c.removeFromGraph();
+ ArrayList unsatisfied = removePropagateFrom(outvar);
+ Strength strength = Strength.required;
+ do
+ {
+ for (int i = 0; i < unsatisfied.Count; ++i)
+ {
+ Constraint u = (Constraint)unsatisfied[i];
+ if (u.strength == strength)
+ incrementalAdd(u);
+ }
+ strength = strength.nextWeaker();
+ } while (strength != Strength.weakest);
+ }
+
+ // Recompute the walkabout strengths and stay flags of all variables
+ // downstream of the given constraint and recompute the actual
+ // values of all variables whose stay flag is true. If a cycle is
+ // detected, remove the given constraint and answer
+ // false. Otherwise, answer true.
+ // Details: Cycles are detected when a marked variable is
+ // encountered downstream of the given constraint. The sender is
+ // assumed to have marked the inputs of the given constraint with
+ // the given mark. Thus, encountering a marked node downstream of
+ // the output constraint means that there is a path from the
+ // constraint's output to one of its inputs.
+ //
+ public Boolean addPropagate(Constraint c, int mark)
+ {
+ ArrayList todo = new ArrayList();
+ todo.Add(c);
+ while (!(todo.Count == 0))
+ {
+#if USE_STACK
+ Constraint d = (Constraint)todo[todo.Count - 1];
+ todo.RemoveAt(todo.Count - 1);
+#else
+ Constraint d= (Constraint)todo[0];
+ todo.RemoveAt(0);
+#endif
+ if (d.output().mark == mark)
+ {
+ incrementalRemove(c);
+ return false;
+ }
+ d.recalculate();
+ addConstraintsConsumingTo(d.output(), todo);
+ }
+ return true;
+ }
+
+
+ // The given variable has changed. Propagate new values downstream.
+ public void propagateFrom(Variable v)
+ {
+ ArrayList todo = new ArrayList();
+ addConstraintsConsumingTo(v, todo);
+ while (!(todo.Count == 0))
+ {
+#if USE_STACK
+ Constraint c = (Constraint)todo[todo.Count - 1];
+ todo.RemoveAt(0);
+#else
+ Constraint c= (Constraint)todo[todo.Count-1];
+ todo.RemoveAt(0);
+#endif
+ c.execute();
+ addConstraintsConsumingTo(c.output(), todo);
+ }
+ }
+
+ // Update the walkabout strengths and stay flags of all variables
+ // downstream of the given constraint. Answer a collection of
+ // unsatisfied constraints sorted in order of decreasing strength.
+ //
+ public ArrayList removePropagateFrom(Variable outvar)
+ {
+ outvar.determinedBy = null;
+ outvar.walkStrength = Strength.weakest;
+ outvar.stay = true;
+ ArrayList unsatisfied = new ArrayList();
+ ArrayList todo = new ArrayList();
+ todo.Add(outvar);
+ while (!(todo.Count == 0))
+ {
+#if USE_STACK
+ Variable v = (Variable)todo[todo.Count - 1];
+ todo.RemoveAt(todo.Count - 1);
+#else
+ Variable v= (Variable)todo[0];
+ todo.RemoveAt(0);
+#endif
+ for (int i = 0; i < v.constraints.Count; ++i)
+ {
+ Constraint c = (Constraint)v.constraints[i];
+ if (!c.isSatisfied())
+ unsatisfied.Add(c);
+ }
+ Constraint determiningC = v.determinedBy;
+ for (int i = 0; i < v.constraints.Count; ++i)
+ {
+ Constraint nextC = (Constraint)v.constraints[i];
+ if (nextC != determiningC && nextC.isSatisfied())
+ {
+ nextC.recalculate();
+ todo.Add(nextC.output());
+ }
+ }
+ }
+ return unsatisfied;
+ }
+
+ // Extract a plan for resatisfaction starting from the outputs of
+ // the given constraints, usually a set of input constraints.
+ //
+ public Plan extractPlanFromConstraints(ArrayList constraints)
+ {
+ ArrayList sources = new ArrayList();
+ for (int i = 0; i < constraints.Count; ++i)
+ {
+ Constraint c = (Constraint)constraints[i];
+ if (c.isInput() && c.isSatisfied())
+ sources.Add(c);
+ }
+ return makePlan(sources);
+ }
+
+ // Extract a plan for resatisfaction starting from the given source
+ // constraints, usually a set of input constraints. This method
+ // assumes that stay optimization is desired; the plan will contain
+ // only constraints whose output variables are not stay. Constraints
+ // that do no computation, such as stay and edit constraints, are
+ // not included in the plan.
+ // Details: The outputs of a constraint are marked when it is added
+ // to the plan under construction. A constraint may be appended to
+ // the plan when all its input variables are known. A variable is
+ // known if either a) the variable is marked (indicating that has
+ // been computed by a constraint appearing earlier in the plan), b)
+ // the variable is 'stay' (i.e. it is a constant at plan execution
+ // time), or c) the variable is not determined by any
+ // constraint. The last provision is for past states of history
+ // variables, which are not stay but which are also not computed by
+ // any constraint.
+ // Assume: sources are all satisfied.
+ //
+ public Plan makePlan(ArrayList sources)
+ {
+ int mark = newMark();
+ Plan plan = new Plan();
+ ArrayList todo = sources;
+ while (!(todo.Count == 0))
+ {
+#if USE_STACK
+ Constraint c = (Constraint)todo[todo.Count - 1];
+ todo.RemoveAt(todo.Count - 1);
+#else
+ Constraint c= (Constraint)todo[todo.Count-1];
+ todo.RemoveAt(0);
+#endif
+ if (c.output().mark != mark && c.inputsKnown(mark))
+ {
+ // not in plan already and eligible for inclusion
+ plan.addConstraint(c);
+ c.output().mark = mark;
+ addConstraintsConsumingTo(c.output(), todo);
+ }
+ }
+ return plan;
+ }
+
+ public void addConstraintsConsumingTo(Variable v, ArrayList coll)
+ {
+ Constraint determiningC = v.determinedBy;
+ ArrayList cc = v.constraints;
+ for (int i = 0; i < cc.Count; ++i)
+ {
+ Constraint c = (Constraint)cc[i];
+ if (c != determiningC && c.isSatisfied())
+ coll.Add(c);
+ }
+ }
+}
+
+//------------------------------------------------------------
+
+public class deltablue
+{
+ internal static Planner planner;
+ internal static int chains, projections;
+
+ public static int Main(String[] args)
+ {
+ deltablue d = new deltablue();
+ bool result = d.inst_main(args);
+ return (result ? 100 : -1);
+ }
+
+ [Benchmark]
+ public static void Bench()
+ {
+ deltablue d = new deltablue();
+ int iterations = 200;
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ d.inst_inner(iterations, false);
+ }
+ }
+ }
+
+ public bool inst_main(String[] args)
+ {
+ int iterations = 200; // read iterations from arguments, walter 7/97
+ if (args.Length > 0)
+ {
+ bool parsed = Int32.TryParse(args[0], out iterations);
+ if (!parsed)
+ {
+ Console.WriteLine("Error: expected iteration count, got '{0}'", args[0]);
+ return false;
+ }
+ }
+
+ inst_inner(iterations, true);
+
+ return true;
+ }
+
+ public void inst_inner(int iterations, bool verbose)
+ {
+ chains = 0; // NS 11/11
+ projections = 0; // NS 11/11
+ if (verbose)
+ {
+ Console.WriteLine("deltablue parameters: " + iterations + " iterations");
+ }
+
+ DateTime start = DateTime.Now;
+ for (int i = 0; i < iterations; i++)
+ {
+ chainTest(1000);
+ projectionTest(1000);
+ }
+ DateTime end = DateTime.Now;
+ TimeSpan dur = end - start;
+ if (verbose)
+ {
+ Console.WriteLine("chains : " + chains); //NS
+ Console.WriteLine("projections : " + projections); //NS
+ Console.WriteLine("Doing {0} iters of Deltablue takes {1} ms; {2} us/iter.",
+ iterations, dur.TotalMilliseconds, (1000.0 * dur.TotalMilliseconds) / iterations);
+ }
+ }
+
+ // This is the standard DeltaBlue benchmark. A long chain of
+ // equality constraints is constructed with a stay constraint on
+ // one end. An edit constraint is then added to the opposite end
+ // and the time is measured for adding and removing this
+ // constraint, and extracting and executing a constraint
+ // satisfaction plan. There are two cases. In case 1, the added
+ // constraint is stronger than the stay constraint and values must
+ // propagate down the entire length of the chain. In case 2, the
+ // added constraint is weaker than the stay constraint so it cannot
+ // be accomodated. The cost in this case is, of course, very
+ // low. Typical situations lie somewhere between these two
+ // extremes.
+ //
+ private void chainTest(int n)
+ {
+ planner = new Planner();
+
+ Variable prev = null, first = null, last = null;
+
+ // Build chain of n equality constraints
+ for (int i = 0; i <= n; i++)
+ {
+ String name = "v" + i;
+ Variable v = new Variable(name);
+ if (prev != null)
+ new EqualityConstraint(prev, v, Strength.required);
+ if (i == 0) first = v;
+ if (i == n) last = v;
+ prev = v;
+ }
+
+ new StayConstraint(last, Strength.strongDefault);
+ Constraint editC = new EditConstraint(first, Strength.preferred);
+ ArrayList editV = new ArrayList();
+ editV.Add(editC);
+ Plan plan = planner.extractPlanFromConstraints(editV);
+ for (int i = 0; i < 100; i++)
+ {
+ first.value = i;
+ plan.execute();
+ if (last.value != i)
+ error("Chain test failed!");
+ }
+ editC.destroyConstraint();
+ deltablue.chains++;
+ }
+
+
+ // This test constructs a two sets of variables related to each
+ // other by a simple linear transformation (scale and offset). The
+ // time is measured to change a variable on either side of the
+ // mapping and to change the scale and offset factors.
+ //
+ private void projectionTest(int n)
+ {
+ planner = new Planner();
+
+ Variable scale = new Variable("scale", 10);
+ Variable offset = new Variable("offset", 1000);
+ Variable src = null, dst = null;
+
+ ArrayList dests = new ArrayList();
+
+ for (int i = 0; i < n; ++i)
+ {
+ src = new Variable("src" + i, i);
+ dst = new Variable("dst" + i, i);
+ dests.Add(dst);
+ new StayConstraint(src, Strength.normal);
+ new ScaleConstraint(src, scale, offset, dst, Strength.required);
+ }
+
+ change(src, 17);
+ if (dst.value != 1170) error("Projection test 1 failed!");
+
+ change(dst, 1050);
+ if (src.value != 5) error("Projection test 2 failed!");
+
+ change(scale, 5);
+ for (int i = 0; i < n - 1; ++i)
+ {
+ if (((Variable)dests[i]).value != i * 5 + 1000)
+ error("Projection test 3 failed!");
+ }
+
+ change(offset, 2000);
+ for (int i = 0; i < n - 1; ++i)
+ {
+ if (((Variable)dests[i]).value != i * 5 + 2000)
+ error("Projection test 4 failed!");
+ }
+ deltablue.projections++;
+ }
+
+ private void change(Variable var, int newValue)
+ {
+ EditConstraint editC = new EditConstraint(var, Strength.preferred);
+ ArrayList editV = new ArrayList();
+ editV.Add(editC);
+ Plan plan = planner.extractPlanFromConstraints(editV);
+ for (int i = 0; i < 10; i++)
+ {
+ var.value = newValue;
+ plan.execute();
+ }
+ editC.destroyConstraint();
+ }
+
+ public static void error(String s)
+ {
+ throw new Exception(s);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.csproj b/tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.csproj
new file mode 100644
index 0000000000..0b25633aeb
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.csproj
@@ -0,0 +1,44 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ <GCStressIncompatible>true</GCStressIncompatible>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="DeltaBlue.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/V8/Richards/Richards.cs b/tests/src/JIT/Performance/CodeQuality/V8/Richards/Richards.cs
new file mode 100644
index 0000000000..6d26593e2f
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/V8/Richards/Richards.cs
@@ -0,0 +1,757 @@
+// 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.
+//
+// This is a C# implementation of the Richards benchmark from:
+//
+// http://www.cl.cam.ac.uk/~mr10/Bench.html
+//
+// The benchmark was originally implemented in BCPL by Martin Richards.
+
+#define INTF_FOR_TASK
+
+using Microsoft.Xunit.Performance;
+using System;
+using System.Collections.Generic;
+
+[assembly: OptimizeForBenchmarks]
+[assembly: MeasureInstructionsRetired]
+
+// using System.Diagnostics;
+// using System.Text.RegularExpressions;
+
+namespace Richards
+{
+ /// <summary>
+ /// Support is used for a place to generate any 'miscellaneous' methods generated as part
+ /// of code generation, (which do not have user-visible names)
+ /// </summary>
+ public class Support
+ {
+ public static bool runRichards()
+ {
+ Scheduler scheduler = new Scheduler();
+ scheduler.addIdleTask(ID_IDLE, 0, null, COUNT);
+ Packet queue = new Packet(null, ID_WORKER, KIND_WORK);
+ queue = new Packet(queue, ID_WORKER, KIND_WORK);
+ scheduler.addWorkerTask(ID_WORKER, 1000, queue);
+
+ queue = new Packet(null, ID_DEVICE_A, KIND_DEVICE);
+ queue = new Packet(queue, ID_DEVICE_A, KIND_DEVICE);
+ queue = new Packet(queue, ID_DEVICE_A, KIND_DEVICE);
+ scheduler.addHandlerTask(ID_HANDLER_A, 2000, queue);
+
+ queue = new Packet(null, ID_DEVICE_B, KIND_DEVICE);
+ queue = new Packet(queue, ID_DEVICE_B, KIND_DEVICE);
+ queue = new Packet(queue, ID_DEVICE_B, KIND_DEVICE);
+ scheduler.addHandlerTask(ID_HANDLER_B, 3000, queue);
+
+ scheduler.addDeviceTask(ID_DEVICE_A, 4000, null);
+ scheduler.addDeviceTask(ID_DEVICE_B, 5000, null);
+ scheduler.schedule();
+
+ return ((scheduler.queueCount == EXPECTED_QUEUE_COUNT)
+ && (scheduler.holdCount == EXPECTED_HOLD_COUNT));
+ }
+
+ public const int COUNT = 1000;
+
+ /**
+ * These two constants specify how many times a packet is queued and
+ * how many times a task is put on hold in a correct run of richards.
+ * They don't have any meaning a such but are characteristic of a
+ * correct run so if the actual queue or hold count is different from
+ * the expected there must be a bug in the implementation.
+ **/
+ public const int EXPECTED_QUEUE_COUNT = 2322;
+ public const int EXPECTED_HOLD_COUNT = 928;
+
+ public const int ID_IDLE = 0;
+ public const int ID_WORKER = 1;
+ public const int ID_HANDLER_A = 2;
+ public const int ID_HANDLER_B = 3;
+ public const int ID_DEVICE_A = 4;
+ public const int ID_DEVICE_B = 5;
+ public const int NUMBER_OF_IDS = 6;
+
+ public const int KIND_DEVICE = 0;
+ public const int KIND_WORK = 1;
+
+ /**
+ * The task is running and is currently scheduled.
+ */
+ public const int STATE_RUNNING = 0;
+
+ /**
+ * The task has packets left to process.
+ */
+ public const int STATE_RUNNABLE = 1;
+
+ /**
+ * The task is not currently running. The task is not blocked as such and may
+ * be started by the scheduler.
+ */
+ public const int STATE_SUSPENDED = 2;
+
+ /**
+ * The task is blocked and cannot be run until it is explicitly released.
+ */
+ public const int STATE_HELD = 4;
+
+ public const int STATE_SUSPENDED_RUNNABLE = STATE_SUSPENDED | STATE_RUNNABLE;
+ public const int STATE_NOT_HELD = ~STATE_HELD;
+
+ /* --- *
+ * P a c k e t
+ * --- */
+
+ public const int DATA_SIZE = 4;
+
+ public static int Main(String[] args)
+ {
+ int n = 1;
+ if (args.Length > 0)
+ {
+ n = Int32.Parse(args[0]);
+ }
+ bool result = Measure(n);
+ return (result ? 100 : -1);
+ }
+
+ public static bool Measure(int n)
+ {
+ DateTime start = DateTime.Now;
+ bool result = true;
+ for (int i = 0; i < n; i++)
+ {
+ result &= runRichards();
+ }
+ DateTime end = DateTime.Now;
+ TimeSpan dur = end - start;
+ Console.WriteLine("Doing {0} iters of Richards takes {1} ms; {2} us/iter.",
+ n, dur.TotalMilliseconds, (1000.0 * dur.TotalMilliseconds) / n);
+ return result;
+ }
+
+ [Benchmark]
+ public static void Bench()
+ {
+ const int Iterations = 5000;
+
+ foreach (var iteration in Benchmark.Iterations)
+ {
+ using (iteration.StartMeasurement())
+ {
+ for (int i = 0; i < Iterations; i++)
+ {
+ runRichards();
+ }
+ }
+ }
+ }
+ }
+
+ internal class Scheduler
+ {
+ public int queueCount;
+ public int holdCount;
+ public TaskControlBlock[] blocks;
+ public TaskControlBlock list;
+ public TaskControlBlock currentTcb;
+ public int currentId;
+
+ public Scheduler()
+ {
+ this.queueCount = 0;
+ this.holdCount = 0;
+ this.blocks = new TaskControlBlock[Support.NUMBER_OF_IDS];
+ this.list = null;
+ this.currentTcb = null;
+ this.currentId = 0;
+ }
+
+ /**
+ * Add an idle task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ * @param {int} count the number of times to schedule the task
+ */
+ public void addIdleTask(int id, int priority, Packet queue, int count)
+ {
+ this.addRunningTask(id, priority, queue,
+ new IdleTask(this, 1, count));
+ }
+
+ /**
+ * Add a work task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ */
+ public void addWorkerTask(int id, int priority, Packet queue)
+ {
+ this.addTask(id, priority, queue,
+ new WorkerTask(this, Support.ID_HANDLER_A, 0));
+ }
+
+ /**
+ * Add a handler task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ */
+ public void addHandlerTask(int id, int priority, Packet queue)
+ {
+ this.addTask(id, priority, queue, new HandlerTask(this));
+ }
+
+ /**
+ * Add a handler task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ */
+ public void addDeviceTask(int id, int priority, Packet queue)
+ {
+ this.addTask(id, priority, queue, new DeviceTask(this));
+ }
+
+ /**
+ * Add the specified task and mark it as running.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ * @param {Task} task the task to add
+ */
+ public void addRunningTask(int id, int priority, Packet queue, Task task)
+ {
+ this.addTask(id, priority, queue, task);
+ this.currentTcb.setRunning();
+ }
+
+ /**
+ * Add the specified task to this scheduler.
+ * @param {int} id the identity of the task
+ * @param {int} priority the task's priority
+ * @param {Packet} queue the queue of work to be processed by the task
+ * @param {Task} task the task to add
+ */
+ public void addTask(int id, int priority, Packet queue, Task task)
+ {
+ this.currentTcb = new TaskControlBlock(this.list, id, priority, queue, task);
+ this.list = this.currentTcb;
+ this.blocks[id] = this.currentTcb;
+ }
+
+ /**
+ * Execute the tasks managed by this scheduler.
+ */
+ public void schedule()
+ {
+ this.currentTcb = this.list;
+#if TRACEIT
+ int kkk = 0;
+#endif
+ while (this.currentTcb != null)
+ {
+#if TRACEIT
+ Console.WriteLine("kkk = {0}", kkk); kkk++;
+#endif
+ if (this.currentTcb.isHeldOrSuspended())
+ {
+#if TRACEIT
+ Console.WriteLine("held");
+#endif
+ this.currentTcb = this.currentTcb.link;
+ }
+ else
+ {
+ this.currentId = this.currentTcb.id;
+#if TRACEIT
+ Console.WriteLine("currentId is now...{0}", this.currentId.ToString());
+#endif
+ this.currentTcb = this.currentTcb.run();
+ }
+ }
+ }
+
+ /**
+ * Release a task that is currently blocked and return the next block to run.
+ * @param {int} id the id of the task to suspend
+ */
+ public TaskControlBlock release(int id)
+ {
+ TaskControlBlock tcb = this.blocks[id];
+ if (tcb == null) return tcb;
+ tcb.markAsNotHeld();
+ if (tcb.priority >= this.currentTcb.priority)
+ {
+ return tcb;
+ }
+ else
+ {
+ return this.currentTcb;
+ }
+ }
+
+ /**
+ * Block the currently executing task and return the next task control block
+ * to run. The blocked task will not be made runnable until it is explicitly
+ * released, even if new work is added to it.
+ */
+ public TaskControlBlock holdCurrent()
+ {
+ this.holdCount++;
+ this.currentTcb.markAsHeld();
+ return this.currentTcb.link;
+ }
+
+ /**
+ * Suspend the currently executing task and return the next task control block
+ * to run. If new work is added to the suspended task it will be made runnable.
+ */
+ public TaskControlBlock suspendCurrent()
+ {
+ this.currentTcb.markAsSuspended();
+ return this.currentTcb;
+ }
+
+ /**
+ * Add the specified packet to the end of the worklist used by the task
+ * associated with the packet and make the task runnable if it is currently
+ * suspended.
+ * @param {Packet} packet the packet to add
+ */
+ public TaskControlBlock queue(Packet packet)
+ {
+ TaskControlBlock t = this.blocks[packet.id];
+ if (t == null) return t;
+ this.queueCount++;
+ packet.link = null;
+ packet.id = this.currentId;
+ return t.checkPriorityAdd(this.currentTcb, packet);
+ }
+ }
+
+ /**
+ * A task control block manages a task and the queue of work packages associated
+ * with it.
+ * @param {TaskControlBlock} link the preceding block in the linked block list
+ * @param {int} id the id of this block
+ * @param {int} priority the priority of this block
+ * @param {Packet} queue the queue of packages to be processed by the task
+ * @param {Task} task the task
+ * @constructor
+ */
+ public class TaskControlBlock
+ {
+ public TaskControlBlock link;
+ public int id;
+ public int priority;
+ public Packet queue;
+ public Task task;
+ public int state;
+
+ public TaskControlBlock(TaskControlBlock link, int id, int priority,
+ Packet queue, Task task)
+ {
+ this.link = link;
+ this.id = id;
+ this.priority = priority;
+ this.queue = queue;
+ this.task = task;
+ if (queue == null)
+ {
+ this.state = Support.STATE_SUSPENDED;
+ }
+ else
+ {
+ this.state = Support.STATE_SUSPENDED_RUNNABLE;
+ }
+ }
+
+ public void setRunning()
+ {
+ this.state = Support.STATE_RUNNING;
+ }
+
+ public void markAsNotHeld()
+ {
+ this.state = this.state & Support.STATE_NOT_HELD;
+ }
+
+ public void markAsHeld()
+ {
+ this.state = this.state | Support.STATE_HELD;
+ }
+
+ public bool isHeldOrSuspended()
+ {
+ return ((this.state & Support.STATE_HELD) != 0) || (this.state == Support.STATE_SUSPENDED);
+ }
+
+ public void markAsSuspended()
+ {
+ this.state = this.state | Support.STATE_SUSPENDED;
+ }
+
+ public void markAsRunnable()
+ {
+ this.state = this.state | Support.STATE_RUNNABLE;
+ }
+
+ /**
+ * Runs this task, if it is ready to be run, and returns the next task to run.
+ */
+ public TaskControlBlock run()
+ {
+ Packet packet;
+#if TRACEIT
+ Console.WriteLine(" TCB::run, state = {0}", this.state);
+#endif
+ if (this.state == Support.STATE_SUSPENDED_RUNNABLE)
+ {
+ packet = this.queue;
+ this.queue = packet.link;
+ if (this.queue == null)
+ {
+ this.state = Support.STATE_RUNNING;
+ }
+ else
+ {
+ this.state = Support.STATE_RUNNABLE;
+ }
+#if TRACEIT
+ Console.WriteLine(" State is now {0}", this.state);
+#endif
+ }
+ else
+ {
+#if TRACEIT
+ Console.WriteLine(" TCB::run, setting packet = Null.");
+#endif
+ packet = null;
+ }
+ return this.task.run(packet);
+ }
+
+ /**
+ * Adds a packet to the worklist of this block's task, marks this as runnable if
+ * necessary, and returns the next runnable object to run (the one
+ * with the highest priority).
+ */
+ public TaskControlBlock checkPriorityAdd(TaskControlBlock task, Packet packet)
+ {
+ if (this.queue == null)
+ {
+ this.queue = packet;
+ this.markAsRunnable();
+ if (this.priority >= task.priority) return this;
+ }
+ else
+ {
+ this.queue = packet.addTo(this.queue);
+ }
+ return task;
+ }
+
+ public String toString()
+ {
+ return "tcb { " + this.task.toString() + "@" + this.state.ToString() + " }";
+ }
+ }
+
+#if INTF_FOR_TASK
+ // I deliberately ignore the "I" prefix convention here so that we can use Task as a type in both
+ // cases...
+ public interface Task
+ {
+ TaskControlBlock run(Packet packet);
+ String toString();
+ }
+#else
+ public abstract class Task
+ {
+ public abstract TaskControlBlock run(Packet packet);
+ public abstract String toString();
+ }
+#endif
+
+ /**
+ * An idle task doesn't do any work itself but cycles control between the two
+ * device tasks.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @param {int} v1 a seed value that controls how the device tasks are scheduled
+ * @param {int} count the number of times this task should be scheduled
+ * @constructor
+ */
+ internal class IdleTask : Task
+ {
+ public Scheduler scheduler;
+ public int _v1;
+ public int _count;
+
+ public IdleTask(Scheduler scheduler, int v1, int count)
+ {
+ this.scheduler = scheduler;
+ this._v1 = v1;
+ this._count = count;
+ }
+
+ public
+#if !INTF_FOR_TASK
+ override
+#endif
+ TaskControlBlock run(Packet packet)
+ {
+ this._count--;
+ if (this._count == 0) return this.scheduler.holdCurrent();
+ if ((this._v1 & 1) == 0)
+ {
+ this._v1 = this._v1 >> 1;
+ return this.scheduler.release(Support.ID_DEVICE_A);
+ }
+ else
+ {
+ this._v1 = (this._v1 >> 1) ^ 0xD008;
+ return this.scheduler.release(Support.ID_DEVICE_B);
+ }
+ }
+
+ public
+#if !INTF_FOR_TASK
+ override
+#endif
+ String toString()
+ {
+ return "IdleTask";
+ }
+ }
+
+ /**
+ * A task that suspends itself after each time it has been run to simulate
+ * waiting for data from an external device.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @constructor
+ */
+ internal class DeviceTask : Task
+ {
+ public Scheduler scheduler;
+ private Packet _v1;
+
+ public DeviceTask(Scheduler scheduler)
+ {
+ this.scheduler = scheduler;
+ _v1 = null;
+ }
+
+ public
+#if !INTF_FOR_TASK
+ override
+#endif
+ TaskControlBlock run(Packet packet)
+ {
+ if (packet == null)
+ {
+ if (_v1 == null) return this.scheduler.suspendCurrent();
+ Packet v = _v1;
+ _v1 = null;
+ return this.scheduler.queue(v);
+ }
+ else
+ {
+ _v1 = packet;
+ return this.scheduler.holdCurrent();
+ }
+ }
+
+ public
+#if !INTF_FOR_TASK
+ override
+#endif
+ String toString()
+ {
+ return "DeviceTask";
+ }
+ }
+
+ /**
+ * A task that manipulates work packets.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @param {int} v1 a seed used to specify how work packets are manipulated
+ * @param {int} v2 another seed used to specify how work packets are manipulated
+ * @constructor
+ */
+ internal class WorkerTask : Task
+ {
+ public Scheduler scheduler;
+ public int v1;
+ public int _v2;
+
+ public WorkerTask(Scheduler scheduler, int v1, int v2)
+ {
+ this.scheduler = scheduler;
+ this.v1 = v1;
+ this._v2 = v2;
+ }
+
+ public
+#if !INTF_FOR_TASK
+ override
+#endif
+ TaskControlBlock run(Packet packet)
+ {
+ if (packet == null)
+ {
+ return this.scheduler.suspendCurrent();
+ }
+ else
+ {
+ if (this.v1 == Support.ID_HANDLER_A)
+ {
+ this.v1 = Support.ID_HANDLER_B;
+ }
+ else
+ {
+ this.v1 = Support.ID_HANDLER_A;
+ }
+ packet.id = this.v1;
+ packet.a1 = 0;
+ for (int i = 0; i < Support.DATA_SIZE; i++)
+ {
+ this._v2++;
+ if (this._v2 > 26) this._v2 = 1;
+ packet.a2[i] = this._v2;
+ }
+ return this.scheduler.queue(packet);
+ }
+ }
+
+ public
+#if !INTF_FOR_TASK
+ override
+#endif
+ String toString()
+ {
+ return "WorkerTask";
+ }
+ }
+
+ /**
+ * A task that manipulates work packets and then suspends itself.
+ * @param {Scheduler} scheduler the scheduler that manages this task
+ * @constructor
+ */
+ internal class HandlerTask : Task
+ {
+ public Scheduler scheduler;
+ public Packet v1;
+ public Packet v2;
+
+ public HandlerTask(Scheduler scheduler)
+ {
+ this.scheduler = scheduler;
+ this.v1 = null;
+ this.v2 = null;
+ }
+
+ public
+#if !INTF_FOR_TASK
+ override
+#endif
+ TaskControlBlock run(Packet packet)
+ {
+ if (packet != null)
+ {
+ if (packet.kind == Support.KIND_WORK)
+ {
+ this.v1 = packet.addTo(this.v1);
+ }
+ else
+ {
+ this.v2 = packet.addTo(this.v2);
+ }
+ }
+ if (this.v1 != null)
+ {
+ int count = this.v1.a1;
+ Packet v;
+ if (count < Support.DATA_SIZE)
+ {
+ if (this.v2 != null)
+ {
+ v = this.v2;
+ this.v2 = this.v2.link;
+ v.a1 = this.v1.a2[count];
+ this.v1.a1 = count + 1;
+ return this.scheduler.queue(v);
+ }
+ }
+ else
+ {
+ v = this.v1;
+ this.v1 = this.v1.link;
+ return this.scheduler.queue(v);
+ }
+ }
+ return this.scheduler.suspendCurrent();
+ }
+
+ public
+#if !INTF_FOR_TASK
+ override
+#endif
+ String toString()
+ {
+ return "HandlerTask";
+ }
+ }
+
+ /**
+ * A simple package of data that is manipulated by the tasks. The exact layout
+ * of the payload data carried by a packet is not importaint, and neither is the
+ * nature of the work performed on packets by the tasks.
+ *
+ * Besides carrying data, packets form linked lists and are hence used both as
+ * data and worklists.
+ * @param {Packet} link the tail of the linked list of packets
+ * @param {int} id an ID for this packet
+ * @param {int} kind the type of this packet
+ * @constructor
+ */
+ public class Packet
+ {
+ public Packet link;
+ public int id;
+ public int kind;
+ public int a1;
+ public int[] a2;
+
+ public Packet(Packet link, int id, int kind)
+ {
+ this.link = link;
+ this.id = id;
+ this.kind = kind;
+ this.a1 = 0;
+ this.a2 = new int[Support.DATA_SIZE];
+ }
+
+ public Packet addTo(Packet queue)
+ {
+ this.link = null;
+ if (queue == null) return this;
+ Packet peek;
+ Packet next = queue;
+ while ((peek = next.link) != null)
+ next = peek;
+ next.link = this;
+ return queue;
+ }
+
+ public String toString()
+ {
+ return "Packet";
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/V8/Richards/Richards.csproj b/tests/src/JIT/Performance/CodeQuality/V8/Richards/Richards.csproj
new file mode 100644
index 0000000000..b4572c61a5
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/V8/Richards/Richards.csproj
@@ -0,0 +1,43 @@
+<?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>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.4</NuGetTargetMoniker>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Richards.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/RunBenchmarks/RunBenchmarks.cmd b/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.cmd
new file mode 100644
index 0000000000..e85e226392
--- /dev/null
+++ b/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.cmd
@@ -0,0 +1,63 @@
+@setlocal
+@echo off
+@rem ***************************************************************************
+@rem RunBenchmarks.cmd
+@rem
+@rem This is a sample script for how to run benchmarks on Windows.
+@rem
+@rem It requires the user to set CORECLR_ROOT to the root directory
+@rem of the enlistment(repo). It also requires that CoreCLR has been built,
+@rem and that all CoreCLR tests have been built.
+@rem
+@rem The preformance harness "RunBencchmarks.exe" is built as a test case
+@rem as are all the performance tests it runs.
+@rem
+@rem For the ByteMark tests, it must copy the command scripts to the
+@rem binary directory for the tests.
+@rem
+@rem By default, the performance harness is run on top of CoreCLR. There
+@rem is a commented out section that can be used to run on top of DesktopCLR.
+@rem
+@rem A standard benchmark run is done with one warmup run, and five iterations
+@rem of the benchmark.
+@rem
+@rem ***************************************************************************
+
+set ARCH=%1
+set BUILD=%2
+
+if /I "%ARCH%" == "" set ARCH=x64
+if /I "%BUILD%" == "" set BUILD=Release
+
+rem *** set this appropriately for enlistment you are running benchmarks in
+if /I NOT "%CORECLR_ROOT%" == "" goto over
+@echo "You must set CORECLR_ROOT to be the root of your coreclr repo (e.g. \git\repos\coreclr)"
+@goto done
+:over
+
+set BENCHMARK_ROOT_DIR=%CORECLR_ROOT%\bin\tests\Windows_NT.%ARCH%.%BUILD%\JIT\Performance\CodeQuality
+set BENCHMARK_SRC_DIR=%CORECLR_ROOT%\tests\src\JIT\Performance\RunBenchmarks
+set BENCHMARK_HOST=CoreRun.exe %CORECLR_ROOT%\bin\tests\Windows_NT.%ARCH%.%BUILD%\JIT\Performance\RunBenchmarks\RunBenchmarks\RunBenchmarks.exe
+set BENCHMARK_RUNNER=-runner CoreRun.exe
+
+rem *** used for desktop hosted run
+rem set BENCHMARK_HOST=%BENCHMARK_SRC_DIR%\bin\%BUILD%\desktop\RunBenchmarks.exe
+
+rem *** need to copy command files for Bytemark
+xcopy /y /e /s %CORECLR_ROOT%\tests\src\JIT\Performance\CodeQuality\Bytemark\commands %BENCHMARK_ROOT_DIR%\Bytemark\Bytemark\commands
+
+rem *** if you have problems with pop-ups, enable DHandler.exe
+rem start DHandler.exe
+
+set BENCHMARK_CONTROLS=-run -v -w -n 5
+set BENCHMARK_SET=-f %BENCHMARK_SRC_DIR%\coreclr_benchmarks.xml -notags broken
+set BENCHMARK_OUTPUT=-csvfile %BENCHMARK_SRC_DIR%\coreclr_benchmarks.csv
+set BENCHMARK_SWITCHES=%BENCHMARK_CONTROLS% -r %BENCHMARK_ROOT_DIR%
+
+%BENCHMARK_HOST% %BENCHMARK_RUNNER% %BENCHMARK_SET% %BENCHMARK_OUTPUT% %BENCHMARK_SWITCHES%
+
+rem *** if you have problems with pop-ups, enable DHandler.exe
+rem taskkill /im DHandler.exe
+
+:done
+@endlocal
diff --git a/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.cs b/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.cs
new file mode 100644
index 0000000000..d5920e4b3f
--- /dev/null
+++ b/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.cs
@@ -0,0 +1,1155 @@
+// 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.
+//
+// RunBenchmark - .NET Benchmark Performance Harness
+//
+// Note: This harness is currently built as a CoreCLR test case for ease of running
+// against test CORE_ROOT assemblies. As such, when run with out any parameters,
+// it will do nothing and simply return 100. Use "-run" to actually run tests cases.
+//
+// Usage: RunBenchmarks [options]
+//
+// options:
+//
+// -f <xmlFile> specify benchmark xml control file (default benchmarks.xml)
+// -n <number> specify number of runs for each benchmark (default is 1)
+// -w specify that warmup run should be done first
+// -v run in verbose mode
+// -r <rootDir> specify root directory to run from
+// -s <suite> specify a single benchmark suite to run (by name)
+// -i <benchmark> specify benchmark to include by name (multiple -i's allowed)
+// -e <benchmark> specify benchmark to exclude by name (multiple -e's allowed)
+// -list prints a list of the benchmark names and does nothing else
+// -listsuites prints a list of the suite names and does nothing else
+// -listtags prints a list of the tag names and does nothing else
+// -listexes prints a list of full path names to executables in benchmarks
+// -runner run benchmarks on using runner(e.g. corerun, default is DesktopCLR)
+// -complus_version <version> run benchmarks on particular DesktopCLR version
+// -run run benchmarks
+// -testcase run as CoreCLR test case (default)
+// -norun prints what would be run, but don't run benchmarks
+// -tags <tags> specify benchmarks with tags to include
+// -notags <tags> specify benchmarks with tags to exclude
+// -csvfile specify name of Comma Seperated Value output file (default console)
+//
+// Benchmark .XML Control File format:
+//
+// <?xml version="1.0" encoding="UTF-8"?>
+// <benchmark-system>
+// <benchmark-root-directory>ROOT_DIRECTORY</benchmark-root-directory> // optional, can be on command line
+// <benchmark-suite>
+// <name>SUITE_NAME</name>
+// <benchmark>
+// <name>BENCHMARK_NAME</name>
+// <directory>BENCHMARK_DIRECTORY</directory>
+// <executable>EXECUTABLE_PATH</executable>
+// <args>EXECUTABLE_ARGUMENTS</args> // optional args, can redirect output: &gt; > out
+// <run-in-shell>true</run-in-shell> // optional
+// <useSSE>true</useSSE> // optional use SSE
+// <useAVX>true</useAVX> // optional use AVX
+// <tags>SIMD,SSE</tags> // optional tags for inclusion/exclusion
+// </benchmark>
+// ...
+// LIST_OF_BENCHMARKS
+// ...
+// </benchmark-suite>
+// ...
+// LIST_OF_BENCHMARK_SUITES
+// ...
+// </benchmark-system>
+//
+// Where:
+//
+// ROOT_DIRECTORY = root directory for all benchmarks described in this file
+// SUITE_NAME = suite name that benchmark belongs to
+// BENCHMARK_NAME = benchmark name
+// BENCHMARK_DIRECTORY = benchmark directory, relative to root (becomes working directory for benchmark)
+// EXECUTABLE_PATH = relative path (to working directory) for benchmark (simplest form foo.exe)
+// EXECUTABLE_ARGUMENTS = argument for benchmark if any
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Xml;
+using System.Xml.XPath;
+using System.IO;
+
+namespace BenchmarkConsoleApplication
+{
+ // Benchmark Suite - includes suite name an list of benchmarks included in suite.
+
+ internal class BenchmarkSuite
+ {
+ public string SuiteName;
+ public List<Benchmark> BenchmarkList;
+
+ public BenchmarkSuite
+ (
+ string suiteName
+ )
+ {
+ SuiteName = suiteName;
+ BenchmarkList = new List<Benchmark>();
+ }
+ }
+
+ // Benchmark Tag Set - includes tag name an list of benchmarks that have been tagged with this tag.
+
+ internal class BenchmarkTagSet
+ {
+ public string TagName;
+ public List<Benchmark> BenchmarkList;
+
+ public BenchmarkTagSet
+ (
+ string tagName
+ )
+ {
+ TagName = tagName;
+ BenchmarkList = new List<Benchmark>();
+ }
+ }
+
+ // Benchmark - includes benchmark name, suite name, tags, working directory, executable name,
+ // executable argurments, whether to run in a shell, whether to use SSE, whether to use
+ // AVX and expected results (exit code).
+
+ internal class Benchmark
+ {
+ public string Name;
+ public string SuiteName;
+ public string Tags;
+ public string WorkingDirectory;
+ public string ExeName;
+ public string ExeArgs;
+ public bool DoRunInShell;
+ public bool UseSSE;
+ public bool UseAVX;
+ public int ExpectedResults;
+
+ public Benchmark
+ (
+ string name,
+ string suiteName,
+ string tags,
+ string workingDirectory,
+ string exeName,
+ string exeArgs,
+ bool doRunInShell,
+ bool useSSE,
+ bool useAVX,
+ int expectedResults
+ )
+ {
+ Name = name;
+ SuiteName = suiteName;
+ Tags = tags;
+ WorkingDirectory = workingDirectory;
+ ExeName = exeName;
+ ExeArgs = exeArgs;
+ DoRunInShell = doRunInShell;
+ UseSSE = useSSE;
+ UseAVX = useAVX;
+ ExpectedResults = expectedResults;
+ }
+ }
+
+ // Benchmark Results - includes benchmark, array of times for each iteration of the benchmark
+ // minimum time, maximum time, average time, standard deviation and number
+ // of failures.
+
+ internal class Results
+ {
+ public Benchmark Benchmark;
+ public long[] Times;
+ public long Minimum;
+ public long Maximum;
+ public long Average;
+ public double StandardDeviation;
+ public int Failures;
+
+ public Results
+ (
+ Benchmark benchmark,
+ int numberOfRuns
+ )
+ {
+ Benchmark = benchmark;
+ Times = new long[numberOfRuns + 1]; // leave empty slot at index 0, not used.
+ Minimum = 0;
+ Maximum = 0;
+ Average = 0;
+ StandardDeviation = 0.0;
+ Failures = 0;
+ }
+ }
+
+ // Controls - command line controls used to
+
+ internal class Controls
+ {
+ public bool DoRun; // Actually execute the benchmarks
+ public bool DoWarmUpRun; // Do a warmup run first.
+ public bool DoVerbose; // Run in verbose mode.
+ public bool DoPrintResults; // Print results of runs.
+ public bool DoRunAsTestCase; // Run as test case (default)
+ public string Runner; // Use the runner to execute benchmarks (e.g. corerun.exe)
+ public bool DoDebugBenchmark; // Execute benchmark under debugger (Windows).
+ public bool DoListBenchmarks; // List out the benchmarks from .XML file
+ public bool DoListBenchmarkSuites; // List out the benchmark suites from .XML file
+ public bool DoListBenchmarkTagSets; // List out the benchmark tag sets from the .XML file
+ public bool DoListBenchmarkExecutables; // List out the benchmark exectubles from the .XML file
+ public int NumberOfRunsPerBenchmark; // Number of runs/iterations each benchmark should be run
+ public string ComplusVersion; // COMPlus_VERSION for desktop CLR hosted runs (optional).
+ public string BenchmarksRootDirectory; // Root directory for benchmark tree specified in .XML file.
+ public string BenchmarkXmlFileName; // Benchmark .XML filename (default coreclr_benchmarks.xml)
+ public string BenchmarkCsvFileName; // Benchmark output .CSV filename (default coreclr_benchmarks.csv)
+ public string SuiteName; // Specific benchmark suite name to be executed (optional).
+ public List<string> IncludeBenchmarkList; // List of specific benchmarks to be included (optional)
+ public List<string> ExcludeBenchmarkList; // List of specific benchmarks to be excluded (optional)
+ public List<string> IncludeTagList; //List of specific benchmark tags to be included (optional)
+ public List<string> ExcludeTagList; //List of specific benchmark tags to be excluded (optional)
+ }
+
+ // Benchmark System - actual benchmark system. Includes the controls, the command processer, main
+ // execution engine, benchmarks lists, selected benchmark lists,
+ // benchmark suite dictionary, benchmark tag dictionary, and results table.
+
+ internal class BenchmarkSystem
+ {
+ public const bool OptionalField = true;
+
+ public Controls Controls = new Controls()
+ {
+ NumberOfRunsPerBenchmark = 1,
+ DoWarmUpRun = false,
+ DoVerbose = false,
+ Runner = "",
+ DoDebugBenchmark = false,
+ DoListBenchmarks = false,
+ DoListBenchmarkSuites = false,
+ DoListBenchmarkTagSets = false,
+ DoListBenchmarkExecutables = false,
+ DoRun = false,
+ DoRunAsTestCase = true,
+ DoPrintResults = false,
+ ComplusVersion = "",
+ SuiteName = "",
+ BenchmarksRootDirectory = "",
+ BenchmarkXmlFileName = "coreclr_benchmarks.xml",
+ BenchmarkCsvFileName = "coreclr_benchmarks.csv",
+ IncludeBenchmarkList = new List<string>(),
+ ExcludeBenchmarkList = new List<string>(),
+ IncludeTagList = new List<string>(),
+ ExcludeTagList = new List<string>()
+ };
+
+ public Dictionary<string, BenchmarkSuite>
+ BenchmarkSuiteTable = new Dictionary<string, BenchmarkSuite>();
+ public Dictionary<string, BenchmarkTagSet>
+ BenchmarkTagSetTable = new Dictionary<string, BenchmarkTagSet>();
+ public List<Benchmark>
+ BenchmarkList = new List<Benchmark>();
+ public List<Benchmark>
+ SelectedBenchmarkList = new List<Benchmark>();
+ public List<Results>
+ ResultsList = new List<Results>();
+
+ public int NumberOfBenchmarksRun;
+ public int Failures = 0;
+
+ public char[] ListSeparatorCharSet = new char[] { ',', ' ' };
+ public char[] DirectorySeparatorCharSet = new char[] { '/', '\\' };
+
+ // Main driver for benchmark system.
+
+ public static int Main(string[] args)
+ {
+ int exitCode = 0;
+
+ Console.WriteLine("RyuJIT Benchmark System");
+ try
+ {
+ BenchmarkSystem benchmarkSystem = new BenchmarkSystem();
+ benchmarkSystem.ProcessCommandLine(args);
+ benchmarkSystem.BuildBenchmarksList();
+ benchmarkSystem.SelectBenchmarks();
+ benchmarkSystem.RunBenchmarks();
+ benchmarkSystem.ReportResults();
+
+ bool doRunAsTestCase = benchmarkSystem.Controls.DoRunAsTestCase;
+ if (doRunAsTestCase)
+ {
+ exitCode = 100;
+ }
+ }
+ catch (Exception exception)
+ {
+ // Need to find portable Environment.Exit()
+ if (exception.Message == "Exit")
+ {
+ exitCode = 0;
+ }
+ else
+ {
+ Console.WriteLine("{0}", exception.ToString());
+ exitCode = -1;
+ }
+ }
+
+ return exitCode;
+ }
+
+ // Command line processor.
+
+ public void ProcessCommandLine(string[] args)
+ {
+ Controls controls = Controls;
+ try
+ {
+ for (int i = 0; i < args.Length;)
+ {
+ string arg = args[i++];
+ string benchmark;
+ string[] tags;
+ string runner;
+
+ switch (arg)
+ {
+ case "-n":
+ arg = args[i++];
+ controls.NumberOfRunsPerBenchmark = Int32.Parse(arg);
+ break;
+ case "-testcase":
+ controls.DoRun = false;
+ controls.DoPrintResults = false;
+ controls.DoRunAsTestCase = true;
+ break;
+ case "-run":
+ controls.DoRun = true;
+ controls.DoPrintResults = true;
+ controls.DoRunAsTestCase = false;
+ break;
+ case "-norun":
+ controls.DoRun = false;
+ controls.DoPrintResults = true;
+ controls.DoRunAsTestCase = false;
+ break;
+ case "-w":
+ controls.DoWarmUpRun = true;
+ break;
+ case "-v":
+ controls.DoVerbose = true;
+ break;
+ case "-r":
+ arg = args[i++];
+ controls.BenchmarksRootDirectory = PlatformSpecificDirectoryName(arg);
+ break;
+ case "-f":
+ arg = args[i++];
+ controls.BenchmarkXmlFileName = arg;
+ break;
+ case "-csvfile":
+ arg = args[i++];
+ controls.BenchmarkCsvFileName = arg;
+ break;
+ case "-s":
+ arg = args[i++];
+ controls.SuiteName = arg;
+ break;
+ case "-i":
+ arg = args[i++];
+ benchmark = arg;
+ controls.IncludeBenchmarkList.Add(benchmark);
+ break;
+ case "-e":
+ arg = args[i++];
+ benchmark = arg;
+ controls.ExcludeBenchmarkList.Add(benchmark);
+ break;
+ case "-list":
+ controls.DoListBenchmarks = true;
+ controls.DoRunAsTestCase = false;
+ break;
+ case "-listsuites":
+ controls.DoListBenchmarkSuites = true;
+ controls.DoRunAsTestCase = false;
+ break;
+ case "-listtags":
+ controls.DoListBenchmarkTagSets = true;
+ controls.DoRunAsTestCase = false;
+ break;
+ case "-listexes":
+ controls.DoListBenchmarkExecutables = true;
+ controls.DoRunAsTestCase = false;
+ break;
+ case "-tags":
+ arg = args[i++];
+ tags = arg.Split(ListSeparatorCharSet, StringSplitOptions.RemoveEmptyEntries);
+ controls.IncludeTagList.AddRange(tags);
+ break;
+ case "-notags":
+ arg = args[i++];
+ tags = arg.Split(ListSeparatorCharSet, StringSplitOptions.RemoveEmptyEntries);
+ controls.ExcludeTagList.AddRange(tags);
+ break;
+ case "-runner":
+ arg = args[i++];
+ runner = arg;
+ controls.Runner = runner;
+ break;
+ case "-debug":
+ controls.DoDebugBenchmark = true;
+ break;
+ case "-complus_version":
+ arg = args[i++];
+ controls.ComplusVersion = arg;
+ break;
+ default:
+ throw new Exception("invalid argument: " + arg);
+ }
+ }
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine("Exception: {0}", exception);
+ Usage();
+ }
+ }
+
+ // Print out usage and exit.
+
+ public void Usage()
+ {
+ Console.WriteLine("");
+ Console.WriteLine("Usage: RunBenchmarks [options]");
+ Console.WriteLine("");
+ Console.WriteLine(" options: ");
+ Console.WriteLine("");
+ Console.WriteLine(" -f <xmlFile> specify benchmark xml file (default coreclr_benchmarks.xml)");
+ Console.WriteLine(" -n <number> specify number of runs for each benchmark (default is 1)");
+ Console.WriteLine(" -w specify that warmup run should be done first");
+ Console.WriteLine(" -v run in verbose mode");
+ Console.WriteLine(" -r <rootDir> specify root directory to run from");
+ Console.WriteLine(" -s <suite> specify a single benchmark suite to run (by name)");
+ Console.WriteLine(" -i <benchmark> specify benchmark to include by name (multiple -i's allowed)");
+ Console.WriteLine(" -e <benchmark> specify benchmark to exclude by name (multiple -e's allowed)");
+ Console.WriteLine(" -list prints a list of the benchmark names and does nothing else");
+ Console.WriteLine(" -listsuites prints a list of the suite names and does nothing else");
+ Console.WriteLine(" -listtags prints a list of the tag names and does nothing else");
+ Console.WriteLine(" -listexes prints a list of the benchmark executables and does nothing else");
+ Console.WriteLine(" -runner runner to be used to run benchmarks (e.g. corerun, default is DesktopCLR)");
+ Console.WriteLine(" -complus_version <version> run benchmarks on particular DesktopCLR version");
+ Console.WriteLine(" -run run benchmarks");
+ Console.WriteLine(" -norun prints what would be run, but nothing is executed");
+ Console.WriteLine(" -testcase run as CoreCLR test case (default)");
+ Console.WriteLine(" -norun prints what would be run, but don't run benchmarks");
+ Console.WriteLine(" -tags <tags> specify benchmarks with tags to include");
+ Console.WriteLine(" -notags <tags> specify benchmarks with tags to exclude");
+ Console.WriteLine(" -csvfile specify name of Comma Seperated Value output file (default coreclr_benchmarks.csv)");
+
+ Exit(-1);
+ }
+
+ // Add a benchmark to the list of benchmarks read in from the .XML file.
+
+ public void AddBenchmark
+ (
+ string name,
+ string suiteName,
+ string tags,
+ string workingDirectory,
+ string exeName,
+ string exeArgs,
+ bool doRunInShell,
+ bool useSSE,
+ bool useAVX,
+ int expectedResults
+ )
+ {
+ BenchmarkSuite benchmarkSuite;
+ BenchmarkTagSet benchmarkTagSet;
+ Benchmark benchmark;
+
+ benchmark = new Benchmark(name, suiteName, tags,
+ workingDirectory, exeName, exeArgs, doRunInShell, useSSE, useAVX, expectedResults);
+ BenchmarkList.Add(benchmark);
+
+ if (!BenchmarkSuiteTable.TryGetValue(suiteName, out benchmarkSuite))
+ {
+ benchmarkSuite = new BenchmarkSuite(suiteName);
+ BenchmarkSuiteTable.Add(suiteName, benchmarkSuite);
+ }
+ benchmarkSuite.BenchmarkList.Add(benchmark);
+
+ string[] tagList = tags.Split(ListSeparatorCharSet, StringSplitOptions.RemoveEmptyEntries);
+ foreach (string tag in tagList)
+ {
+ if (!BenchmarkTagSetTable.TryGetValue(tag, out benchmarkTagSet))
+ {
+ benchmarkTagSet = new BenchmarkTagSet(tag);
+ BenchmarkTagSetTable.Add(tag, benchmarkTagSet);
+ }
+ benchmarkTagSet.BenchmarkList.Add(benchmark);
+ }
+ }
+
+ // XML processing, select a single node given root node and xpath field name.
+
+ public XmlNode SelectSingleNode
+ (
+ XmlNode node,
+ string xpath
+ )
+ {
+#if DESKTOP
+ return node.SelectSingleNode(xpath);
+#else
+ return XmlDocumentXPathExtensions.SelectSingleNode(node, xpath);
+#endif
+ }
+
+ // XML processing, get a string field value given a node and xpath field name.
+ // Can be optional field.
+
+ public string GetField
+ (
+ XmlNode node,
+ string xpath,
+ bool optional = false
+ )
+ {
+ XmlNode fieldNode = SelectSingleNode(node, xpath);
+ if (fieldNode == null)
+ {
+ if (optional)
+ {
+ return "";
+ }
+ throw new Exception("missing field: " + xpath);
+ }
+
+ return fieldNode.InnerText;
+ }
+
+ // XML processing, get a boolean field value given a node and xpath field name.
+ // Can be optional field.
+
+ public bool GetBooleanField
+ (
+ XmlNode node,
+ string xpath,
+ bool optional = false
+ )
+ {
+ string value = GetField(node, xpath, optional);
+
+ if (value == "true")
+ return true;
+ if (value == "false")
+ return false;
+ if (optional)
+ return false;
+
+ throw new Exception("bad boolean value: " + value);
+ }
+
+ // XML processing, get an integer field value given a node and xpath field name.
+ // Can be optional field.
+
+ public int GetIntegerField
+ (
+ XmlNode node,
+ string xpath,
+ bool optional = false
+ )
+ {
+ string value = GetField(node, xpath, optional);
+
+ if (value != "")
+ {
+ int number = Int32.Parse(value);
+ return number;
+ }
+ if (optional)
+ return 0;
+
+ throw new Exception("bad integer value: " + value);
+ }
+
+ // XML processing, select a list of nodes given root node and xpath field name.
+
+ public XmlNodeList SelectNodes
+ (
+ XmlNode node,
+ string xpath
+ )
+ {
+#if DESKTOP
+ return node.SelectNodes(xpath);
+#else
+ return XmlDocumentXPathExtensions.SelectNodes(node, xpath);
+#endif
+ }
+
+ // XML processing, get a list of nodes given root node and xpath field name.
+
+ public XmlNodeList GetList
+ (
+ XmlNode node,
+ string xpath
+ )
+ {
+ return SelectNodes(node, xpath);
+ }
+
+ // Exit benchmark system with specified exit code.
+
+ public int Exit(int exitCode)
+ {
+ // Need to find portable Environment.Exit()
+ switch (exitCode)
+ {
+ case 0:
+ case -1:
+ case -2:
+ throw new Exception("Exit");
+ default:
+ throw new Exception("BadExit");
+ }
+ }
+
+ // Constructed platform specific field name given either Unix style or Windows style
+ // directory name.
+
+ public string PlatformSpecificDirectoryName
+ (
+ string directoryName
+ )
+ {
+ if (directoryName == "")
+ return "";
+
+ string[] path = directoryName.Split(DirectorySeparatorCharSet,
+ StringSplitOptions.RemoveEmptyEntries);
+ string platformSpecificDirectoryName = System.IO.Path.Combine(path);
+
+ bool absolutePath = false;
+ char firstChar = directoryName[0];
+
+ for (int i = 0; i < DirectorySeparatorCharSet.Length; i++)
+ {
+ if (firstChar == DirectorySeparatorCharSet[i])
+ {
+ absolutePath = true;
+ break;
+ }
+ }
+
+ if (absolutePath)
+ {
+ platformSpecificDirectoryName = (Path.DirectorySeparatorChar + platformSpecificDirectoryName);
+ }
+
+ return platformSpecificDirectoryName;
+ }
+
+ // Build list of benchmarks by reading in and processing .XML file.
+
+ public void BuildBenchmarksList()
+ {
+ bool doRunAsTestCase = Controls.DoRunAsTestCase;
+ string benchmarksRootDirectory = Controls.BenchmarksRootDirectory;
+ string benchmarkXmlFileName = Controls.BenchmarkXmlFileName;
+ string benchmarkXmlFullFileName;
+
+ string benchmarkRootDirectoryName;
+ string benchmarkSuiteName;
+ string benchmarkDirectoryName;
+ string benchmarkName;
+ string benchmarkExecutableName;
+ string benchmarkArgs;
+ bool doRunInShell;
+ bool useSSE;
+ bool useAVX;
+ int expectedResults;
+ string tags;
+
+ // If we aren't being asked to run benchmarks or print results
+ // then we must be being executed as a simple CoreCLR test case.
+ // Don't bother reading XML file.
+
+ if (doRunAsTestCase)
+ {
+ return;
+ }
+
+ benchmarkXmlFullFileName = benchmarkXmlFileName;
+
+ // Load XML description of benchmarks.
+
+ XmlDocument benchmarkXml = new XmlDocument();
+ var xmlFile = new FileStream(benchmarkXmlFullFileName, FileMode.Open, FileAccess.Read);
+ benchmarkXml.Load(xmlFile);
+
+ // Get root directory for benchmark system. Command line argument overrides
+ // specification in benchmark control file.
+
+ benchmarkRootDirectoryName = Controls.BenchmarksRootDirectory;
+ if (benchmarkRootDirectoryName == "")
+ {
+ benchmarkRootDirectoryName = GetField(benchmarkXml.DocumentElement, "benchmark-root-directory");
+ Controls.BenchmarksRootDirectory = benchmarkRootDirectoryName;
+ }
+ benchmarkRootDirectoryName = PlatformSpecificDirectoryName(benchmarkRootDirectoryName);
+ Controls.BenchmarksRootDirectory = benchmarkRootDirectoryName;
+
+ // Process each benchmark suite in the list of benchmark suites.
+
+ XmlNodeList benchmarkSuiteList = GetList(benchmarkXml.DocumentElement, "benchmark-suite");
+ foreach (XmlNode benchmarkSuite in benchmarkSuiteList)
+ {
+ benchmarkSuiteName = GetField(benchmarkSuite, "name");
+
+ //Process each benchmark in benchmark suite.
+
+ XmlNodeList benchmarkList = GetList(benchmarkSuite, "benchmark");
+ foreach (XmlNode benchmark in benchmarkList)
+ {
+ benchmarkName = GetField(benchmark, "name");
+ benchmarkDirectoryName = GetField(benchmark, "directory", OptionalField);
+ benchmarkDirectoryName = PlatformSpecificDirectoryName(benchmarkDirectoryName);
+ benchmarkExecutableName = GetField(benchmark, "executable");
+ benchmarkArgs = GetField(benchmark, "args", OptionalField);
+ useSSE = GetBooleanField(benchmark, "useSSE", OptionalField);
+ useAVX = GetBooleanField(benchmark, "useAVX", OptionalField);
+ expectedResults = GetIntegerField(benchmark, "expected-results", OptionalField);
+ doRunInShell = GetBooleanField(benchmark, "run-in-shell", OptionalField);
+ tags = GetField(benchmark, "tags", OptionalField);
+ AddBenchmark(benchmarkName, benchmarkSuiteName, tags, benchmarkDirectoryName,
+ benchmarkExecutableName, benchmarkArgs, doRunInShell, useSSE, useAVX, expectedResults);
+ }
+ }
+
+ // Process early out controls that just do listing.
+
+ if (Controls.DoListBenchmarks)
+ {
+ ListBenchmarks();
+ Exit(-2);
+ }
+ if (Controls.DoListBenchmarkSuites)
+ {
+ ListBenchmarkSuites();
+ Exit(-2);
+ }
+ if (Controls.DoListBenchmarkTagSets)
+ {
+ ListBenchmarkTagSets();
+ Exit(-2);
+ }
+ if (Controls.DoListBenchmarkExecutables)
+ {
+ ListBenchmarkExecutables();
+ Exit(-2);
+ }
+ }
+
+ // Print out list of benchmarks read in.
+
+ public void ListBenchmarks()
+ {
+ Console.WriteLine("Benchmark List");
+ foreach (Benchmark benchmark in BenchmarkList)
+ {
+ Console.WriteLine("{0}", benchmark.Name);
+ Console.WriteLine(" Suite: {0}", benchmark.SuiteName);
+ Console.WriteLine(" WorkingDirectory: {0}", benchmark.WorkingDirectory);
+ Console.WriteLine(" ExeName: {0}", benchmark.ExeName);
+ Console.WriteLine(" ExeArgs: {0}", benchmark.ExeArgs);
+ Console.WriteLine(" RunInShell: {0}", benchmark.DoRunInShell);
+ Console.WriteLine(" UseSSE: {0}", benchmark.UseSSE);
+ Console.WriteLine(" UseAVX: {0}", benchmark.UseAVX);
+ Console.WriteLine(" Tags: {0}", benchmark.Tags);
+ }
+ }
+
+ // Print out list of benchmark suites read in.
+
+ public void ListBenchmarkSuites()
+ {
+ Console.WriteLine("Benchmark Suite List");
+ var benchmarkSuiteList = BenchmarkSuiteTable.Keys;
+ foreach (var suiteName in benchmarkSuiteList)
+ {
+ Console.WriteLine("{0}", suiteName);
+ }
+ }
+
+ // Print out list of benchmark tags read in.
+
+ public void ListBenchmarkTagSets()
+ {
+ Console.WriteLine("Benchmark TagSet List");
+ var benchmarkTagSetList = BenchmarkTagSetTable.Keys;
+ foreach (var tagName in benchmarkTagSetList)
+ {
+ Console.WriteLine("{0}", tagName);
+ }
+ }
+
+ // Print out list of benchmark executables read in.
+
+ public void ListBenchmarkExecutables()
+ {
+ Console.WriteLine("Benchmark Executable List");
+ var benchmarkList = BenchmarkList;
+ foreach (var benchmark in benchmarkList)
+ {
+ string benchmarksRootDirectory = Controls.BenchmarksRootDirectory;
+ string benchmarkDirectory = System.IO.Path.Combine(benchmarksRootDirectory, benchmark.WorkingDirectory);
+ string workingDirectory = benchmarkDirectory;
+ string executableName = System.IO.Path.Combine(workingDirectory, benchmark.ExeName);
+
+ Console.WriteLine("{0}", executableName);
+ }
+ }
+
+ // Select benchmarks to run based on controls for suite, tag, or specfic
+ // benchmark inclusion/exclusion.
+
+ public void SelectBenchmarks()
+ {
+ List<Benchmark> benchmarkList = BenchmarkList;
+ List<string> includeBenchmarkList = Controls.IncludeBenchmarkList;
+ List<string> excludeBenchmarkList = Controls.ExcludeBenchmarkList;
+ List<string> includeTagList = Controls.IncludeTagList;
+ List<string> excludeTagList = Controls.ExcludeTagList;
+ string suiteName = Controls.SuiteName;
+
+ if (suiteName != "")
+ {
+ BenchmarkSuite benchmarkSuite = null;
+
+ if (!BenchmarkSuiteTable.TryGetValue(suiteName, out benchmarkSuite))
+ {
+ throw new Exception("bad suite name: " + suiteName);
+ }
+ benchmarkList = benchmarkSuite.BenchmarkList;
+ }
+
+ foreach (Benchmark benchmark in benchmarkList)
+ {
+ string benchmarkName = benchmark.Name;
+ bool include = true;
+
+ if (includeBenchmarkList.Count > 0)
+ {
+ include = false;
+ if (includeBenchmarkList.Contains(benchmarkName))
+ {
+ include = true;
+ }
+ }
+
+ if (include && (excludeBenchmarkList.Count > 0))
+ {
+ if (excludeBenchmarkList.Contains(benchmarkName))
+ {
+ include = false;
+ }
+ }
+
+ if (include && (excludeTagList.Count > 0))
+ {
+ foreach (string tag in excludeTagList)
+ {
+ BenchmarkTagSet benchmarkTagSet = null;
+
+ if (!BenchmarkTagSetTable.TryGetValue(tag, out benchmarkTagSet))
+ {
+ throw new Exception("bad tag: " + tag);
+ }
+
+ List<Benchmark> excludeTagBenchmarkList = benchmarkTagSet.BenchmarkList;
+
+ if (excludeTagBenchmarkList.Contains(benchmark))
+ {
+ include = false;
+ }
+ }
+ }
+
+ if (include)
+ {
+ SelectedBenchmarkList.Add(benchmark);
+ }
+ }
+ }
+
+ // Run benchmark - actually run benchmark the specified number of times and using the specified
+ // controls and return results.
+
+ public Results RunBenchmark(Benchmark benchmark)
+ {
+ bool doRun = Controls.DoRun;
+ int numberOfRuns = Controls.NumberOfRunsPerBenchmark;
+ bool doWarmUpRun = Controls.DoWarmUpRun;
+ string runner = Controls.Runner;
+ bool doDebugBenchmark = Controls.DoDebugBenchmark;
+ bool doVerbose = Controls.DoVerbose;
+ string complusVersion = Controls.ComplusVersion;
+ string benchmarksRootDirectory = Controls.BenchmarksRootDirectory;
+ string benchmarkDirectory = System.IO.Path.Combine(benchmarksRootDirectory, benchmark.WorkingDirectory);
+ bool doRunInShell = benchmark.DoRunInShell;
+ bool useSSE = benchmark.UseSSE;
+ bool useAVX = benchmark.UseAVX;
+ int expectedResults = benchmark.ExpectedResults;
+ int failureResults = ~expectedResults;
+ int actualResults;
+ int failures = 0;
+
+ Results results = new Results(benchmark, numberOfRuns);
+
+ if (!doRun)
+ {
+ return results;
+ }
+
+ string workingDirectory = benchmarkDirectory;
+ string fileName = System.IO.Path.Combine(workingDirectory, benchmark.ExeName);
+ string args = benchmark.ExeArgs;
+
+ if (runner != "")
+ {
+ args = fileName + " " + args;
+ fileName = runner;
+ }
+
+ if (doDebugBenchmark)
+ {
+ args = "/debugexe " + fileName + " " + args;
+ fileName = "devenv.exe";
+ }
+
+ if (doRunInShell)
+ {
+ args = "/C " + fileName + " " + args;
+ fileName = "cmd.exe";
+ }
+
+ if (doVerbose)
+ {
+ Console.WriteLine("Running benchmark {0} ...", benchmark.Name);
+ Console.WriteLine("Invoking: {0} {1}", fileName, args);
+ }
+
+ for (int run = (doWarmUpRun) ? 0 : 1; run <= numberOfRuns; run++)
+ {
+ ProcessStartInfo startInfo = new ProcessStartInfo()
+ {
+ FileName = fileName,
+ Arguments = args,
+ WorkingDirectory = workingDirectory,
+ UseShellExecute = false
+ };
+
+ if (complusVersion != "")
+ {
+ startInfo.Environment["COMPlus_Version"] = complusVersion;
+ startInfo.Environment["COMPlus_DefaultVersion"] = complusVersion;
+ }
+ if (useSSE)
+ {
+ startInfo.Environment["COMPlus_FeatureSIMD"] = "1";
+ startInfo.Environment["COMPlus_EnableAVX"] = "0";
+ }
+ if (useAVX)
+ {
+ startInfo.Environment["COMPlus_FeatureSIMD"] = "1";
+ startInfo.Environment["COMPlus_EnableAVX"] = "1";
+ }
+ startInfo.Environment["COMPlus_gcConcurrent"] = "0";
+ startInfo.Environment["COMPlus_gcServer"] = "0";
+ startInfo.Environment["COMPlus_NoGuiOnAssert"] = "1";
+ startInfo.Environment["COMPlus_BreakOnUncaughtException"] = "0";
+
+ var clockTime = Stopwatch.StartNew();
+ int exitCode = 0;
+ try
+ {
+ using (var proc = Process.Start(startInfo))
+ {
+ proc.EnableRaisingEvents = true;
+ proc.WaitForExit();
+ exitCode = proc.ExitCode;
+ }
+ this.NumberOfBenchmarksRun++;
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine("Could not launch test {0} exception: {1}",
+ startInfo.FileName, exception);
+ exitCode = failureResults;
+ }
+ clockTime.Stop();
+ actualResults = exitCode;
+
+ long time = clockTime.ElapsedMilliseconds;
+ if (actualResults != expectedResults)
+ {
+ failures++;
+ time = 0;
+ }
+ results.Times[run] = time;
+
+ if (doVerbose)
+ {
+ Console.Write("Iteration benchmark {0} ", benchmark.Name);
+ if (actualResults == expectedResults)
+ {
+ Console.Write("elapsed time {0}ms", time);
+ }
+ else
+ {
+ Console.Write("FAILED(expected={0}, actual={1})", expectedResults, actualResults);
+ }
+ if (run == 0)
+ {
+ Console.Write(" (warmup)");
+ }
+ Console.WriteLine("");
+ }
+ }
+
+ // Calculate min, max, avg, and std devation.
+
+ long sum = 0;
+ long minimum = results.Times[1];
+ long maximum = minimum;
+
+ for (int run = 1; run <= numberOfRuns; run++)
+ {
+ long time = results.Times[run];
+
+ sum += time;
+ minimum = Math.Min(minimum, time);
+ maximum = Math.Max(maximum, time);
+ }
+
+ long average = sum / (long)numberOfRuns;
+ double standardDeviation = 0.0;
+
+ if (numberOfRuns > 1)
+ {
+ double s = 0.0;
+ double a = (double)average;
+ double n = (double)numberOfRuns;
+ for (int run = 1; run <= numberOfRuns; run++)
+ {
+ double time = (double)results.Times[run];
+ double t = (time - a);
+ s += (t * t);
+ }
+ double variance = s / n;
+
+ if (a == 0.0)
+ {
+ standardDeviation = 0.0;
+ }
+ else
+ {
+ standardDeviation = 100.0 * (Math.Sqrt(variance) / a); // stddev as a percentage
+ standardDeviation = Math.Round(standardDeviation, 2, MidpointRounding.AwayFromZero);
+ }
+ }
+
+ // Record results and return.
+
+ results.Average = average;
+ results.Minimum = minimum;
+ results.Maximum = maximum;
+ results.StandardDeviation = standardDeviation;
+ results.Failures = failures;
+
+ return results;
+ }
+
+ // Run the list of selected benchmarks.
+
+ public void RunBenchmarks()
+ {
+ bool doVerbose = Controls.DoVerbose;
+
+ if (doVerbose)
+ {
+ Console.WriteLine("Run benchmarks ...");
+ }
+
+ foreach (Benchmark benchmark in SelectedBenchmarkList)
+ {
+ Results results = RunBenchmark(benchmark);
+ Failures += results.Failures;
+ ResultsList.Add(results);
+ }
+ }
+
+ // Report the results of the benchmark run.
+
+ public void ReportResults()
+ {
+ bool doVerbose = Controls.DoVerbose;
+ bool doPrintResults = Controls.DoPrintResults;
+ string benchmarkCsvFileName = Controls.BenchmarkCsvFileName;
+ int numberOfBenchmarksRun = this.NumberOfBenchmarksRun;
+ int numberOfFailures = this.Failures;
+ int numberOfPasses = numberOfBenchmarksRun - numberOfFailures;
+ int numberOfRunsPerBenchmark = Controls.NumberOfRunsPerBenchmark;
+ int numberOfFailuresPerBenchmark = 0;
+
+ if (!doPrintResults)
+ {
+ return;
+ }
+
+ if (doVerbose)
+ {
+ Console.WriteLine("Generating benchmark report on {0}", benchmarkCsvFileName);
+ }
+
+ using (TextWriter outputFile = File.CreateText(benchmarkCsvFileName))
+ {
+ outputFile.WriteLine("Benchmark,Minimum(ms),Maximum(ms),Average(ms),StdDev(%),Passed/Failed(#)");
+ foreach (Results results in ResultsList)
+ {
+ string name = results.Benchmark.Name;
+ outputFile.Write("{0},", name);
+
+ long minimum = results.Minimum;
+ long maximum = results.Maximum;
+ long average = results.Average;
+ double standardDeviation = results.StandardDeviation;
+ outputFile.Write("{0},{1},{2},{3}", minimum, maximum, average, standardDeviation);
+
+ numberOfFailuresPerBenchmark = results.Failures;
+ numberOfPasses = (numberOfPasses < 0) ? 0 : numberOfPasses;
+ if (numberOfFailuresPerBenchmark > 0)
+ {
+ outputFile.Write(",FAILED({0})", numberOfFailuresPerBenchmark);
+ }
+ else
+ {
+ outputFile.Write(",PASSED({0})", numberOfRunsPerBenchmark);
+ }
+ outputFile.WriteLine("");
+ }
+
+ outputFile.WriteLine("TOTAL BENCHMARKS({0}), PASSED({1}), FAILED({2})",
+ numberOfBenchmarksRun, numberOfPasses, numberOfFailures);
+ }
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.csproj b/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.csproj
new file mode 100644
index 0000000000..64ceed990a
--- /dev/null
+++ b/tests/src/JIT/Performance/RunBenchmarks/RunBenchmarks.csproj
@@ -0,0 +1,42 @@
+<?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' ">
+ </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>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="RunBenchmarks.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/RunBenchmarks/benchmarks.xml b/tests/src/JIT/Performance/RunBenchmarks/benchmarks.xml
new file mode 100644
index 0000000000..7ce79e0897
--- /dev/null
+++ b/tests/src/JIT/Performance/RunBenchmarks/benchmarks.xml
@@ -0,0 +1,812 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<benchmark-system>
+ <benchmark-root-directory>\tf\CodeGen\src\QA\CLR\CQPerfSuite\benchmarks</benchmark-root-directory>
+ <benchmark-suite>
+ <name>Roslyn</name>
+ <benchmark>
+ <name>Roslyn</name>
+ <directory>.\RoslynSep13\SourcesSnapShot</directory>
+ <executable>..\CompilerBinaries\rcsc.exe</executable>
+ <args>/nologo /optimize+ /noconfig @Repro.rsp</args>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>System.XML</name>
+ <benchmark>
+ <name>System.XML</name>
+ <directory>.\System.XML\x86ret</directory>
+ <executable>SimpleTest.exe</executable>
+ <args>2000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>SharpChess</name>
+ <benchmark>
+ <name>SharpChess</name>
+ <directory>.\SharpChess</directory>
+ <executable>SharpChess2.exe</executable>
+ <args>6 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>V8</name>
+ <benchmark>
+ <name>v8-richards</name>
+ <directory>.\v8\richards</directory>
+ <executable>richards.exe</executable>
+ <args>20000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>v8-crypto</name>
+ <directory>.\v8\crypto</directory>
+ <executable>crypto.exe</executable>
+ <args>200 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>v8-deltablue</name>
+ <directory>.\v8\deltablue</directory>
+ <executable>deltablue.exe</executable>
+ <args>1000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>BIO</name>
+ <benchmark>
+ <name>bio-mums</name>
+ <directory>.\bio\test</directory>
+ <executable>MumUtil.exe</executable>
+ <args>/v /o:mum.out ..\TestData\NC_000913.bd.fasta ..\TestData\NC_000913.bd_10xWithError_1.fa &gt; out 2&gt;&amp;1</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Fractals</name>
+ <benchmark>
+ <name>Fractals</name>
+ <directory>.\Fractals</directory>
+ <executable>FractalPerf.exe</executable>
+ <args>&gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Spec</name>
+ <benchmark>
+ <name>bzip2</name>
+ <directory>.\bzip2</directory>
+ <executable>bzip2.exe</executable>
+ <args>mscorlib.il &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Crafty</name>
+ <directory>.\crafty</directory>
+ <executable>crafty.exe</executable>
+ <args>&lt; crafty.in &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Mono</name>
+ <benchmark>
+ <name>mono-binarytrees</name>
+ <directory>.\mono</directory>
+ <executable>binarytrees.csharp.exe</executable>
+ <args>20 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>mono-chameneos-redux</name>
+ <directory>.\mono</directory>
+ <executable>chameneosredux.csharp.exe</executable>
+ <args>6000000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>mono-fannkuch-redux</name>
+ <directory>.\mono</directory>
+ <executable>fannkuchredux.csharp-3.exe</executable>
+ <args>12 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>mono-fasta</name>
+ <directory>.\mono</directory>
+ <executable>fasta.csharp-2.exe</executable>
+ <args>25000000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>mono-fasta-redux</name>
+ <directory>.\mono</directory>
+ <executable>fastaredux.csharp.exe</executable>
+ <args>25000000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>mono-knucleotide</name>
+ <directory>.\mono</directory>
+ <executable>knucleotide.csharp-4.exe</executable>
+ <args>0 &lt; knucleotide-input25000000.txt &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>mono-nbody</name>
+ <directory>.\mono</directory>
+ <executable>nbody.csharp-3.exe</executable>
+ <args>50000000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>mono-regexdna</name>
+ <directory>.\mono</directory>
+ <executable>regexdna.csharp-6.exe</executable>
+ <args>0 &lt; regexdna-input2500000.txt &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>mono-revcomp</name>
+ <directory>.\mono</directory>
+ <executable>revcomp.csharp.exe</executable>
+ <args>0 &lt; revcomp-input25000000.txt &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>mono-spectralnorm</name>
+ <directory>.\mono</directory>
+ <executable>spectralnorm.csharp-2.exe</executable>
+ <args>5500 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>mono-threadring</name>
+ <directory>.\mono</directory>
+ <executable>threadring.csharp.exe</executable>
+ <args>2000000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>mono-pi-digits</name>
+ <directory>.\mono</directory>
+ <executable>pi-digits.exe</executable>
+ <args>10000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Benchstone</name>
+ <benchmark>
+ <name>BenchI-8queens</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>8queens.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-ackerman</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>ackerman.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-addarra2</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>addarra2.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-addarray</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>addarray.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-array1</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>array1.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-array2</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>array2.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-benche</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>benche.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-binserch</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>binserch.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-bubsort</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>bubsort.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-bubsort2</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>bubsort2.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-csieve</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>csieve.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-dhrysto</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>dhrysto.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-fib</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>fib.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-heapsort</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>heapsort.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-iniarray</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>iniarray.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-logicarr</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>logicarr.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-midpoint</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>midpoint.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-mulmtx</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>mulmtx.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-permutat</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>permutat.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-pi</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>pi.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-puzzle</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>puzzle.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-quicksrt</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>quicksrt.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-shellsrt</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>shellsrt.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-sq_mtx</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>sq_mtx.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-treesort</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>treesort.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-tree_ins</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>tree_ins.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-xpos_mtx</name>
+ <directory>.\Benchstone\BenchI</directory>
+ <executable>xpos_mtx.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-adams_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>adams_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-benchmk2</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>benchmk2.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-benchmrk</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>benchmrk.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-bisect_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>bisect_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-dmath</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>dmath.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-fft</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>fft.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-inprod_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>inprod_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-inv_mt_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>inv_mt_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-lloops</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>lloops.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-lorenz</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>lorenz.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-matinv4</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>matinv4.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-newt_e_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>newt_e_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-newt_r_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>newt_r_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-regula_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>regula_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-romber_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>romber_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-secant_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>secant_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-simpsn_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>simpsn_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-sq_mtx_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>sq_mtx_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-trap_d_d</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>trap_d_d.exe</executable>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-whetsto</name>
+ <directory>.\Benchstone\BenchF</directory>
+ <executable>whetsto.exe</executable>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>ByteMark</name>
+ <benchmark>
+ <name>ByteMark-assignjagged</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\assignjagged.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-assignrect</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\assignrect.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-bitfield</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\bitfield.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-emfclass</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\emfclass.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-emfstruct</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\emfstruct.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-four</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\four.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-huff</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\huff.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-idea</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\idea.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-lu</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\lu.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-nnetjagged</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\nnetjagged.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-nnetrect</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\nnetrect.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-numsortjagged</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\numsortjagged.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-numsortrect</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\numsortrect.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>ByteMark-stringsort</name>
+ <directory>.\bytemark</directory>
+ <executable>bytemark.exe</executable>
+ <args>-ccommands\stringsort.dat &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>CoreMark</name>
+ <benchmark>
+ <name>CoreMark</name>
+ <directory>.\CoreMark</directory>
+ <executable>coremark.exe</executable>
+ <args>0 0 0x66 160000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>SciMark</name>
+ <benchmark>
+ <name>SciMark</name>
+ <directory>.\SciMark</directory>
+ <executable>scimark-csharp.exe</executable>
+ <args>&gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>FSharpFFT</name>
+ <benchmark>
+ <name>FSharpFFT</name>
+ <directory>.\FSharpFFT</directory>
+ <executable>FSharpFFT.exe</executable>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>TrueTypeBench</name>
+ <benchmark>
+ <name>TrueTypeBench</name>
+ <directory>.\TrueTypeBench\bin\release</directory>
+ <executable>truetypebench.exe</executable>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Micro</name>
+ <benchmark>
+ <name>Micro-InlineClassConstructorHelper</name>
+ <directory>..\micros</directory>
+ <executable>InlineClassConstructorHelper.exe</executable>
+ <args>&gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Json</name>
+ <benchmark>
+ <name>Json-Serialize</name>
+ <directory>.\JSON.Net\Src\Newtonsoft.Json.BenchmarkConsole\bin\Release\Net45</directory>
+ <executable>Newtonsoft.Json.BenchmarkConsole.exe</executable>
+ <args>Serialize-JsonNet-TestClass 1500000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Json-Deserialize</name>
+ <directory>.\JSON.Net\Src\Newtonsoft.Json.BenchmarkConsole\bin\Release\Net45</directory>
+ <executable>Newtonsoft.Json.BenchmarkConsole.exe</executable>
+ <args>Deserialize-JsonNet-String 750000 &gt; out</args>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Rotate</name>
+ <benchmark>
+ <name>Rotate</name>
+ <directory>.\Rotate</directory>
+ <executable>rotate.exe</executable>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>ConsoleMandel</name>
+ <benchmark>
+ <name>ConsoleMandel-8</name>
+ <directory>.\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>8 -S -bench 2</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>ConsoleMandel-9</name>
+ <directory>.\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>9 -S -bench 2</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>ConsoleMandel-8-SSE</name>
+ <directory>.\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>8 -S -bench 2</args>
+ <useSSE>true</useSSE>
+ <tags>SIMD,SSE</tags>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>ConsoleMandel-9-SSE</name>
+ <directory>.\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>9 -S -bench 2</args>
+ <useSSE>true</useSSE>
+ <tags>SIMD,SSE</tags>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>ConsoleMandel-8-AVX</name>
+ <directory>.\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>8 -S -bench 2</args>
+ <useAVX>true</useAVX>
+ <tags>SIMD,AVX</tags>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>ConsoleMandel-9-AVX</name>
+ <directory>.\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>9 -S -bench 2</args>
+ <useAVX>true</useAVX>
+ <tags>SIMD,AVX</tags>
+ <expected-results>100</expected-results>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>RayTracer</name>
+ <benchmark>
+ <name>RayTracer</name>
+ <directory>.\RayTracer</directory>
+ <executable>RunAuto.cmd</executable>
+ <args>RayTracer.exe</args>
+ </benchmark>
+ <benchmark>
+ <name>RayTracer-SSE</name>
+ <directory>.\RayTracer</directory>
+ <executable>RunAuto.cmd</executable>
+ <args>RayTracer.exe</args>
+ <useSSE>true</useSSE>
+ <tags>SIMD,SSE</tags>
+ </benchmark>
+ <benchmark>
+ <name>RayTracer-AVX</name>
+ <directory>.\RayTracer</directory>
+ <executable>RunAuto.cmd</executable>
+ <args>RayTracer.exe</args>
+ <useAVX>true</useAVX>
+ <tags>SIMD,AVX</tags>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Math</name>
+ <benchmark>
+ <name>Functions-AbsDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>absdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-AbsSingle</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>abssingle -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-AcosDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>acosdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-AsinDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>asindouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-AtanDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>atandouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-Atan2Double</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>atan2double -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-CeilingDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>ceilingdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-CosDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>cosdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-CoshDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>coshdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-ExpDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>expdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-FloorDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>floordouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-LogDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>logdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-Log10Double</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>log10double -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-PowDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>powdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-RoundDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>rounddouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-SinDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>sindouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-SinhDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>sinhdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-SqrtDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>sqrtdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-TanDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>tandouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-TanhDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>tanhdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ </benchmark-suite>
+</benchmark-system>
diff --git a/tests/src/JIT/Performance/RunBenchmarks/build.cmd b/tests/src/JIT/Performance/RunBenchmarks/build.cmd
new file mode 100644
index 0000000000..3b8db07838
--- /dev/null
+++ b/tests/src/JIT/Performance/RunBenchmarks/build.cmd
@@ -0,0 +1,28 @@
+@setlocal
+@echo off
+
+rem *** Alternative build process for running harness on Desktop CLR on Windows.
+rem *** Otherwise, RunBenchmarks.exe is built when CoreCLR hosted tests are built.
+
+if /I "%1" == "debug" goto build_debug
+if /I "%1" == "release" goto build_release
+
+echo "Usage build {debug | release}"
+goto done
+
+:build_debug
+
+mkdir bin\Debug\desktop >NUL 2>&1
+csc /define:DESKTOP /nologo /debug /target:exe /out:bin\Debug\desktop\RunBenchmarks.exe RunBenchmarks.cs
+
+goto done
+
+:build_release
+
+mkdir bin\Release\desktop >NUL 2>&1
+csc /define:DESKTOP /nologo /debug:pdbonly /target:exe /out:bin\Release\desktop\RunBenchmarks.exe RunBenchmarks.cs
+
+goto done
+
+:done
+@endlocal
diff --git a/tests/src/JIT/Performance/RunBenchmarks/coreclr_benchmarks.xml b/tests/src/JIT/Performance/RunBenchmarks/coreclr_benchmarks.xml
new file mode 100644
index 0000000000..ebbc2ea11f
--- /dev/null
+++ b/tests/src/JIT/Performance/RunBenchmarks/coreclr_benchmarks.xml
@@ -0,0 +1,728 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<benchmark-system>
+ <benchmark-suite>
+ <name>BenchStone</name>
+ <benchmark>
+ <name>BenchI-8Queens</name>
+ <directory>.\BenchI\8Queens\8Queens</directory>
+ <executable>8Queens.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-Ackermann</name>
+ <directory>.\BenchI\Ackermann\Ackermann</directory>
+ <executable>Ackermann.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-AddArray</name>
+ <directory>.\BenchI\AddArray\AddArray</directory>
+ <executable>AddArray.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-AddArray2</name>
+ <directory>.\BenchI\AddArray2\AddArray2</directory>
+ <executable>AddArray2.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-Array1</name>
+ <directory>.\BenchI\Array1\Array1</directory>
+ <executable>Array1.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-Array2</name>
+ <directory>.\BenchI\Array2\Array2</directory>
+ <executable>Array2.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-BenchE</name>
+ <directory>.\BenchI\BenchE\BenchE</directory>
+ <executable>BenchE.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-BubbleSort</name>
+ <directory>.\BenchI\BubbleSort\BubbleSort</directory>
+ <executable>BubbleSort.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-BubbleSort2</name>
+ <directory>.\BenchI\BubbleSort2\BubbleSort2</directory>
+ <executable>BubbleSort2.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-CSieve</name>
+ <directory>.\BenchI\CSieve\CSieve</directory>
+ <executable>CSieve.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-Fib</name>
+ <directory>.\BenchI\Fib\Fib</directory>
+ <executable>Fib.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-HeapSort</name>
+ <directory>.\BenchI\HeapSort\HeapSort</directory>
+ <executable>HeapSort.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-IniArray</name>
+ <directory>.\BenchI\IniArray\IniArray</directory>
+ <executable>IniArray.exe</executable>
+ <args>2000000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-LogicArray</name>
+ <directory>.\BenchI\LogicArray\LogicArray</directory>
+ <executable>LogicArray.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-Midpoint</name>
+ <directory>.\BenchI\Midpoint\Midpoint</directory>
+ <executable>Midpoint.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-MulMatrix</name>
+ <directory>.\BenchI\MulMatrix\MulMatrix</directory>
+ <executable>MulMatrix.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-NDhrystone</name>
+ <directory>.\BenchI\NDhrystone\NDhrystone</directory>
+ <executable>NDhrystone.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-Permutate</name>
+ <directory>.\BenchI\Permutate\Permutate</directory>
+ <executable>Permutate.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-Pi</name>
+ <directory>.\BenchI\Pi\Pi</directory>
+ <executable>Pi.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-Puzzle</name>
+ <directory>.\BenchI\Puzzle\Puzzle</directory>
+ <executable>Puzzle.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-QuickSort</name>
+ <directory>.\BenchI\QuickSort\QuickSort</directory>
+ <executable>QuickSort.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-TreeSort</name>
+ <directory>.\BenchI\TreeSort\TreeSort</directory>
+ <executable>TreeSort.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-TreeInsert</name>
+ <directory>.\BenchI\TreeInsert\TreeInsert</directory>
+ <executable>TreeInsert.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchI-XposMatrix</name>
+ <directory>.\BenchI\XposMatrix\XposMatrix</directory>
+ <executable>XposMatrix.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-Adams</name>
+ <directory>.\BenchF\Adams\Adams</directory>
+ <executable>Adams.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-BenchMk2</name>
+ <directory>.\BenchF\BenchMk2\BenchMk2</directory>
+ <executable>BenchMk2.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-BenchMrk</name>
+ <directory>.\BenchF\BenchMrk\BenchMrk</directory>
+ <executable>BenchMrk.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-Bisect</name>
+ <directory>.\BenchF\Bisect\Bisect</directory>
+ <executable>Bisect.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-DMath</name>
+ <directory>.\BenchF\DMath\DMath</directory>
+ <executable>DMath.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-FFT</name>
+ <directory>.\BenchF\FFT\FFT</directory>
+ <executable>FFT.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-InProd</name>
+ <directory>.\BenchF\InProd\InProd</directory>
+ <executable>InProd.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-InvMt</name>
+ <directory>.\BenchF\InvMt\InvMt</directory>
+ <executable>InvMt.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-LLoops</name>
+ <directory>.\BenchF\LLoops\LLoops</directory>
+ <executable>LLoops.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-Lorenz</name>
+ <directory>.\BenchF\Lorenz\Lorenz</directory>
+ <executable>Lorenz.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-MatInv4</name>
+ <directory>.\BenchF\MatInv4\MatInv4</directory>
+ <executable>MatInv4.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-NewtE</name>
+ <directory>.\BenchF\NewtE\NewtE</directory>
+ <executable>NewtE.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-NewtR</name>
+ <directory>.\BenchF\NewtR\NewtR</directory>
+ <executable>NewtR.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-Regula</name>
+ <directory>.\BenchF\Regula\Regula</directory>
+ <executable>Regula.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-Romber</name>
+ <directory>.\BenchF\Romber\Romber</directory>
+ <executable>Romber.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-Secant</name>
+ <directory>.\BenchF\Secant\Secant</directory>
+ <executable>Secant.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-Simpsn</name>
+ <directory>.\BenchF\Simpsn\Simpsn</directory>
+ <executable>Simpsn.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-SqMtx</name>
+ <directory>.\BenchF\SqMtx\SqMtx</directory>
+ <executable>SqMtx.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-Trap</name>
+ <directory>.\BenchF\Trap\Trap</directory>
+ <executable>Trap.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>BenchF-Whetsto</name>
+ <directory>.\BenchF\Whetsto\Whetsto</directory>
+ <executable>Whetsto.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>BenchmarksGame</name>
+ <benchmark>
+ <name>binarytrees</name>
+ <directory>.\BenchmarksGame\binarytrees\binarytrees</directory>
+ <executable>binarytrees.exe</executable>
+ <args>&gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>fasta</name>
+ <directory>.\BenchmarksGame\fasta\fasta</directory>
+ <executable>fasta.exe</executable>
+ <args>16000000 &gt;out 2&gt;&amp;1</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>fastaredux</name>
+ <directory>.\BenchmarksGame\fastaredux\fastaredux</directory>
+ <executable>fastaredux.exe</executable>
+ <args>60000000 &gt;out 2&gt;&amp;1</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>nbody</name>
+ <directory>.\BenchmarksGame\nbody\nbody</directory>
+ <executable>nbody.exe</executable>
+ <args>20000000 &gt;out 2&gt;&amp;1</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>pidigits</name>
+ <directory>.\BenchmarksGame\pidigits\pi-digits</directory>
+ <executable>pi-digits.exe</executable>
+ <args>1300 &gt;out 2&gt;&amp;1</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>spectralnorm</name>
+ <directory>.\BenchmarksGame\spectralnorm\spectralnorm</directory>
+ <executable>spectralnorm.exe</executable>
+ <args>5000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Burgers</name>
+ <benchmark>
+ <name>Burgers</name>
+ <directory>.\Burgers\Burgers</directory>
+ <executable>Burgers.exe</executable>
+ <args>&gt;out 2&gt;&amp;1; </args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Bytemark</name>
+ <benchmark>
+ <name>Bytemark-assignjagged</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-c\git\repos\DotNet\coreclr\tests\src\JIT\Performance\CodeQuality\Bytemark\commands\assignjagged.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-assignrect</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-c\git\repos\DotNet\coreclr\tests\src\JIT\Performance\CodeQuality\Bytemark\commands\assignrect.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-bitfield</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\bitfield.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-emfclass</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\emfclass.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-emfstruct</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\emfstruct.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-four</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\four.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-huff</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\huff.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-idea</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\idea.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ <tags>broken</tags>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-lu</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\lu.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-nnetjagged</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\nnetjagged.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-nnetrect</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\nnetrect.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-numsortjagged</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\numsortjagged.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-numsortrect</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\numsortrect.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ <benchmark>
+ <name>Bytemark-stringsort</name>
+ <directory>.\Bytemark\Bytemark</directory>
+ <executable>Bytemark.exe</executable>
+ <args>-ccommands\stringsort.dat &gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>FractalPerf</name>
+ <benchmark>
+ <name>FractalPerf</name>
+ <directory>.\FractalPerf\FractalPerf</directory>
+ <executable>FractalPerf.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Linq</name>
+ <benchmark>
+ <name>Linq</name>
+ <directory>.\Linq\Linq</directory>
+ <executable>Linq.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Roslyn</name>
+ <benchmark>
+ <name>CscBench</name>
+ <directory>.\Roslyn\CscBench</directory>
+ <executable>CscBench.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>SciMark</name>
+ <benchmark>
+ <name>SciMark</name>
+ <directory>.\SciMark\SciMark</directory>
+ <executable>SciMark.exe</executable>
+ <args>&gt;out</args>
+ <expected-results>100</expected-results>
+ <run-in-shell>true</run-in-shell>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Serialization</name>
+ <benchmark>
+ <name>Deserialize</name>
+ <directory>.\Serialization\Deserialize</directory>
+ <executable>Deserialize.exe</executable>
+ <expected-results>100</expected-results>
+ <tags>broken</tags>
+ </benchmark>
+ <benchmark>
+ <name>Serialize</name>
+ <directory>.\Serialization\Serialize</directory>
+ <executable>Serialize.exe</executable>
+ <expected-results>100</expected-results>
+ <tags>broken</tags>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>SIMD</name>
+ <benchmark>
+ <name>ConsoleMandel-8</name>
+ <directory>.\SIMD\ConsoleMandel\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>8 -S -bench 2</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>ConsoleMandel-9</name>
+ <directory>.\SIMD\ConsoleMandel\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>9 -S -bench 2</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>ConsoleMandel-8-SSE</name>
+ <directory>.\SIMD\ConsoleMandel\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>8 -S -bench 2</args>
+ <expected-results>100</expected-results>
+ <useSSE>true</useSSE>
+ <tags>SIMD,SSE</tags>
+ </benchmark>
+ <benchmark>
+ <name>ConsoleMandel-9-SSE</name>
+ <directory>.\SIMD\ConsoleMandel\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>9 -S -bench 2</args>
+ <expected-results>100</expected-results>
+ <useSSE>true</useSSE>
+ <tags>SIMD,SSE</tags>
+ </benchmark>
+ <benchmark>
+ <name>ConsoleMandel-8-AVX</name>
+ <directory>.\SIMD\ConsoleMandel\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>8 -S -bench 2</args>
+ <expected-results>100</expected-results>
+ <useAVX>true</useAVX>
+ <tags>SIMD,AVX</tags>
+ </benchmark>
+ <benchmark>
+ <name>ConsoleMandel-9-AVX</name>
+ <directory>.\SIMD\ConsoleMandel\ConsoleMandel</directory>
+ <executable>ConsoleMandel.exe</executable>
+ <args>9 -S -bench 2</args>
+ <expected-results>100</expected-results>
+ <useAVX>true</useAVX>
+ <tags>SIMD,AVX</tags>
+ </benchmark>
+ <benchmark>
+ <name>RayTracer</name>
+ <directory>.\SIMD\RayTracer\RayTracer</directory>
+ <executable>RayTracer.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>V8</name>
+ <benchmark>
+ <name>Crypto</name>
+ <directory>.\V8\Crypto\Crypto</directory>
+ <executable>Crypto.exe</executable>
+ <args>500</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>DeltaBlue</name>
+ <directory>.\V8\DeltaBlue\DeltaBlue</directory>
+ <executable>DeltaBlue.exe</executable>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Richards</name>
+ <directory>.\V8\Richards\Richards</directory>
+ <executable>Richards.exe</executable>
+ <args>30000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ </benchmark-suite>
+ <benchmark-suite>
+ <name>Math</name>
+ <benchmark>
+ <name>Functions-AbsDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>absdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-AbsSingle</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>abssingle -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-AcosDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>acosdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-AsinDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>asindouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-AtanDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>atandouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-Atan2Double</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>atan2double -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-CeilingDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>ceilingdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-CosDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>cosdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-CoshDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>coshdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-ExpDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>expdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-FloorDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>floordouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-LogDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>logdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-Log10Double</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>log10double -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-PowDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>powdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-RoundDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>rounddouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-SinDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>sindouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-SinhDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>sinhdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-SqrtDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>sqrtdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-TanDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>tandouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ <benchmark>
+ <name>Functions-TanhDouble</name>
+ <directory>.\Math\Functions\Functions</directory>
+ <executable>Functions.exe</executable>
+ <args>tanhdouble -bench 1000000</args>
+ <expected-results>100</expected-results>
+ </benchmark>
+ </benchmark-suite>
+</benchmark-system>