dotnet/runtime

Jit x86: improve codegen for compares with long statics

Open

#8,555 opened on 2017年7月14日

GitHub で見る
 (2 comments) (0 reactions) (0 assignees)C# (5,445 forks)batch import
arch-x86area-CodeGen-coreclrenhancementhelp wantedoptimizationtenet-performance

Repository metrics

Stars
 (17,886 stars)
PR merge metrics
 (平均マージ 12d 11h) (30d で 661 merged PRs)

説明

For current x86 jit codegen, it appears long statics must be fully loaded into registers before they can be compared. For example:

using System;
using System.Runtime.CompilerServices;

class L
{
    static long Iterations;

    [MethodImpl(MethodImplOptions.NoInlining)]
    static int F(int x)
    {
        return x + 1;
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    static int Test()
    {
        int j = 0;

        for (int i = 0; i < Iterations; i++)
        {
            j = F(j);
        }

        return j;
    }

    public static int Main()
    {
        int i = 1000000;
        Iterations = i;
        int j = Test();
        return j == i ? 100 : 0;
    }
}
;; RyuJit x86
G_M25199_IG03:
       8BC8         mov      ecx, eax
       FF158C49EA00 call     [L:F(int):int]
       46           inc      esi
       8BD6         mov      edx, esi
       8BCA         mov      ecx, edx
       C1F91F       sar      ecx, 31
       8D3D5848EA00 lea      edi, [classVar[0xea493c]]
       8B1F         mov      ebx, dword ptr [edi]
       3B4F04       cmp      ecx, dword ptr [edi+4]
       7F06         jg       SHORT G_M25199_IG04
       7CE1         jl       SHORT G_M25199_IG03
       3BD3         cmp      edx, ebx
       72DD         jb       SHORT G_M25199_IG03

Jit32 will fetch the pieces from memory directly, which reduces register cross-section. Jit32 also defers reading the low part of of the static until it's needed:

;; Jit32
G_M25199_IG03:
       FF15FC46FF00 call     [L:F(int):int]
       8BC8         mov      ecx, eax
       46           inc      esi
       8BC6         mov      eax, esi
       C1F81F       sar      eax, 31
       3B05CC45FF00 cmp      eax, dword ptr [classVar[0xff46ac]+4]
       7F0A         jg       SHORT G_M25199_IG04
       7CE8         jl       SHORT G_M25199_IG03
       3B35C845FF00 cmp      esi, dword ptr [classVar[0xff46ac]]
       72E0         jb       SHORT G_M25199_IG03

This pattern appears in the inner iteration loop of many of the perf benchmarks since the Benchmark.InnerIterationCount property is a long.

category:cq theme:basic-cq skill-level:expert cost:small impact:small

コントリビューターガイド