Files
hakorune/docs/archive/phases/phase-12.5/implementation-examples.md

5.1 KiB
Raw Blame History

Phase 12.5: 実装例集

1. MIRMetadataの具体例

StringBox.lengthのヒント付与

// Beforeヒントなし
BoxCall {
    target: ValueId(0),
    method: "length",
    args: vec![],
}

// Afterヒント付き
BoxCall {
    target: ValueId(0),
    method: "length",
    args: vec![],
    metadata: MIRMetadata {
        pure: true,        // 同じ文字列→同じ長さ
        readonly: true,    // 文字列を変更しない
        nothrow: true,     // 例外を投げない
        noalias: true,     // 結果は新しい整数
        ..Default::default()
    },
}

ループの最適化ヒント

// Nyashコード
for i in 0..1000 {
    array.push(i * 2)
}
// MIRでのヒント
Branch {
    cond: ValueId(5),  // i < 1000
    then_block: BlockId(2),
    else_block: BlockId(3),
    metadata: MIRMetadata {
        likely: Some(true),     // ループ継続が高確率
        loop_count: Some(1000), // ループ回数ヒント
        ..Default::default()
    },
}

2. Cエミッタでの変換例

純粋関数の最適化

// MIR: BoxCall(StringBox, "length") with {pure: true}
// ↓
// C出力:
static inline int64_t __attribute__((pure)) 
ny_string_length(NyashHandle h) {
    NyashString* s = ny_handle_to_string(h);
    return s->length;
}

分岐予測の最適化

// MIR: Branch with {likely: Some(false)}
// ↓
// C出力:
if (__builtin_expect(!!(error_condition), 0)) {
    // エラー処理(めったに実行されない)
    ny_handle_error();
} else {
    // 通常処理(ほぼ常に実行)
    continue;
}

3. 最適化パスの実装例

定数畳み込みConstFoldingPass

impl OptPass for ConstFoldingPass {
    fn run(&self, mir: &mut MIR) -> bool {
        let mut changed = false;
        
        for block in &mut mir.blocks {
            for inst in &mut block.instructions {
                match inst {
                    // Const(3) + Const(5) → Const(8)
                    BinOp { op: Add, left, right, result } => {
                        if let (Some(a), Some(b)) = (
                            self.get_const_value(*left),
                            self.get_const_value(*right)
                        ) {
                            *inst = Const { 
                                value: Value::Integer(a + b),
                                result: *result 
                            };
                            changed = true;
                        }
                    }
                    _ => {}
                }
            }
        }
        changed
    }
}

デッドコード除去DeadCodeElimPass

impl OptPass for DeadCodeElimPass {
    fn run(&self, mir: &mut MIR) -> bool {
        // 1. 使用されている値を収集
        let used = self.collect_used_values(mir);
        
        // 2. 未使用の命令を削除
        let mut changed = false;
        for block in &mut mir.blocks {
            block.instructions.retain(|inst| {
                if let Some(result) = inst.get_result() {
                    if !used.contains(&result) && !inst.has_side_effects() {
                        changed = true;
                        return false; // 削除
                    }
                }
                true
            });
        }
        changed
    }
}

4. バックエンド別の出力例

zig cc向けUbuntu/macOS

# MIRからCへ変換
nyash --emit-c program.hako -o program.c

# 最適化コンパイル
zig cc -O3 -flto -march=native \
    -fno-plt \
    -fomit-frame-pointer \
    program.c nyrt.c \
    -o program

MSVC向けWindows

REM リンク時最適化を有効化
cl /O2 /GL /MD program.c nyrt.c /Fe:program.exe ^
   /link /LTCG /OPT:REF /OPT:ICF

プロファイルガイド最適化PGO

# Step 1: プロファイル収集
zig cc -O3 -fprofile-generate program.c -o program_prof
./program_prof < typical_input.txt

# Step 2: プロファイルを使用して再コンパイル
zig cc -O3 -fprofile-use program.c -o program_opt

5. 性能測定の例

// benchmark.hako
static box Benchmark {
    main() {
        local start, end, result
        
        // ウォームアップ
        me.fibonacci(20)
        
        // 測定開始
        start = Time.now()
        result = me.fibonacci(40)
        end = Time.now()
        
        print("Fibonacci(40) = " + result)
        print("Time: " + (end - start) + "ms")
    }
    
    @[pure, nothrow]  // 最適化ヒント
    fibonacci(n) {
        if n <= 1 {
            return n
        }
        return me.fibonacci(n - 1) + me.fibonacci(n - 2)
    }
}

6. 最適化レベルごとの比較

レベル MIR最適化 Cコンパイラ 想定性能 用途
0 なし -O0 10% デバッグ
1 基本 -O2 50% 開発
2 全て -O3 -flto 70% リリース
3 全て+PGO -O3 -flto -fprofile-use 85% 高性能
4 全て LLVM -O3 90%+ 特殊用途

*性能は理論上の最大性能を100%とした場合の目安