mod binop_identities;
mod cast_rules;
mod fma_rules;
pub mod reaching_def_propagate;
mod select_rules;
mod unary_rules;
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::{fingerprint_program, vyre_pass, PassAnalysis, PassResult};
#[derive(Debug, Default)]
#[vyre_pass(name = "const_fold", requires = [], invalidates = ["value_numbering"])]
pub struct ConstFold;
impl ConstFold {
#[must_use]
#[inline]
pub fn analyze(_program: &Program) -> PassAnalysis {
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,
}
}
#[must_use]
#[inline]
pub fn fingerprint(program: &Program) -> u64 {
fingerprint_program(program)
}
}
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;