feat(joinir): Phase 222-3 if-sum normalization integration

Phase 222: If Condition Normalization - Part 3
Goal: Integrate normalization into if-sum pattern detection and lowering

Changes:
1. pattern_pipeline.rs (is_if_sum_pattern):
   - Updated to use analyze_condition_pattern() + normalize_comparison()
   - Added two-step validation:
     (a) Pattern must be SimpleComparison
     (b) Condition must be normalizable
   - Replaced is_simple_comparison() with Phase 222 API

2. loop_with_if_phi_if_sum.rs (extract_loop_condition):
   - Added Phase 222 normalization
   - Normalize condition to canonical form (var on left)
   - Support both literal and variable on right-hand side
   - Added mir::CompareOp → join_ir::CompareOp conversion
   - Handles:
     * Phase 219: var CmpOp literal (e.g., i > 0)
     * Phase 222: literal CmpOp var (e.g., 0 < i) → normalized
     * Phase 222: var CmpOp var (e.g., i > j)

Status: Integration complete, ready for E2E testing
Next: Phase 222-4 - verify regression tests and add new test cases
This commit is contained in:
nyash-codex
2025-12-10 09:23:44 +09:00
parent f0536fa330
commit bcdad203f0
2 changed files with 53 additions and 20 deletions

View File

@ -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

View File

@ -352,27 +352,49 @@ fn extract_loop_condition<F>(
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