use crate::rewrites::rhs_lit_chain::{combine_rhs_lit_chain, RhsLitChainRule};
use crate::KernelDescriptor;
use vyre_foundation::ir::BinOp;
#[must_use]
pub fn sub_combine(desc: &KernelDescriptor) -> KernelDescriptor {
combine_rhs_lit_chain(
desc,
RhsLitChainRule {
op: BinOp::Sub,
combine_literals: u32::checked_add,
},
)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::rewrites::rhs_lit_chain::test_support::{
assert_multi_consumer_rhs_chain_left_alone, assert_rhs_chain_combines,
assert_rhs_chain_left_alone, assert_rhs_chain_recurses_into_child,
assert_rhs_chain_rewrite_is_idempotent, binop, descriptor_with, empty_body, lit_u32,
nonliteral_source, op_at,
};
use vyre_foundation::ir::BinOp;
const DESC_ID: &str = "sub_combine_test";
#[test]
fn sub_chain_combines_when_no_wrap() {
assert_rhs_chain_combines(DESC_ID, sub_combine, BinOp::Sub, 3, 5, 8);
}
#[test]
fn wrapping_sum_left_alone() {
assert_rhs_chain_left_alone(
DESC_ID,
sub_combine,
BinOp::Sub,
0xFFFF_FFFF,
1,
"Fix: refuse to combine when literal sum overflows u32.",
);
}
#[test]
fn inner_sub_with_multiple_consumers_left_alone() {
assert_multi_consumer_rhs_chain_left_alone(DESC_ID, sub_combine, BinOp::Sub, 3, 5);
}
#[test]
fn sub_with_lhs_lit_left_alone() {
let mut body = empty_body();
nonliteral_source(&mut body, 0);
lit_u32(&mut body, 100, 1);
binop(&mut body, BinOp::Sub, 1, 0, 2);
lit_u32(&mut body, 5, 3);
binop(&mut body, BinOp::Sub, 2, 3, 4);
let desc = sub_combine(&descriptor_with(DESC_ID, body));
let outer = op_at(&desc, 4);
assert_eq!(
outer.operands[0], 2,
"Fix: Sub(Lit, x) inner shape must not fold via the sum path."
);
}
#[test]
fn rewrite_is_idempotent() {
assert_rhs_chain_rewrite_is_idempotent(DESC_ID, sub_combine, BinOp::Sub, 3, 5);
}
#[test]
fn recurses_into_child_bodies() {
assert_rhs_chain_recurses_into_child(DESC_ID, sub_combine, BinOp::Sub, 4, 6, 10);
}
}