dotnet/runtime
Auf GitHub ansehenJit x86: improve codegen for compares with long statics
Open
#8.555 geöffnet am 14. Juli 2017
arch-x86area-CodeGen-coreclrenhancementhelp wantedoptimizationtenet-performance
Repository-Metriken
- Stars
- (17.886 Stars)
- PR-Merge-Metriken
- (Durchschn. Merge 12T 11h) (661 gemergte PRs in 30 T)
Beschreibung
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