きりかノート 3冊め

おあそびプログラミング

Clangでruby-1.8.7をコンパイルしてみる (2) -Osなら最適化できる?

http://d.hatena.ne.jp/kimuraw/20120628/p1 のつづき。最適化を有効にしたときにダメ。じゃあどうすんの?というのが前回の課題でしたね。

とりあえず-Osでは正常に動作するようになった気がするので、そこまでの記録です。

まずはbignumだ

とりあえずテストまで実行できるbignumの件を調べてみた。

一部を最適化をオフにしてコンパイルしてみる。

   % CFLAGS=-Os ./configure ...
   % make
   % clang -O0 ... -c bignum.c
   % make ruby
   % make test
     :
   test failed
   make: *** [test] Error 1
   # 結果変わらず

んー。じゃあ、上位のnumericですかねえ。

   % make clean
   % make
   % clang -O0 ... -c numeric.c
   % make ruby
   % make test
   test succeeded
   # ビンゴ!

ということでnumeric.cにアタリをつけ、テストのエラー部分や、1.9のnumeric.cと見比べたりしつつ、パッチをつくりました!(ほんとはこのいろいろの部分をちゃんと書きたいのですが記憶に残ってなかった…)
結果だけ言うとvolatile足しただけですけどね!

実際に試してくれたりする人はgistにも貼っておいたのでどうぞ。

   Index: numeric.c
   ===================================================================
   --- numeric.c       (revision 36354)
   +++ numeric.c       (working copy)
   @@ -2161,7 +2161,7 @@
        VALUE x, y;
    {
        if (FIXNUM_P(y)) {
   -#ifdef __HP_cc
   +#if defined(__HP_cc) || defined(__clang__)
            /* avoids an optimization bug of HP aC++/ANSI C B3910B A.06.05 [Jul 25 2005] */
            volatile
    #endif
   @@ -2319,9 +2319,9 @@
        y &= ~1;
        do {
           while (y % 2 == 0) {
   -       long x2 = x * x;
   +       volatile long x2 = x * x;
               if (x2/x != x || !POSFIXABLE(x2)) {
   -           VALUE v;
   +           volatile VALUE v;
                 bignum:
                   v = rb_big_pow(rb_int2big(x), LONG2NUM(y));
                   if (z != 1) v = rb_big_mul(rb_int2big(neg ? -z : z), v);
   @@ -2331,7 +2331,7 @@
               y >>= 1;
           }
           {
   -       long xz = x * z;
   +       volatile long xz = x * z;
               if (!POSFIXABLE(xz) || xz / x != z) {
                   goto bignum;
               }

ruby-1.9のFIT_SQRT_LONG()マクロを持ってきたかったのですが、芋づる式にいろいろ足す必要がありそうで断念。

まだまだ調査中

とりあえずこれでいいかなあ、とMacPortsのほうはclangもokにしようかと作業中。でも主目的だった、某OSのGM版で不安定なカンジなのですよねえ…

ちなみに、-O2や-O1で最適化すると、callccやスレッドのあたりでSEGVします。