gcc 4.0 で lucille のコンパイル不都合
by syoyo
Tiger では開発ツールをインストールすると標準で gcc 4.0 のコンパイラがインストールされます。
で、gcc 4.0 で lucille をコンパイルしてみたのですが、最適化が有効になっていると、
コンパイルは通るのですが、結果の画像が真っ白、という結果となりました。
colinux に gcc 4.0 をコンパイルしてインストールして、同じように lucille をコンパイルしても
同じ結果となりました。
いくつか手探りでまずそうなコードをあたってみたところ、ひとつ原因がみつかりました。
flipcode に載っていた、逆平方根を求めるコードです。
float fastrsqrt(float number) { long i; float x2, y; const float threehalfs = 1.5f; x2 = (number) * 0.5f; y = (number); i = *(long *)&y; i = 0x5f3759df - (i << 1); y = *(float *)&i; y = y * (threehalfs - (x2 * y * y)); return y; }
-O2 などの最適化オプションをつけると、なぜか間違った値が出力されてしまいます。
-Wall をつけると、コンパイル時に
warning: dereferencing type-punned pointer will break strict-aliasing rules
という警告を出すので(これがどういう意味なのかよく理解できていませんが、
無理やり違う型同士を変換すると出るみたい…)、
これが原因でしょうか。
まあもともと私も意味があまりわからないようなトリッキーなコードですので、
いつコンパイルが通らなくなってもおかしくはないコードではあります。
あまり高速化を求めてへんてこりんなコードを書くよりは、
安全で素直なコードを使ったほうがのちのち問題なさそうですね。
ほかにも lucille には gcc 4.0 ではうまく通らない(そもそも C 言語の仕様から外れているコード?)
コードがあるでしょうから、しばらくは gcc 4.0 用にコードの見直しです。
ちなみに、上記のコードは、union を使って以下のように対処すれば動きました。
float fastrsqrt(float number) { long i; float x2, y; const float threehalfs = 1.5f; union { long l; float f; } data32; x2 = (number) * 0.5f; y = (number); data32.f = y; //i = *(long *)&y; i = data32.l; i = 0x5f3759df - (i << 1); data32.l = i; //y = *(float *)&i; y = data32.f; y = y * (threehalfs - (x2 * y * y)); return y; }
Advertisements