Minor improvements to the optimizer.
This commit is contained in:
parent
91317c0d3e
commit
9bd66c7db3
@ -3,6 +3,26 @@ use crate::parser::{Expr, Stmt};
|
|||||||
|
|
||||||
fn optimize_stmt(stmt: Stmt, changed: &mut bool, preserve_result: bool) -> Stmt {
|
fn optimize_stmt(stmt: Stmt, changed: &mut bool, preserve_result: bool) -> Stmt {
|
||||||
match stmt {
|
match stmt {
|
||||||
|
Stmt::IfElse(expr, stmt1, None) if stmt1.is_noop() => {
|
||||||
|
*changed = true;
|
||||||
|
|
||||||
|
let pos = expr.position();
|
||||||
|
let expr = optimize_expr(*expr, changed);
|
||||||
|
|
||||||
|
match expr {
|
||||||
|
Expr::False(_) | Expr::True(_) => Stmt::Noop(stmt1.position()),
|
||||||
|
expr => {
|
||||||
|
let stmt = Stmt::Expr(Box::new(expr));
|
||||||
|
|
||||||
|
if preserve_result {
|
||||||
|
Stmt::Block(vec![stmt, *stmt1], pos)
|
||||||
|
} else {
|
||||||
|
stmt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Stmt::IfElse(expr, stmt1, None) => match *expr {
|
Stmt::IfElse(expr, stmt1, None) => match *expr {
|
||||||
Expr::False(pos) => {
|
Expr::False(pos) => {
|
||||||
*changed = true;
|
*changed = true;
|
||||||
@ -22,7 +42,10 @@ fn optimize_stmt(stmt: Stmt, changed: &mut bool, preserve_result: bool) -> Stmt
|
|||||||
expr => Stmt::IfElse(
|
expr => Stmt::IfElse(
|
||||||
Box::new(optimize_expr(expr, changed)),
|
Box::new(optimize_expr(expr, changed)),
|
||||||
Box::new(optimize_stmt(*stmt1, changed, true)),
|
Box::new(optimize_stmt(*stmt1, changed, true)),
|
||||||
Some(Box::new(optimize_stmt(*stmt2, changed, true))),
|
match optimize_stmt(*stmt2, changed, true) {
|
||||||
|
stmt if stmt.is_noop() => None,
|
||||||
|
stmt => Some(Box::new(stmt)),
|
||||||
|
},
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -274,10 +297,14 @@ pub(crate) fn optimize(statements: Vec<Stmt>) -> Vec<Stmt> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Eliminate No-op's but always keep the last statement
|
// Eliminate code that is pure but always keep the last statement
|
||||||
let last_stmt = result.pop();
|
let last_stmt = result.pop();
|
||||||
|
|
||||||
result.retain(Stmt::is_op); // Remove all No-op's
|
// Remove all pure statements at top level
|
||||||
|
result.retain(|stmt| match stmt {
|
||||||
|
Stmt::Expr(expr) if expr.is_pure() => false,
|
||||||
|
_ => true,
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(stmt) = last_stmt {
|
if let Some(stmt) = last_stmt {
|
||||||
result.push(stmt); // Add back the last statement
|
result.push(stmt); // Add back the last statement
|
||||||
|
@ -186,6 +186,13 @@ pub enum Stmt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Stmt {
|
impl Stmt {
|
||||||
|
pub fn is_noop(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Stmt::Noop(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_op(&self) -> bool {
|
pub fn is_op(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Stmt::Noop(_) => false,
|
Stmt::Noop(_) => false,
|
||||||
@ -265,6 +272,7 @@ impl Expr {
|
|||||||
pub fn is_pure(&self) -> bool {
|
pub fn is_pure(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Expr::Array(expressions, _) => expressions.iter().all(Expr::is_pure),
|
Expr::Array(expressions, _) => expressions.iter().all(Expr::is_pure),
|
||||||
|
Expr::And(x, y) | Expr::Or(x, y) | Expr::Index(x, y, _) => x.is_pure() && y.is_pure(),
|
||||||
expr => expr.is_constant() || expr.is_identifier(),
|
expr => expr.is_constant() || expr.is_identifier(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user