なんか、すごい最適化をすることがあるのを発見した。

ソースは

void foo( char * ); void bar() { char buf[] = { 0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9, 0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9, }; foo( buf ); }

こんな感じ。これを gcc でコンパイルして -O3 で最適化すると、データをまず定義して、bar の中ではそのデータをスタック上にある buf にコピー。普通だと思う。

これが。マイクロソフトコンパイラだと全然違う最適化になる。

コマンドラインは

cl -GX -Ox -c -Fa test.cpp

こんな感じ。

折角なので、コンパイルした結果を(ほぼ)そのまま載せてしまおう：

sub esp, 60 ; 0000003cH mov al, 9 mov dl, 7 mov cl, 8 mov BYTE PTR _buf$[esp+69], al mov BYTE PTR _buf$[esp+79], al mov BYTE PTR _buf$[esp+89], al mov BYTE PTR _buf$[esp+99], al mov BYTE PTR _buf$[esp+109], al mov BYTE PTR _buf$[esp+119], al push ebx mov bl, 6 lea eax, DWORD PTR _buf$[esp+64] push eax mov BYTE PTR _buf$[esp+68], 0 mov BYTE PTR _buf$[esp+69], 1 mov BYTE PTR _buf$[esp+70], 2 mov BYTE PTR _buf$[esp+71], 3 mov BYTE PTR _buf$[esp+72], 4 mov BYTE PTR _buf$[esp+73], 5 mov BYTE PTR _buf$[esp+74], bl mov BYTE PTR _buf$[esp+75], dl mov BYTE PTR _buf$[esp+76], cl mov BYTE PTR _buf$[esp+78], 0 mov BYTE PTR _buf$[esp+79], 1 mov BYTE PTR _buf$[esp+80], 2 mov BYTE PTR _buf$[esp+81], 3 mov BYTE PTR _buf$[esp+82], 4 mov BYTE PTR _buf$[esp+83], 5 mov BYTE PTR _buf$[esp+84], bl mov BYTE PTR _buf$[esp+85], dl mov BYTE PTR _buf$[esp+86], cl mov BYTE PTR _buf$[esp+88], 0 mov BYTE PTR _buf$[esp+89], 1 mov BYTE PTR _buf$[esp+90], 2 mov BYTE PTR _buf$[esp+91], 3 mov BYTE PTR _buf$[esp+92], 4 mov BYTE PTR _buf$[esp+93], 5 mov BYTE PTR _buf$[esp+94], bl mov BYTE PTR _buf$[esp+95], dl mov BYTE PTR _buf$[esp+96], cl mov BYTE PTR _buf$[esp+98], 0 mov BYTE PTR _buf$[esp+99], 1 mov BYTE PTR _buf$[esp+100], 2 mov BYTE PTR _buf$[esp+101], 3 mov BYTE PTR _buf$[esp+102], 4 mov BYTE PTR _buf$[esp+103], 5 mov BYTE PTR _buf$[esp+104], bl mov BYTE PTR _buf$[esp+105], dl mov BYTE PTR _buf$[esp+106], cl mov BYTE PTR _buf$[esp+108], 0 mov BYTE PTR _buf$[esp+109], 1 mov BYTE PTR _buf$[esp+110], 2 mov BYTE PTR _buf$[esp+111], 3 mov BYTE PTR _buf$[esp+112], 4 mov BYTE PTR _buf$[esp+113], 5 mov BYTE PTR _buf$[esp+114], bl mov BYTE PTR _buf$[esp+115], dl mov BYTE PTR _buf$[esp+116], cl mov BYTE PTR _buf$[esp+118], 0 mov BYTE PTR _buf$[esp+119], 1 mov BYTE PTR _buf$[esp+120], 2 mov BYTE PTR _buf$[esp+121], 3 mov BYTE PTR _buf$[esp+122], 4 mov BYTE PTR _buf$[esp+123], 5 mov BYTE PTR _buf$[esp+124], bl mov BYTE PTR _buf$[esp+125], dl mov BYTE PTR _buf$[esp+126], cl call ?foo@@YAXPAD@Z ; foo add esp, 4 pop ebx add esp, 60 ; 0000003cH ret 0

マイクロソフトコンパイラの判断は、敢えて byte 単位で move。

レジスタは活用するかもしれないが、eax とかは使わず、敢えて al〜dl。

なんで?＞マイクロソフト