arch-x86area-CodeGen-coreclrenhancementhelp wantedoptimizationtenet-performance
仓库指标
- Star
- (17,886 star)
- PR 合并指标
- (平均合并 12天 11小时) (30 天内合并 661 个 PR)
描述
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