使用32位JIT编译器时,我认为罪魁祸首就是Raymond Chen提到的问题,即当输入和输出是本地变量时,它们可以保存在寄存器中,但如果它们不是本地变量,则需要每次重新加载。生成的汇编代码如下:
对于本地变量:
007426F0 mov eax,dword ptr [ebp-18h]
007426F3 mov edi,dword ptr [eax+4]
int pixel = Input[InputIndex];
007426F6 mov eax,dword ptr [ebp-18h]
007426F9 cmp edx,edi
007426FB jae 0074276E
007426FD mov ecx,dword ptr [eax+edx*4+8]
对于静态内容:
011C2718 mov dword ptr [ebp-18h],edx
011C271B mov esi,dword ptr ds:[3BB7E90h]
011C2721 mov eax,dword ptr [esi+4]
011C2724 mov dword ptr [ebp-1Ch],eax
int pixel = Input[InputIndex];
011C2727 mov eax,dword ptr [ebp-1Ch]
011C272A cmp ecx,eax
011C272C jae 011C27A2
011C272E mov edi,dword ptr [esi+ecx*4+8]
正如您所看到的,
mov esi,dword ptr ds:[3BB7E90h]
访问数据段。
正如您还可以看到的那样,在两种情况下都进行了边界检查(
cmp-jae
),因此这是无关紧要的,并且循环实际上并没有被优化为什么都不做。
64位JIT是如何避免这个问题的我不知道。
以下是两种情况的完整反汇编:
快速版本:
for (int x = 0; x < Width; x++) {
007426EB mov dword ptr [ebp-14h],edx
for (int y = 0; y < Height; y++) {
007426EE xor ebx,ebx
007426F0 mov eax,dword ptr [ebp-18h]
007426F3 mov edi,dword ptr [eax+4]
int pixel = Input[InputIndex];
007426F6 mov eax,dword ptr [ebp-18h]
007426F9 cmp edx,edi
007426FB jae 0074276E
007426FD mov ecx,dword ptr [eax+edx*4+8]
var OutputIndex = InputIndex * 2;
00742701 mov esi,edx
00742703 add esi,esi
Output[OutputIndex] = pixel;
00742705 mov eax,dword ptr [ebp-1Ch]
00742708 cmp esi,dword ptr [eax+4]
0074270B jae 0074276E
0074270D mov dword ptr [eax+esi*4+8],ecx
Output[OutputIndex + 1] = pixel;
00742711 inc esi
00742712 mov eax,dword ptr [ebp-1Ch]
00742715 cmp esi,dword ptr [eax+4]
00742718 jae 0074276E
0074271A mov dword ptr [eax+esi*4+8],ecx
InputIndex++;
0074271E inc edx
for (int y = 0; y < Height; y++) {
0074271F inc ebx
for (int y = 0; y < Height; y++) {
00742720 cmp ebx,1388h
00742726 jl 007426F6
for (int x = 0; x < Width; x++) {
00742728 inc dword ptr [ebp-14h]
0074272B cmp dword ptr [ebp-14h],1388h
00742732 jl 007426EE
缓慢版本:
for (int x = 0; x < Width; x++) {
011C2713 mov dword ptr [ebp-14h],ecx
for (int y = 0; y < Height; y++) {
011C2716 xor edx,edx
011C2718 mov dword ptr [ebp-18h],edx
011C271B mov esi,dword ptr ds:[3BB7E90h]
011C2721 mov eax,dword ptr [esi+4]
011C2724 mov dword ptr [ebp-1Ch],eax
int pixel = Input[InputIndex];
011C2727 mov eax,dword ptr [ebp-1Ch]
011C272A cmp ecx,eax
011C272C jae 011C27A2
011C272E mov edi,dword ptr [esi+ecx*4+8]
var OutputIndex = InputIndex * 2;
011C2732 mov ebx,ecx
011C2734 add ebx,ebx
Output[OutputIndex] = pixel;
011C2736 mov edx,dword ptr ds:[3BB7E94h]
011C273C cmp ebx,dword ptr [edx+4]
011C273F jae 011C27A2
011C2741 mov dword ptr [edx+ebx*4+8],edi
Output[OutputIndex + 1] = pixel;
011C2745 inc ebx
011C2746 cmp ebx,dword ptr [edx+4]
011C2749 jae 011C27A2
011C274B mov dword ptr [edx+ebx*4+8],edi
InputIndex++;
011C274F inc ecx
for (int y = 0; y < Height; y++) {
011C2750 inc dword ptr [ebp-18h]
011C2753 cmp dword ptr [ebp-18h],1388h
011C275A jl 011C2727
for (int x = 0; x < Width; x++) {
011C275C inc dword ptr [ebp-14h]
011C275F cmp dword ptr [ebp-14h],1388h
011C2766 jl 011C2716