++C++; // 未確認飛行 C ブログ

http://ufcpp.net/

LLILC (ライラック: LLVM ベースの IL コンパイラー)

with one comment

なんか割かしひっそりと公開されていましたが、.NET Foundation 配下で、LLVM ベースの IL コンパイラー(.NET の IL コードをネイティブ コード化)が出てきました。

プロジェクト名 LLILC。LLVM な IL Compiler で LL IL C でしょうし割かし安直なんですが、「lilac」(普通に花のライラック)と読ませるそうで読み方的には結構おしゃれ。縦棒並びすぎロシアの筆記体かよとか、L 並びすぎ呪文かよとか思ったりもしますが。

LLVM

大きなイベントで発表があったわけではなく、MSDN Blogs で取り上げられるでもなく(.NET Foundation のブログ記事はあり)、LLVM Project Blog でブログ記事が上がるってあたりが何か新しい。

マイクロソフトが LLVM を使うこと自体は少し前から前兆みたいなものはあって、例えば、去年、インターンで来た学生が、.NET Native のコード生成部分での LLVM 利用について調査してたとかがあったりします。

LLILC (JIT)と RyuJIT

LLILC は、予定としては JIT と AOT の両方を提供するそうですが、最初のターゲットは JIT だそうです。つまるところ、やってること自体は RyuJIT (マイクロソフトの最新の JIT 実装)と同じになります。

LLILC と RyuJIT は求めるものが異なっていて相補的な立ち位置にあります。

RyuJIT は高いパフォーマンスを求めていて、.NET 特有の(特に、C# 特有の)最適化をガチガチに掛けます。

一方で、LLILC は、LLVM の中間形式を経るので(Clang などの実績があってかなりよい最適化がかかるとはいえ)、RyuJIT ほどのパフォーマンスは出ないはずです。パフォーマンスよりも、より多くの環境で .NET プログラムが動くという点を求めています。

LLILC の現状の進捗としては Windows のみ。当面の目標としては Linux と Mac OS を狙っているそうです。また、LLILC が見本となることで、他の開発者による LLVM 実装が容易になればという期待もあるそうです。

LLILC (AOT)と .NET Native

(予定には含まれている) AOT 対応では、今度は .NET Native に近い土俵になります。ただ、.NET Native は単に IL からのネイティブ コード生成すること以外にも、より多くの仕事を担っています:

  1. (JIT の場合動的にやっている)マーシャリング向けのコードをコンパイル時に生成する
  2. (これも通常は動的にやる)シリアライズ用のコードを生成する
  3. 複数のアセンブリ(DLL, EXE)を1つにまとめる(アセンブリをまたいだ最適化が掛かるようにする)
  4. AOT 向けに IL コードを書き替え・最適化する
  5. 使われていないコード・型情報を削除する
  6. ネイティブ コード化する

(詳しくは .NET Native Performance and Internals を参照)

このうち、LLILC (AOT)が担える仕事は 6. の部分になります。今の .NET Native はこの部分にマイクロソフト製 C++ コンパイラー(cl.exe)と共通のインフラを使っているそうです。当然、この部分は LLILC での置き替えも考えられます。おそらくは、LLILC (JIT)と RyuJIT と同じような、高いパフォーマンスと、多くの環境で動くことのトレードオフになるでしょう。

マイクロソフト以外による LLVM 実装

Mono のランタイムは今、IL のコンパイル(JIT も AOT も)に LLVM を使って(使えるオプションを提供して)います。他にも、SharpLang とか LLVMSharp とか、いくつかの実装があるみたいです。それにマイクロソフト自身も、内部的には(たぶん、研究目的)LLVM 実装を持っていたそうです。

これらをそのまま使わなかった理由は、CoreCLR のインターフェイスに合わせるためとのこと。なので、LLILC のインターフェイスは RyuJIT のものとそろっているそうです。

LLILC と Roslyn (コンパイラーのフロントエンドとバックエンド)

RyuJIT が出た時にも詳しくない人は少し混乱したみたいなんですが、コンパイラーにはフロントエンドとバックエンドがあります。

フロントエンドの仕事は、高級言語から何らかの中間形式(抽象構文木(AST: abstract syntax tree)とか、仮想マシン語コード(.NET でいう IL、LLVM でいう BitCode)とか)に変換するところまで。バックエンドの仕事は、その中間形式から何らかの成果物(特定 CPU のマシン語コード化や、他の高級言語への変換)を得ることです。

フロントエンドとバックエンドが分かれていることで、高級言語の専門家と、CPU コード生成の専門家が分業できるというメリットがあります。分業によって、いろんな高級言語を、いろんな環境に対応させやすくなります。また、多くの場合、それぞれの専門家の努力によって、高級言語から一気に CPU コードを生成するよりも、中間形式を挟む方がよりよいコード生成ができたりします。

Roslyn (C#/VB コンパイラー)の仕事はフロントエンドです。C#/VB のソースコードを、IL (.NET の中間言語)に変換するところまでが仕事です。この範疇でやれることは、例えば以下のようなものです。

  • 高級言語の構文ハイライト
  • 警告やエラーが出ている箇所を(下線を引くなどして)表示
  • 変数やメソッドなどの「定義へ移動」「参照の検索」
  • ソースコードのリファクタリングや整形
  • 静的ソースコード分析(人的ミスを起こしやすそうなコードの発見や、コーディング規約への準拠チェックなど)

一方、LLILC の仕事はバックエンドで、CPU コード生成に加えて、以下のようなものが含まれ得ます。

  • プロファイリング、コード追跡、デバッグなど用の IL コード追加
  • 自動ベクトル化(SIMD 命令や GPU の活用)や自動並列化
  • テストケース削減(コード分析によってある程度のテストケースを自動的に作る。この手の機能は、Visual Studio 2015 にも載る予定: Smart Unit Tests)

LLILC がやっていること

LLILC は、要するに以下のような仕事をします。

  • IL (.NET の中間形式)の読み込み
  • IL から BitCode (LLVM の中間形式)への変換
  • .NET 固有な機能の提供

.NET 固有な機能には例えば以下のようなものがあります。

  • COFF (Common Object File Format: 実行形式ファイル中の情報)ローダー
  • ガベージ コレクション(.NET は強い型情報を持っているので、この情報に基づいて効率よくガベージ コレクションを提供できる)
  • 型情報に基づく最適化
  • 例外処理機構

Written by ufcpp

2015年4月17日 @ 02:36

カテゴリー: 未分類

1件のフィードバック

Subscribe to comments with RSS.

  1. […] なんか割かしひっそりと公開されていましたが、.NET Foundation 配下で、LLVM ベースの IL コンパイラー(.NET の IL コードをネイティブ コード化)が出てきました。 プロジェクト名 LLILC。LLVM な IL Compiler で LL IL C でしょうし割かし安直なんですが、「lilac」(普通に花のライラック)と読ませるそうで読み方的には結構おしゃれ。縦棒並びす…[続きを読む] […]


コメントを残す