Skip to content

Commit

Permalink
perf(es/minifier): Make the first run of DCE more efficient (#9868)
Browse files Browse the repository at this point in the history
**Description:**

We can drop constant branches from precompress pass to make the pass after it faster.
  • Loading branch information
kdy1 authored Jan 12, 2025
1 parent caed78a commit 7329824
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 12 deletions.
6 changes: 6 additions & 0 deletions .changeset/stale-apricots-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
swc_core: minor
swc_ecma_minifier: minor
---

perf(es/minifier): Make the first run of DCE more efficient
7 changes: 6 additions & 1 deletion crates/swc_ecma_minifier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use swc_common::{comments::Comments, pass::Repeated, sync::Lrc, SourceMap, Synta
use swc_ecma_ast::*;
use swc_ecma_transforms_optimization::debug_assert_valid;
use swc_ecma_usage_analyzer::marks::Marks;
use swc_ecma_utils::ExprCtx;
use swc_ecma_visit::VisitMutWith;
use swc_timer::timer;

Expand Down Expand Up @@ -126,7 +127,11 @@ pub fn optimize(
if let Some(_options) = &options.compress {
let _timer = timer!("precompress");

n.visit_mut_with(&mut precompress_optimizer());
n.visit_mut_with(&mut precompress_optimizer(ExprCtx {
unresolved_ctxt: SyntaxContext::empty().apply_mark(marks.unresolved_mark),
is_unresolved_ref_safe: false,
in_strict: false,
}));
debug_assert_valid(&n);
}

Expand Down
52 changes: 41 additions & 11 deletions crates/swc_ecma_minifier/src/pass/precompress.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,50 @@
use std::vec::Vec;

use swc_common::util::take::Take;
use swc_ecma_ast::*;
use swc_ecma_transforms_base::perf::{Parallel, ParallelExt};
use swc_ecma_utils::{ExprCtx, ExprExt, Value::Known};
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};

use crate::HEAVY_TASK_PARALLELS;
use crate::CPU_COUNT;

/// Optimizer invoked before invoking compressor.
///
/// - Remove parens.
///
/// TODO: remove completely after #8333
pub(crate) fn precompress_optimizer<'a>() -> impl 'a + VisitMut {
PrecompressOptimizer {}
pub(crate) fn precompress_optimizer<'a>(expr_ctx: ExprCtx) -> impl 'a + VisitMut {
PrecompressOptimizer { expr_ctx }
}

#[derive(Debug)]
pub(crate) struct PrecompressOptimizer {}
pub(crate) struct PrecompressOptimizer {
expr_ctx: ExprCtx,
}

impl PrecompressOptimizer {
/// Drops RHS from `null && foo`
fn optimize_bin_expr(&mut self, n: &mut Expr) {
let Expr::Bin(b) = n else {
return;
};

if b.op == op!("&&") && b.left.as_pure_bool(&self.expr_ctx) == Known(false) {
*n = *b.left.take();
return;
}

if b.op == op!("||") && b.left.as_pure_bool(&self.expr_ctx) == Known(true) {
*n = *b.left.take();
}
}
}

impl Parallel for PrecompressOptimizer {
fn create(&self) -> Self {
Self {}
Self {
expr_ctx: self.expr_ctx.clone(),
}
}

fn merge(&mut self, _: Self) {}
Expand All @@ -29,38 +53,44 @@ impl Parallel for PrecompressOptimizer {
impl VisitMut for PrecompressOptimizer {
noop_visit_mut_type!();

fn visit_mut_expr(&mut self, n: &mut Expr) {
n.visit_mut_children_with(self);

self.optimize_bin_expr(n);
}

fn visit_mut_stmts(&mut self, n: &mut Vec<Stmt>) {
self.maybe_par(*HEAVY_TASK_PARALLELS, n, |v, n| {
self.maybe_par(*CPU_COUNT, n, |v, n| {
n.visit_mut_with(v);
});
}

fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {
self.maybe_par(*HEAVY_TASK_PARALLELS, n, |v, n| {
self.maybe_par(*CPU_COUNT, n, |v, n| {
n.visit_mut_with(v);
});
}

fn visit_mut_exprs(&mut self, n: &mut Vec<Box<Expr>>) {
self.maybe_par(*HEAVY_TASK_PARALLELS, n, |v, n| {
self.maybe_par(*CPU_COUNT, n, |v, n| {
n.visit_mut_with(v);
});
}

fn visit_mut_opt_vec_expr_or_spreads(&mut self, n: &mut Vec<Option<ExprOrSpread>>) {
self.maybe_par(*HEAVY_TASK_PARALLELS, n, |v, n| {
self.maybe_par(*CPU_COUNT, n, |v, n| {
n.visit_mut_with(v);
});
}

fn visit_mut_expr_or_spreads(&mut self, n: &mut Vec<ExprOrSpread>) {
self.maybe_par(*HEAVY_TASK_PARALLELS, n, |v, n| {
self.maybe_par(*CPU_COUNT, n, |v, n| {
n.visit_mut_with(v);
});
}

fn visit_mut_var_declarators(&mut self, n: &mut Vec<VarDeclarator>) {
self.maybe_par(*HEAVY_TASK_PARALLELS, n, |v, n| {
self.maybe_par(*CPU_COUNT, n, |v, n| {
n.visit_mut_with(v);
});
}
Expand Down

0 comments on commit 7329824

Please sign in to comment.