高速/高性能でフリーのコンパイラ、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が利用されるなど、採用例も増えており、今後の発展も期待されているようだ。人柱上等!な方はぜひ試してみてはいかがでしょうか。
簡単に実験してみた (スコア:5, 興味深い)
負荷は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のオプション等を頑張って最適化しないとダメなのかも。
Re:簡単に実験してみた (スコア:2, 参考になる)
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 bitcode を出力してアセンブラにコンパイルしてMinGW-gccでアセンブルしました。
Re:簡単に実験してみた (スコア:1, 参考になる)
あたりが関係しているのかも。この問題はまだ fix されてません。
一つ判ったのは… (スコア:3, すばらしい洞察)
# コンパイラが馬鹿なら、ソースを読める権限を持っている連中が言ってくる嘘も簡単に見抜けるのに…
fjの教祖様
Re: (スコア:0)
それってもしかして、
エラーだけじゃなく、
GPL違反みたいなのを探索するのも
困難になるのかな?
Re:一つ判ったのは… (スコア:1)
最適化を目一杯かけられてしまうと、区別するのに苦労する、という可能性はあるのではないでしょうか??
# 昔の MS-C なんか if/then/else で書いたのか 三項演算子で書いたのかまで露骨に判ったものなのに。
fjの教祖様
Re: (スコア:0)
ここにある寿司が「職人が握った」ものか「ロボットが握った」ものかわかりにくくなるのは、
(寿司職人にはともかく)多くの消費者にとって歓迎できることではないでしょうか。だとすれば(ry
Re:一つ判ったのは… (スコア:1)
ただし、最適化が進むことが消費者にとってうれしい話かどうかは、そうそう簡単に結論付けられる話ではない。
最適化が進んでソースコードとの対応がとりにくいコードを吐くようになったコンパイラは、それ自体の出力コードの中にバグを内包しやすい。それをデバッガで追いかけようとした場合に、どのコードがソースコードで言うどの部分の何をどうしているのか、デバッガによる対応もつけにくくなるし、アセンブリコードを表示されて「機械はギブアップしました。頑張ってね」と言われたプログラマも同じぐらい困るでしょう。つまりデバッグもとてつもなく大変になる。
結果として、ソフトウェアの品質がトータルで見ると下がってしまう可能性はあります。これは消費者にとってマイナスですよね? しかも、その下がってしまった品質ゆえに発生する障害に対する対策は、なかなか出てこなくなるって事です。アセンブラレベルで「どこ」でおかしいのかは判っても、それが「ソースコードで言うどのロジック」なのか、きちんと一対一対応しなくなるわけですから。
ようするに 最適化も 塞翁が馬 ってことですな。
fjの教祖様
Re: (スコア:0)
これまでコンパイラが「ソースコードとの対応が取りやすいバイナリコードを生成」していたとしたら、それは「コンパイラの未熟さ」によって「不本意ながら」得られてしまっていた副作用に過ぎない、と考えるほうが健全。
ましてコンパイラは、GPLチェッカーじゃないし。
# 「3Rの意識が広がったせいで、質のいい粗大ゴミが出されなくなった」と嘆いてもしょうがない。
Re:一つ判ったのは… (スコア:1)
そんなことは誰も言うておらんが…ましてやこれが意味が乏しいという事は、想像力が著しく欠けているとしか思えん。何しろこれは、古典中の古典だ。
プログラムをソースコードだけでデバッグする事は、「機種依存性」を必ず持っているプログラミング言語においては不可能だ。CとかC++は典型的に「不可能」な例だ。端的な話、アセンブリコードとのインターフェースはコンパイラの出力依存だが、「プログラミング言語」はそんなところを規定しない。
と言うことは、プログラムは必ず「ソースコード」とコンパイル結果の「アセンブリコード」のペアでデバッグされる。gdbのようなツールは「アセンブリコード」を実行していく過程を「ソースコード」にマップしてくれているわけだが、このマッピングはコンパイラの最適化技術が未熟であるが故にこそ実現可能なわけだ。
-----
有名な話だが
「コンパイラの最適化があまりにも進歩して、バブルソートのコードを組んだら勝手にライブラリのQuickソートに置き換えられていたら、デバッガはそこを実行している間ソースコードのどこを指したらいいと思う? 特にステップ実行/インストラクションステップ実行の間」
という問いがある。
個人的には「『姉が不調法をいたしまして…』と言いながら困ったような、誇らしそうな顔をしてその部分の実行が終わるのを待つ」っていう答だが、ようするに「そういう豪快なパターンマッチ & 置き換え」をやられるとデバッガは役に立たなくなる。
これはすなわち、バグを修正するまでのサイクルが長くなってしまう事を意味し、結果として修正されたバグの量が少ないまま出荷されるコードが増大する事を意味する。
-----
この問題を考えるときによく間違えるのが「バグがあるならばそういうグローバル最適化パターンとは合致しないだろう」という勘違いだ。『既存のコードをコピペした後、一部分書き換えるべきところを失念した』というタイプのバグの事を考えていない。つまり「本来合致しないはずのグローバル最適化パターンに合致してしま」ったために最適化が大幅に進んでしまうと、ソースコードロジックの間違いをデバッガでは追跡できなくなる。
.
GPL追跡がやりにくくなる、と言うのは実はこの(古典的で面白い)『バギーなソースコードに対する究極の最適化(ただしバグを修正するなどの「最終結果を変更してしまうような最適化」は含まない)は、何をもたらすのか』というテーマの1変種だ。
fjの教祖様
Re: (スコア:0)
> 「コンパイラの最適化があまりにも進歩して、バブルソートのコードを組んだら勝手にライブラリのQuickソートに置き換えられていたら、デバッガはそこを実行している間ソースコードのどこを指したらいいと思う? 特にステップ実行/インストラクションステップ実行の間」
> という問いがある。
なあんだ。
デバッガというとステップデバッガしか知らねーでやんの。
プッ
Re:一つ判ったのは… (スコア:1)
デバッガの基本がわかってねーでやんの。
全てのデバッガは「ステップデバッガ」の上にインテリゲンチャな機能をつけたものだという事を理解してから口を開きな。
fjの教祖様
Re: (スコア:0)
Re:一つ判ったのは… (スコア:1)
特にCとかでは厳しいんじゃないのかなぁ。ソースに対応する意味のある計算木なんて作れるのかしらん?
関数型や論理型になるようにプログラムを変換するとすると結局そこでソース・コードからは離れてしまうし…。
加えてアルゴリズミック・デバッギングがうまくいったとしてソース・コードの論理的な誤りは分かるだろうけど、
コンパイル&最適化済バイナリ・コードの誤りはわからないんじゃないの?
コンパイラが無条件で信頼できて、他言語やアセンブリ言語のコードとかが混入しない前提が成り立つなら心配はいらないんだろうけども。
仮にバイナリをデバッグすべくアルゴリズミック・でバッギングに必要な情報をソースの論理的構造ではなく
コンパイル済バイナリから取り出そうとすると結局通常のデバッガと同じ問題が発生するわけで。
今やデバッガでしんどいのは別にステップ実行する機構(昔は問題だったけど最近のプロセッサはそれを支援するメカニズムを備えてることが多い)じゃなくて
マシンの状態とソースコードを結びつけるための情報を構築したり検索したりする部分だと思うわけで…。
#昨年実際にバイナリフォーマットも決まっていない独自プロセッサ向けにデバッグ情報の抽出作業をやったのだけど
#コンパイラのバックエンド、アセンブラ、リンカ、デバッガの間の責任分担を調整して回る作業は本気で面倒くさかったw
#行番号や変数のアドレスを一貫させるだけで大騒ぎ、時間がなくなってローカル変数の生存区間は先送りしたくらいに面倒くさかった。
#あんまりそんなことする機会もないからいい経験にはなった気がするけどその知識が役立つ日が来るのかは謎。
興味はある (スコア:1)
LLVMといえばlucille (スコア:1)
まずlucilleの藤田氏のブログが思い浮かびます。
下記記事が最初に取り上げられたものみたい。
The LLVM Compiler Infrastructure [atso-net.jp]
The LLVM Compiler "Infrastructure" (スコア:0)
Re: (スコア:0)
インフラだけどコンパイラじゃないものは知らないし。
coins や jastadd もコンパイラがついてくるでしょう。
それに、スラドで知る程度の人は、コンパイラとしてしか利用しないでしょ?
Re:The LLVM Compiler "Infrastructure" (スコア:2, 参考になる)
その仮想マシンで走るコードを出力出来るのがllvm-gccなりなだけで。
Re: (スコア:0)
Re:The LLVM Compiler "Infrastructure" (スコア:2, すばらしい洞察)
自作言語を作るとき、フロントエンドを自作して、バックエンドでLLVMを使う、
ある言語機能を実験するために、エンジンに機能を差し込む等が普通だろう。
いろいろな部分の差し替えが利くInfrastructureである点を省くと、LLVMの価値の大半が消える。
Re: (スコア:0)
ユーザが使うバージョンは LLVM less で作り直すというのがこれの正しい使い方なのかな。
中間コード… (スコア:0)
gimple,rtlとかは違うの?
というか、まじめにC/C++のコンパイラを書こうとしたら、
構文木はどこかにして保持したくなるんじゃないの?
それがあるからってどこが単なるコンパイラじゃないの?
llvmがよさげなのは、実行時プロファイルを元にvm用のコードを最適化してくれるところでしょ。
Re:中間コード… (スコア:2, 参考になる)
中間コードでも意味が違う(Re:中間コード… (スコア:1, 興味深い)
# RTL式を動かすインタプリタは出来ないことはないけど、あんまし効率がよくないのではないかと思うのですが…
つまりは、この手のコンパイラの工程を簡略に表すと、以下のような感じになります(斜体は中間でVM吐く場合に追加)
ソース
↓
RTL
↓
最適化・(必要なら)リンク
↓
仮想マシンバイトコード出力
↓
最適化・リンク
↓
実マシン実行コード
つまりは、多分最近のgccもある程度手を出してるような気がするのですが(gcc4になってからソース見てないから自信ない)、この手のコンパイラでは共通仮想マシンで動かすための最適化と「リッチな」共通仮想マシンのコードからレジスタ資源がより厳しい(と思われる)マシン固有の実行コードに落とすときの最適化の二回最適化を行っています。
後者に付いてはJavaのバイトコードインタプリタのように仮想マシンで動かして(遅くなるけど)ソースコードのデバッグをやってしまう事も出来るようになる。
こうすることで、gccがハマっていたターゲットの機械語依存のコード生成とソース解釈レベルでの中間コード生成がぐちゃぐちゃになりかねないリスクを(理論上)完全に排除できます。
これはコンパイラのソースコードを書く工程での不具合発生可能性を劇的に減らせるだけでなく、コンパイラの内部でコード生成のバグが出たときやその可能性が出たときのデバッグ工程の工数を大きく減らせる可能性も持ち得ます。
その結果(というよりは目的その物だろうけど)、コンパイラでのバグの最大要因であるターゲット向け最適化の部分を全く綺麗なコードで書けるようになると同時に、利用者も大概の場合は高級言語で記述する部分のデバッグに専念出来るようになって、デバッグの負担をかなり軽減できる筈です。仮想マシンが練り上げられていれば。ですけど。
ターゲット向け最適化は中間コードになった物からターゲット向けコード生成の部分だけを・高級言語に依存した構文内最適化はソースコードから中間コード生成の部分だけを考えて書けば済むので、あらゆる工程でDIRTY HACKの必要な部分を非常に減らせます。あくまでも理論的には。
Re:中間コードでも意味が違う(Re:中間コード… (スコア:1, 参考になる)
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
を読もう!
Re: (スコア:0)
> 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.
とあるのだけれど、バイトコードって書くと間違いなの?
Re:中間コードでも意味が違う(Re:中間コード… (スコア:1, 参考になる)
バイトコード [e-words.jp] とあるように中間コードの意味でなら「バイトコード」と書くのは間違いでは無いように思うが、 という使い方が多いことを考えると「バイトコード」と書くのは間違いだと思う。
引用されている文章も"as an on-disk bitcode representation"って表現を変えてるし。
Re:中間コードでも意味が違う(Re:中間コード… (スコア:1, 参考になる)
バイトコードの意味を広くとらえるなら間違いではないでしょう。
しかし実際のところLLVMは型付きSSA+αなので、Artane.の分類に従うならバイトコードではなくRTLとほぼ等しいものになります。
だからArtane.は一知半解なんですよ。
> んー、llvmの吐く中間コードはUCSD Pascal仮想マシン [wikipedia.org]やJava仮想マシン [wikipedia.org]のように完結性の高い仮想マシンで共通して「One write,All run」(だっけか)動くバイトコードであって、RTL式のようなコンパイラが内部で使うための構文木とは違います。
Re:中間コードでも意味が違う(Re:中間コード… (スコア:1)
# もう、AC氏は見てないかもだけど。
Re:中間コードでも意味が違う(Re:中間コード… (スコア:1)
この一文は余計。「元のコメントにはこのような間違いがある」といった文でいい。横から見ている人間にとっては正しいのか、一部に間違いがあるのか、まるっきり正反対のことを言っているのか、その内容が重要なので。
こんなことを言ってうまく通じるのか分からないが、どっちかの味方をしているというわけではないです。個人攻撃が含まれると書いている内容が参考にならないので残念なだけです。
LIVE-GON(リベゴン)
Re: (スコア:0)
C - LLVM -------------- 機械語
C ------- gcc RTL ------ 機械語
C ---------------- CLI - 機械語
こんな感じ?
Re:中間コードでも意味が違う(Re:中間コード… (スコア:1, 興味深い)
何言ってんだか。その正反対ですよ。各CPUの機械語に落とし込みやすいLLVM IRを定めるための、現存CPUの差異を捨象した仕様こそがLLVMですよ。
Re:中間コードでも意味が違う(Re:中間コード… (スコア:2, 興味深い)
LLVMはcompiler infrastructureであり、最適化やセマンティクスの拡張などコンパイラの実装に必要な情報を可能な限り保持し抽象化したものです。
だから伝統的な内部表現とは違い型情報がついている。
コンパイラ実装者以外には、基本的には無用の長物。
> 各CPUの機械語に落とし込みやすいLLVM IRを定めるための、現存CPUの差異を捨象した仕様こそがLLVMですよ。
これはまあ、結果的にはそうなってはいるんだけども。
Re: (スコア:0)
それで (スコア:0)