pub(crate) mod binop_identities;
mod cast_rules;
mod fma_rules;
pub mod reaching_def_propagate;
mod select_rules;
mod unary_rules;
pub(crate) use binop_identities::is_float_expr;
use crate::ir::eval::{fold_binary_literal, fold_literal_tree, fold_unary_literal};
use crate::ir::{Expr, Program};
use crate::optimizer::rewrite::rewrite_program;
use crate::optimizer::{vyre_pass, PassAnalysis, PassResult};
#[derive(Debug, Default)]
#[vyre_pass(
name = "const_fold",
requires = [],
invalidates = ["value_numbering"],
phase = "scalar_algebra",
boundary_class = "abi_preserving",
cost_model_family = "scalar"
)]
pub struct ConstFold;
impl ConstFold {
#[must_use]
fn analyze_impl(program: &Program) -> PassAnalysis {
if !program
.stats()
.has_any_node_kind(crate::ir::stats::NODE_KIND_EXPRESSION_BEARING_MASK)
{
return PassAnalysis::SKIP;
}
PassAnalysis::RUN
}
#[must_use]
pub fn transform(mut program: Program) -> PassResult {
let mut overall_changed = false;
let mut lookbehind_changed = false;
let new_entry =
binop_identities::fold_mod_lookbehind(program.entry(), &mut lookbehind_changed);
if lookbehind_changed {
overall_changed = true;
program = program.with_rewritten_entry(new_entry);
}
let (program, changed) = rewrite_program(program, fold_expr);
PassResult {
program,
changed: overall_changed || changed,
}
}
}
pub(crate) fn fold_expr(expr: &Expr) -> Option<Expr> {
if let Some(folded) = fold_literal_tree(expr) {
return Some(folded.into_owned());
}
match expr {
Expr::BinOp { op, left, right } => {
if let Some(simplified) = binop_identities::simplify_binop(*op, left, right) {
return Some(simplified);
}
fold_binary_literal(op, left, right)
}
Expr::UnOp { op, operand } => {
if let Some(simplified) = unary_rules::simplify_unop(op, operand) {
return Some(simplified);
}
fold_unary_literal(op, operand)
}
Expr::Select {
cond,
true_val,
false_val,
} => select_rules::simplify_select(cond, true_val, false_val),
Expr::Fma { a, b, c } => fma_rules::simplify_fma(a, b, c),
Expr::Cast { target, value } => cast_rules::fold_cast(target, value),
_ => None,
}
}
#[cfg(test)]
mod tests;