Swanman's Horizon

性欲をもてあましつつなんらかの話をするよ。

DelphiとFreePascalの最適化比較。

はじめに

先日a-1-4がa-5に最適化されない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

ちなみに

VC++の場合、

mov eax,$00000004

まで最適化されます。さすがですね…。