mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-01-15 00:18:06 -05:00
remove_noops
This commit is contained in:
@@ -326,7 +326,13 @@ impl Instruction {
|
||||
UnpackIterRes(iter_res, value_dst, done_dst) => {
|
||||
visit(RegisterVisitMut::write(done_dst));
|
||||
visit(RegisterVisitMut::write(value_dst));
|
||||
visit(RegisterVisitMut::read_and_write(iter_res));
|
||||
|
||||
// This does a write in the sense that the register is consumed. However, the new value
|
||||
// being written is not supposed to matter, `unpack_iter_res` should only be used once and
|
||||
// the emptiness of the register isn't supposed to be then consumed the way a regular write
|
||||
// would. In other words, well-constructed programs should be equivalent whether the VM
|
||||
// decides to consume this memory or not.
|
||||
visit(RegisterVisitMut::read(iter_res));
|
||||
}
|
||||
|
||||
UnsetCatch | RequireMutableThis => {}
|
||||
|
||||
@@ -2,6 +2,7 @@ mod collapse_pointers_of_pointers;
|
||||
mod extract_constants;
|
||||
mod optimize;
|
||||
mod remove_meta_lines;
|
||||
mod remove_noops;
|
||||
mod shake_tree;
|
||||
mod simplify;
|
||||
pub mod try_to_val;
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::name_allocator::NameAllocator;
|
||||
use super::collapse_pointers_of_pointers::collapse_pointers_of_pointers;
|
||||
use super::extract_constants::extract_constants;
|
||||
use super::remove_meta_lines::remove_meta_lines;
|
||||
use super::remove_noops::remove_noops;
|
||||
use super::shake_tree::shake_tree;
|
||||
use super::simplify::simplify;
|
||||
|
||||
@@ -12,5 +13,6 @@ pub fn optimize(module: &mut Module, pointer_allocator: &mut NameAllocator) {
|
||||
extract_constants(module, pointer_allocator);
|
||||
shake_tree(module);
|
||||
simplify(module);
|
||||
remove_noops(module);
|
||||
remove_meta_lines(module);
|
||||
}
|
||||
|
||||
74
valuescript_compiler/src/optimization/remove_noops.rs
Normal file
74
valuescript_compiler/src/optimization/remove_noops.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
use std::mem::take;
|
||||
|
||||
use crate::{
|
||||
asm::{DefinitionContent, FnLine, Module, Value},
|
||||
instruction::Instruction,
|
||||
};
|
||||
|
||||
pub fn remove_noops(module: &mut Module) {
|
||||
for defn in &mut module.definitions {
|
||||
if let DefinitionContent::Function(fn_) = &mut defn.content {
|
||||
for line in take(&mut fn_.body) {
|
||||
if let FnLine::Instruction(instr) = &line {
|
||||
if is_noop(instr) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
fn_.body.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_noop(instr: &Instruction) -> bool {
|
||||
use Instruction::*;
|
||||
|
||||
match instr {
|
||||
End | OpInc(..) | OpDec(..) | Call(..) | Apply(..) | SubCall(..) | Jmp(..) | New(..)
|
||||
| Throw(..) | SetCatch(..) | UnsetCatch | ConstSubCall(..) | RequireMutableThis
|
||||
| ThisSubCall(..) | Next(..) | Yield(..) | YieldStar(..) => false,
|
||||
|
||||
Mov(_, dst)
|
||||
| OpPlus(_, _, dst)
|
||||
| OpMinus(_, _, dst)
|
||||
| OpMul(_, _, dst)
|
||||
| OpDiv(_, _, dst)
|
||||
| OpMod(_, _, dst)
|
||||
| OpExp(_, _, dst)
|
||||
| OpEq(_, _, dst)
|
||||
| OpNe(_, _, dst)
|
||||
| OpTripleEq(_, _, dst)
|
||||
| OpTripleNe(_, _, dst)
|
||||
| OpAnd(_, _, dst)
|
||||
| OpOr(_, _, dst)
|
||||
| OpNot(_, dst)
|
||||
| OpLess(_, _, dst)
|
||||
| OpLessEq(_, _, dst)
|
||||
| OpGreater(_, _, dst)
|
||||
| OpGreaterEq(_, _, dst)
|
||||
| OpNullishCoalesce(_, _, dst)
|
||||
| OpOptionalChain(_, _, dst)
|
||||
| OpBitAnd(_, _, dst)
|
||||
| OpBitOr(_, _, dst)
|
||||
| OpBitNot(_, dst)
|
||||
| OpBitXor(_, _, dst)
|
||||
| OpLeftShift(_, _, dst)
|
||||
| OpRightShift(_, _, dst)
|
||||
| OpRightShiftUnsigned(_, _, dst)
|
||||
| TypeOf(_, dst)
|
||||
| InstanceOf(_, _, dst)
|
||||
| In(_, _, dst)
|
||||
| Bind(_, _, dst)
|
||||
| Sub(_, _, dst)
|
||||
| SubMov(_, _, dst)
|
||||
| UnaryPlus(_, dst)
|
||||
| UnaryMinus(_, dst)
|
||||
| Import(_, dst)
|
||||
| ImportStar(_, dst)
|
||||
| Cat(_, dst) => dst.is_ignore(),
|
||||
|
||||
JmpIf(cond, _) => *cond == Value::Bool(false),
|
||||
UnpackIterRes(_, value_dst, done_dst) => value_dst.is_ignore() && done_dst.is_ignore(),
|
||||
}
|
||||
}
|
||||
@@ -347,26 +347,26 @@ impl FnState {
|
||||
|
||||
if !taken {
|
||||
instr.visit_registers_mut_rev(&mut |rvm| {
|
||||
if !taken && !rvm.write && rvm.register.name == released_reg.name {
|
||||
if rvm.register.name != released_reg.name {
|
||||
return;
|
||||
}
|
||||
|
||||
if !taken && !rvm.write {
|
||||
*rvm.register = rvm.register.take();
|
||||
taken = true;
|
||||
}
|
||||
|
||||
if rvm.write && rvm.register.name == released_reg.name {
|
||||
if !write_found && rvm.write {
|
||||
write_found = true;
|
||||
|
||||
if !rvm.read && !taken {
|
||||
*rvm.register = Register::ignore();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if write_found {
|
||||
if !taken {
|
||||
// TODO: Support removal of more instructions.
|
||||
if let Instruction::Mov(..) = instr {
|
||||
let line = &mut body[j];
|
||||
*line = FnLine::Comment(line.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user