gcc の最適化の罠

最近立て続けに GCC の最適化関連でバグが発生した。

三項演算子のネストを解釈しきれない
int i = strcmp("abc", str) == 0 ? func0(str) :
    strcmp("def", str) == 0 ? func1(str) :
    strcmp("ghi", str) == 0 ? func2(str) :
    strcmp("jkl", str) == 0 ? func3(str) :
    strcmp("mno", str) == 0 ? func4(str) :
    strcmp("pqr", str) == 0 ? func5(str) :
    strcmp("stu", str) == 0 ? func6(str) :
    func7(str);

こんな感じの処理が最適化 -O2 だと期待通りに動作しない。

以下のように書き換えて対応した。

int i;
if (strcmp("abc", str) == 0) i = func0(str);
else if (strcmp("def", str) == 0) i = func1(str);
else if (strcmp("ghi", str) == 0) i = func2(str);
else if (strcmp("jkl", str) == 0) i = func3(str);
else if (strcmp("mno", str) == 0) i = func4(str);
else if (strcmp("pqr", str) == 0) i = func5(str);
else if (strcmp("stu", str) == 0) i = func6(str);
else i = func7(str);

もしかすると、以下のように明示的に括弧をつけることで対応できたかもしれない。

int i = strcmp("abc", str) == 0 ? func0(str) :
    (strcmp("def", str) == 0 ? func1(str) :
    (strcmp("ghi", str) == 0 ? func2(str) :
    (strcmp("jkl", str) == 0 ? func3(str) :
    (strcmp("mno", str) == 0 ? func4(str) :
    (strcmp("pqr", str) == 0 ? func5(str) :
    (strcmp("stu", str) == 0 ? func6(str) :
    (func7(str))))))));

最後の行が Scheme みたいだ。

GCC 4.4

GCC 4.4 では最適化に磨きがかかって、処理の順番を変えたりするみたいだ。

ビルド環境は「LinuxGCC」みたいなアバウトな感じだったんだけど、僕の環境でのみ SEGV が発生し、ありとあらゆるチェックをして、結局違うのは GCC のバージョンぐらい、ということで明日には裏付けが取れると思うんだけど、これが原因で丸一日つぶしてしまった。

GCC 4.4 固有の最適化によって SEGV が発生しているのであれば、それはそれで危ないコードのような気がするので原因を突き止めたい気もしなくもないんだけど、それは半分以上は自己満足の世界だと思うので、着手はできなさそうだ。