Files
hakorune/src/mir/join_ir/lowering/if_dry_runner.rs
nyash-codex 3ea397fd3e feat(joinir): Phase 61-1 If-in-loop JoinIR化インフラ整備完了
## 実装内容

### 新規ファイル
- `if_phi_context.rs`: If-in-loop用PHIコンテキスト構造体 (135行)
  - `IfPhiContext::for_loop_body()`: ループ内if用コンストラクタ
  - `is_carrier()`: ループキャリア変数判定
  - 単体テスト2個完全動作

### 既存ファイル拡張
- `if_select.rs`, `if_merge.rs`: context パラメータ追加 (+68行)
  - `with_context()` コンストラクタ実装
  - Pure If との完全互換性維持
- `mod.rs`: `try_lower_if_to_joinir()` シグネチャ拡張 (+25行)
  - `context: Option<&IfPhiContext>` パラメータ追加
  - 既存呼び出し箇所6箇所修正完了
- `loop_builder.rs`: JoinIR経路実装 (+43行)
  - `NYASH_JOINIR_IF_SELECT=1` で試行
  - フォールバック設計(PhiBuilderBox経路保持)
  - デバッグログ完備

## テスト結果
-  loopform テスト 14/14 PASS(退行なし)
-  ビルド成功(エラー0件)
-  Borrow Checker 問題解決

## コード変更量
- 新規: +135行
- 拡張: +136行
- 削除: -18行
- 純増: +253行(インフラ投資、Phase 61-3で-226行削減予定)

## 次のステップ
Phase 61-2: join_inst dry-run実装で実際のPHI生成を行う

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 11:53:57 +09:00

167 lines
5.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Phase 33-10.0: If lowering dry-run スキャナー(箱化版)
//!
//! ## 責務
//! - MIR モジュール内のすべての Branch ブロックをスキャン
//! - try_lower_if_to_joinir() でパターンマッチングを試行MIR書き換えなし
//! - パフォーマンス計測と統計情報の収集
//!
//! ## 非責務
//! - MIR の書き換えRoute B実装時に別モジュールで実施
//! - Loop lowering別のdispatch経路
use crate::mir::join_ir::JoinInst;
use crate::mir::{MirFunction, MirInstruction};
use std::collections::HashMap;
use std::time::{Duration, Instant};
/// If lowering dry-run スキャナー
pub struct IfLoweringDryRunner {
debug_level: u8,
}
/// Dry-run スキャン結果の統計情報
#[derive(Debug, Clone)]
pub struct DryRunStats {
pub total_branches: usize,
pub lowered_count: usize,
pub select_count: usize,
pub ifmerge_count: usize,
pub scan_duration: Duration,
}
impl IfLoweringDryRunner {
/// 新しい dry-run スキャナーを作成
pub fn new(debug_level: u8) -> Self {
Self { debug_level }
}
/// MIR モジュール全体をスキャンして If lowering 成功率を計測
///
/// ## 実装方針Phase 33-9.2
/// - Loop専任関数はスキップis_loop_lowered_function()
/// - 各 Branch ブロックで try_lower_if_to_joinir() 試行
/// - パフォーマンス計測(マイクロ秒レベル)
/// - 統計情報収集Select/IfMerge分類
pub fn scan_module(&self, functions: &HashMap<String, MirFunction>) -> DryRunStats {
let mut total_branches = 0;
let mut lowered_count = 0;
let mut select_count = 0;
let mut ifmerge_count = 0;
let start_scan = Instant::now();
for (func_name, func) in functions {
// Phase 33-9.1: Loop専任関数をスキップ
if crate::mir::join_ir::lowering::is_loop_lowered_function(func_name) {
continue;
}
// 各Branchブロックに対してtry_lower_if_to_joinir()試行
for (block_id, block) in &func.blocks {
if matches!(block.terminator, Some(MirInstruction::Branch { .. })) {
total_branches += 1;
let start = Instant::now();
match crate::mir::join_ir::lowering::try_lower_if_to_joinir(
func,
*block_id,
self.debug_level >= 3,
None, // Phase 61-1: Pure Ifdry-runは常にPure If
) {
Some(join_inst) => {
lowered_count += 1;
let elapsed = start.elapsed();
let inst_type = match &join_inst {
JoinInst::Select { .. } => {
select_count += 1;
"Select"
}
JoinInst::IfMerge { .. } => {
ifmerge_count += 1;
"IfMerge"
}
_ => "Other",
};
if self.debug_level >= 1 {
eprintln!(
"[joinir/if_lowering] ✅ {} block {:?}: {} ({:.2}μs)",
func_name,
block_id,
inst_type,
elapsed.as_micros()
);
}
}
None => {
if self.debug_level >= 2 {
eprintln!(
"[joinir/if_lowering] ⏭️ {} block {:?}: pattern not matched",
func_name, block_id
);
}
}
}
}
}
}
let scan_duration = start_scan.elapsed();
DryRunStats {
total_branches,
lowered_count,
select_count,
ifmerge_count,
scan_duration,
}
}
/// 統計情報を標準エラー出力に表示
pub fn print_stats(&self, stats: &DryRunStats) {
if self.debug_level >= 1 && stats.total_branches > 0 {
eprintln!("[joinir/if_lowering] 📊 Scan complete:");
eprintln!(" Total branches: {}", stats.total_branches);
eprintln!(
" Lowered: {} ({:.1}%)",
stats.lowered_count,
(stats.lowered_count as f64 / stats.total_branches as f64) * 100.0
);
eprintln!(" - Select: {}", stats.select_count);
eprintln!(" - IfMerge: {}", stats.ifmerge_count);
eprintln!(
" Scan time: {:.2}ms",
stats.scan_duration.as_secs_f64() * 1000.0
);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dry_runner_creation() {
let runner = IfLoweringDryRunner::new(0);
assert_eq!(runner.debug_level, 0);
let runner_verbose = IfLoweringDryRunner::new(3);
assert_eq!(runner_verbose.debug_level, 3);
}
#[test]
fn test_dry_run_stats_default() {
let stats = DryRunStats {
total_branches: 0,
lowered_count: 0,
select_count: 0,
ifmerge_count: 0,
scan_duration: Duration::from_millis(10),
};
assert_eq!(stats.total_branches, 0);
assert_eq!(stats.lowered_count, 0);
}
}