use crate::rewrites::rhs_lit_chain::{combine_rhs_lit_chain, RhsLitChainRule};
use crate::KernelDescriptor;
use vyre_foundation::ir::BinOp;
#[must_use]
pub fn div_combine(desc: &KernelDescriptor) -> KernelDescriptor {
combine_rhs_lit_chain(
desc,
RhsLitChainRule {
op: BinOp::Div,
combine_literals: |a, b| {
if a == 0 || b == 0 {
None
} else {
a.checked_mul(b)
}
},
},
)
}
#[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,
};
use vyre_foundation::ir::BinOp;
const DESC_ID: &str = "div_combine_test";
#[test]
fn div_chain_combines_when_no_wrap_and_nonzero() {
assert_rhs_chain_combines(DESC_ID, div_combine, BinOp::Div, 3, 5, 15);
}
#[test]
fn wrapping_product_left_alone() {
assert_rhs_chain_left_alone(
DESC_ID,
div_combine,
BinOp::Div,
0x1_0000,
0x1_0000,
"Fix: refuse on overflow.",
);
}
#[test]
fn zero_divisor_left_alone() {
assert_rhs_chain_left_alone(
DESC_ID,
div_combine,
BinOp::Div,
0,
5,
"Fix: never absorb a div-by-zero into a fold.",
);
}
#[test]
fn outer_zero_divisor_left_alone() {
assert_rhs_chain_left_alone(
DESC_ID,
div_combine,
BinOp::Div,
5,
0,
"Fix: outer div-by-zero must remain observable.",
);
}
#[test]
fn inner_div_with_multiple_consumers_left_alone() {
assert_multi_consumer_rhs_chain_left_alone(DESC_ID, div_combine, BinOp::Div, 3, 5);
}
#[test]
fn rewrite_is_idempotent() {
assert_rhs_chain_rewrite_is_idempotent(DESC_ID, div_combine, BinOp::Div, 3, 5);
}
#[test]
fn recurses_into_child_bodies() {
assert_rhs_chain_recurses_into_child(DESC_ID, div_combine, BinOp::Div, 4, 6, 24);
}
}