1.3K Views
October 03, 25
スライド概要
2025/10/03 の コンパイラのコンパの部分 で発表しました
はじめてのコンパイラ最適化 ―レジスタ割り付け編― しーぴー (@cp20) コンパイラのコンパの部分 @2025.10.03
自己紹介 しーぴー🍀 @cp20 traP代表 / ぷよぷよが好き @__cp20__
おことわり - ある程度コンパイラの知識がある人向けに話します どれくらいのレベルを想定すれば良いのか分からなかったので、、、 - 間違いがあったら優しく教えてください 専門家とかではないので間違っている可能性はそれなりにあります
コンパイラ最適化といっても... - 定数展開・定数伝播 - 関数のインライン展開 - 部分式計算の共通化 - のぞき穴最適化 (命令の置換など) - レジスタ割り付け
今日はレジスタ割り付けの話をします - 定数展開・定数伝播 - 関数のインライン展開 - 部分式計算の共通化 - のぞき穴最適化 (命令の置換など) - レジスタ割り付け 👈
レジスタ割り付けの必要性 square: 前提 自作コンパイラでよく使われる スタックマシン方式の計算方法は 非常に効率が悪い (その分実装が非常に単純である) push %rbp movq %rsp, %rbp mov %edi, -4(%rbp) push -4(%rbp) push -4(%rbp) pop %eax pop %edi imul %edi, %eax push %eax pop %eax leave ret
レジスタ割り付けの必要性 適切なレジスタ割り付けを行うと - 命令数が減る パフォーマンス▲、バイナリサイズ▼ - メモリアクセスが減る パフォーマンス▲ square: imul %edi, %edi mov %edx, %eax ret
レジスタ割り付けの必要性 適切なレジスタ割り付けを行うと - 命令数が減る パフォーマンス▲、バイナリサイズ▼ - メモリアクセスが減る パフォーマンス▲ ナイーブな自作コンパイラにおいて パフォーマンス向上の余地が大きい! square: imul %edi, %edi mov %edx, %eax ret
レジスタ割り付けに必要なもの - 物理レジスタを割り付ける対象 (仮想レジスタ) 計算途中の値や変数など - それぞれの仮想レジスタの生存期間 同時に使われている仮想レジスタに同じ物理レジスタを割り当てないため これを求めるために制御フローの解析も必要
頑張って実装する 今回は (機能を絞った) Cコンパイラを実装した - 字句解析器 (Lexer) / 構文解析器 (Parser) - 中間表現の生成 - 制御フロー解析 - 生存期間解析 - レジスタ割り付け
頑張って実装する 今回は (機能を絞った) Cコンパイラを実装した - 字句解析器 (Lexer) / 構文解析器 (Parser) 👈 普通に実装する - 中間表現の生成 - 制御フロー解析 - 生存期間解析 - レジスタ割り付け
頑張って実装する 今回は (機能を絞った) Cコンパイラを実装した - 字句解析器 (Lexer) / 構文解析器 (Parser) 👈 普通に実装する - 中間表現の生成 👈 Code Generator の気持ちで実装する - 制御フロー解析 - 生存期間解析 - レジスタ割り付け
頑張って実装する 今回は (機能を絞った) Cコンパイラを実装した - 字句解析器 (Lexer) / 構文解析器 (Parser) 👈 普通に実装する - 中間表現の生成 👈 Code Generator の気持ちで実装する - 制御フロー解析 👈 中間表現を工夫して制御フローを表現した - 生存期間解析 - レジスタ割り付け
頑張って実装する 今回は (機能を絞った) Cコンパイラを実装した - 字句解析器 (Lexer) / 構文解析器 (Parser) 👈 普通に実装する - 中間表現の生成 👈 Code Generator の気持ちで実装する - 制御フロー解析 👈 中間表現を工夫して制御フローを表現した - 生存期間解析 👈 IN/OUTを追う方法で実装した with ChatGPT (ref: wiki) - レジスタ割り付け
頑張って実装する 今回は (機能を絞った) Cコンパイラを実装した - 字句解析器 (Lexer) / 構文解析器 (Parser) 👈 普通に実装する - 中間表現の生成 👈 Code Generator の気持ちで実装する - 制御フロー解析 👈 中間表現を工夫して制御フローを表現した - 生存期間解析 👈 IN/OUTを追う方法で実装した with ChatGPT (ref: wiki) - レジスタ割り付け 👈 Geminiに丸投げして実装してもらった
完成したものがこちらになります github.com/cp-20/pocc
パフォーマンス測定
パフォーマンス測定 O0より速い O3の30%ぐらい
今後の課題 - レジスタ割り付けのアルゴリズムが嘘 現状だとスピルが上手くできないという問題がある そもそも全部Geminiに書かせて理解できてないので既存のコンパイラを コードリーディングして勉強中 ref: Clang のレジスタ割り付けをコードリーディングする