Phase 21: LLVM最適化フェーズ 🚀
開始予定: Phase 15完了後(Phase 21-30の間) 目標: nyashの14命令 → LLVM最適化能力の最大活用
🎯 フェーズの目的
現在の実装は正確性優先:
- ✅ 型変換統一(TypeCoercion箱)
- ✅ 値解決統一(PhiDispatchPoint)
- ✅ 文字列判定(StringTagPolicy)
Phase 21ではパフォーマンス最適化にフォーカス:
- LLVMの強力な最適化機能を活用
- ポリシー箱による戦略的最適化
- 未定義動作(UB)の完全回避
📋 実装ステージ(4段階)
Stage 1: 基礎インフラ(必須) 🏗️
目的: 安全な最適化の土台作り
1.1 LLVM Verifier統合
# 全関数生成後に自動検証
def verify_function(func):
"""LLVM Verifierで検証"""
if not func.verify():
raise CompilerError(f"Invalid IR in {func.name}")
実装タイミング: Stage 1最優先 効果: バグの早期発見(開発速度向上)
1.2 未定義動作(UB)検出
class UBChecker:
"""未定義動作の自動検出"""
def check_null_deref(self, ptr):
"""nullポインタ参照チェック"""
if ptr might be null:
insert_null_check(ptr)
def check_overflow(self, val):
"""整数オーバーフローチェック"""
if signed_int:
use_checked_arithmetic(val)
対象UB:
- ✅ nullポインタ参照
- ✅ 符号付き整数オーバーフロー
- ✅ 未初期化変数の使用
- ✅ 配列境界外アクセス
1.3 データレイアウト標準化
# ターゲット別のレイアウト定義
target_layouts = {
"x86_64": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"wasm32": "e-m:e-p:32:32-i64:64-n32:64-S128",
}
Stage 2: 型情報活用 📦
目的: Everything is Box → LLVMに構造を教える
2.1 Box構造のLLVM定義
# StringBox の構造体定義
StringBox = ir.LiteralStructType([
ir.IntType(32), # length
ir.IntType(8).as_pointer() # data*
])
# extractvalue で高速アクセス
length = builder.extract_value(string_box, 0) # 関数呼び出し不要!
効果:
- BoxCall呼び出し削減
- メモリアクセス最適化
- インライン展開促進
2.2 TBAA(Type-Based Alias Analysis)
class TBAAPolicy:
"""型ベースエイリアシング情報"""
def annotate_box_access(self, inst, box_type):
"""Box型ごとのTBAA付与"""
tbaa_metadata = {
"StringBox": self.string_tbaa_node,
"IntegerBox": self.integer_tbaa_node,
}
inst.set_metadata("tbaa", tbaa_metadata[box_type])
効果:
- 命令並び替え最適化
- 不要なメモリアクセス削減
- ループ最適化向上
2.3 extractvalue命令への置き換え
# Before: 関数呼び出し(遅い)
length = builder.call(get_length_func, [string_box])
# After: 構造体アクセス(速い)
length = builder.extract_value(string_box, 0, name="length")
Stage 3: 関数最適化 ⚡
目的: LLVM Intrinsics活用 + 関数属性付与
3.1 LLVM Intrinsics活用
# memcpy最適化
# Before: ループでコピー
for i in range(len):
dst[i] = src[i]
# After: LLVM Intrinsic
builder.call(llvm_memcpy, [dst, src, length])
対象Intrinsics:
@llvm.memcpy: メモリ一括コピー@llvm.memmove: オーバーラップ対応コピー@llvm.memset: メモリ初期化@llvm.sqrt: 平方根計算@llvm.abs: 絶対値計算
3.2 関数属性付与
class FunctionAttributePolicy:
"""関数の性質を明示"""
def annotate_pure_function(self, func):
"""副作用なし関数"""
func.attributes.add("readnone")
# LLVMが同じ引数の呼び出しを1回に最適化!
def annotate_readonly_function(self, func):
"""読み込み専用関数"""
func.attributes.add("readonly")
属性一覧:
readnone: 完全な純粋関数(Math.add等)readonly: 読み込みのみ(Array.length等)nounwind: 例外を投げないalwaysinline: 常にインライン展開
3.3 インライン展開ヒント
# 小さい関数は積極的にインライン化
if func_size < 10:
func.attributes.add("alwaysinline")
elif func_size > 100:
func.attributes.add("noinline")
Stage 4: ポリシー箱実装 🎁
目的: 戦略的最適化の統一管理
4.1 TypeSafetyPolicy
class TypeSafetyPolicy:
"""型安全性戦略"""
STRICT = "strict" # 型不一致は即エラー
PERMISSIVE = "permissive" # 暗黙的変換OK(現在)
DEBUG = "debug" # 全変換をログ出力
def convert(self, val, target_type, mode):
if mode == STRICT:
if val.type != target_type:
raise TypeError(f"Strict mode: {val.type} != {target_type}")
elif mode == PERMISSIVE:
return TypeCoercion.to_type(builder, val, target_type)
elif mode == DEBUG:
log_conversion(val, target_type)
return TypeCoercion.to_type(builder, val, target_type)
4.2 ErrorHandlingPolicy
class ErrorHandlingPolicy:
"""エラー処理戦略"""
FAIL_FAST = "panic" # 即座にエラー
FALLBACK = "default" # デフォルト値(現在)
COLLECT = "accumulate" # エラー収集後一括報告
def handle_type_error(self, error, mode):
if mode == FAIL_FAST:
raise error
elif mode == FALLBACK:
return Constant(i64, 0) # ← 現在の実装
elif mode == COLLECT:
self.errors.append(error)
return Constant(i64, 0)
4.3 OptimizationPolicy
class OptimizationPolicy:
"""最適化レベル戦略"""
def convert_with_opt(self, val, opt_level):
if opt_level == 0: # -O0(デバッグ)
# 境界チェック付き変換
return checked_conversion(val)
elif opt_level >= 2: # -O2/-O3(リリース)
# 高速変換(チェックなし)
return TypeCoercion.to_i64(builder, val)
4.4 PlatformPolicy
class PlatformPolicy:
"""プラットフォーム戦略"""
def get_native_int(self, target):
"""ターゲット別のネイティブ整数型"""
if target == "x86_64":
return ir.IntType(64) # ← 現在
elif target == "wasm32":
return ir.IntType(32)
elif target == "arm32":
return ir.IntType(32)
🎯 実装優先順位
| Stage | 優先度 | 実装タイミング |
|---|---|---|
| Stage 1(基礎インフラ) | 🔴 最高 | Phase 21開始直後 |
| Stage 2(型情報活用) | 🟡 高 | Stage 1完了後 |
| Stage 3(関数最適化) | 🟢 中 | Stage 2完了後 |
| Stage 4(ポリシー箱) | 🔵 低 | 具体的問題発生時 |
📊 期待される効果
パフォーマンス向上
- BoxCall削減: 30-50%削減(extractvalue化)
- メモリアクセス最適化: TBAA活用
- 関数呼び出しオーバーヘッド削減: Intrinsics/インライン化
開発体験向上
- Verifier: バグの早期発見
- UBチェック: 未定義動作の完全回避
- エラー収集モード: デバッグ効率化
移植性向上
- PlatformPolicy: 複数プラットフォーム対応
- データレイアウト標準化: クロスコンパイル対応
🚨 注意点(Gemini指摘事項)
1. 未定義動作(UB)を絶対に避ける
- nullポインタ参照
- 符号付き整数オーバーフロー
- 未初期化変数の使用
2. PHI命令は特に慎重に
- 全ての前任ブロックからの値を指定
- 漏れがあると検証エラー
3. Verifierを親友にする
- 開発中は毎回実行
- 問題の早期発見が鍵
4. データレイアウト・呼び出し規約の統一
- ターゲット別の標準ルールに従う
- C言語ライブラリとの互換性確保
📚 関連ドキュメント
- llvm-optimization-strategy.md - Gemini提案統合
- policy-box-design.md - ポリシー箱詳細設計
- integration-plan.md - 統合実装計画
- Phase 15.8 - 現在の型変換統一実装
🎊 まとめ
Phase 21は正確性から性能への転換点:
- Stage 1-3: 実装必須(基礎インフラ・型活用・関数最適化)
- Stage 4: YAGNI原則(必要になったら実装)
箱理論の実践: 最適化戦略も箱で管理!
作成日: 2025-10-02 ベース: Gemini最適化提案 + Claude分析統合