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:
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user