diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern_pipeline.rs b/src/mir/builder/control_flow/joinir/patterns/pattern_pipeline.rs index ea3004cb..1f1a1bd3 100644 --- a/src/mir/builder/control_flow/joinir/patterns/pattern_pipeline.rs +++ b/src/mir/builder/control_flow/joinir/patterns/pattern_pipeline.rs @@ -189,14 +189,25 @@ impl PatternPipelineContext { return false; } - // Phase 219-fix: Check if if condition is a simple comparison + // Phase 222: Check if if condition is a simple comparison and normalizable // Complex conditions (e.g., i % 2 == 1) → fallback to legacy mode if let Some(ASTNode::If { condition, .. }) = if_stmt { - use crate::mir::join_ir::lowering::condition_pattern::is_simple_comparison; - if !is_simple_comparison(condition) { + use crate::mir::join_ir::lowering::condition_pattern::{ + analyze_condition_pattern, normalize_comparison, ConditionPattern + }; + + // (a) Pattern check: must be SimpleComparison + let pattern = analyze_condition_pattern(condition); + if pattern != ConditionPattern::SimpleComparison { // Complex condition → legacy mode (PoC lowering) return false; } + + // (b) Normalization check: must be normalizable + if normalize_comparison(condition).is_none() { + // Normalization failed → legacy mode + return false; + } } // Phase 219: Use assignment-based carrier detection diff --git a/src/mir/join_ir/lowering/loop_with_if_phi_if_sum.rs b/src/mir/join_ir/lowering/loop_with_if_phi_if_sum.rs index 4ece3956..72e0af41 100644 --- a/src/mir/join_ir/lowering/loop_with_if_phi_if_sum.rs +++ b/src/mir/join_ir/lowering/loop_with_if_phi_if_sum.rs @@ -352,27 +352,49 @@ fn extract_loop_condition( where F: FnMut() -> ValueId, { - match cond { - ASTNode::BinaryOp { operator, left, right, .. } => { - let var_name = extract_variable_name(left)?; + // Phase 222: Normalize condition to canonical form (var on left) + use crate::mir::join_ir::lowering::condition_pattern::{normalize_comparison, ConditionValue}; - // Lower the right-hand side (limit) using condition_lowerer - // This handles both literals and variables via ConditionEnv - let mut limit_instructions = Vec::new(); - let limit_value = lower_value_expression(right, alloc_value, cond_env, &mut limit_instructions)?; + let norm = normalize_comparison(cond) + .ok_or_else(|| "[if-sum] Condition normalization failed".to_string())?; - let op = match operator { - crate::ast::BinaryOperator::Less => CompareOp::Lt, - crate::ast::BinaryOperator::LessEqual => CompareOp::Le, - crate::ast::BinaryOperator::Greater => CompareOp::Gt, - crate::ast::BinaryOperator::GreaterEqual => CompareOp::Ge, - _ => return Err(format!("[if-sum] Unsupported loop condition operator: {:?}", operator)), - }; + // Extract normalized variable name and operator + let var_name = norm.left_var; - Ok((var_name, op, limit_value, limit_instructions)) + // Convert mir::CompareOp to join_ir::CompareOp + let op = match norm.op { + crate::mir::CompareOp::Lt => CompareOp::Lt, + crate::mir::CompareOp::Gt => CompareOp::Gt, + crate::mir::CompareOp::Le => CompareOp::Le, + crate::mir::CompareOp::Ge => CompareOp::Ge, + crate::mir::CompareOp::Eq => CompareOp::Eq, + crate::mir::CompareOp::Ne => CompareOp::Ne, + }; + + // Lower the right-hand side using condition_lowerer + // This handles both literals and variables via ConditionEnv + let mut limit_instructions = Vec::new(); + let limit_value = match norm.right { + ConditionValue::Literal(lit) => { + // Create Const instruction for literal + let val_id = alloc_value(); + limit_instructions.push(JoinInst::Compute(MirLikeInst::Const { + dst: val_id, + value: ConstValue::Integer(lit), + })); + val_id } - _ => Err("[if-sum] Loop condition must be a binary comparison".to_string()), - } + ConditionValue::Variable(var_name) => { + // Create Variable node and lower it via condition_lowerer + let var_node = ASTNode::Variable { + name: var_name, + span: crate::ast::Span { start: 0, end: 0, line: 1, column: 1 }, + }; + lower_value_expression(&var_node, alloc_value, cond_env, &mut limit_instructions)? + } + }; + + Ok((var_name, op, limit_value, limit_instructions)) } /// Extract if condition: variable, operator, and value