第2章 作者・誕生の背景・MLIR

2.1 この章で学ぶこと

この章で学ぶ内容は以下のとおりです。

表2-1: この章で学ぶこと

学ぶこと

ポイント

AI インフラのスタック断層問題

なぜ新しい言語が必要になったか

MLIR とは何か

複数レベルの中間表現を扱うコンパイラ基盤

lowering とは何か

高水準表現から機械語へ段階的に変換する仕組み

アセンブリの中の MLIR の痕跡

第1章の .asmKGENParamList という文字列が現れる理由

2.2 AI インフラのスタック断層問題

Python は AI の入り口として定着しています。 しかし本番で高い性能を出すレイヤーになると、現実には多くの異なる技術が積み重なっています。

典型的な AI スタック(Mojo 以前)

レイヤー

言語 / 技術

最適化器

役割

アプリ

Python

モデル定義と学習ループ

フレームワーク

Python + C 拡張

PyTorch / TensorFlow

テンソル演算グラフ

カーネル

CUDA C++ / Triton

cuBLAS / cuDNN

GPU 行列演算

中間表現

PTX / LLVM IR

nvcc / LLVM

デバイス別コード生成

ハードウェア

GPU / CPU

実際の演算

各レイヤーは異なる言語、ツール、コンパイラを持ちます。 「Python で書いた処理がどのように GPU で走るか」を人間が全部追うのは現実的ではなく、レイヤーをまたぐ最適化も難しい状況です。

Mojo が目指すのは、この断層を一つの言語と一つのコンパイラスタックで解消することです。

2.3 MLIR とは何か

MLIR(Multi-Level Intermediate Representation)は、2020 年に Google がオープンソース化した汎用コンパイラ基盤です。

コラム: 従来の LLVM との違い

LLVM(2000 年ごろ〜)は「ソース言語 → LLVM IR → 機械語」という 1 段階の変換を担います。 C、C++、Rust などはすべて LLVM IR に落としてから最適化します。 強力ですが、「テンソル演算」「GPU スレッドブロック」「ニューラルネットのグラフ」のような高水準の概念は LLVM IR では直接扱えません。

MLIR はこの問題を解決するために設計されました。 「抽象度の異なる複数の中間表現(ダイアレクト)を同時に使える」基盤です。 高水準の演算グラフのまま最適化し、徐々に低水準へ変換(lowering)していきます。

2.3.1 MLIR のダイアレクト

MLIR では、目的に応じた「ダイアレクト」(方言)を定義します。 Mojo のコンパイラは複数のダイアレクトを通じて段階的に変換を行います。

表2-2: MLIR のダイアレクト

ダイアレクト

抽象度

扱うもの

kgen(Mojo 独自)

最高水準

Mojo の型、ジェネリクス、所有権

linalg

高水準

行列演算とループ抽象

affine

中間

ループ境界とアクセスパターン

llvm

低水準

LLVM IR に相当する命令

LLVM IR → x86 / PTX

最低水準

CPU / GPU 向けの機械語

MLIR のダイアレクト lowering 全体像

図2-1: MLIR のダイアレクト lowering 全体像

kgen → linalg → affine → llvm の各ダイアレクトを「低水準化」しながら x86-64(機械語)または PTX(GPU)へ変換する流れ。 各段階でループ抽象、アクセスパターン、LLVM IR 命令へと表現が具体化していく。

2.4 lowering:段階的な変換の流れ

Mojo のソースコードは次の経路でコンパイルされます。

hello_mojo_minimal.mojo
        │  ← Mojo フロントエンド
        ▼
   kgen ダイアレクト(型・所有権・ジェネリクス)
        │  ← lowering pass
        ▼
   linalg / affine ダイアレクト(ループ・演算)
        │  ← lowering pass
        ▼
   llvm ダイアレクト(LLVM IR 相当)
        │  ← LLVM バックエンド
        ▼
   x86-64 機械語 / PTX(GPU 向け)

ポイントは「共通の中間表現基盤の上で、ターゲットに応じて lowering(低水準化)の経路が変わる」点です。 CPU 向けなら x86-64 を、GPU 向けなら PTX を、同じ高水準コードから生成し分けられます(GPU 対応の範囲は発展途上で、すべてのコードがそのまま PTX になるわけではありません)。 bin/mojo-build.sh--target-triple x86_64-apple-macosx15.0 を渡しているのはこのためです。

2.5 アセンブリの中に見える MLIR の痕跡

第1章で逆アセンブルした hello_mojo_minimal.asm には、MLIR の痕跡が文字列として刻まれています。

76:  callq  "_std::io::io::print[KGENParamList[::Writable],*::Writable,
              LITImmutOrigin,::Origin[::Bool(False), $2]]
              (*$0, sep:::StringSlice[...], end:::StringSlice[...],
               flush:::Bool, file:::FileDescriptor$),
             Ts.values`=[[typevalue<...>, struct<...>]]"

この長いシンボル名の中に KGENParamList という文字列が含まれています。

コラム: KGENParamList とは

KGENKernel GENeration)は Mojo のコンパイラが内部で使う MLIR ダイアレクトの名前です。 KGENParamList は、このダイアレクトがジェネリクスの型パラメータリストを表現するために使う構造です。

Mojo の print はジェネリック関数として定義されており、どの型の引数を受け取るかをコンパイル時に特化(specialization)します。 その特化情報が KGENParamList[::Writable] という形でシンボル名に埋め込まれます。

つまり、逆アセンブルのシンボル名は「Mojo の型システム → KGEN ダイアレクト → マングル済みシンボル」という変換の最終結果です。 .asm を読むだけで、MLIR の変換経路の一端が見えます。

このように、アセンブリのシンボル名は MLIR の処理を通じて確定します。 第1章で「なぜシンボル名がこんなに長いのか」と感じたとすれば、その答えがここにあります。

2.6 Chris Lattner と LLVM/MLIR の系譜

Mojo の背景を理解するうえで、Chris Lattner の仕事の流れが参考になります。

表2-3: Chris Lattner と LLVM/MLIR の系譜

時期

プロジェクト

主な貢献

2000〜

LLVM

汎用コンパイラ基盤。C、C++、Rust など多くの言語のバックエンドになる

2010〜

Swift

Apple のシステム言語。型安全と所有権の設計で Mojo の文法設計に影響

2019〜

MLIR

Google で開発。多段 IR によるコンパイラ基盤。TensorFlow などに採用

2022〜

Mojo / Modular

MLIR を基盤に AI インフラ向け言語を構築

注目すべきは「言語(Swift)とコンパイラ基盤(LLVM と MLIR)の両方を深く経験した人物が、その集大成として Mojo を設計した」という点です。 Mojo の ownership が Rust より柔らかく Python より明示的な形になっているのも、その経緯を反映しています。

2.7 CPU と GPU、同じコードから

MLIR が実現する最大のメリットの一つが、CPU と GPU の統一です。

表2-4: CPU と GPU、同じコードから

MLIR 以前

Mojo + MLIR

GPU カーネルの言語

CUDA C++(専用言語)

Mojo(同じ言語)

CPU コードとの共有

原則できない

Layout / LayoutTensor で統一

最適化のタイミング

GPU と CPU で別々のツールチェーン

lowering パスで一括

デバッグ

GPU 専用ツール(cuda-gdb 等)

統一されたコンパイラスタック

現時点(2025 年)では GPU サポートはまだ発展途上ですが、この設計思想は 第2部 の 第12章 ポインタ・GPU・レイアウト 章で改めて取り上げます。

2.8 まとめ

  • AI インフラは「Python / C++ / CUDA / PTX」がレイヤーをまたいで混在する構造になっていました。

  • MLIR(Multi-Level IR)は、高水準から低水準まで複数の中間表現を段階的に変換(lowering)できるコンパイラ基盤です。

  • Mojo は MLIR を基盤とすることで、同じ高水準コードから CPU と GPU 向けの機械語を生成し分けられる設計を目指しています(GPU 対応は発展途上)。

  • 第1章の .asm に現れた KGENParamList は、MLIR の kgen ダイアレクトがシンボル名に残した痕跡です。

  • MLIR の詳細を暗記する必要はありません。「なぜ Mojo が一つの言語で幅広いハードウェアを扱えるか」の答えが MLIR にある、と理解すれば十分です。