add pass_add_sub_offset

This commit is contained in:
nora 2022-04-16 12:35:26 +02:00
parent 4490d49d35
commit 014770b6fe
4 changed files with 51 additions and 15 deletions

View file

@ -27,6 +27,8 @@ use std::fmt::{Debug, Formatter};
pub enum Stmt { pub enum Stmt {
Add(u8), Add(u8),
Sub(u8), Sub(u8),
AddOffset(i32, u8),
SubOffset(i32, u8),
Right(u32), Right(u32),
Left(u32), Left(u32),
Out, Out,
@ -86,6 +88,8 @@ 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::SubOffset(o, n) => Stmt::SubOffset(*o, *n),
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

@ -6,15 +6,17 @@ const MEM_SIZE: usize = 32_000;
type Memory = [Wrapping<u8>; MEM_SIZE]; type Memory = [Wrapping<u8>; MEM_SIZE];
// TODO maybe repr(C) to prevent field reordering? // `repr(C)` to make sure rustc never reorders the fields weirdly
// maybe useless, but seems to give tiny wins
#[repr(C)]
struct Interpreter<'c, W, R, P> { struct Interpreter<'c, W, R, P> {
code: &'c Code<'c>, code: &'c Code<'c>,
profile_collector: P,
ip: usize, ip: usize,
ptr: usize, ptr: usize,
mem: Memory,
stdout: W, stdout: W,
stdin: R, stdin: R,
mem: Memory,
profile_collector: P,
} }
pub fn run<W, R, P>(code: &Code<'_>, stdout: W, stdin: R, profile_collector: P) pub fn run<W, R, P>(code: &Code<'_>, stdout: W, stdin: R, profile_collector: P)
@ -60,6 +62,16 @@ where
Stmt::Sub(n) => { Stmt::Sub(n) => {
*self.elem_mut() -= n; *self.elem_mut() -= n;
} }
Stmt::AddOffset(o, n) => unsafe {
*self
.mem
.get_unchecked_mut((self.ptr as isize + (o as isize)) as usize) += n;
},
Stmt::SubOffset(o, n) => unsafe {
*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 {

View file

@ -42,6 +42,8 @@ impl Debug for Stmt<'_> {
pub enum StmtKind<'ir> { pub enum StmtKind<'ir> {
Add(u8), Add(u8),
Sub(u8), Sub(u8),
AddOffset(i32, u8),
SubOffset(i32, u8),
Right(usize), Right(usize),
Left(usize), Left(usize),
Loop(Ir<'ir>), Loop(Ir<'ir>),
@ -211,9 +213,27 @@ fn pass_cancel_left_right_add_sub(ir: &mut Ir<'_>) {
}) })
} }
/// pass that replaces `Right(9) Add(5) Left(9)` with `AddOffset(9)` /// pass that replaces `Right(9) Add(5) Left(9)` with `AddOffset(9, 5)`
#[tracing::instrument] #[tracing::instrument]
fn pass_add_sub_offset(ir: &mut Ir<'_>) {} fn pass_add_sub_offset(ir: &mut Ir<'_>) {
window_pass(ir, pass_add_sub_offset, |[a, b, c]| {
match (a.kind(), b.kind(), c.kind()) {
(StmtKind::Right(r), StmtKind::Add(n), StmtKind::Left(l)) if r == l => {
WindowPassAction::Merge(StmtKind::AddOffset(i32::try_from(*r).unwrap(), *n))
}
(StmtKind::Left(l), StmtKind::Add(n), StmtKind::Right(r)) if r == l => {
WindowPassAction::Merge(StmtKind::AddOffset(-i32::try_from(*r).unwrap(), *n))
}
(StmtKind::Right(r), StmtKind::Sub(n), StmtKind::Left(l)) if r == l => {
WindowPassAction::Merge(StmtKind::SubOffset(i32::try_from(*r).unwrap(), *n))
}
(StmtKind::Left(l), StmtKind::Sub(n), StmtKind::Right(r)) if r == l => {
WindowPassAction::Merge(StmtKind::SubOffset(-i32::try_from(*r).unwrap(), *n))
}
_ => WindowPassAction::None,
}
})
}
enum WindowPassAction<'ir> { enum WindowPassAction<'ir> {
None, None,
@ -236,13 +256,10 @@ where
pass_recur(body); pass_recur(body);
} }
if i >= stmts.len() - (N - 1) { if i + N > stmts.len() {
break; // there aren't N elements left break; // there aren't N elements left
} }
let a = &stmts[i];
let b = &stmts[i + 1];
let mut elements = stmts[i..][..N].iter(); let mut elements = stmts[i..][..N].iter();
let elements = [(); N].map(|()| elements.next().unwrap()); let elements = [(); N].map(|()| elements.next().unwrap());
@ -255,13 +272,16 @@ where
i += 1; i += 1;
} }
WindowPassAction::RemoveAll => { WindowPassAction::RemoveAll => {
trace!(?a, ?b, "Removing both statements"); trace!(?elements, "Removing all statements");
stmts.remove(i); for _ in 0..N {
stmts.remove(i); stmts.remove(i);
} }
}
WindowPassAction::Merge(new) => { WindowPassAction::Merge(new) => {
trace!(?a, ?b, ?new, "Merging statements"); trace!(?elements, ?new, "Merging statements");
stmts.remove(i + 1); for _ in 1..N {
stmts.remove(i);
}
stmts[i] = Stmt::new(new, merged_span); stmts[i] = Stmt::new(new, merged_span);
} }
} }

View file

@ -1 +1 @@
<<>>-<<>>>>>>>>>>>+<<<<<<<<<<<>> <<<<->>>>