dotnet / dotnet/fsharp

Tail opcode being emitted for normal methods, destroys JIT optimizations

Open
#6,329 31 comments 11 reactions 0 assignees View on GitHub
Area-Compiler-Optimization Feature Improvement
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 22h
Merged PRs (30d)
144

Description

After a benchmarking discussion in the FSSF slack we found the main culprit for the C# / F# speed differences. `tail.` was being emitted for a non recursive method, that turns off JIT inlining and other optimizations.

Repro can be found here.

https://sharplab.io/#v2:DYLgZgzgNALiCWwA+B7ADgUwHYAIDKAnhDBgLYCwAUOtvkSaQHQBKArljPKRowMIqk0iDACc8ogG7wAxhghUqMAphwAZFAHMNo1RgkZgOALw4AgsZwAGHEhwAhHBYCMOBZSUr1W0QAoAlMZUjo7AGDA43BAQAIbaEBaExGR8KMCh0pwoWBCMAOLYojKMqvDEADzEIvBYGgB8Pk6WTZZ+ANxBwR2OANplALJhABYoACYAkoLAPgMww+OTAPJomdmMploichDw+mNYwNXVGn61ALpdOKHhWOg4/hb+F9ykAEaiOLOlxZo+ofqGIDUmm0Il0/ygEQgGhwgMqRwCRguwQiW1icjWIxGPlIUL8SOCNzQj0oTzIbxEH0GXy8vz0BhhQO8oLpwAhKBeACsGQByaII/GOSIxOIYrHsjmMAAqKDwMCqNX8eMoyORhOJimUGBwkuiiC8IPuiOVwSuKKiaPiJkSDBSaQwGXgWRy+SwhWkxVKMAqcqO9UazTaF1Jr3enxyNL+9MB+p0LIhOOhsJ9NX5xpVZuF6NMmOxuLcyOe5Mp1J+kYBjJBYIMbM5PL5gTTKqFFtFPnFUplyY0iqoQA===

Another smaller codegen issue can be seen in the IL for `ObjLog<'a>`
```
.locals init (
[0] !!a
)

IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Collections.Generic.List`1 _/TailLogger::messages
IL_0006: ldarg.2
IL_0007: stloc.0
IL_0008: ldloca.s 0
IL_000a: constrained. !!a
[...]
```
The C# IL for the same method completely does away with the arg to local dance and just uses the arg directly.

These extraneous load/store patterns confuse the JITs dataflow analysis whether things are being modified or not, hampering enregistration.

https://sharplab.io/#v2:C4LglgNgNAJiDUAfAAgBgATIIwBYDcAsAFDHIDM6ApgHYCuAtugDID2A5m5QE5OUBulCOmIBvYunQBBKOPQAhYgF9ipCsgBM8gIYBnSqw7dRsiQAcuYPluCVmYHcAA82VAD509Sjp1bOO9AC86NSUAO52Ds5YbgAU0agJAJSERBISJphqOMzsMQacPPyC6BBF0JjRHjpsiRliqWmNnt6+XgB0kjAwMfTVyRnKJA0S5JjZBo4AKq557AW8AkKli1Dok+gsAEYAVrXD6PWNTV4+fh1dMVvbbZMsAMrAFtRsMYn9+4OKQA=

If anything the focus should be on making sure `tail.` is only ever emitted for real recursive methods/functions

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.