Skip to content

feat(optimize): Guard reasoning v2 for dead-code elimination - #658

Merged
nahime0 merged 5 commits into
mainfrom
cursor/guard-reasoning-v2-dbd8
Aug 3, 2026
Merged

feat(optimize): Guard reasoning v2 for dead-code elimination#658
nahime0 merged 5 commits into
mainfrom
cursor/guard-reasoning-v2-dbd8

Conversation

@nahime0

@nahime0 nahime0 commented Jul 31, 2026

Copy link
Copy Markdown
Member

Summary

Implements the v0.26 ROADMAP item Guard reasoning v2 for dead-code elimination.

AST DCE (src/optimize/control/dce/) now tracks:

  1. Proven-integer range facts (RangeGuard / IntInterval) from $x <op> int branches when $x is known to be an integer through an int parameter, an exact-int guard, or an existing range. Bounds intersect across nested and elseif paths and prune transitive conditions, strict-int contradictions, and impossible switch cases.
  2. Cross-variable relational / strict-equality atoms (RelationalGuard) with operand-swapped forms, safe complements, and exact/range substitution ($x === 3 + $y > $x$y > 3). Substitution derives structural atoms for mixed values and creates discrete ranges only for proven integers.

Soundness

  • Float, string, and mixed values never acquire discrete integer intervals.
  • Taken-false relational atoms are inverted only when both sides have proven integer domains, preserving NaN behavior.
  • Point integer intervals decide === / !== without confusing 0.0 and 0.
  • Direct writes, global rebinding, loop/backedge writes, and foreach key/value overwrites invalidate affected facts.
  • Overflowing bound shifts (> at i64::MAX, < at i64::MIN) refuse to record.
  • The pass stays on the existing path-local extend_guards / known_condition_value / invalidation protocol; there is no EIR port.

Design / plan

Full design, non-goals, completed task checklist, and test strategy: .plans/guard-reasoning-v2.md

Verification

cargo build
cargo test --lib optimize::tests::dce::guards
cargo test --test codegen_tests dead_code_elimination::guards
ELEPHC_PHP_CHECK=1 cargo test --test codegen_tests dead_code_elimination::guards::range_guards
ELEPHC_PHP_CHECK=1 cargo test --test codegen_tests dead_code_elimination::guards::relational_guards
git diff --check

Local result: 38 focused unit tests and 37 focused end-to-end tests pass; the range and relational e2e fixtures also pass PHP cross-checking.

Docs

  • docs/internals/the-optimizer.md and docs/internals/how-elephc-works.md updated
  • ROADMAP item marked [x]
  • CHANGELOG [Unreleased] bullet added

@github-actions github-actions Bot added area:optimizer Touches AST or EIR optimization passes. size:m Medium-sized pull request. type:feature Introduces new user-visible behavior or capabilities. size:l Large pull request. and removed size:m Medium-sized pull request. labels Jul 31, 2026
@nahime0
nahime0 marked this pull request as ready for review July 31, 2026 12:51
@nahime0
nahime0 requested a review from Guikingone July 31, 2026 12:52
@greptile-apps

greptile-apps Bot commented Jul 31, 2026

Copy link
Copy Markdown

Greptile Summary

This PR implements Guard Reasoning v2 for dead-code elimination, adding two new fact domains to the AST DCE pass: integer interval range facts (RangeGuard / IntInterval) for $x <op> int branches, and cross-variable relational atoms (RelationalGuard) for var-vs-var comparisons. Both systems integrate into the existing extend_guards / known_condition_value / invalidation protocol and are gated behind proven-integer domain checks to preserve PHP's float, NaN, and mixed-comparison semantics.

  • Adds src/optimize/control/dce/guards/range.rs and relational.rs: integer interval arithmetic (intersecting bounds, overflow-safe bound shifts, point intervals for exact literals) and a relational atom store with operand-swapped forms, safe complements, and exact/range substitution.
  • Updates loop handling in dce.rs to pre-invalidate guards for variables written inside while, do-while, for, and foreach bodies; seeds function and method DCE with integer-domain facts from typed int parameters via GuardState::for_params.
  • Extends writes.rs to invalidate the three new guard fields (integer_domain_vars, range_guards, relational_guards) on any write, plus adds StmtKind::Global invalidation (necessary now that param-typed facts can cross function boundaries via global rebinding).

Confidence Score: 5/5

This PR is safe to merge. The guard reasoning additions are path-local, conservative, and correctly gated behind integer-domain proofs, so they cannot eliminate code that is reachable at runtime.

The interval arithmetic, complement recording, NaN-safety guards, overflow refusal, and write invalidation all behave correctly. Loop pre-invalidation for While/DoWhile/For/Foreach is sound. The Global rebinding invalidation is added exactly where it becomes necessary. The 75-test suite (38 unit + 37 e2e, with PHP cross-checking on both sub-suites) gives strong functional coverage of the new paths.

Files Needing Attention: No files require special attention. The core logic files (range.rs, relational.rs, state.rs) are straightforward and well-tested.

Important Files Changed

Filename Overview
src/optimize/control/dce/guards/range.rs New file implementing integer interval facts. Overflow-safe bound shifts via checked_add/checked_sub, correct interval intersection, sound point-interval handling for strict-eq. Logic in interval_entails_relational covers all four operators on bounded, lower-bounded, and upper-bounded intervals correctly.
src/optimize/control/dce/guards/relational.rs New file implementing cross-variable relational atoms. NaN-safety preserved: inverse complements for relational ops on false branches only recorded when both sides are proven integers; true-branch inverses are always sound.
src/optimize/control/dce/state.rs Adds IntInterval, RangeGuard, RelSide, RelOp, RelationalGuard types plus GuardState::for_params() seeding integer domain facts from typed int parameters. IntInterval::intersect correctly returns None for empty intersections.
src/optimize/control/dce.rs Loop handling upgraded to pre-invalidate guards written inside body/init/update/condition. FunctionDecl now seeds GuardState::for_params().
src/optimize/control/dce/writes.rs Correctly extends invalidation to clear integer_domain_vars, range_guards, and relational_guards on write. Adds StmtKind::Global handling and invalidated_guards_for_expr helper.
src/optimize/control/dce/switches.rs Adds range-based switch case pruning: integer patterns outside the known range for the subject variable are skipped soundly.
src/optimize/control/dce/guards/record.rs Updated clear_guards_for_name and extend_guards to integrate new guard types. record_exact_literal_guard links exact int guards to point range intervals.
src/optimize/control/dce/methods.rs Both dce_method variants now seed GuardState::for_params() from typed method parameters.
src/optimize/tests/dce/guards/range_guards.rs 38 unit tests covering transitive bounds, intersection, switch pruning, overflow refusal, elseif refinement, write invalidation, and domain safety.
src/optimize/tests/dce/guards/relational_guards.rs Unit tests for cross-variable relational atoms: lookup, substitution, range derivation, NaN-safe false-branch handling, and loop invalidation.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[extend_guards called\nfor branch condition] --> B[record_condition_guard]
    B --> C[extend_range_guards]
    C --> D{has_integer_domain\nfor variable?}
    D -- No --> E[skip: mixed/float not given\ndiscrete interval]
    D -- Yes --> F[interval_from_relational\nbuild IntInterval contrib]
    F --> G{overflow check\nchecked_add/sub}
    G -- overflows --> H[refuse to record]
    G -- OK --> I[record_range_guard\nintersect or install]
    I --> J[extend_relational_guards]
    J --> K[record_relational_guard\natom + swapped + conditionally inverse]
    K --> L{false branch AND\nnot relational_inverse_safe?}
    L -- true --> M[record only false-polarity atom\nno complement]
    L -- false --> N[strengthen_from_relational\nsubstitute concrete ints]
    N --> O{one side has\nexact int value?}
    O -- Yes --> P[strengthen_variable_from_exact\nderive var/int atom + range]
    O -- No --> Q[no derivation]

    R[known_condition_value_base] --> S[existing checks 1-5]
    S --> T[known_from_range\nrange guard lookup]
    T --> U[known_from_relational\nrelational atom lookup + substitution]
    U --> V[Some/None result]
Loading

Reviews (3): Last reviewed commit: "refactor(optimize): share interval entai..." | Re-trigger Greptile

Comment thread src/optimize/control/dce/guards/relational.rs Outdated
cursoragent and others added 5 commits August 3, 2026 16:45
…atoms

Extend AST DCE GuardState with integer interval facts from relational
int-literal branches and cross-variable relational/strict-equality atoms,
including exact/range substitution, switch case pruning, and tests.

Co-authored-by: Vincenzo Petrucci <nahime0@users.noreply.github.com>
Co-authored-by: Vincenzo Petrucci <nahime0@users.noreply.github.com>
Co-authored-by: Vincenzo Petrucci <nahime0@users.noreply.github.com>
@nahime0
nahime0 force-pushed the cursor/guard-reasoning-v2-dbd8 branch from a64ee61 to 9991d8e Compare August 3, 2026 14:47
@nahime0 nahime0 moved this from Backlog to In review in Elephc Release Track Aug 3, 2026
@nahime0 nahime0 self-assigned this Aug 3, 2026
@nahime0
nahime0 merged commit d389b3a into main Aug 3, 2026
117 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in Elephc Release Track Aug 3, 2026
@nahime0
nahime0 deleted the cursor/guard-reasoning-v2-dbd8 branch August 3, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants