use vyre_foundation::ir::{Expr, Ident, Node, Program};
use vyre_foundation::optimizer::passes::loops::loop_lower_bound_normalize::LoopLowerBoundNormalize;
use vyre_foundation::optimizer::passes::loops::loop_redundant_bound_check_elide::LoopRedundantBoundCheckElidePass;
use vyre_foundation::optimizer::passes::loops::loop_strip_mine::LoopStripMine;
use vyre_foundation::optimizer::passes::loops::loop_unroll::LoopUnroll;
use vyre_foundation::optimizer::passes::loops::loop_var_range_fold::LoopVarRangeFoldPass;
use vyre_foundation::optimizer::{PassAnalysis, ProgramPass};
fn program_with_entry(entry: Vec<Node>) -> Program {
Program::wrapped(vec![], [1, 1, 1], entry)
}
fn entry_body(program: &Program) -> &[Node] {
match program.entry() {
[Node::Region { body, .. }] => body.as_slice(),
other => other,
}
}
fn count_ifs(nodes: &[Node]) -> usize {
let mut n = 0;
for node in nodes {
match node {
Node::If {
then, otherwise, ..
} => {
n += 1;
n += count_ifs(then);
n += count_ifs(otherwise);
}
Node::Block(b) | Node::Loop { body: b, .. } => n += count_ifs(b),
Node::Region { body, .. } => n += count_ifs(body),
_ => {}
}
}
n
}
fn rebind_via_let_load() -> Vec<Node> {
vec![
Node::let_bind("i", Expr::load("buf", Expr::var("i"))),
Node::if_then(
Expr::lt(Expr::var("i"), Expr::u32(4)),
vec![Node::store("buf", Expr::var("i"), Expr::u32(7))],
),
]
}
fn rebind_via_assign() -> Vec<Node> {
vec![
Node::assign("i", Expr::load("buf", Expr::var("i"))),
Node::if_then(
Expr::lt(Expr::var("i"), Expr::u32(4)),
vec![Node::store("buf", Expr::var("i"), Expr::u32(7))],
),
]
}
#[test]
fn elide_keeps_guard_after_let_rebind() {
let program = program_with_entry(vec![Node::Loop {
var: Ident::from("i"),
from: Expr::u32(0),
to: Expr::u32(4),
body: rebind_via_let_load(),
}]);
let result = LoopRedundantBoundCheckElidePass::transform(program.clone());
assert!(!result.changed);
assert_eq!(count_ifs(entry_body(&result.program)), 1);
assert_eq!(
ProgramPass::analyze(&LoopRedundantBoundCheckElidePass, &program),
PassAnalysis::SKIP
);
}
#[test]
fn elide_keeps_guard_after_assign_rebind() {
let program = program_with_entry(vec![Node::Loop {
var: Ident::from("i"),
from: Expr::u32(0),
to: Expr::u32(4),
body: rebind_via_assign(),
}]);
let result = LoopRedundantBoundCheckElidePass::transform(program);
assert!(
!result.changed,
"Assign rebind is as real as Let rebind — guard must stay"
);
assert_eq!(count_ifs(entry_body(&result.program)), 1);
}
#[test]
fn range_fold_skips_when_induction_rebound() {
let program = program_with_entry(vec![Node::Loop {
var: Ident::from("i"),
from: Expr::u32(0),
to: Expr::u32(4),
body: rebind_via_let_load(),
}]);
let result = LoopVarRangeFoldPass::transform(program);
assert!(
!result.changed,
"range fold must not treat a rebound Var(i) as the loop range"
);
assert_eq!(count_ifs(entry_body(&result.program)), 1);
}
#[test]
fn lower_bound_normalize_skips_when_induction_rebound() {
let program = program_with_entry(vec![Node::Loop {
var: Ident::from("i"),
from: Expr::u32(4),
to: Expr::u32(12),
body: vec![
Node::let_bind("i", Expr::load("buf", Expr::var("i"))),
Node::store("buf", Expr::var("i"), Expr::u32(1)),
],
}]);
let result = LoopLowerBoundNormalize::transform(program);
assert!(
!result.changed,
"lower-bound normalize must decline when the body rebinds the loop var"
);
}
#[test]
fn strip_mine_skips_when_induction_rebound() {
let program = program_with_entry(vec![Node::Loop {
var: Ident::from("i"),
from: Expr::u32(0),
to: Expr::u32(32),
body: vec![Node::let_bind("i", Expr::u32(7))],
}]);
let result = LoopStripMine::transform(program);
assert!(!result.changed);
}
#[test]
fn unroll_skips_when_induction_written() {
let program = program_with_entry(vec![Node::Loop {
var: Ident::from("i"),
from: Expr::u32(0),
to: Expr::u32(3),
body: vec![
Node::let_bind("i", Expr::u32(0)),
Node::store("buf", Expr::var("i"), Expr::u32(1)),
],
}]);
let before = program.clone();
let result = LoopUnroll::transform(program);
assert!(
!result.changed || result.program == before,
"unroll must not expand a loop whose body writes the induction var"
);
let still_has_loop = entry_body(&result.program).iter().any(|n| {
matches!(n, Node::Loop { .. }) || {
if let Node::Block(b) = n {
b.iter().any(|c| matches!(c, Node::Loop { .. }))
} else {
false
}
}
});
assert!(
still_has_loop
|| entry_body(&result.program)
.iter()
.any(|n| matches!(n, Node::Loop { .. })),
"loop with induction write must remain a Loop, not an unrolled splat; got {:?}",
entry_body(&result.program)
);
}
#[test]
fn nested_same_name_loop_blocks_range_fold_on_outer() {
let inner = Node::Loop {
var: Ident::from("i"),
from: Expr::u32(0),
to: Expr::u32(2),
body: vec![Node::store("buf", Expr::var("i"), Expr::u32(1))],
};
let program = program_with_entry(vec![Node::Loop {
var: Ident::from("i"),
from: Expr::u32(0),
to: Expr::u32(8),
body: vec![
inner,
Node::if_then(
Expr::lt(Expr::var("i"), Expr::u32(8)),
vec![Node::store("buf", Expr::var("i"), Expr::u32(2))],
),
],
}]);
let result = LoopVarRangeFoldPass::transform(program);
assert_eq!(
count_ifs(entry_body(&result.program)),
1,
"nested same-name loop must keep outer range fold conservative"
);
}
#[test]
fn elide_keeps_guard_when_rebind_is_nested_inside_if() {
let program = program_with_entry(vec![Node::Loop {
var: Ident::from("i"),
from: Expr::u32(0),
to: Expr::u32(4),
body: vec![
Node::If {
cond: Expr::bool(true),
then: vec![Node::let_bind("i", Expr::load("buf", Expr::var("i")))],
otherwise: vec![],
},
Node::if_then(
Expr::lt(Expr::var("i"), Expr::u32(4)),
vec![Node::store("buf", Expr::var("i"), Expr::u32(7))],
),
],
}]);
let result = LoopRedundantBoundCheckElidePass::transform(program);
assert!(
!result.changed,
"rebind inside If must still poison induction-based elision"
);
assert_eq!(count_ifs(entry_body(&result.program)), 2);
}
#[test]
fn elide_still_fires_when_unrelated_name_is_bound() {
let program = program_with_entry(vec![Node::Loop {
var: Ident::from("i"),
from: Expr::u32(0),
to: Expr::u32(4),
body: vec![
Node::let_bind("j", Expr::load("buf", Expr::var("i"))),
Node::if_then(
Expr::lt(Expr::var("i"), Expr::u32(4)),
vec![Node::store("buf", Expr::var("i"), Expr::u32(7))],
),
],
}]);
let result = LoopRedundantBoundCheckElidePass::transform(program);
assert!(
result.changed,
"binding an unrelated name must not disable redundant-guard elision"
);
assert_eq!(count_ifs(entry_body(&result.program)), 0);
}
#[test]
fn strip_mine_still_fires_when_unrelated_name_is_bound() {
let program = program_with_entry(vec![Node::Loop {
var: Ident::from("i"),
from: Expr::u32(0),
to: Expr::u32(32),
body: vec![
Node::let_bind("j", Expr::u32(0)),
Node::store("buf", Expr::var("i"), Expr::u32(1)),
],
}]);
let result = LoopStripMine::transform(program);
assert!(
result.changed,
"unrelated let must not look like an induction rebind to strip-mine"
);
}