GCC 4 について学ぶ

GNU Compiler Collection の一連のリリースで新しくなった内容とは

この 2、3 年の間に、GCC (GNU Compiler Collection) は GCC バージョン 3 からバージョン 4 へと大きな変化を遂げました。GCC 4 には新しい最適化フレームワーク (そして新たな中間コード表現)、新しいターゲットおよび言語サポート、そして新しいさまざまな属性とオプションが備わっています。この記事を読んで、GCC 4 の新たな機能とそれぞれの利点について学んでください。

M. Tim Jones, Consultant Engineer, Emulex Corp.

M. Tim JonesM. Tim Jones は組み込みソフトウェアのエンジニアであり、『GNU/Linux Application Programming』(現在、第 2 版です) や『AI Application Programming』(こちらも現在、第 2 版です)、それに『BSD Sockets Programming from a Multilanguage Perspective』などの著者でもあります。技術的な経歴は静止軌道衛星用のカーネル開発から、組み込みシステム・アーキテクチャーやネットワーク・プロトコル開発まで、広範にわたっています。また、コロラド州ロングモン所在の Emulex Corp. の顧問エンジニアでもあります。



2008年 10月 28日

オープンソースとクローズド・ソース両方の世界で開発の要となっている GCC は、アーキテクチャーおよびオペレーティング・システムの構築に使われます。新しく登場するプロセッサーが成功するか否かは、そのプロセッサーをサポートする GCC のバージョン (そのプロセッサーのコードを生成可能なバックエンド) にかかっています。GCC は Linux® の構築にも使われます。オペレーティング・システムとしての Linux は極めて多岐にわたるアーキテクチャーで実行されていることから幅広く成功を収めていますが、ここでもやはり、ターゲット環境へ移植した GCC によって、Linux をそのターゲット環境へ移植して実行することが可能になっているのです。GCC が Linux と組み込み開発の道を開いていると言っても過言ではありません。

しかし、GCC は進化を止めるわけにはいきません。新しいプロセッサーのアーキテクチャーは次々と登場し、新しい調査によってさらに優れたコードの最適化および生成方法が見つかっています。そのため GCC は進化し、現在では 4 番目のメジャー・リリースにまで成熟しました。この記事では、GCC バージョン 4 の基本的な変更内容を探り、(まだ GCC バージョン 4 に切り替えていないとしたら) このコンパイラー標準を使用するべき理由を明らかにします。

GCC の略歴

1987年に Richard Stallman によってリリースされた当初、GCC とは GNU C Compiler のことでした (図 1 に、近年の GCC リリース年表を示しています)。Richard が 1984年に開始したこのプロジェクトの目的は、無料で使用でき、変更、進化させることも可能な C コンパイラーを作成することでした。GCC は当初、初期の Sun のシステムおよび DEC VAX システムで実行されていました。

オープン・コンパイラー (つまり、ソースが自由に入手可能だったということ) として、他の人々が修正コードを提供し始め、さらに重要なことには新しい言語とターゲット・アーキテクチャーを対象とした更新も提供するようになりました。まもなくすると、GCC という頭字語の意味は変わり、よく使用されているアーキテクチャー (しかも難解なアーキテクチャー) のほとんどを対象とした多数の言語をサポートすることから、GNU Compiler Collection を意味するようになったのです。

図 1. 近年の GCC リリースの歴史
Modern history of GCC releases

現在、GCC は利用可能なコンパイラーのツール・チェーンとして最もよく使われるようになっています。同じソース・ベースを使用して Ada、Fortran、Java™ 言語、C の派生形 (C++ および Objective-C) に対応したコンパイラーを作成できるだけでなく、ターゲットとするプロセッサー・アーキテクチャーの数はどのコンパイラーと比べても勝っています (30 のプロセッサー・ファミリーをサポート)。ソース・ベースは完全に移植可能であり、60 を超えるプラットフォームで動作します。極めて柔軟に調整できるコンパイラーには、生成されるコードを微調整するための多数のオプションが用意されています。要するに、GCC はいわばスイス・アーミー・ナイフのようなコンパイラーで、柔軟性という言葉に新たな意味を定義します。それと同時に、現存する最も複雑なオープンソース・システムでもあります。現在、GCC を構成するソース・コードは約 1500 万行にものぼります。

以上の説明だけでも、読者は私が心底 GCC に夢中になっているという印象を持つことでしょう。その点に関しては、GCC を使用してソフトウェアを開発している最中に私の妻が部屋に入ってくると、多少の居心地の悪さを覚えるとだけ言っておきます。


始める前に

コンパイラーは、複数のステージからなるパイプライン・アーキテクチャーで構成されます。アーキテクチャーのそれぞれのステージでは、異なる形式のデータの受け渡しが行われます (図 2 を参照)。コンパイラーのフロント・エンドは言語に固有で、ここには特定の言語に対応したパーサーが含まれ、それぞれの言語のソース・コードが処理され、解析済みツリーと中間表現 (RTL (Register Transfer Language)) が生成されます。バックエンドの役割は、言語に依存しない表現を使用して、特定のターゲット・アーキテクチャーに対する命令を生成することです。そのために最適化プログラムは RTL を使用して、高速なコード、または簡潔なコード (可能な場合には高速かつ簡潔なコード) を作成します。するとこの最適化された RTL がコード・ジェネレーターに提供されて、ターゲット・コードが生成されます。

図 2. コンパイラー・ステージの簡略図
Simplified view of the compiler stages

GCC 4 の核心部の変更

GCC 4 では標準コンパイラー・スイートに多くの変更を取り込んでいます。なかでも最大の変更はツリー形式の SSA (Static Single Assignment) の導入による最適化サポートを中心とした変更ですが、全体として言えば、このコンパイラーは一部の最適化モードで処理速度が向上し、新しいターゲットのサポートをはじめとした多くの点で新たに機能が強化されています。さらに、GCC 4 は警告とエラーについてもかなり徹底されています (事実、GCC 4 では一部の警告はエラーとして現れるようになっています)。GCC 4 には GCC 3 コンパイラーで作成されたオブジェクトとのバイナリー互換性を持たないという欠点がありますが (つまり、ソースを GCC 4 で再コンパイルしなければなりません)、これは進化に伴うやむを得ない代償です。

ここからは、GCC 4 になって新たに導入された機能や進化した機能のうち、重要なものをいくつか見ていきます。

4.0 リリース・シリーズ

4.0 リリース (このシリーズでは 4.0.4 が最後のリリースです) は、GCC 4 に足を踏み入れる最初のステップです。そのため、安定化プロセスが完了するまでは本番用の開発には推奨されていませんでした。このリリースには数多くの変更が盛り込まれました。そのうちの 2 つを具体的に挙げると、新しい最適化フレームワークである、Tree SSA の導入、そして自動ベクトル化サポートの導入があります。

GCC 4 になる前に使用されていた中間表現は RTL (Register Transfer Language) と呼ばれていました。RTL は、アセンブリー言語に非常によく似た下位レベルの表現です (LISP S 表現に着想を得ています)。RTL の問題は、この表現によって実現される最適化が、ターゲットに近いものであるという点です。RTL ではプログラムに関する上位レベルの情報の表現が失われてしまうため、そのような情報を必要とする最適化は不可能な場合があります。Tree SSA は言語にもターゲットにも依存しないように設計されており、RTL に比べて分析機能が改善され、最適化機能も充実したものになっています。

Tree SSA は、2 つの新しい中間表現を導入しています。その 1 つは言語のフロント・エンドのツリーから生成される汎用ツリー表現、GENERIC です。GENERIC ツリーは SSA ベースの最適化をサポートするために、GIMPLE 形式と後続の制御フロー・グラフに変換されます。SSA ツリーは最終的に RTL に変換され、この変換後の RTL をバックエンドが使用してターゲット・コードを生成するというわけです。かなり簡略化した説明ですが、結果としては上位レベルの最適化と下位レベルの最適化の両方に適した新しい中間形式となります (このプロセスについての詳細は、「参考文献」を参照してください)。

これらの変更はまさに新しいフレームワークを表すことから、新しい最適化を定義することができます。これまでにもいくつか新しい最適化が実装されてきましたが、GCC が可能な限り簡潔かつ効率的なコードを生成することを確実にするには、さらなる取り組みが必要なことは明らかです。

GCC 4 の興味深い変更としては、(Tree SSA フレームワークをベースとした) ループ・ベクトル化機能の追加も見逃せません。自動ベクトル化機能によって、コンパイラーはコードのなかから、ターゲット・プロセッサーに用意されたベクトル命令が役立つスカラー値の処理ループを識別できるようになるため、ターゲット・コードはより堅固で効率的になります。もう 1 つのループ・ベースの最適化には、SMS (Swing Modulo Scheduling) もあります。SMS は、命令パイプラインを作成するために使用されます。その目的は、命令レベルの並列化を利用してサイクル・カウントを最小限にすることです。これらの新しい手法それぞれに関する詳細は、「参考文献」を参照してください。

4.0 シリーズでは多数の C および C++ の変更に加え、GCC 3 でサポートされていた古い Fortran 77 ではなく、Fortran 90 および 95 をサポートする新しい Fortran フロント・エンドも導入しました。また、さらに多くのターゲット・アーキテクチャーで、Ada 機能だけでなく新しい Ada 2005 機能もサポートされるようになっています。

4.1 リリース・シリーズ

新しい最適化フレームワークが整ったことから、4.1 リリース・シリーズではプロファイル作成サポートの改善と、より正確な分岐可能性の評価をはじめとする多数の最適化が導入されました。なかでも特に有益な 2 つの最適化は、インライン・サポートの改善、そして命令キャッシュの局所性を利用する機能です。関数がインライン化されるとなると、コンパイラーは頻繁に実行されることのない関数をインライン化しなくなります。代わりに、コードのサイズを抑えるとともにインライン関数の利点も引き続き生かすため、頻繁に呼び出される部分がインライン化される可能性が高くなります。GCC は、関数をホット・セクションとコールド・セクションに切り分ける上でも役立ちます。ホット関数 (使用される頻度が多い関数) を 1 つにまとめておくと、キャッシュをコールド関数で占有する場合に比べ、命令キャッシュをより賢く使用することになります。

フロント・エンドには、Objective-C++ のサポートを含めた多数の更新が適用されました。さらに、Java コア・ライブラリー (libgc) にも著しい数の更新が加えられています。一方、バックエンドには IBM® System z™ 9-109 プロセッサーのサポートが導入されました。例えば、128-bit のIEEE (Institute of Electrical and Electronics Engineers) 浮動小数点数、組み込みアトミック・メモリー・アクセスなどです。それに加え、現在ではバックエンドがスタック・スマッシング攻撃を防ぐコードを出力できるようになっています (つまり、ポインター破損から保護するためにバッファー・オーバーフローを検出して再配列します)。さらに一部の組み込み関数も、最小限のオーバーヘッドでバッファー・オーバーランを保護するように更新されています。

4.2 リリース・シリーズ

4.2 リリース・シリーズでも、言語とプロセッサー・アーキテクチャーに対応する新しい最適化と機能強化の取り組みが続けられています。バックエンドは更新され、Sun の UltraSPARC T1 プロセッサー (Niagara というコード・ネーム) と Broadcom の SB-1A MIPS コアが組み込まれました。

バージョン 4.2 でもフロント・エンドは変更されており、C++ フロント・エンドの可視部分の操作が改良され、Fortran 2003 ストリーミング入出力 (I/O) 拡張機能が加えられていますが、4.2 リリースで最も興味深い変更と言えば、CC++、および Fortran コンパイラー対応の OpenMP が追加されたことです。OpenMP はマルチスレッド化の実装で、コンパイラーがタスクおよびデータ並列処理用のコードを生成できるようにします。

OpenMP の 1 つの特徴を使用して、プリプロセッサーのディレクティブで並列処理を行うコードのエリアにはアノテーションが付けられます。ブロック期間中、このコードはマルチスレッド化プログラムに変換され、ブロック内の各スレッドが終了すると再び結合されます。

図 3 に、このプロセスが実際にはどのように行われるかを示します。OpenMP は一連の pragma (プリプロセッサー・ディレクティブ) を提供するだけでなく、CC++、および Fortran 対応の関数も提供します。図 3 で表しているのは、コードの要素を複数のスレッドに変換する単純なプログラム (for ブロックの並列化) で、この図にはその作用が示されています。従来のプログラムであればループを順次実行しますが、OpenMP 実装はスレッドを作成して for ブロックを並列化します。OpenMP についての詳細は、「参考文献」を参照してください。

図 3. 単純な OpenMP サポートの例
Simple example of OpenMP support

4.3 リリース・シリーズ

GCC 4 の現行のリリース・シリーズは 4.3 です。このリリース・シリーズでは、機能が増え、サポートされるアーキテクチャーもさらに増えています (サポートされなくなったアーキテクチャーとポートが多数削除されているため、サポートされないアーキテクチャーも同様に増えています)。Fortran 2003 を対象とした新しい言語サポートが追加されるとともに、多数の一般的な最適化プログラムも改善されました。

このリリース・シリーズで新たにサポートされるようになったプロセッサーには、Coldfire プロセッサー・ファミリーの一部のプロセッサー、IBM System z9 EC/BC プロセッサー、Cell ブロードバンド・エンジン・アーキテクチャーの SPU (Synergistic Processor Unit) があります。さらに SmartMIPS の他にも多数のアーキテクチャーのプロセッサーがサポートされるようになっています。このリリース・シリーズには、Thumb2 (ARM 命令の圧縮版) および ARMv7 アーキテクチャーのコンパイラーとライブラリーのサポート、さらに Core2 プロセッサーと Geode プロセッサー・ファミリーの調整サポートも備わっています。

コンパイラーのフロント・エンドでは、GIMPLE の内部表現が再定義されました。これは、コンパイラーが使用するメモリーが少なくなることを意味します。

4.3 リリース以降

4.4 リリース・シリーズへの取り組みはすでに始まっており、一般リリースに向けて作業が進んでいます。バージョン 4.4 には多数のバグ・フィックス、そして最適化プログラムのより全般的な改善が行われているはずです。バージョン 3.0 の OpenMP 仕様も CC++、Fortran 用に統合されています。

現在、コンパイラーでは最適化レベルを (以前はデフォルトに設定されていたファイル単位ではなく) 関数単位で定義できるようにもなっています。この機能を実現する optimize 属性を使用して、最適化プログラムに個々のオプションを指定することも可能です。

このリリースではついに、16-bit のマルチコア・プロセッサー、Picochip を対象としたプロセッサー・サポートを追加しました。Picochip の興味深い点は、メッシュ型の通信で、各コアをそれぞれ独自にプログラムできることです。


今後の展開

GCC の未来が明るいことは確かです。このツール・チェーンは最新のプロセッサー・アーキテクチャーをサポートするために進化を続けています (アーキテクチャー全体についても、個々の機能の追加に関しても)。また、GCC が対応する言語も広範囲にわたります。現在、Mercury、GHDL (VHDL 対応の GCC フロント・エンド)、UPC (Unified Parallel C) など、さまざまな言語に対するサポートの開発が行われています。

GCC の明るい未来に加え、その継続的改善は Linux、BSD (Berkeley Software Distribution) から Apache、そしてその間に存在するあらゆるタイプのソフトウェアにメリットをもたらすことを意味します。GCC 4 でコンパイルされたソフトウェアは、一般にサイズが小さくて高速な動作が可能なはずであり、あらゆる点でソフトウェア業界にとってメリットとなるからです。

参考文献

学ぶために

製品や技術を入手するために

  • developerWorks から直接ダウンロードできる IBM ソフトウェアの試用版を使用して、Linux で次の開発プロジェクトを構築してください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=354432
ArticleTitle=GCC 4 について学ぶ
publish-date=10282008