Skip to content

feat: add exception-aware dead-code elimination - #736

Open
nahime0 wants to merge 7 commits into
mainfrom
feat/exception-aware-dce-2
Open

feat: add exception-aware dead-code elimination#736
nahime0 wants to merge 7 commits into
mainfrom
feat/exception-aware-dce-2

Conversation

@nahime0

@nahime0 nahime0 commented Aug 20, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds post-typecheck exception-flow analysis for AST dead-code elimination, using exact and constrained throwable domains instead of a single may-throw bit.
  • Routes catch handlers in PHP source order from explicit throws, statically proven operator failures, fixed-point direct-function and exact-receiver method summaries, and caught-variable rethrows.
  • Makes catch and finally guard invalidation path- and exception-type-aware while preserving conservative barriers for unresolved calls, open dispatch, external or trait-provided constructors, and complex control flow.
  • Integrates immediately before the declaration-reachability pass landed in feat: prune unused declarations before EIR lowering #714, allowing declarations referenced only by removed exceptional paths to be pruned before EIR lowering.

Behavior

  • Builds the throwable hierarchy from checker-provided class and interface metadata, with case-insensitive PHP symbol matching.
  • Tracks exact thrown classes and constrained unknown domains, including source-order subtraction across catch handlers and the Throwable = Exception | Error root partition.
  • Computes callable summaries to a fixed point for direct user functions and exact method targets.
  • Preserves caught-variable domains through nested try blocks and simple aliases or reassignments so throw $e retains useful type information.
  • Narrows catch-side invalidation to writes on paths that can actually enter the selected handler, including by-reference mutations performed by the throwing call.
  • Excludes unconditional exit and die paths from finally-entry invalidation because PHP does not execute finally after process termination.

Conservative boundaries

The optimizer retains an unknown throwable domain for dynamic or unresolved calls, late-bound/open instance dispatch, external constructors, trait-provided methods or constructors, and operand-dependent runtime failures that cannot be classified exactly. These paths continue to keep potentially matching handlers and their guard invalidations.

Pipeline integration

The post-typecheck optimizer constructs exception summaries from the complete checked program. Exception-aware DCE then removes impossible handlers and non-observable paths. The declaration-reachability pass from #714 runs afterward, reconciles CheckResult, and prunes functions, classes, methods, externs, and libraries that are no longer reachable before EIR lowering.

A dedicated integration regression verifies that a function referenced only by a disjoint catch is removed by declaration reachability after exception-aware DCE drops that handler.

Tests

  • cargo build
  • cargo test --test codegen_tests dead_code_elimination::tries - 51 passed
  • cargo test --lib optimize::tests::dce::tries - 17 passed
  • cargo test --test codegen_tests declaration_reachability - 42 passed
  • cargo test --lib optimize::reachability - 74 passed
  • Targeted rustfmt --check and git diff --check

CI remains responsible for the complete macOS AArch64, Linux AArch64, and Linux x86_64 matrix.

@github-actions github-actions Bot added area:optimizer Touches AST or EIR optimization passes. size:l Large pull request. type:feature Introduces new user-visible behavior or capabilities. labels Aug 20, 2026
@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds exception-type-aware dead-code elimination and integrates it before declaration reachability.

  • Builds throwable hierarchy and fixed-point callable summaries from checked-program metadata.
  • Routes exact and constrained throwable domains through source-ordered catch handlers.
  • Narrows catch and finally guard invalidation to relevant exceptional paths.
  • Updates lowering, documentation, and optimizer integration regressions.

Confidence Score: 4/5

The PR is not yet safe to merge because a condition-side caught-variable rebind can still cause DCE to remove a reachable nested catch.

Active caught-variable bindings are invalidated only after an enclosing statement and all its nested bodies have been optimized, so catch reachability inside a selected branch can still observe the pre-rebind exception class and delete the runtime-matching handler.

Files Needing Attention: src/optimize/control/dce.rs, src/optimize/exception_flow.rs, src/optimize/control/dce/tries.rs

Important Files Changed

Filename Overview
src/optimize/exception_flow.rs Adds throwable-domain inference and catch routing, but active caught-variable domains can remain stale while nested branch bodies are optimized.
src/optimize/control/dce.rs Wires caught-binding invalidation into DCE after each statement; its post-statement placement leaves nested-body processing exposed to stale domains.
src/optimize/control/dce/tries.rs Uses exception-flow reachability to remove impossible catches and applies handler-specific guard invalidation.
src/optimize/control/dce/writes/finally_paths.rs Adds path-sensitive finally invalidation and preserves explicitly throwing exit/die argument paths.
src/optimize.rs Constructs and scopes reusable exception-flow analysis alongside existing callable and by-reference analyses.
src/pipeline.rs Integrates exception-aware DCE before declaration reachability and EIR lowering.
src/ir_lower/stmt/exceptions.rs Routes catchless try/finally through runtime handler-based lowering so call-induced throws execute the finalizer.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Checked PHP AST] --> B[Exception-flow analysis]
  B --> C[Exception-aware AST DCE]
  C --> D[Declaration reachability]
  D --> E[EIR lowering]
  E --> F[Validated EIR]
Loading

Reviews (5): Last reviewed commit: "fix(optimizer): preserve implicit string..." | Re-trigger Greptile

Comment thread src/optimize/exception_flow.rs
Comment thread src/optimize/control/dce/writes/finally_paths.rs Outdated
@nahime0
nahime0 force-pushed the feat/exception-aware-dce-2 branch from ecf0286 to 17d21ce Compare August 20, 2026 19:50
Comment thread src/optimize/exception_flow.rs
@github-actions github-actions Bot added the area:eir Touches EIR definitions, lowering, validation, or passes. label Aug 20, 2026
@nahime0
nahime0 force-pushed the feat/exception-aware-dce-2 branch from 17d21ce to 2ce318c Compare August 21, 2026 08:11
Infer exact and constrained throwable domains from explicit throws, proven operator failures, and fixed-point callable summaries. Route catches in source order and invalidate catch/finally guards only along matching executable paths while preserving conservative dynamic-call barriers.
Exercise exact and constrained catch routing, callable and method throw summaries, nested rethrows, type-specific guard invalidation, conservative dispatch barriers, and exit-only finally paths.
Record the completed roadmap item and describe typed handler routing, caught-variable rethrows, call-aware guard invalidation, and finally-path precision.
Verify that exception-aware DCE removes a disjoint catch before declaration reachability scans its references, allowing a catch-only function declaration to be pruned before EIR lowering.
@nahime0
nahime0 force-pushed the feat/exception-aware-dce-2 branch from a56842d to 3a38f43 Compare August 21, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:eir Touches EIR definitions, lowering, validation, or passes. area:optimizer Touches AST or EIR optimization passes. size:l Large pull request. type:feature Introduces new user-visible behavior or capabilities.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant