use crate::ir::prelude::*;
use crate::opt::prelude::*;
pub struct InstSimplification;
impl Pass for InstSimplification {
fn run_on_inst(ctx: &PassContext, inst: Inst, unit: &mut UnitBuilder) -> bool {
unit.insert_after(inst);
match unit[inst].opcode() {
Opcode::DrvCond => {
if let Some(konst) = unit.get_const_int(unit[inst].args()[3]) {
if konst.is_one() {
let signal = unit[inst].args()[0];
let value = unit[inst].args()[1];
let delay = unit[inst].args()[2];
unit.ins().drv(signal, value, delay);
}
unit.delete_inst(inst);
}
}
_ => (),
}
let value = match unit.get_inst_result(inst) {
Some(value) => value,
None => return false,
};
match unit[inst].opcode() {
Opcode::And | Opcode::Or if unit[inst].args()[0] == unit[inst].args()[1] => {
replace(inst, value, unit[inst].args()[0], unit)
}
Opcode::Xor | Opcode::Umod | Opcode::Urem | Opcode::Smod | Opcode::Srem
if unit[inst].args()[0] == unit[inst].args()[1] =>
{
let ty = unit.value_type(value);
let zero = unit.ins().const_zero(&ty);
replace(inst, value, zero, unit)
}
Opcode::Mux => simplify_mux(ctx, inst, value, unit),
_ => false,
}
}
}
fn replace(from_inst: Inst, from_value: Value, to: Value, unit: &mut UnitBuilder) -> bool {
debug!("Replace {} with {}", from_inst.dump(&unit), to.dump(&unit));
unit.replace_use(from_value, to) > 0
}
fn simplify_mux(_ctx: &PassContext, inst: Inst, value: Value, unit: &mut UnitBuilder) -> bool {
let array = unit[inst].args()[0];
if let Some(array_inst) = unit.get_value_inst(array) {
let mut iter = unit[array_inst].args().iter().cloned();
let first = match iter.next() {
Some(first) => first,
None => return false,
};
let identical = iter.all(|a| a == first);
if identical {
return replace(inst, value, first, unit);
}
}
false
}