From df2248d3c198ee6a485ad1eba31a87956bad44af Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Sun, 23 Nov 2025 10:08:48 +0900 Subject: [PATCH] feat(phi): Phase 27.4-C - HeaderPhiBuilder bypass for JoinIR experiment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JoinIR 実験経路限定で Header φ 生成をスキップ可能に。 実装内容: - トグルシステム: joinir_header_bypass_enabled() / is_joinir_header_bypass_target() - バイパス実装: loop_builder.rs で関数名チェック後に emit_header_phis() をスキップ - ターゲット関数: Main.skip/1, FuncScannerBox.trim/1 のみ - テスト更新: JoinIR テストファイルに Phase 27.4-C 対応コメント追加 環境変数: - NYASH_JOINIR_EXPERIMENT=1 AND NYASH_JOINIR_HEADER_EXP=1 の両方が必要 本線影響: ゼロ(MIR/LoopForm→VM 経路は完全に影響なし) --- src/mir/join_ir.rs | 2 +- src/mir/loop_builder.rs | 26 +++++++++++++++++++++++- src/mir/phi_core/header_phi_builder.rs | 25 +++++++++++++++++++++++ src/tests/mir_joinir_funcscanner_trim.rs | 6 ++++++ src/tests/mir_joinir_skip_ws.rs | 6 ++++++ 5 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/mir/join_ir.rs b/src/mir/join_ir.rs index 5c5b9702..11ef113d 100644 --- a/src/mir/join_ir.rs +++ b/src/mir/join_ir.rs @@ -44,7 +44,7 @@ impl JoinContId { pub type VarId = ValueId; /// 環境変数フラグが "1" かチェックするヘルパー(JoinIR 実験経路用) -fn env_flag_is_1(name: &str) -> bool { +pub(crate) fn env_flag_is_1(name: &str) -> bool { std::env::var(name).ok().as_deref() == Some("1") } diff --git a/src/mir/loop_builder.rs b/src/mir/loop_builder.rs index 5b91c0fe..ab223291 100644 --- a/src/mir/loop_builder.rs +++ b/src/mir/loop_builder.rs @@ -295,7 +295,31 @@ impl<'a> LoopBuilder<'a> { // Ensure header block exists before emitting PHIs self.parent_builder.ensure_block_exists(header_id)?; - loopform.emit_header_phis(self)?; + // Phase 27.4-C: JoinIR Header φ バイパスチェック + let fn_name = self + .parent_builder + .current_function + .as_ref() + .map(|f| f.signature.name.as_str()) + .unwrap_or(""); + + let header_bypass = crate::mir::phi_core::header_phi_builder::joinir_header_bypass_enabled() + && crate::mir::phi_core::header_phi_builder::is_joinir_header_bypass_target(fn_name); + + if header_bypass { + // Phase 27.4-C: JoinIR 実験経路では Header φ を生成しない。 + // Pinned/Carrier の値は preheader の copy をそのまま使う。 + // + // ⚠️ 重要: このモードでは MIR は不完全(φ 抜け)であり、VM で実行できない。 + // JoinIR runner 専用モードであることに注意。 + if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() { + eprintln!("[loopform/27.4-C] Header φ bypass active for: {}", fn_name); + eprintln!("[loopform/27.4-C] Skipping emit_header_phis() - using preheader values directly"); + } + } else { + // 従来どおり HeaderPhiBuilder を使って φ を準備 + loopform.emit_header_phis(self)?; + } if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() { eprintln!("[loopform] variable_map after emit_header_phis:"); diff --git a/src/mir/phi_core/header_phi_builder.rs b/src/mir/phi_core/header_phi_builder.rs index 837f83b6..f22c5a9b 100644 --- a/src/mir/phi_core/header_phi_builder.rs +++ b/src/mir/phi_core/header_phi_builder.rs @@ -35,6 +35,31 @@ fn joinir_header_experiment_enabled() -> bool { == Some("1") } +/// Phase 27.4-C: JoinIR Header φ バイパスが有効かチェック +/// +/// 条件: NYASH_JOINIR_EXPERIMENT=1 AND NYASH_JOINIR_HEADER_EXP=1 の両方が必要 +/// +/// **用途**: JoinIR 実験経路限定で Header φ 生成をスキップする場合に true を返す。 +/// 本線(MIR/LoopForm→VM)には一切影響しない。 +pub(crate) fn joinir_header_bypass_enabled() -> bool { + // JoinIR がそもそも実験モードか + let joinir_exp = crate::mir::join_ir::env_flag_is_1("NYASH_JOINIR_EXPERIMENT"); + // Header 実験フラグが ON か + let header_exp = joinir_header_experiment_enabled(); + joinir_exp && header_exp +} + +/// Phase 27.4-C: JoinIR Header φ バイパス対象関数かチェック +/// +/// Phase 27.4-C のスコープは以下の 2 関数のみ: +/// - Main.skip/1 (minimal_ssa_skip_ws.hako) +/// - FuncScannerBox.trim/1 (funcscanner_trim_min.hako) +/// +/// **重要**: 他の関数では Header φ を絶対にスキップしないこと。 +pub(crate) fn is_joinir_header_bypass_target(fn_name: &str) -> bool { + matches!(fn_name, "Main.skip/1" | "FuncScannerBox.trim/1") +} + /// Header PHI生成専門Box /// /// # Purpose diff --git a/src/tests/mir_joinir_funcscanner_trim.rs b/src/tests/mir_joinir_funcscanner_trim.rs index 5f276bfb..767d71b5 100644 --- a/src/tests/mir_joinir_funcscanner_trim.rs +++ b/src/tests/mir_joinir_funcscanner_trim.rs @@ -9,6 +9,12 @@ // 実行条件: // - デフォルトでは #[ignore] にしておいて手動実行用にする // - 環境変数 NYASH_JOINIR_EXPERIMENT=1 で実験モード有効化 +// +// Phase 27.4-C 対応: +// - このテストは JoinIR 変換のみを検証(VM 実行なし) +// - NYASH_JOINIR_HEADER_EXP=1 を併用すると Header φ bypass が有効化される +// - bypass 時は MIR に Header φ が生成されないが、このテストでは JoinIR のみ検証するため問題なし +// - 将来的に JoinIR runner 実行を追加する際は、bypass モードでも正しく動作することを確認する use crate::ast::ASTNode; use crate::mir::join_ir::*; diff --git a/src/tests/mir_joinir_skip_ws.rs b/src/tests/mir_joinir_skip_ws.rs index 870fa96b..8b2c03ce 100644 --- a/src/tests/mir_joinir_skip_ws.rs +++ b/src/tests/mir_joinir_skip_ws.rs @@ -9,6 +9,12 @@ // 実行条件: // - デフォルトでは #[ignore] にしておいて手動実行用にする // - 環境変数 NYASH_JOINIR_EXPERIMENT=1 で実験モード有効化 +// +// Phase 27.4-C 対応: +// - このテストは JoinIR 変換のみを検証(VM 実行なし) +// - NYASH_JOINIR_HEADER_EXP=1 を併用すると Header φ bypass が有効化される +// - bypass 時は MIR に Header φ が生成されないが、このテストでは JoinIR のみ検証するため問題なし +// - 将来的に JoinIR runner 実行を追加する際は、bypass モードでも正しく動作することを確認する use crate::ast::ASTNode; use crate::mir::join_ir::*;