add pass_move_add_to

This commit is contained in:
nora 2022-04-16 14:35:56 +02:00
parent 014770b6fe
commit 93f97e9a08
4 changed files with 95 additions and 25 deletions

View file

@ -27,8 +27,9 @@ use std::fmt::{Debug, Formatter};
pub enum Stmt { pub enum Stmt {
Add(u8), Add(u8),
Sub(u8), Sub(u8),
AddOffset(i32, u8), AddOffset { offset: i32, n: u8 },
SubOffset(i32, u8), SubOffset { offset: i32, n: u8 },
MoveAddTo { offset: i32 },
Right(u32), Right(u32),
Left(u32), Left(u32),
Out, Out,
@ -88,8 +89,15 @@ fn ir_to_stmt<'c>(code: &mut Code<'c>, ir_stmt: &IrStmt<'_>) {
let stmt = match &ir_stmt.kind { let stmt = match &ir_stmt.kind {
StmtKind::Add(n) => Stmt::Add(*n), StmtKind::Add(n) => Stmt::Add(*n),
StmtKind::Sub(n) => Stmt::Sub(*n), StmtKind::Sub(n) => Stmt::Sub(*n),
StmtKind::AddOffset(o, n) => Stmt::AddOffset(*o, *n), StmtKind::AddOffset { offset, n } => Stmt::AddOffset {
StmtKind::SubOffset(o, n) => Stmt::SubOffset(*o, *n), offset: *offset,
n: *n,
},
StmtKind::SubOffset { offset, n } => Stmt::SubOffset {
offset: *offset,
n: *n,
},
StmtKind::MoveAddTo { offset } => Stmt::MoveAddTo { offset: *offset },
StmtKind::Right(n) => Stmt::Right(u32::try_from(*n).unwrap()), StmtKind::Right(n) => Stmt::Right(u32::try_from(*n).unwrap()),
StmtKind::Left(n) => Stmt::Left(u32::try_from(*n).unwrap()), StmtKind::Left(n) => Stmt::Left(u32::try_from(*n).unwrap()),
StmtKind::Out => Stmt::Out, StmtKind::Out => Stmt::Out,

View file

@ -62,16 +62,13 @@ where
Stmt::Sub(n) => { Stmt::Sub(n) => {
*self.elem_mut() -= n; *self.elem_mut() -= n;
} }
Stmt::AddOffset(o, n) => unsafe { Stmt::AddOffset { offset, n } => *self.elem_mut_offset(offset) += n,
*self Stmt::SubOffset { offset, n } => *self.elem_mut_offset(offset) -= n,
.mem Stmt::MoveAddTo { offset } => {
.get_unchecked_mut((self.ptr as isize + (o as isize)) as usize) += n; let value = self.elem();
}, *self.elem_mut() = Wrapping(0);
Stmt::SubOffset(o, n) => unsafe { *self.elem_mut_offset(offset) += value;
*self }
.mem
.get_unchecked_mut((self.ptr as isize + (o as isize)) as usize) -= n;
},
Stmt::Right(n) => { Stmt::Right(n) => {
self.ptr += n as usize; self.ptr += n as usize;
if self.ptr >= MEM_SIZE { if self.ptr >= MEM_SIZE {
@ -116,15 +113,24 @@ where
(self.profile_collector)(self.ip); (self.profile_collector)(self.ip);
} }
} }
fn elem_mut_offset(&mut self, offset: i32) -> &mut Wrapping<u8> {
let ptr = self.ptr as isize;
let offset = offset as isize;
// SAFETY: `self.ptr` is never out of bounds
debug_assert!(self.ptr < self.mem.len());
unsafe { self.mem.get_unchecked_mut((ptr + offset) as usize) }
}
fn elem_mut(&mut self) -> &mut Wrapping<u8> { fn elem_mut(&mut self) -> &mut Wrapping<u8> {
// SAFETY: `self.ptr` is never out of bounds // SAFETY: `self.ptr` is never out of bounds
//debug_assert!(self.ptr < self.mem.len()); debug_assert!(self.ptr < self.mem.len());
unsafe { self.mem.get_unchecked_mut(self.ptr) } unsafe { self.mem.get_unchecked_mut(self.ptr) }
} }
fn elem(&self) -> u8 { fn elem(&self) -> u8 {
// SAFETY: `self.ptr` is never out of bounds // SAFETY: `self.ptr` is never out of bounds
//debug_assert!(self.ptr < self.mem.len()); debug_assert!(self.ptr < self.mem.len());
unsafe { self.mem.get_unchecked(self.ptr).0 } unsafe { self.mem.get_unchecked(self.ptr).0 }
} }
} }

View file

@ -40,10 +40,20 @@ impl Debug for Stmt<'_> {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum StmtKind<'ir> { pub enum StmtKind<'ir> {
Add(u8), Add(u8), // todo: we probably want to remove this
Sub(u8), Sub(u8), // todo: we probably want to remove this
AddOffset(i32, u8), AddOffset {
SubOffset(i32, u8), offset: i32,
n: u8,
},
SubOffset {
offset: i32,
n: u8,
},
/// Sets the current cell to 0 and adds that value of the cell to another cell at `offset`
MoveAddTo {
offset: i32,
},
Right(usize), Right(usize),
Left(usize), Left(usize),
Loop(Ir<'ir>), Loop(Ir<'ir>),
@ -59,6 +69,7 @@ pub fn optimize<'ir>(alloc: &'ir Bump, instrs: &[(Instr<'_>, Span)]) -> Ir<'ir>
pass_set_n(&mut ir); pass_set_n(&mut ir);
pass_cancel_left_right_add_sub(&mut ir); pass_cancel_left_right_add_sub(&mut ir);
pass_add_sub_offset(&mut ir); pass_add_sub_offset(&mut ir);
pass_move_add_to(&mut ir);
ir ir
} }
@ -219,22 +230,67 @@ fn pass_add_sub_offset(ir: &mut Ir<'_>) {
window_pass(ir, pass_add_sub_offset, |[a, b, c]| { window_pass(ir, pass_add_sub_offset, |[a, b, c]| {
match (a.kind(), b.kind(), c.kind()) { match (a.kind(), b.kind(), c.kind()) {
(StmtKind::Right(r), StmtKind::Add(n), StmtKind::Left(l)) if r == l => { (StmtKind::Right(r), StmtKind::Add(n), StmtKind::Left(l)) if r == l => {
WindowPassAction::Merge(StmtKind::AddOffset(i32::try_from(*r).unwrap(), *n)) WindowPassAction::Merge(StmtKind::AddOffset {
offset: i32::try_from(*r).unwrap(),
n: *n,
})
} }
(StmtKind::Left(l), StmtKind::Add(n), StmtKind::Right(r)) if r == l => { (StmtKind::Left(l), StmtKind::Add(n), StmtKind::Right(r)) if r == l => {
WindowPassAction::Merge(StmtKind::AddOffset(-i32::try_from(*r).unwrap(), *n)) WindowPassAction::Merge(StmtKind::AddOffset {
offset: -i32::try_from(*r).unwrap(),
n: *n,
})
} }
(StmtKind::Right(r), StmtKind::Sub(n), StmtKind::Left(l)) if r == l => { (StmtKind::Right(r), StmtKind::Sub(n), StmtKind::Left(l)) if r == l => {
WindowPassAction::Merge(StmtKind::SubOffset(i32::try_from(*r).unwrap(), *n)) WindowPassAction::Merge(StmtKind::SubOffset {
offset: i32::try_from(*r).unwrap(),
n: *n,
})
} }
(StmtKind::Left(l), StmtKind::Sub(n), StmtKind::Right(r)) if r == l => { (StmtKind::Left(l), StmtKind::Sub(n), StmtKind::Right(r)) if r == l => {
WindowPassAction::Merge(StmtKind::SubOffset(-i32::try_from(*r).unwrap(), *n)) WindowPassAction::Merge(StmtKind::SubOffset {
offset: -i32::try_from(*r).unwrap(),
n: *n,
})
} }
_ => WindowPassAction::None, _ => WindowPassAction::None,
} }
}) })
} }
/// pass that replaces `Loop([Sub(1) AddOffset(o, 1)])` with `MoveAddTo(o)`
#[tracing::instrument]
fn pass_move_add_to(ir: &mut Ir<'_>) {
for stmt in &mut ir.stmts {
if let Stmt {
kind: StmtKind::Loop(body),
span,
} = stmt
{
if let [Stmt {
kind: StmtKind::Sub(1),
..
}, Stmt {
kind: StmtKind::AddOffset { offset, n: 1 },
..
}]
| [Stmt {
kind: StmtKind::AddOffset { offset, n: 1 },
..
}, Stmt {
kind: StmtKind::Sub(1),
..
}] = body.stmts.as_slice()
{
trace!(?span, ?offset, "Replacing Statement with MoveAddTo");
*stmt = Stmt::new(StmtKind::MoveAddTo { offset: *offset }, *span);
} else {
pass_move_add_to(body);
}
}
}
}
enum WindowPassAction<'ir> { enum WindowPassAction<'ir> {
None, None,
Merge(StmtKind<'ir>), Merge(StmtKind<'ir>),

View file

@ -1 +1 @@
<<<<->>>> [->>>>>>>>>+<<<<<<<<<]