add opt that doesn't make anything faster but might allow better opts later

This commit is contained in:
nora 2022-04-15 23:07:51 +02:00
parent 6575e09957
commit c3c24c73fe
7 changed files with 59 additions and 24 deletions

View file

@ -31,6 +31,7 @@ pub enum Stmt {
Out, Out,
In, In,
SetNull, SetNull,
SetN(u8),
JmpIfZero(u32), JmpIfZero(u32),
JmpIfNonZero(u32), JmpIfNonZero(u32),
End, End,
@ -84,6 +85,7 @@ fn ir_to_stmt<'c>(code: &mut Code<'c>, ir_stmt: &IrStmt<'_>) {
StmtKind::Out => Stmt::Out, StmtKind::Out => Stmt::Out,
StmtKind::In => Stmt::In, StmtKind::In => Stmt::In,
StmtKind::SetNull => Stmt::SetNull, StmtKind::SetNull => Stmt::SetNull,
StmtKind::SetN(n) => Stmt::SetN(*n),
StmtKind::Loop(instr) => { StmtKind::Loop(instr) => {
let skip_jmp_idx = code.stmts.len(); let skip_jmp_idx = code.stmts.len();
code.stmts.push(Stmt::JmpIfZero(0)); // placeholder code.stmts.push(Stmt::JmpIfZero(0)); // placeholder

View file

@ -87,6 +87,9 @@ where
Stmt::SetNull => { Stmt::SetNull => {
*self.elem_mut() = Wrapping(0); *self.elem_mut() = Wrapping(0);
} }
Stmt::SetN(n) => {
*self.elem_mut() = Wrapping(n);
}
Stmt::JmpIfZero(pos) => { Stmt::JmpIfZero(pos) => {
if self.elem() == 0 { if self.elem() == 0 {
self.ip = pos as usize; self.ip = pos as usize;

View file

@ -1,7 +1,6 @@
#![feature(allocator_api, let_else)] #![feature(allocator_api, let_else)]
#![deny(unsafe_op_in_unsafe_fn)] #![deny(unsafe_op_in_unsafe_fn)]
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]
#![allow(dead_code)]
use crate::parse::ParseError; use crate::parse::ParseError;
use bumpalo::Bump; use bumpalo::Bump;

View file

@ -20,7 +20,12 @@ fn main() {
let stdin = io::stdin(); let stdin = io::stdin();
let stdin = stdin.lock(); let stdin = stdin.lock();
brainfuck::run(&file, stdout, stdin, UseProfile::Yes).unwrap_or_else(|_| { let profile = env::args()
.any(|a| a == "--profile")
.then(|| UseProfile::Yes)
.unwrap_or(UseProfile::No);
brainfuck::run(&file, stdout, stdin, profile).unwrap_or_else(|_| {
eprintln!("error: Failed to parse brainfuck code"); eprintln!("error: Failed to parse brainfuck code");
process::exit(1); process::exit(1);
}); });

View file

@ -14,11 +14,12 @@ pub struct Stmt<'ir> {
} }
impl<'ir> Stmt<'ir> { impl<'ir> Stmt<'ir> {
fn lol(kind: StmtKind<'ir>) -> Stmt<'ir> { fn new(kind: StmtKind<'ir>, span: Span) -> Stmt<'ir> {
Self { Self { kind, span }
kind, }
span: Span::default(),
} fn kind(&self) -> &StmtKind<'ir> {
&self.kind
} }
} }
@ -32,12 +33,14 @@ pub enum StmtKind<'ir> {
Out, Out,
In, In,
SetNull, SetNull,
SetN(u8),
} }
pub fn optimize<'ir>(alloc: &'ir Bump, instrs: &[(Instr<'_>, Span)]) -> Ir<'ir> { pub fn optimize<'ir>(alloc: &'ir Bump, instrs: &[(Instr<'_>, Span)]) -> Ir<'ir> {
let ir = ast_to_ir(alloc, instrs); let ir = ast_to_ir(alloc, instrs);
let mut ir = pass_group(alloc, ir); let mut ir = pass_group(alloc, ir);
pass_find_set_null(&mut ir); pass_find_set_null(&mut ir);
pass_set_n(&mut ir);
ir ir
} }
@ -57,7 +60,7 @@ fn ast_to_ir<'ir>(alloc: &'ir Bump, ast: &[(Instr<'_>, Span)]) -> Ir<'ir> {
StmtKind::Loop(ir_body) StmtKind::Loop(ir_body)
} }
}; };
Stmt { kind, span: *span } Stmt::new(kind, *span)
}); });
stmts.extend(stmts_iter); stmts.extend(stmts_iter);
@ -65,6 +68,7 @@ fn ast_to_ir<'ir>(alloc: &'ir Bump, ast: &[(Instr<'_>, Span)]) -> Ir<'ir> {
Ir { stmts } Ir { stmts }
} }
/// pass that replaces things like `Sub(1) Sub(1)` with `Sub(2)`
fn pass_group<'ir>(alloc: &'ir Bump, ir: Ir<'ir>) -> Ir<'ir> { fn pass_group<'ir>(alloc: &'ir Bump, ir: Ir<'ir>) -> Ir<'ir> {
let new_stmts = Vec::new_in(alloc); let new_stmts = Vec::new_in(alloc);
let stmts = ir let stmts = ir
@ -74,10 +78,10 @@ fn pass_group<'ir>(alloc: &'ir Bump, ir: Ir<'ir>) -> Ir<'ir> {
let Some(old) = stmts.last_mut() else { let Some(old) = stmts.last_mut() else {
if let StmtKind::Loop(body) = next.kind { if let StmtKind::Loop(body) = next.kind {
let new_body = pass_group(alloc, body); let new_body = pass_group(alloc, body);
stmts.push(Stmt { stmts.push(Stmt::new(
span: next.span, StmtKind::Loop(new_body),
kind: StmtKind::Loop(new_body), next.span,
}); ));
} else { } else {
stmts.push(next); stmts.push(next);
} }
@ -109,10 +113,7 @@ fn pass_group<'ir>(alloc: &'ir Bump, ir: Ir<'ir>) -> Ir<'ir> {
}); });
} }
(_, kind) => { (_, kind) => {
stmts.push(Stmt { stmts.push(Stmt::new(kind, next.span));
span: next.span,
kind,
});
} }
} }
@ -122,6 +123,7 @@ fn pass_group<'ir>(alloc: &'ir Bump, ir: Ir<'ir>) -> Ir<'ir> {
Ir { stmts } Ir { stmts }
} }
/// pass that replaces `Loop([Sub(_)])` to `SetNull`
fn pass_find_set_null(ir: &mut Ir<'_>) { fn pass_find_set_null(ir: &mut Ir<'_>) {
for stmt in &mut ir.stmts { for stmt in &mut ir.stmts {
if let Stmt { if let Stmt {
@ -131,13 +133,37 @@ fn pass_find_set_null(ir: &mut Ir<'_>) {
{ {
if let [Stmt { if let [Stmt {
kind: StmtKind::Sub(_), kind: StmtKind::Sub(_),
.. span,
}] = body.stmts.as_slice() }] = body.stmts.as_slice()
{ {
*stmt = Stmt::lol(StmtKind::SetNull); *stmt = Stmt::new(StmtKind::SetNull, *span);
} else { } else {
pass_find_set_null(body); pass_find_set_null(body);
} }
} }
} }
} }
/// pass that replaces `SetNull Add(5)` with `SetN(5)`
fn pass_set_n(ir: &mut Ir<'_>) {
let stmts = &mut ir.stmts;
let mut i = 0;
while i < stmts.len() - 1 {
let a = &stmts[i];
if let StmtKind::SetNull = a.kind() {
let b = &stmts[i + 1];
let new = match b.kind() {
StmtKind::Add(n) => StmtKind::SetN(*n),
StmtKind::Sub(n) => StmtKind::SetN(0u8.wrapping_sub(*n)),
_ => {
i += 1;
continue;
}
};
let span = a.span.merge(b.span);
stmts.remove(i + 1);
stmts[i] = Stmt::new(new, span);
}
i += 1;
}
}

View file

@ -1,6 +1,6 @@
--- ---
source: src/parse.rs source: src/parse.rs
assertion_line: 132 assertion_line: 164
expression: instrs expression: instrs
--- ---
Ok( Ok(
@ -46,14 +46,14 @@ Ok(
), ),
Span { Span {
start: 5, start: 5,
len: 2, len: 3,
}, },
), ),
], ],
), ),
Span { Span {
start: 3, start: 3,
len: 5, len: 6,
}, },
), ),
( (
@ -88,7 +88,7 @@ Ok(
), ),
Span { Span {
start: 1, start: 1,
len: 12, len: 13,
}, },
), ),
], ],

View file

@ -1,6 +1,6 @@
--- ---
source: src/parse.rs source: src/parse.rs
assertion_line: 123 assertion_line: 155
expression: instrs expression: instrs
--- ---
Ok( Ok(
@ -54,7 +54,7 @@ Ok(
), ),
Span { Span {
start: 5, start: 5,
len: 2, len: 3,
}, },
), ),
( (