2009年09月30日

GCC LTO marge

GoogleのDiego Novillo氏が、GCCのtrunkに大量のパッチを投げました。

[LTO merge][0/15] Description of the final 15 patches
http://gcc.gnu.org/ml/gcc/2009-09/msg00578.html
http://gcc.gnu.org/ml/gcc-patches/2009-09/

ついにLTO(Link-Time Optimization)branchがGCC trunkにmergeされるようです。



具体的には、-fltoや-fwhopr(Whole Program Optimization)というオプションが増えます。このオプションにより、GCCは通常のアセンブリコードの代わりに、最適化のための情報を含んだGIMPLEという中間表現をダンプし、後でそれをまとめることにより、コンパイル単位をまたいだ、プログラム全体にわたる関数のインライン化や定数伝播、リンク時の不要関数削除などの様々な最適化が行われるようになる(どこまで最適化パスが実装されているのかはまだ(私が)わかってないのですが、少なくとも、フレームワークは完成しつつある)ようです。

具体的には、gccコンパイラドライバがcc1を起動してGIMPLEをダンプします。ここまでは通常の.oの生成と同じです。その後、リンク時に、gccドライバから起動されたcollect2が、lto1を起動してLTOを行うそうです。(佐藤さん談。)

Link-Timeとは言うものの、ldが最適化を行っているわけでは無い点に注意してください。GIMPLEの解析や最適化はGCCしかできないためです。GNU ldは最適化のパスを持っていません。

(GNU ldがあまりにも遅い上に、.o単位でのリンクしかできない(不要な関数までリンクされてしまう)のでGoogleが新たに開発したリンカgoldは、最適化のパスを持っているそうです。ただしgoldはELF以外は未サポートらしいので、WindowsやMacintosh環境のPEやCOFFはリンクできないようです。)

# 追記: 佐藤さんから指摘されたのですが、goldはdead code strippingなどの最適化は行ってくれないようです。(ただし、goldは、最適化のフレームワークは存在するので、様々な最適化は書きやすいそう。) また、最適化の機能自体はldにも存在するようです。gcc側で-ffunction-sectionsというオプションを付けて、各関数を別々のセクションに分割し、ld側で--gc-sectionsオプションを付けて不要関数をGCすれば、dead code strippingが可能のようです。ldは、セクション単位でリンクを行うので、セクションが関数ごとに分かれていれば、必要な関数だけをリンクできるみたいです。

とはいえ、これは決して目新しい概念ではなく、事実Microsoft Visual C++は、既に以下のようなオプションをサポートしています。(少なくとも、VC++6.0(98年)の時代ぐらいからは、プロパティで「プログラム全体の最適化」や「リンク時のコード生成」などがサポートされていたように思います。)

Visual C++ コンパイラ オプション /GL (プログラム全体の最適化)
Visual C++ リンカ オプション /LTCG (リンク時のコード生成)

あまりメジャーなオプションでは無いと思いますが(検索してみると「ビルド時のトラブルの原因になったので/GLを外してプログラム全体の最適化を無効にした」みたいな文章の方が多かったりも。苦笑。)、例えば光成さんの記事などが参考になります。
http://homepage1.nifty.com/herumi/diary/0903.html#19
http://homepage1.nifty.com/herumi/diary/0903.html#25
/GLで、ライブラリ化されたオブジェクトファイル間をまたぐ関数インライン化や定数伝播などが行われている様子がわかります。/LTCGをリンク時に付ければ、不要関数削除なども行われていると思います。

私はIntelのICCは使ったことが無いのですが、同様の機能や、さらにはプロファイルによる自動最適化などが非常に充実していると聞きます。(VC++にも同様のプロファイル機能があるようです。)

プロファイルによるリンク時の最適化とは、例えば関数コードの位置を並び替えるなどがあるそうです。統計的によく使われる関数同士を近くに配置することにより、まとめてキャッシュに乗りやすくなるなどの効果があるようです。(Linkers&Loaders(翻訳版、2001年)の11章にも「11.3 リンク時ガベージコレクション」「11.4 リンク時最適化」「11.5 リンク時コード生成」などの項目が少しあります。)

また、近年FreeBSDのコンパイラをclangに置き換える動きがあったり(おそらくBSDプロジェクトにとっては、GPLのGCCは望ましくないのでしょう。)と、注目を集めつつあるLLVMプロジェクトのリンカ(llvm-link)は、既に不要関数削除(dead code stripping)などのLTO機能が存在しています。

このようにLTOは、GCCの対抗馬と言われる場合もあるLLVMや、商用コンパイラなどでは比較的以前より実装されていた機能群ですが、ようやくGCCも追いついてきたというところでしょうか。

それに伴い、LTO時のデバッグ情報生成など、まだまだ課題も多いようです。(VC++でも、/GLオプションを付けるとデバッグ情報は生成されないようです。また、生成されたオブジェクトファイルの(VC++の異なるバージョンでの)可搬性も保証されないようです。)Diego氏は4.5のstage3までには何とかすると言っているようですが。

もう少し時間が必要そうですが、この調子でGCCのLTOが成熟してくれば、特にバイナリサイズが重要となる、多くの組み込み開発が恩恵を受けることができると思われます。(特定のOSやCPUベンダのコンパイラの最適化がいかに優れていたとしても、その恩恵を受けられるのは限られたプラットフォームとアーキテクチャだけです。GCCの最大の価値は、非常に広範なプログラミング言語と環境をサポートしていることだと、個人的には思っています。)GCC4.5かそれ以降の目玉機能となりそうですね。

トラックバックURL

トラックバック一覧

1. [ソフトウェア][GCC] GCC Link-Time Optimization  [ kikairoyaの日記 ]   2009年10月01日 17:22
9/28にGCCにLink-Time Optimizationのパッチがマージされた模様です。 KMC Staff Blog:GCC LTO margeでも述べられているとおり、既にMicrosoftやIntelでは実装されていて、恩恵を受けている人も多いと思います。 GCCの最適化はほかに比べて劣ると言われるようになって久しく

コメント一覧

1. Posted by 名無し   2009年10月09日 19:43
VC++の不要関数削除は/OPT:REFがやってるんじゃないかなあ
/GLかつ(暗黙的に/LTCGかつ)/OPT:REFの時だけTLSコールバック関数が消えて「おや?」になった記憶があるので
2. Posted by 若槻   2009年10月14日 12:50
なるほど、コメントありがとうございます。

MSDN で確認したところ、詳しい条件が書いてました。

http://msdn.microsoft.com/ja-jp/library/bxwfs976(VS.80).aspx

デフォルトで既に /OPT:REF とのことですが、/DEBUG が指定されている場合には
/OPT:NOREF 扱いになるので、明示的に /OPT:REF を指定する必要があるようです。
3. Posted by hik   2010年06月28日 10:09
gcc 4.5.1 では cygwin が support されたようです。
mingw
cygwin
darwin

すべて x86 ですが。

http://gcc.gnu.org/gcc-4.5/changes.html
4. Posted by hik   2010年06月28日 12:13
ほかの blog にもありましたが 4.5.1 で x86 ですが、 cygwin/mingw/darwin が support される、7 月頃のリリースで、とありました。

http://gcc.gnu.org/ml/gcc-announce/2010/msg00001.html
http://gcc.gnu.org/gcc-4.5/changes.html

4.5.0 を少し試してみて、LTO を使って、圧縮 program を compile してみたりしています。実行速度の評価はしていませんが、size は小さくなっていました。

emacs の compile は 4.5.0 をおすすめしていないようです。(etc/PROBLEMS)

4.5.1 に期待ですが、個人的には、LTO に期待しています。
source code があれば、LTO 付きで .o/.a を作っておけば、
static link なら global optimize がきくだろう、とか
kernel はどうなるのだろう、とか、dynamic link でも
dynamic linker を LTO 対応にしておくのは、ありのなのかなぁ、
とか等々、

ひとりごと失礼しました。
5. Posted by kekyo   2010年10月14日 19:06
> VC++でも、/GLオプションを付けるとデバッグ情報は生成されないようです。

そのようなことはありません。/GLでもデバッグ情報は出力されます。リリースビルドでは既定でデバッグ情報を生成しないからではないでしょうか?

# VCでも設定すれば出力されますし、DDKやWDKではデフォルトで/LTCGかつ/DEBUGです。
# でないと、Windowsカーネルはシンボルファイルを提供出来なくなってしまいます :-)
6. Posted by 若槻   2010年10月21日 17:01
> kekyo さん

コメントありがとうございます。

1 年以上前の記事なので当時の記憶があやふやなのですが、MSDN に「/Z7、/Zi、/ZI (デバッグ情報の形式) は、/GL を使うことはできません。 」とあるのを勘違いしたのだと思います。
http://msdn.microsoft.com/ja-jp/library/0zza0de8(VS.80).aspx

ところで、/LTCG はリンク時の話なので、デバッグ情報の生成とはあまり関係ないような気がしたのですが、いかがでしょうか ?

コメントする

名前
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード