DelphiとFreePascalの最適化比較。
検証用コード
Wikipediaより拝借したコードをPascalに書き直した以下のコードを使用、それぞれのコンパイラでどの程度最適化がかかるか調べる。ともにx86ターゲットで、Delphiは10.1 BerlinのO+、FreePascalは3.0.0の-O4で検証した。
function GetValue: Integer; inline; var a, b, c: Integer; begin a := 30; b := 9 - a div 5; c := b * 4; if c > 10 then c := c - 10; Result := c * (60 div a); end; var a: Integer; begin a := GetValue; Random(a); // aが無効化されないように end;
ちなみに変数を展開していけば分かりますが、最終的に4になります。
FreePascalの場合
mov eax,$0000001e mov eax,$00000003 mov eax,$0000000c mov eax,$00000002 mov eax,$00000004
最終的に4が導き出されてはいるものの、途中の不要な定数が残ってしまっているのが残念。
Delphiの場合
mov ebx,$0000001e mov eax,ebx mov ecx,$00000005 cdq idiv ecx push eax mov eax,$00000009 pop edx sub eax,edx mov ecx,eax add ecx,ecx add ecx,ecx cmp ecx,$0a jle @@1 sub ecx,$0a @@1: mov eax,$0000003c cdq idiv ebx imul ecx
ザ・ウンコ。FreePascalの足元にも及ばないまさかの最適化ゼロ。あまりにも酷いので、最適化オンにしてもデバッグ実行しちゃうとオフになるバグでもあるのでは?と思い、Releaseビルドした上で別のデバッガで逆アセンブルかけてみましたが結果は同じでした…。ちなみに「x64ターゲットだとマシ」という話もあったんで念のためx64でも試したところ、ほぼ同じコードが生成されて膝から崩れ落ちましたw