Skip to content

refactor(minifier): make DCE remove more code to align with rollup#12427

Merged
graphite-app[bot] merged 1 commit into
mainfrom
07-21-refactor_minifier_improve_dce
Jul 21, 2025
Merged

refactor(minifier): make DCE remove more code to align with rollup#12427
graphite-app[bot] merged 1 commit into
mainfrom
07-21-refactor_minifier_improve_dce

Conversation

@Boshen

@Boshen Boshen commented Jul 21, 2025

Copy link
Copy Markdown
Member

No description provided.

@graphite-app

graphite-app Bot commented Jul 21, 2025

Copy link
Copy Markdown
Contributor

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

@github-actions github-actions Bot added the A-minifier Area - Minifier label Jul 21, 2025
@Boshen Boshen force-pushed the 07-21-refactor_minifier_improve_dce branch from aca9e0a to 687e708 Compare July 21, 2025 13:29
@Boshen Boshen changed the title 07 21 refactor minifier improve dce refactor(minifier): make DCE remove more code and align with rollup Jul 21, 2025
@github-actions github-actions Bot added the C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior label Jul 21, 2025
@Boshen Boshen changed the title refactor(minifier): make DCE remove more code and align with rollup refactor(minifier): make DCE remove more code to align with rollup Jul 21, 2025
@codspeed-hq

codspeed-hq Bot commented Jul 21, 2025

Copy link
Copy Markdown

CodSpeed Instrumentation Performance Report

Merging #12427 will not alter performance

Comparing 07-21-refactor_minifier_improve_dce (1cf08c0) with main (c375981)

Summary

✅ 34 untouched benchmarks

@Boshen Boshen added the 0-merge Merge with Graphite Merge Queue label Jul 21, 2025

Boshen commented Jul 21, 2025

Copy link
Copy Markdown
Member Author

Merge activity

@graphite-app graphite-app Bot force-pushed the 07-21-refactor_minifier_improve_dce branch from 687e708 to 1cf08c0 Compare July 21, 2025 13:42
@graphite-app graphite-app Bot merged commit 1cf08c0 into main Jul 21, 2025
24 checks passed
@graphite-app graphite-app Bot removed the 0-merge Merge with Graphite Merge Queue label Jul 21, 2025
@graphite-app graphite-app Bot deleted the 07-21-refactor_minifier_improve_dce branch July 21, 2025 13:50
Dunqing added a commit that referenced this pull request May 26, 2026
…places an identifier

Before the minifier's incremental-scoping refactor (#22736), the per-pass
`LiveUsageCollector` walked the live program at `exit_program` and rebuilt
`Scoping::resolved_references` from scratch. That walk silently masked the
fact that `ReplaceGlobalDefines` never told `Scoping` about the identifier
references it was replacing — the next minifier pass would simply recompute
them and find that the replaced identifier had no surviving occurrences.

With the LiveUsageCollector gone, only references that the minifier itself
drops via `replace_*`/`drop_*` helpers are pruned. References that callers
drop before `dead_code_elimination_with_scoping` get to run are now visible
as stale entries in `resolved_references`, and `symbol_is_unused` returns
`false` for symbols whose every textual occurrence has been replaced.

Concretely, the existing `replace_global_defines::declare_const` integration
test (added by #12427 to align with rollup) fails: the test expects the
`declare const IS_PROD: boolean;` line to be DCE'd after every reference to
`IS_PROD` is replaced with `true`, but the leaked references keep DCE from
seeing IS_PROD as unused.

The fix delegates reference deletion to the plugin: when
`replace_identifier_define_impl` returns a replacement value, the caller
captures the old identifier's `(reference_id, symbol_id, name)` BEFORE the
replacement and calls `Scoping::delete_reference` (resolved case) or
`delete_root_unresolved_reference` (truly global case) only AFTER the AST
mutation actually commits. The split matters at the assignment-target site —
`replace_define_with_assignment_expr` may bail when the replacement value
isn't a valid LHS (e.g. `IS_PROD = 0` with define `IS_PROD -> true` would
need `true = 0`, which `assignment_target_from_expr` rejects); the
reference must stay in that case.

New test `declare_const_assignment_target_bailout` pins the bail path.
Dunqing added a commit that referenced this pull request Jun 9, 2026
…places an identifier

Before the minifier's incremental-scoping refactor (#22736), the per-pass
`LiveUsageCollector` walked the live program at `exit_program` and rebuilt
`Scoping::resolved_references` from scratch. That walk silently masked the
fact that `ReplaceGlobalDefines` never told `Scoping` about the identifier
references it was replacing — the next minifier pass would simply recompute
them and find that the replaced identifier had no surviving occurrences.

With the LiveUsageCollector gone, only references that the minifier itself
drops via `replace_*`/`drop_*` helpers are pruned. References that callers
drop before `dead_code_elimination_with_scoping` get to run are now visible
as stale entries in `resolved_references`, and `symbol_is_unused` returns
`false` for symbols whose every textual occurrence has been replaced.

Concretely, the existing `replace_global_defines::declare_const` integration
test (added by #12427 to align with rollup) fails: the test expects the
`declare const IS_PROD: boolean;` line to be DCE'd after every reference to
`IS_PROD` is replaced with `true`, but the leaked references keep DCE from
seeing IS_PROD as unused.

The fix delegates reference deletion to the plugin: when
`replace_identifier_define_impl` returns a replacement value, the caller
captures the old identifier's `(reference_id, symbol_id, name)` BEFORE the
replacement and calls `Scoping::delete_reference` (resolved case) or
`delete_root_unresolved_reference` (truly global case) only AFTER the AST
mutation actually commits. The split matters at the assignment-target site —
`replace_define_with_assignment_expr` may bail when the replacement value
isn't a valid LHS (e.g. `IS_PROD = 0` with define `IS_PROD -> true` would
need `true = 0`, which `assignment_target_from_expr` rejects); the
reference must stay in that case.

New test `declare_const_assignment_target_bailout` pins the bail path.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-minifier Area - Minifier C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant