dotnet / dotnet/fsharp

[IL Emit] Impove string null check il codegen

Open
#12,139 7 comments 0 reactions 0 assignees View on GitHub
Area-Compiler-CodeGen Feature Request
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 11h
Merged PRs (30d)
131

Description

Consider those 2 methods:

``` fsharp
let test() =
while Console.ReadLine() <> null do
Console.WriteLine(1)
```

``` csharp
static void Test()
{
while (Console.ReadLine() != null)
Console.WriteLine(1);
}
```
If we compare outputs of F# and C# compilers in IL we can see that C# does a simple nullpointer check while F# calls to String.Equals method

F# version:
``` il
// loop start
IL_0000: call string [System.Console]System.Console::ReadLine()
IL_0005: ldnull
IL_0006: call bool [netstandard]System.String::Equals(string, string)
IL_000b: brtrue.s IL_0015 // F# is emitting a String.Equals call which then will be cut by jit in runtime but it increases dll size nonetheless

IL_000d: ldc.i4.1
IL_000e: call void [System.Console]System.Console::WriteLine(int32)
IL_0013: br.s IL_0000
// end loop

IL_0015: ret
```

C# version:
``` il
// sequence point: hidden
IL_0000: br.s IL_0008
// loop start (head: IL_0008)
IL_0002: ldc.i4.1
IL_0003: call void [System.Console]System.Console::WriteLine(int32)

IL_0008: call string [System.Console]System.Console::ReadLine()
IL_000d: brtrue.s IL_0002 // C# is emitting a simply nullpointer check here
// end loop

IL_000f: ret
```

Note that C# on top of this reverses condition and useful work resulting in better jit codegen. Coincidentally this is even more simplified repro for (https://github.com/dotnet/fsharp/issues/12138).

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.