route127の日記: ふーん、アンタが私のコンパイラー?…まあ、悪くないかな…。 2
過去ログでgccの末尾再帰最適化に触れられていたので自分の環境で試してみた。
gcc version 4.9.2 (i686-posix-sjlj, built by strawberryperl.com project)
最適化のレベルを変えながらアセンブリを出力してみて関数呼び出しを数えてみると、
階乗は末尾再帰で書かなくとも-O2で関数呼び出しが減っていた。
一方フィボナッチ関数は末尾再帰で書かないと最適化でcall数減少につながらなかった。
そもそも自分で書いた関数がアセンブリになると消えていてGDBで見るとスタックを全然使わなくなっていた。
find "call" fib*.s
---------- FIB.S
call fib
call fib
call __main
call atoi
call fib
call printf
---------- FIB_O2.S
call fib
call __main
call atoi
call fib
---------- FIB_TC.S
call fib
call __main
call atoi
call fib
call printf
---------- FIB_TC_O2.S
call __main
call atoi
偶奇判定の相互再帰関数(与えられた引数から1ひいて偶数判定/奇数判定するevenpとoddpの組)についても試したがあまり最適化が利いてなかった。
たらいまわし関数についても試したが最適化でかえってcallが大幅に増えていた。
コンパイラが何を考えているのか良く分からん。
また、-O2の代わりに-foptimize-sibling-calls(gcc 2.95~)を指定してみたが関数呼び出しの回数は-O2のように減らなかった。
あほやなぁ (スコア:0)
末尾再帰で書いたらとか、書かなかったらとか、スタックがどうとか、コンパイラの最適化がどうとか、
そういうしょうもない方向から理解しようとするから、いつも微妙にズレた中途半端な理解で終わるんだよ。
gcc 4.9.2なんていう遺物を持ち出してみたり、意味もなく逆アセしてわかったふりしなくていいから、
コンパイラの最適化のように曖昧なものでなく、luaやschemeのように言語仕様上要求してくるプログラム言語の実装部分を読め。
すると lua -e 'local x=0; for i=1,1e9 do x=x+i end; print(x)' のような、
末尾再帰関係ない単なるループでさえ何故あれほど早くこなせるのかも同時に理解できるやろ。
luajitなんざCの同等コード越えてくるレベル。
Re: (スコア:0)
Cのプログラムを題材にメモリ管理の実習をしているときに、それ Rustつかえば大丈夫とか言われたような的外れ具合
# 日記のほうも callの数数えてどう評価したいのかよくわからないけどまあ独り言だし?