dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.97k stars 4.65k forks source link

JIT: Generalize "downwards loop transformation" into linear function test replacement #105242

Open jakobbotsch opened 1 month ago

jakobbotsch commented 1 month ago

Today the JIT can replace loop tests by downwards counted ones that do not require an additional compare after a decrement. We can more generally have linear function test replacement that tries to rephrase the loop test in terms of other existing IVs. One example that would benefit is the one in https://github.com/dotnet/runtime/issues/102068; after implementing #105241 we will end up in a situation where we have an IV with step = 2 that the loop test can be phrased in terms of.

That is, the codegen for

public static void Foo()
{
    string puzzle = "003020600900305001001806400008102900700000008006708200002609500800203009005010300";
    int[] board = new int[81];

    for (int i = 0; i < puzzle.Length; i++)
    {
        board[i] = puzzle[i] - '0';
    }
}

today looks like

       xor      ecx, ecx
       align    [0 bytes for IG03]
                        ;; size=22 bbWeight=1 PerfScore 1.75
G_M24659_IG03:  ;; offset=0x001A
       mov      edx, ecx
       mov      r8, 0x160D4E52C30      ; '003020600900305001001806400008102900700000008006708200002609500'
       movzx    r8, word  ptr [r8+2*rdx+0x0C]
       add      r8d, -48
       mov      dword ptr [rax+4*rdx+0x10], r8d
       inc      ecx
       cmp      ecx, 81
       jl       SHORT G_M24659_IG03
                        ;; size=34 bbWeight=3.96 PerfScore 20.79

but it can become something like

  xor ecx, ecx

LoopStart:
  mov      r8, 0x160D4E52C30      ; '003020600900305001001806400008102900700000008006708200002609500'
  movzx r8, word ptr [r8+rdx+0x0C]
  add r8d, -48
  mov dword ptr [rax+2*rdx+0x10], r8d
  add edx, 2
  cmp edx, 162  ; Linear function test replacement rephrased the test in terms of the IV that counts by 2 every iteration
  jl LoopStart
dotnet-policy-service[bot] commented 1 month ago

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch See info in area-owners.md if you want to be subscribed.