feat(optimize): Guard reasoning v2 for dead-code elimination - #658
Conversation
Greptile SummaryThis PR implements Guard Reasoning v2 for dead-code elimination, adding two new fact domains to the AST DCE pass: integer interval range facts (
Confidence Score: 5/5This 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.
|
| 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]
Reviews (3): Last reviewed commit: "refactor(optimize): share interval entai..." | Re-trigger Greptile
…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>
a64ee61 to
9991d8e
Compare
Summary
Implements the v0.26 ROADMAP item Guard reasoning v2 for dead-code elimination.
AST DCE (
src/optimize/control/dce/) now tracks:RangeGuard/IntInterval) from$x <op> intbranches when$xis known to be an integer through anintparameter, an exact-int guard, or an existing range. Bounds intersect across nested andelseifpaths and prune transitive conditions, strict-int contradictions, and impossibleswitchcases.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
===/!==without confusing0.0and0.globalrebinding, loop/backedge writes, andforeachkey/value overwrites invalidate affected facts.>ati64::MAX,<ati64::MIN) refuse to record.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.mdVerification
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.mdanddocs/internals/how-elephc-works.mdupdated[x][Unreleased]bullet added