use crate::{Inst, Offset, Optimizer};
impl Optimizer {
pub(in crate::optimization) fn fold_ptr_add(&self, insts: Vec<Inst>) -> Vec<Inst> {
let mut new_insts = Vec::with_capacity(insts.len());
let mut iter = insts.into_iter().peekable();
while let Some(inst) = iter.next() {
if let Inst::PtrAdd {
ptr: ptr1,
offset: offset1,
dst: dst1,
} = &inst
{
match iter.peek() {
Some(Inst::PtrAdd {
ptr: ptr2,
offset: offset2,
dst: dst2,
}) => {
if ptr1 == ptr2
&& dst1 == dst2
&& let Some(combined) = combine_offset(offset1, offset2)
{
new_insts.push(Inst::PtrAdd {
ptr: *ptr1,
offset: combined,
dst: *dst1,
});
iter.next();
continue;
}
}
Some(Inst::Load {
ty,
src_ptr: ptr2,
src_offset: offset2,
dst,
}) => {
if ptr1 == ptr2
&& offset1 == offset2
&& let Some(combined) = combine_offset(offset1, offset2)
{
new_insts.push(Inst::Load {
ty: *ty,
src_ptr: *ptr1,
src_offset: combined,
dst: *dst,
});
iter.next();
continue;
}
}
_ => {}
}
}
new_insts.push(inst);
}
new_insts
}
}
fn combine_offset(offset1: &Offset, offset2: &Offset) -> Option<Offset> {
match (offset1, offset2) {
(Offset::PointerScaled(s1), Offset::PointerScaled(s2)) => {
Some(Offset::PointerScaled(s1 + s2))
}
(Offset::Immediate(i1), Offset::Immediate(i2)) => Some(Offset::Immediate(i1 + i2)),
_ => None,
}
}