refactor(minifier): move dce conditional expression to RemoveDeadCode (#5971)

This is aligned to closure compiler
This commit is contained in:
Boshen 2024-09-23 10:22:00 +00:00
parent 860f108a75
commit 0a2f68756f
5 changed files with 60 additions and 65 deletions

View file

@ -113,7 +113,13 @@ impl<'a> PeepholeFoldConstants {
match expr.operator {
UnaryOperator::Void => Self::try_reduce_void(expr, ctx),
UnaryOperator::Typeof => self.try_fold_type_of(expr, ctx),
#[allow(clippy::float_cmp)]
UnaryOperator::LogicalNot => {
if let Expression::NumericLiteral(n) = &expr.argument {
if n.value == 0.0 || n.value == 1.0 {
return None;
}
}
expr.argument.to_boolean().map(|b| ctx.ast.expression_boolean_literal(SPAN, !b))
}
// `-NaN` -> `NaN`

View file

@ -1,7 +1,7 @@
use oxc_ast::ast::*;
use oxc_traverse::{Ancestor, Traverse, TraverseCtx};
use oxc_traverse::{Traverse, TraverseCtx};
use crate::{node_util::NodeUtil, tri::Tri, CompressorPass};
use crate::CompressorPass;
/// Minimize Conditions
///
@ -16,44 +16,18 @@ impl<'a> CompressorPass<'a> for PeepholeMinimizeConditions {}
impl<'a> Traverse<'a> for PeepholeMinimizeConditions {
fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
self.fold_expression(expr, ctx);
}
}
impl<'a> PeepholeMinimizeConditions {
pub fn new() -> Self {
Self
}
fn fold_expression(&self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
if let Some(folded_expr) = match expr {
Expression::ConditionalExpression(e) => self.try_fold_conditional_expression(e, ctx),
Expression::UnaryExpression(e) if e.operator.is_not() => self.try_minimize_not(e, ctx),
_ => None,
} {
*expr = folded_expr;
};
}
}
fn try_fold_conditional_expression(
&self,
expr: &mut ConditionalExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Option<Expression<'a>> {
match ctx.get_boolean_value(&expr.test) {
Tri::True => {
// Bail `let o = { f() { assert.ok(this !== o); } }; (true ? o.f : false)(); (true ? o.f : false)``;`
let parent = ctx.ancestry.parent();
if parent.is_tagged_template_expression()
|| matches!(parent, Ancestor::CallExpressionCallee(_))
{
return None;
}
Some(ctx.ast.move_expression(&mut expr.consequent))
}
Tri::False => Some(ctx.ast.move_expression(&mut expr.alternate)),
Tri::Unknown => None,
}
impl<'a> PeepholeMinimizeConditions {
pub fn new() -> Self {
Self
}
/// Try to minimize NOT nodes such as `!(x==y)`.

View file

@ -1,7 +1,7 @@
use oxc_allocator::Vec;
use oxc_ast::{ast::*, Visit};
use oxc_span::SPAN;
use oxc_traverse::{Traverse, TraverseCtx};
use oxc_traverse::{Ancestor, Traverse, TraverseCtx};
use crate::{keep_var::KeepVar, node_util::NodeUtil, tri::Tri, CompressorPass};
@ -23,6 +23,15 @@ impl<'a> Traverse<'a> for PeepholeRemoveDeadCode {
stmts.retain(|stmt| !matches!(stmt, Statement::EmptyStatement(_)));
self.dead_code_elimination(stmts, ctx);
}
fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
if let Some(folded_expr) = match expr {
Expression::ConditionalExpression(e) => self.try_fold_conditional_expression(e, ctx),
_ => None,
} {
*expr = folded_expr;
}
}
}
impl<'a> PeepholeRemoveDeadCode {
@ -114,22 +123,26 @@ impl<'a> PeepholeRemoveDeadCode {
Tri::Unknown => {}
}
}
/// Try folding conditional expression (?:) if the condition results of the condition is known.
fn try_fold_conditional_expression(
&self,
expr: &mut ConditionalExpression<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Option<Expression<'a>> {
match ctx.get_boolean_value(&expr.test) {
Tri::True => {
// Bail `let o = { f() { assert.ok(this !== o); } }; (true ? o.f : false)(); (true ? o.f : false)``;`
let parent = ctx.ancestry.parent();
if parent.is_tagged_template_expression()
|| matches!(parent, Ancestor::CallExpressionCallee(_))
{
return None;
}
Some(ctx.ast.move_expression(&mut expr.consequent))
}
Tri::False => Some(ctx.ast.move_expression(&mut expr.alternate)),
Tri::Unknown => None,
}
}
}
// /// <https://github.com/google/closure-compiler/blob/master/test/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java>
// #[cfg(test)]
// mod test {
// use oxc_allocator::Allocator;
// use crate::{tester, CompressOptions};
// fn test(source_text: &str, expected: &str) {
// let allocator = Allocator::default();
// let mut pass = super::PeepholeRemoveDeadCode::new();
// tester::test(&allocator, source_text, expected, &mut pass);
// }
// fn test_same(source_text: &str) {
// test(source_text, source_text);
// }
// }

View file

@ -42,13 +42,24 @@ impl<'a> Compressor<'a> {
return;
}
self.fold_constants(program, &mut ctx);
// earlyPeepholeOptimizations
// TODO: MinimizeExitPoints
self.minimize_conditions(program, &mut ctx);
self.remove_dead_code(program, &mut ctx);
// self.statement_fusion(program, &mut ctx);
self.substitute_alternate_syntax(program, &mut ctx);
self.collapse_variable_declarations(program, &mut ctx);
// TODO: PeepholeReplaceKnownMethods
self.remove_dead_code(program, &mut ctx);
self.fold_constants(program, &mut ctx);
// latePeepholeOptimizations
// TODO: StatementFusion
self.remove_dead_code(program, &mut ctx);
self.minimize_conditions(program, &mut ctx);
self.substitute_alternate_syntax(program, &mut ctx);
// TODO: PeepholeReplaceKnownMethods
self.fold_constants(program, &mut ctx);
self.exploit_assigns(program, &mut ctx);
self.collapse_variable_declarations(program, &mut ctx);
}
fn dead_code_elimination(self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {

View file

@ -2,13 +2,4 @@ commit: d62fa93c
minifier_test262 Summary:
AST Parsed : 43765/43765 (100.00%)
Positive Passed: 43756/43765 (99.98%)
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A3_T2.js
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A3_T3.js
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A3_T4.js
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A4_T2.js
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A4_T3.js
Compress: tasks/coverage/test262/test/language/expressions/conditional/S11.12_A4_T4.js
Compress: tasks/coverage/test262/test/language/statements/if/S12.5_A12_T1.js
Compress: tasks/coverage/test262/test/language/statements/if/S12.5_A12_T3.js
Compress: tasks/coverage/test262/test/language/statements/if/S12.5_A12_T4.js
Positive Passed: 43765/43765 (100.00%)