feat(joinir): Phase 33-7 IfMerge lowering for multiple-variable PHI
Implements IfMerge instruction lowering to support multiple variables merging from if/else branches (Phase 33-7: return pattern only). ## Changes - Add src/mir/join_ir/lowering/if_merge.rs (232 lines) - IfMergeLowerer with pattern matching for common variables - extract_written_vars() / find_written_value() helpers - Phase 33-7 constraint: return pattern only (k_next=None) - Update src/mir/join_ir/lowering/mod.rs - Unified entry point: try_lower_if_to_joinir() - Priority: IfMerge → Select → if_phi fallback - Add IfMergeTest.* to whitelist - Add unit tests in src/tests/mir_joinir_if_select.rs - test_if_merge_simple_pattern (2 variables) - test_if_merge_multiple_pattern (3 variables) - All 7/7 tests PASS ✅ - Add reference test cases - apps/tests/joinir_if_merge_simple.hako (2-var pattern) - apps/tests/joinir_if_merge_multiple.hako (3-var pattern) ## Test Results ✅ Simple pattern (2 vars): merges=2, k_next=None ✅ Multiple pattern (3 vars): merges=3, k_next=None ✅ test result: ok. 7 passed; 0 failed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -19,6 +19,7 @@ pub mod exit_args_resolver;
|
||||
pub mod funcscanner_append_defs;
|
||||
pub mod funcscanner_trim;
|
||||
pub mod generic_case_a;
|
||||
pub mod if_merge; // Phase 33-7
|
||||
pub mod if_select; // Phase 33
|
||||
pub mod loop_form_intake;
|
||||
pub mod loop_scope_shape;
|
||||
@ -46,29 +47,35 @@ pub use stageb_funcscanner::lower_stageb_funcscanner_to_joinir;
|
||||
use crate::mir::join_ir::JoinInst;
|
||||
use crate::mir::{BasicBlockId, MirFunction};
|
||||
|
||||
/// Phase 33-3: Try to lower if/else to JoinIR Select instruction
|
||||
/// Phase 33-7: Try to lower if/else to JoinIR Select/IfMerge instruction
|
||||
///
|
||||
/// Scope:
|
||||
/// - Only applies to whitelisted functions:
|
||||
/// - IfSelectTest.* (Phase 33-2/33-3)
|
||||
/// - IfMergeTest.* (Phase 33-7)
|
||||
/// - JsonShapeToMap._read_value_from_pair/1 (Phase 33-4 Stage-1)
|
||||
/// - Stage1JsonScannerBox.value_start_after_key_pos/2 (Phase 33-4 Stage-B)
|
||||
/// - Requires NYASH_JOINIR_IF_SELECT=1 environment variable
|
||||
/// - Falls back to traditional if_phi on pattern mismatch
|
||||
///
|
||||
/// Returns Some(JoinInst::Select) if pattern matched, None otherwise.
|
||||
/// Pattern selection:
|
||||
/// - 1 variable → Select
|
||||
/// - 2+ variables → IfMerge
|
||||
///
|
||||
/// Returns Some(JoinInst::Select) or Some(JoinInst::IfMerge) if pattern matched, None otherwise.
|
||||
pub fn try_lower_if_to_joinir(
|
||||
func: &MirFunction,
|
||||
block_id: BasicBlockId,
|
||||
debug: bool,
|
||||
) -> Option<JoinInst> {
|
||||
// dev トグルチェック
|
||||
// 1. dev トグルチェック
|
||||
if !crate::config::env::joinir_if_select_enabled() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Phase 33-4/33-5: 関数名ガード拡張(テスト + Stage-1/Stage-B 候補)
|
||||
// 2. Phase 33-7: 関数名ガード拡張(テスト + Stage-1/Stage-B 候補)
|
||||
let is_allowed = func.signature.name.starts_with("IfSelectTest.")
|
||||
|| func.signature.name.starts_with("IfMergeTest.") // Phase 33-7
|
||||
|| func.signature.name.starts_with("Stage1JsonScannerTestBox.") // Phase 33-5 test
|
||||
|| func.signature.name == "JsonShapeToMap._read_value_from_pair/1"
|
||||
|| func.signature.name == "Stage1JsonScannerBox.value_start_after_key_pos/2";
|
||||
@ -83,10 +90,26 @@ pub fn try_lower_if_to_joinir(
|
||||
return None;
|
||||
}
|
||||
|
||||
// if_select lowering を試行
|
||||
let lowerer = if_select::IfSelectLowerer::new(debug);
|
||||
// 3. Phase 33-7: IfMerge を優先的に試行(複数変数パターン)
|
||||
// IfMerge が成功すればそれを返す、失敗したら Select を試行
|
||||
let if_merge_lowerer = if_merge::IfMergeLowerer::new(debug);
|
||||
|
||||
if !lowerer.can_lower_to_select(func, block_id) {
|
||||
if if_merge_lowerer.can_lower_to_if_merge(func, block_id) {
|
||||
if let Some(result) = if_merge_lowerer.lower_if_to_if_merge(func, block_id) {
|
||||
if debug {
|
||||
eprintln!(
|
||||
"[try_lower_if_to_joinir] IfMerge lowering used for {}",
|
||||
func.signature.name
|
||||
);
|
||||
}
|
||||
return Some(result);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. IfMerge が失敗したら Select を試行(単一変数パターン)
|
||||
let if_select_lowerer = if_select::IfSelectLowerer::new(debug);
|
||||
|
||||
if !if_select_lowerer.can_lower_to_select(func, block_id) {
|
||||
if debug {
|
||||
eprintln!(
|
||||
"[try_lower_if_to_joinir] pattern not matched for {}",
|
||||
@ -96,11 +119,11 @@ pub fn try_lower_if_to_joinir(
|
||||
return None;
|
||||
}
|
||||
|
||||
let result = lowerer.lower_if_to_select(func, block_id);
|
||||
let result = if_select_lowerer.lower_if_to_select(func, block_id);
|
||||
|
||||
if result.is_some() && debug {
|
||||
eprintln!(
|
||||
"[try_lower_if_to_joinir] if_select lowering used for {}",
|
||||
"[try_lower_if_to_joinir] Select lowering used for {}",
|
||||
func.signature.name
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user