feat(joinir): Phase 213 AST-based if-sum lowerer for Pattern 3
Implement dual-mode architecture for Pattern 3 (Loop with If-Else PHI): - Add is_simple_if_sum_pattern() detection helper - Detects 1 CounterLike + 1-2 AccumulationLike carrier patterns - Unit tests for various carrier compositions - Add dual-mode dispatch in Pattern3 lowerer - ctx.is_if_sum_pattern() branches to AST-based vs legacy PoC - Legacy mode preserved for backward compatibility - Create loop_with_if_phi_if_sum.rs (~420 lines) - AST extraction: loop condition, if condition, updates - JoinIR generation: main, loop_step, k_exit structure - Helper functions: extract_loop_condition, extract_if_condition, etc. - Extend PatternPipelineContext for Pattern 3 - is_if_sum_pattern() detection using LoopUpdateSummary - extract_if_statement() helper for body analysis Note: E2E RC=2 not yet achieved due to pre-existing Pattern 3 pipeline issue (loop back branch targets wrong block). This affects both if-sum and legacy modes. Fix planned for Phase 214. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -117,6 +117,34 @@ impl LoopUpdateSummary {
|
||||
.filter(|c| c.kind == UpdateKind::AccumulationLike)
|
||||
.count()
|
||||
}
|
||||
|
||||
/// Phase 213: Check if this is a simple if-sum pattern
|
||||
///
|
||||
/// Simple if-sum pattern:
|
||||
/// - Has exactly 1 CounterLike carrier (loop index, e.g., "i")
|
||||
/// - Has exactly 1 AccumulationLike carrier (accumulator, e.g., "sum")
|
||||
/// - Optionally has additional accumulators (e.g., "count")
|
||||
///
|
||||
/// Examples:
|
||||
/// - `loop(i < len) { if cond { sum = sum + 1 } i = i + 1 }` ✅
|
||||
/// - `loop(i < len) { if cond { sum = sum + 1; count = count + 1 } i = i + 1 }` ✅
|
||||
/// - `loop(i < len) { result = result + data[i]; i = i + 1 }` ❌ (no if statement)
|
||||
pub fn is_simple_if_sum_pattern(&self) -> bool {
|
||||
// Must have exactly 1 counter (loop index)
|
||||
if self.counter_count() != 1 {
|
||||
return false;
|
||||
}
|
||||
// Must have at least 1 accumulator (sum)
|
||||
if self.accumulation_count() < 1 {
|
||||
return false;
|
||||
}
|
||||
// For now, only support up to 2 accumulators (sum, count)
|
||||
// This matches the Phase 212 if-sum minimal test case
|
||||
if self.accumulation_count() > 2 {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// キャリア名から UpdateKind を推定(暫定実装)
|
||||
@ -221,4 +249,50 @@ mod tests {
|
||||
assert_eq!(summary.counter_count(), 1);
|
||||
assert_eq!(summary.accumulation_count(), 1);
|
||||
}
|
||||
|
||||
// Phase 213 tests for is_simple_if_sum_pattern
|
||||
#[test]
|
||||
fn test_is_simple_if_sum_pattern_basic() {
|
||||
// phase212_if_sum_min.hako pattern: i (counter) + sum (accumulator)
|
||||
let names = vec!["i".to_string(), "sum".to_string()];
|
||||
let summary = analyze_loop_updates(&names);
|
||||
|
||||
assert!(summary.is_simple_if_sum_pattern());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_simple_if_sum_pattern_with_count() {
|
||||
// Phase 195 pattern: i (counter) + sum + count (2 accumulators)
|
||||
let names = vec!["i".to_string(), "sum".to_string(), "count".to_string()];
|
||||
let summary = analyze_loop_updates(&names);
|
||||
|
||||
assert!(summary.is_simple_if_sum_pattern());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_simple_if_sum_pattern_no_accumulator() {
|
||||
// Only counter, no accumulator
|
||||
let names = vec!["i".to_string()];
|
||||
let summary = analyze_loop_updates(&names);
|
||||
|
||||
assert!(!summary.is_simple_if_sum_pattern()); // No accumulator
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_simple_if_sum_pattern_no_counter() {
|
||||
// Only accumulator, no counter
|
||||
let names = vec!["sum".to_string()];
|
||||
let summary = analyze_loop_updates(&names);
|
||||
|
||||
assert!(!summary.is_simple_if_sum_pattern()); // No counter
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_simple_if_sum_pattern_multiple_counters() {
|
||||
// Multiple counters (not supported)
|
||||
let names = vec!["i".to_string(), "j".to_string(), "sum".to_string()];
|
||||
let summary = analyze_loop_updates(&names);
|
||||
|
||||
assert!(!summary.is_simple_if_sum_pattern()); // 2 counters
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user