[IR Container] Phase 2.4 Per-fusion statement tracking #5961
[IR Container] Phase 2.4 Per-fusion statement tracking #5961mdavis36 wants to merge 2 commits intomd/phase2-shared-ptrfrom
Conversation
|
Review updated until commit bc595c5 Description
|
| Relevant files | |||||||||
|---|---|---|---|---|---|---|---|---|---|
| Enhancement |
| ||||||||
| Bug fix |
|
PR Reviewer Guide
Here are some key observations to aid the review process:
| 🧪 PR contains tests |
| ⚡ Recommended focus areas for review |
Ownership Tracking Synchronization
|
3a199c8 to
53e5045
Compare
|
!test |
33629cb to
8b162d9
Compare
53e5045 to
f8ff364
Compare
|
!test |
Greptile SummaryThis PR implements per-Fusion ownership tracking by adding Key Changes:
Risk Assessment: Confidence Score: 3/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Fusion A] -->|owns| IC[IrContainer shared_ptr]
B[Fusion B] -->|owns| IC
IC -->|contains| VD["vals_up_ deque<br/>global: v0, v1, v2, v3"]
IC -->|contains| ED["exprs_up_ deque<br/>global: e0, e1, e2, e3"]
IC -->|tracks| PFV["per_fusion_vals_<br/>A: v0, v1<br/>B: v2, v3"]
IC -->|tracks| PFE["per_fusion_exprs_<br/>A: e0, e1<br/>B: e2, e3"]
A -->|"vals() call"| FA[valsOwnedBy A]
FA -->|filters by A| PFV
FA -->|"returns"| RAV["only v0, v1"]
B -->|"vals() call"| FB[valsOwnedBy B]
FB -->|filters by B| PFV
FB -->|"returns"| RBV["only v2, v3"]
style IC fill:#e1f5ff
style PFV fill:#fff4e1
style PFE fill:#fff4e1
style RAV fill:#d4edda
style RBV fill:#d4edda
Last reviewed commit: bc595c5 |
Additional Comments (2)
In In a shared container scenario where another Fusion has appended statements after the
The same issue applies to the This is safe for single-Fusion containers today, but since this PR's stated goal is enabling shared-container safety, the rollback path should also clean up the correct owner's per-fusion map — e.g., by looking up which Fusion actually owns each statement being removed.
More importantly, For single-Fusion containers this is fine, but these methods should be updated to return per-Fusion counts (or at least documented as container-global) before shared containers are actually used. |
Add per_fusion_vals_ / per_fusion_exprs_ maps to IrContainer so each Fusion can efficiently query only its own statements in a shared container. Fusion forwarding methods (vals(), unordered_exprs(), deterministic_vals(), etc.) now return per-Fusion filtered results. Fusion::clear() uses removeStatementsOwnedBy(this) instead of ir_container()->clear().
8b162d9 to
b8d202d
Compare
|
!test |
## Summary Review fixes for PR #5961 (Per-Fusion statement tracking): - **O(n²) → O(n)**: Optimize `removeStatementsOwnedBy` with `std::erase_if` - **Per-Fusion counts**: Convert `numExprs()`/`numVals()` to return per-Fusion counts instead of global - **StatementGuard fixes**: Snapshot and compare per-Fusion counts for correct LIFO rollback in shared containers - **LIFO assertions**: Verify tail elements belong to this Fusion before popping ## Tests All tests pass: - ✅ StatementGuardTest.ExecuteAfterGuard - ✅ StatementGuardTest.LazySpecialValsNotDangling - ✅ FusionCopy_CUDA - ✅ FusionMove_CUDA
Summary
Add per-Fusion ownership tracking maps to IrContainer so each Fusion can efficiently query only its own Vals and Exprs within a shared container. Update all Fusion-level accessors to filter by ownership.
This is the highest-risk change in the Phase 2 chain. Every accessor call path is touched —
vals(),deterministic_vals(),deterministic_exprs(),unordered_exprs(), and more now return ownership-filtered results rather than raw container contents. For single-Fusion containers the results are identical, but the implementation changes underneath every consumer.Relationship to Phase 2
This is the critical invariant that makes shared containers safe:
Without per-Fusion filtering, a shared container copy would break every consumer —
Fusion::copywould iterate all vals (including other Fusions'),deterministic_vals()would return interleaved results, andStatementGuardrollback would destroy statements belonging to other Fusions.This invariant is what allows Phase 2 to maintain independent IR graphs despite shared storage:
fusion->vals()returns{v : v in container AND v->container() == fusion}Fusion::clear()only clears THIS Fusion's state (notir_container()->clear())CI Risk
Highest of all Phase 2 PRs. Every accessor-dependent code path is touched. For single-Fusion containers, filtered results are identical to unfiltered — but regressions would surface in accessor-heavy code paths (scheduling, lowering, codegen).