use alloc::vec::Vec;
use pliron_derive::op_interface;
use crate::{
attribute::{AttrObj, attr_cast},
basic_block::BasicBlock,
builtin::{attr_interfaces::MaterializableAttr, op_interfaces::BranchOpInterface},
context::{Context, Ptr},
irbuild::{IRStatus, rewriter::Rewriter},
op::Op,
result::Result,
};
pub mod sccp;
mod state;
#[op_interface]
pub trait ConstFoldInterface {
fn check_fold(&self, ctx: &Context, operand_attrs: &[Option<AttrObj>]) -> Vec<Option<AttrObj>>;
fn fold_in_place(
&self,
ctx: &mut Context,
operand_attrs: &[Option<AttrObj>],
rewriter: &mut dyn Rewriter,
) -> IRStatus;
fn fold_with_materialization(
&self,
ctx: &mut Context,
operand_attrs: &[Option<AttrObj>],
rewriter: &mut dyn Rewriter,
) -> IRStatus {
let folded = self.check_fold(ctx, operand_attrs);
let op = self.get_operation();
let mut status = IRStatus::Unchanged;
for (result_idx, attr) in folded.iter().enumerate() {
let Some(attr) = attr else {
continue;
};
let Some(materializable) = attr_cast::<dyn MaterializableAttr>(&**attr) else {
log::info!(
"Constant propagation tried to materialize {}, but its type does not \
implement MaterializableAttr. This potentially prevents optimizations.",
attr.disp(ctx)
);
continue;
};
let const_op = materializable.materialize(ctx);
rewriter.append_operation(ctx, const_op);
let new_value = const_op.deref(ctx).get_result(0);
let old_value = op.deref(ctx).get_result(result_idx);
rewriter.replace_value_uses_with(ctx, old_value, new_value);
status = IRStatus::Changed;
}
status
}
fn verify(_op: &dyn Op, _ctx: &Context) -> Result<()>
where
Self: Sized,
{
Ok(())
}
}
#[op_interface]
pub trait BranchOpFoldInterface: BranchOpInterface {
fn check_fold(&self, ctx: &Context, operands: &[Option<AttrObj>]) -> Vec<Ptr<BasicBlock>>;
fn fold_in_place(
&self,
ctx: &mut Context,
operand_attrs: &[Option<AttrObj>],
rewriter: &mut dyn Rewriter,
) -> IRStatus;
fn verify(_op: &dyn Op, _ctx: &Context) -> Result<()>
where
Self: Sized,
{
Ok(())
}
}