パスワードを忘れた? アカウント作成
40462 story

高速/高性能でフリーのコンパイラ、LLVM 2.4が登場 36

ストーリー by GetSet

insiderman 曰く、

マイコミジャーナルで知ったのだが、「LLVM(Low Level Virtual Machine)というコンパイラの最新版2.4がリリースされたそうだLLVMプロジェクトのWebサイト)。

LLVMはBSDライセンスで開発されているC/C++/Objective-Cコンパイラで、GCCよりも最適化されたコードを出力できる、と言われている。また、GCC互換のフロントエンドも用意されており、これを使ってコンパイラをGCCからLLVMに入れ替えるだけでコンパイル時間が短縮でき、さらに生成されるコードもより優れたものになるという(マイコミジャーナルの解説記事)。

LLVMは単なるコンパイラではなく、まず仮想マシン用の中間コード(LLVMコード)を出力し、これを最適化を行いつつネイティブコードに変換する(もしくは仮想マシンで動作させる)という動作を行うそうで、また実行時のプロファイルを取得し、そこからフィードバックを行ってより効率の良いコードを出力させる、といった試みも考えられているらしい。

Mac OS X 10.5でOpenGLスタックにLLVMが利用されるなど、採用例も増えており、今後の発展も期待されているようだ。人柱上等!な方はぜひ試してみてはいかがでしょうか。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • by synack (31022) on 2008年11月15日 19時07分 (#1456188)
    Lame-398-2のソースコードを、普通のgccとllvm-gcc4.2のそれぞれでコンパイルして比較してみました。
    負荷は4分ほどのWavファイルのMP3エンコードにしました。

    gcc: 11.64s user 0.17s system 96% cpu 12.181 total
    llvm-gcc: 12.68s user 0.17s system 97% cpu 13.164 total

    というわけでgccの勝ち。あれれ。

    なお、環境はMac OS X 10.5.5 / 2.4GHz Intel Core 2 Duo、llvm-gcc,gccのバージョンは
      LLVM-gcc: gcc version 4.2.1 (Based on Apple Inc. build 5623) (LLVM build 2.4)
      gcc: gcc version 4.0.1 (Apple Inc. build 5484)
    Lameのビルド方法は、Mac版のLLVM-gccを落としてきてパス通してCC=llvm-gcc ./configureしただけです。
    NASMは入ってないのでアセンブラ記述のFFTは使われず、C版になっているはず。

    もっとllvm-gccのオプション等を頑張って最適化しないとダメなのかも。
    • by Anonymous Coward on 2008年11月16日 16時17分 (#1456479)
      私は簡単なプログラムを書いて実験してみました。ソースは汚くてちょっと見せられませんが、1/3の数値を浮動小数点数除算を使わずモンテカルロ法的に求めるものです。

      MinGW-gcc: 9.133s
      VisualStudio-cl: 8.051s
      llvm-gcc: 5.387s

      環境はWindows 2000/Intel Celeron 1.0GHz
      llvm-gcc (GCC) 4.2.1 (Based on Apple Inc. build 5623) (LLVM build)
      gcc (GCC) 3.2 (mingw special 20020817-1)
      cl Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 13.00.9466 for 80x86

      MinGW-gcc のバージョンが古いのが気になりますが、とりあえず Windows 環境では最も効果的に最適化できるようなので、使いではあるのではないかと思います。
      尚、私の環境では

      llvm-gcc -O3 test.c
      としてしまうとなぜか共有違反を起こすバイナリができてしまうので、一度 LLVM bitcode を出力してアセンブラにコンパイルしてMinGW-gccでアセンブルしました。
      親コメント
    • by Anonymous Coward on 2008年11月15日 19時42分 (#1456202)
      http://llvm.org/bugs/show_bug.cgi?id=879 [llvm.org]
      あたりが関係しているのかも。この問題はまだ fix されてません。

      親コメント
  • 一つ判ったのは… (スコア:3, すばらしい洞察)

    by okky (2487) on 2008年11月16日 0時08分 (#1456302) ホームページ 日記
    バイナリを実行していて生じたエラーを「ソースコードを見ずに」問題点を把握するのはますます困難になった、と言うことだ。
    # コンパイラが馬鹿なら、ソースを読める権限を持っている連中が言ってくる嘘も簡単に見抜けるのに…
    --
    fjの教祖様
    • by Anonymous Coward
      >「ソースコードを見ずに」問題点を把握する

      それってもしかして、
      エラーだけじゃなく、
      GPL違反みたいなのを探索するのも
      困難になるのかな?
      • 最適化が進むって言うことは、同じバイトコードを出力するために色々な書き方ができる、っていうことでもあります。
        最適化を目一杯かけられてしまうと、区別するのに苦労する、という可能性はあるのではないでしょうか??

        # 昔の MS-C なんか if/then/else で書いたのか 三項演算子で書いたのかまで露骨に判ったものなのに。
        --
        fjの教祖様
        親コメント
        • by Anonymous Coward
          そういうのが判然としないと困る人/イヤな人がいるであろうことは推測できますが…

          ここにある寿司が「職人が握った」ものか「ロボットが握った」ものかわかりにくくなるのは、
          (寿司職人にはともかく)多くの消費者にとって歓迎できることではないでしょうか。だとすれば(ry
          • いや。『GPLのコードかどうかを識別するのが困難になるのではないか』というテーマと、それが消費者が喜ぶ状態かどうかは全然関係ない。GPLは一度たりとて「消費者がうれしくなる」とは言っていない。だいたいGPLは「著者の権利」においてソースコードを公開する事を他者に強要しているわけですから。消費者を喜ばせるなんて事は全然関係ない。

            ただし、最適化が進むことが消費者にとってうれしい話かどうかは、そうそう簡単に結論付けられる話ではない。

            最適化が進んでソースコードとの対応がとりにくいコードを吐くようになったコンパイラは、それ自体の出力コードの中にバグを内包しやすい。それをデバッガで追いかけようとした場合に、どのコードがソースコードで言うどの部分の何をどうしているのか、デバッガによる対応もつけにくくなるし、アセンブリコードを表示されて「機械はギブアップしました。頑張ってね」と言われたプログラマも同じぐらい困るでしょう。つまりデバッグもとてつもなく大変になる

            結果として、ソフトウェアの品質がトータルで見ると下がってしまう可能性はあります。これは消費者にとってマイナスですよね? しかも、その下がってしまった品質ゆえに発生する障害に対する対策は、なかなか出てこなくなるって事です。アセンブラレベルで「どこ」でおかしいのかは判っても、それが「ソースコードで言うどのロジック」なのか、きちんと一対一対応しなくなるわけですから。

            ようするに 最適化も 塞翁が馬 ってことですな。
            --
            fjの教祖様
            親コメント
            • by Anonymous Coward
              「バグありコンパイラを市場に出すな」という主張なら同意できなくもないけど、 「生成バイナリのランタイム時に問題を来すような、致命的なコンパイラ」の存在を*前提*にした議論は、意味が乏しいと思うな。

              これまでコンパイラが「ソースコードとの対応が取りやすいバイナリコードを生成」していたとしたら、それは「コンパイラの未熟さ」によって「不本意ながら」得られてしまっていた副作用に過ぎない、と考えるほうが健全。
              ましてコンパイラは、GPLチェッカーじゃないし。

              # 「3Rの意識が広がったせいで、質のいい粗大ゴミが出されなくなった」と嘆いてもしょうがない。
              • 「バグありコンパイラを市場に出すな」という主張なら同意できなくもないけど、 「生成バイナリのランタイム時に問題を来すような、致命的なコンパイラ」の存在を*前提*にした議論は、意味が乏しいと思うな。

                そんなことは誰も言うておらんが…ましてやこれが意味が乏しいという事は、想像力が著しく欠けているとしか思えん。何しろこれは、古典中の古典だ。

                プログラムをソースコードだけでデバッグする事は、「機種依存性」を必ず持っているプログラミング言語においては不可能だ。CとかC++は典型的に「不可能」な例だ。端的な話、アセンブリコードとのインターフェースはコンパイラの出力依存だが、「プログラミング言語」はそんなところを規定しない。

                と言うことは、プログラムは必ず「ソースコード」とコンパイル結果の「アセンブリコード」のペアでデバッグされる。gdbのようなツールは「アセンブリコード」を実行していく過程を「ソースコード」にマップしてくれているわけだが、このマッピングはコンパイラの最適化技術が未熟であるが故にこそ実現可能なわけだ。

                -----
                有名な話だが
                「コンパイラの最適化があまりにも進歩して、バブルソートのコードを組んだら勝手にライブラリのQuickソートに置き換えられていたら、デバッガはそこを実行している間ソースコードのどこを指したらいいと思う? 特にステップ実行/インストラクションステップ実行の間」
                という問いがある。

                個人的には「『姉が不調法をいたしまして…』と言いながら困ったような、誇らしそうな顔をしてその部分の実行が終わるのを待つ」っていう答だが、ようするに「そういう豪快なパターンマッチ & 置き換え」をやられるとデバッガは役に立たなくなる。

                これはすなわち、バグを修正するまでのサイクルが長くなってしまう事を意味し、結果として修正されたバグの量が少ないまま出荷されるコードが増大する事を意味する。
                -----

                この問題を考えるときによく間違えるのが「バグがあるならばそういうグローバル最適化パターンとは合致しないだろう」という勘違いだ。『既存のコードをコピペした後、一部分書き換えるべきところを失念した』というタイプのバグの事を考えていない。つまり「本来合致しないはずのグローバル最適化パターンに合致してしま」ったために最適化が大幅に進んでしまうと、ソースコードロジックの間違いをデバッガでは追跡できなくなる。

                .

                GPL追跡がやりにくくなる、と言うのは実はこの(古典的で面白い)『バギーなソースコードに対する究極の最適化(ただしバグを修正するなどの「最終結果を変更してしまうような最適化」は含まない)は、何をもたらすのか』というテーマの1変種だ。
                --
                fjの教祖様
                親コメント
              • by Anonymous Coward
                > 有名な話だが
                > 「コンパイラの最適化があまりにも進歩して、バブルソートのコードを組んだら勝手にライブラリのQuickソートに置き換えられていたら、デバッガはそこを実行している間ソースコードのどこを指したらいいと思う? 特にステップ実行/インストラクションステップ実行の間」
                > という問いがある。

                なあんだ。
                デバッガというとステップデバッガしか知らねーでやんの。
                プッ
              • なぁんだ。
                デバッガの基本がわかってねーでやんの。

                全てのデバッガは「ステップデバッガ」の上にインテリゲンチャな機能をつけたものだという事を理解してから口を開きな。
                --
                fjの教祖様
                親コメント
              • by Anonymous Coward
                とりあえず、"algorithmic debugging"でググってみなよ。
              • 忘れてたので素直にググってみて思うんだけど、アルゴリズミック・デバッギングって、参照透過でない手続き型言語に使えるの?
                特にCとかでは厳しいんじゃないのかなぁ。ソースに対応する意味のある計算木なんて作れるのかしらん?
                関数型や論理型になるようにプログラムを変換するとすると結局そこでソース・コードからは離れてしまうし…。

                加えてアルゴリズミック・デバッギングがうまくいったとしてソース・コードの論理的な誤りは分かるだろうけど、
                コンパイル&最適化済バイナリ・コードの誤りはわからないんじゃないの?
                コンパイラが無条件で信頼できて、他言語やアセンブリ言語のコードとかが混入しない前提が成り立つなら心配はいらないんだろうけども。

                仮にバイナリをデバッグすべくアルゴリズミック・でバッギングに必要な情報をソースの論理的構造ではなく
                コンパイル済バイナリから取り出そうとすると結局通常のデバッガと同じ問題が発生するわけで。

                今やデバッガでしんどいのは別にステップ実行する機構(昔は問題だったけど最近のプロセッサはそれを支援するメカニズムを備えてることが多い)じゃなくて
                マシンの状態とソースコードを結びつけるための情報を構築したり検索したりする部分だと思うわけで…。

                #昨年実際にバイナリフォーマットも決まっていない独自プロセッサ向けにデバッグ情報の抽出作業をやったのだけど
                #コンパイラのバックエンド、アセンブラ、リンカ、デバッガの間の責任分担を調整して回る作業は本気で面倒くさかったw
                #行番号や変数のアドレスを一貫させるだけで大騒ぎ、時間がなくなってローカル変数の生存区間は先送りしたくらいに面倒くさかった。
                #あんまりそんなことする機会もないからいい経験にはなった気がするけどその知識が役立つ日が来るのかは謎。
                親コメント
  • gccがGPL3になって影響を受けるのってsf.netのコンパイルファームみたいにそれ自体をサーブしてる所くらいなので、ライセンスがBSDな事のメリットはそんなにないんじゃないかなぁ...とか思ったりもするけど。まー、そのうち試してみるかも。
  • by 21 (23614) on 2008年11月15日 23時13分 (#1456282)
    それ経由で知ったからですが、LLVMと聞くと、
    まずlucilleの藤田氏のブログが思い浮かびます。
    下記記事が最初に取り上げられたものみたい。

    The LLVM Compiler Infrastructure [atso-net.jp]
  • by Anonymous Coward on 2008年11月15日 18時08分 (#1456155)
    コンパイラと、コンパイラ実装のためのインフラとでは、指すものがだいぶ違うと思うかと。
    • by Anonymous Coward
      compiler infrastructure は compiler を含むから、間違ってはいないとおもうな。
      インフラだけどコンパイラじゃないものは知らないし。
      coins や jastadd もコンパイラがついてくるでしょう。

      それに、スラドで知る程度の人は、コンパイラとしてしか利用しないでしょ?
      • by numberR (34474) on 2008年11月16日 2時47分 (#1456339)
        LLVMそのものは仮想マシンですよ。
        その仮想マシンで走るコードを出力出来るのがllvm-gccなりなだけで。
        親コメント
      • by Anonymous Coward
        むしろこれをコンパイラとして利用する意味あるの?
        • by Anonymous Coward on 2008年11月16日 0時41分 (#1456310)
          あまりない。llvm-gcc使うなら素直にgccをつかうだろう。

          自作言語を作るとき、フロントエンドを自作して、バックエンドでLLVMを使う、
          ある言語機能を実験するために、エンジンに機能を差し込む等が普通だろう。

          いろいろな部分の差し替えが利くInfrastructureである点を省くと、LLVMの価値の大半が消える。
          親コメント
          • by Anonymous Coward
            そうやって作り上げたコンパイラを便利に使っちゃあかんの?
            ユーザが使うバージョンは LLVM less で作り直すというのがこれの正しい使い方なのかな。
  • by Anonymous Coward on 2008年11月15日 19時55分 (#1456209)

    LLVMは単なるコンパイラではなく、まず仮想マシン用の中間コード(LLVMコード)を出力し、これを最適化を行いつつネイティブコードに変換する(もしくは仮想マシンで動作させる)という動作を行うそうで、
    これはgccもやってるでしょ(あとSSAも)
    gimple,rtlとかは違うの?
    というか、まじめにC/C++のコンパイラを書こうとしたら、
    構文木はどこかにして保持したくなるんじゃないの?
    それがあるからってどこが単なるコンパイラじゃないの?
    llvmがよさげなのは、実行時プロファイルを元にvm用のコードを最適化してくれるところでしょ。
    • Re:中間コード… (スコア:2, 参考になる)

      by chapuni (1170) on 2008年11月15日 22時45分 (#1456268) ホームページ 日記
      先の引用文に注釈してみた。

      LLVMは単なるコンパイラではなく、
      *コンパイラ/リンカは*
        まず仮想マシン用の中間コード(LLVMコード)を出力し、これを
      *実行時に*
      最適化を行いつつネイティブコードに変換する(もしくは仮想マシンで動作させる)という動作を行うそうで、
      親コメント
    • んー、llvmの吐く中間コードはUCSD Pascal仮想マシン [wikipedia.org]やJava仮想マシン [wikipedia.org]のように完結性の高い仮想マシンで共通して「One write,All run」(だっけか)動くバイトコードであって、RTL式のようなコンパイラが内部で使うための構文木とは違います。
      # RTL式を動かすインタプリタは出来ないことはないけど、あんまし効率がよくないのではないかと思うのですが…

      つまりは、この手のコンパイラの工程を簡略に表すと、以下のような感じになります(斜体は中間でVM吐く場合に追加)

      ソース

      RTL

      最適化・(必要なら)リンク

      仮想マシンバイトコード出力

      最適化・リンク

      実マシン実行コード

      つまりは、多分最近のgccもある程度手を出してるような気がするのですが(gcc4になってからソース見てないから自信ない)、この手のコンパイラでは共通仮想マシンで動かすための最適化と「リッチな」共通仮想マシンのコードからレジスタ資源がより厳しい(と思われる)マシン固有の実行コードに落とすときの最適化の二回最適化を行っています。
      後者に付いてはJavaのバイトコードインタプリタのように仮想マシンで動かして(遅くなるけど)ソースコードのデバッグをやってしまう事も出来るようになる。

      こうすることで、gccがハマっていたターゲットの機械語依存のコード生成とソース解釈レベルでの中間コード生成がぐちゃぐちゃになりかねないリスクを(理論上)完全に排除できます。
      これはコンパイラのソースコードを書く工程での不具合発生可能性を劇的に減らせるだけでなく、コンパイラの内部でコード生成のバグが出たときやその可能性が出たときのデバッグ工程の工数を大きく減らせる可能性も持ち得ます。

      その結果(というよりは目的その物だろうけど)、コンパイラでのバグの最大要因であるターゲット向け最適化の部分を全く綺麗なコードで書けるようになると同時に、利用者も大概の場合は高級言語で記述する部分のデバッグに専念出来るようになって、デバッグの負担をかなり軽減できる筈です。仮想マシンが練り上げられていれば。ですけど。

      ターゲット向け最適化は中間コードになった物からターゲット向けコード生成の部分だけを・高級言語に依存した構文内最適化はソースコードから中間コード生成の部分だけを考えて書けば済むので、あらゆる工程でDIRTY HACKの必要な部分を非常に減らせます。あくまでも理論的には
      親コメント
      • by Anonymous Coward on 2008年11月15日 23時34分 (#1456285)
        おいこら、毎度毎度大嘘つくんじゃねえ、この半可通がいい加減にしろ。

        LLVMの命令セットは
        > A virtual instruction set - LLVM is a low-level object code representation that uses simple RISC-like instructions, but provides rich, language-independent, type information and dataflow (SSA) information about operands.
        だよ。何がバイトコードだ。

        みんなもArtane.の適当な放言に騙されないように
        http://llvm.org/docs/LangRef.html
        を読もう!

        親コメント
        • by Anonymous Coward
          > みんなもArtane.の適当な放言に騙されないように
          > http://llvm.org/docs/LangRef.html [llvm.org]
          > を読もう!
          読んでみたところイントロダクションに
          >The LLVM code representation is designed to be used in three different forms: as an in-memory compiler IR, as an on-disk bitcode representation (suitable for fast loading by a Just-In-Time compiler), and as a human readable assembly language representation.
          とあるのだけれど、バイトコードって書くと間違いなの?
          • by Anonymous Coward on 2008年11月16日 0時41分 (#1456311)
            別ACだけど、
            バイトコード [e-words.jp]

            人間の書いた設計図であるソースコードと、実際にコンピュータで実行可能なネイティブコードの中間に当たる形式である。
            とあるように中間コードの意味でなら「バイトコード」と書くのは間違いでは無いように思うが、

            Java言語のバイトコード(Javaバイトコード)のことを単に「バイトコード」と呼ぶことが多い。
            という使い方が多いことを考えると「バイトコード」と書くのは間違いだと思う。
            引用されている文章も"as an on-disk bitcode representation"って表現を変えてるし。
            親コメント
            • by Anonymous Coward on 2008年11月16日 0時53分 (#1456314)
              > とあるように中間コードの意味でなら「バイトコード」と書くのは間違いでは無いように思うが、

              バイトコードの意味を広くとらえるなら間違いではないでしょう。
              しかし実際のところLLVMは型付きSSA+αなので、Artane.の分類に従うならバイトコードではなくRTLとほぼ等しいものになります。
              だからArtane.は一知半解なんですよ。

              > んー、llvmの吐く中間コードはUCSD Pascal仮想マシン [wikipedia.org]やJava仮想マシン [wikipedia.org]のように完結性の高い仮想マシンで共通して「One write,All run」(だっけか)動くバイトコードであって、RTL式のようなコンパイラが内部で使うための構文木とは違います。
              親コメント
      • by Anonymous Coward on 2008年11月16日 6時41分 (#1456355)

        んー、llvmの吐く中間コードはUCSD Pascal仮想マシンやJava仮想マシンのように完結性の高い仮想マシンで共通して「One write,All run」(だっけか)動くバイトコードであって、RTL式のようなコンパイラが内部で使うための構文木とは違います。

        何言ってんだか。その正反対ですよ。各CPUの機械語に落とし込みやすいLLVM IRを定めるための、現存CPUの差異を捨象した仕様こそがLLVMですよ。

        親コメント
        • by Anonymous Coward on 2008年11月16日 8時46分 (#1456365)
          これも少し違うかな。
          LLVMはcompiler infrastructureであり、最適化やセマンティクスの拡張などコンパイラの実装に必要な情報を可能な限り保持し抽象化したものです。
          だから伝統的な内部表現とは違い型情報がついている。
          コンパイラ実装者以外には、基本的には無用の長物。

          > 各CPUの機械語に落とし込みやすいLLVM IRを定めるための、現存CPUの差異を捨象した仕様こそがLLVMですよ。
          これはまあ、結果的にはそうなってはいるんだけども。
          親コメント
      • by Anonymous Coward
        日本語でおk
  • by Anonymous Coward on 2008年11月19日 17時15分 (#1458427)
    LLVMでLinuxカーネルが動くようになるのはいつの日ですか
typodupeerror

物事のやり方は一つではない -- Perlな人

読み込み中...