-
Notifications
You must be signed in to change notification settings - Fork 84
PR #5961 Review Fixes — Per-Fusion Statement Tracking - #6015
Conversation
Replace manual iterate-and-erase loops in removeStatementsOwnedBy with std::erase_if, which does single-pass partition-and-truncate instead of repeated O(n) deque shifts. This fixes O(n2) performance when a Fusion with many statements is destroyed.
...ortcuts Change Fusion::numExprs() and Fusion::numVals() to return counts from per_fusion_exprs_/per_fusion_vals_ (filtered to this Fusion) instead of global container counts. This is necessary for correct StatementGuard behavior with shared containers. Add numValsExcludingShortcuts() helper that subtracts active shortcut val pointers (zero_val_, one_val_, etc.) from the per-Fusion count. These singletons should persist across guard scopes, so the count must exclude them for LIFO pop-back consistency in removeStatementsCreatedAfter.
...tainers Update Fusion::removeStatementsCreatedAfter to compare per-Fusion counts (from exprsOwnedBy(this) and numValsExcludingShortcuts()) instead of global deque sizes. This correctly handles shared containers where other Fusions' statements would inflate the global counts. Add NVF_ERROR assertions to verify the LIFO invariant: the tail element of the global deque must belong to this Fusion. If violated, another Fusion appended concurrently (should be prevented by PR #5971 locking). Remove now-unnecessary deque size validation checks.
Change StatementGuard constructor to snapshot numExprs() (already per-Fusion) and numValsExcludingShortcuts() instead of numVals() (now also per-Fusion). This ensures the snapshot is consistent with the LIFO rollback logic in removeStatementsCreatedAfter, which correctly handles shortcut singletons.
mdavis36
commented
Feb 26, 2026
!test
Description
|
| Relevant files | |
|---|---|
| Enhancement |
fusion.cpp
Fix removeStatementsCreatedAfter for per-Fusion counts and LIFO verificationcsrc/fusion.cpp exprsOwnedBy(this) ownership shortcut handling expressions and values container.cpp
Optimize removeStatementsOwnedBy performance with std::erase_ifcsrc/ir/container.cpp performance statements statement_guard.cpp
Update StatementGuard to use per-Fusion counts excluding shortcutscsrc/statement_guard.cpp of numVals() removeStatementsCreatedAfter fusion.h
Convert count methods to per-Fusion and add shortcut exclusion helpercsrc/fusion.h pointers |
PR Reviewer Guide
Here are some key observations to aid the review process:
LIFO Invariant Validation
The new NVF_ERROR checks verify that tail elements belong to the correct Fusion before popping. This is crucial for maintaining the LIFO invariant in per-fusion statement tracking. The error messages are clear and provide context for debugging.
c->per_fusion_exprs_[this].count(e) > 0, "removeStatementsCreatedAfter: tail expr belongs to another Fusion");
Performance Optimization
The optimization from manual iterator manipulation to std::erase_if is a good improvement. This changes the complexity from O(n2) to O(n) for the removeStatementsOwnedBy function. The lambda-based approach is cleaner and more maintainable.
std::erase_if(vals_up_, [&](const std::unique_ptr<Val>& v) { if (owned.count(v.get()) > 0) { vals_.erase(v.get()); return true; } return false; });
Shortcut Value Handling
The new numValsExcludingShortcuts() method correctly handles the edge case where shortcut values (zero_val_, one_val_, etc.) should persist across StatementGuard scopes. This ensures LIFO ordering works correctly by excluding these singleton values from the count used for rollback.
int64_t numValsExcludingShortcuts() const noexcept { int64_t count = std::ssize(ir_container()->valsOwnedBy(this)); count -= (zero_val_ != nullptr) + (one_val_ != nullptr) + (true_val_ != nullptr) + (false_val_ != nullptr) + (magic_zero_val_ != nullptr); return count; }
Greptile SummaryApplies review fixes from PR #5961 for per-Fusion statement tracking in shared containers:
All changes are well-implemented with defensive assertions to catch violations of the LIFO invariant. The optimizations are algorithmically sound and the per-Fusion counting ensures correct behavior when multiple Fusions share an Confidence Score: 5/5
Important Files Changed
Last reviewed commit: 0abaf11 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4 files reviewed, no comments
## Summary Review fixes for PR #5961 (Per-Fusion statement tracking): - **O(n2) → 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 Review fixes for PR #5961 (Per-Fusion statement tracking): - **O(n2) → 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 Review fixes for PR #5961 (Per-Fusion statement tracking): - **O(n2) → 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 Review fixes for PR #5961 (Per-Fusion statement tracking): - **O(n2) → 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
Review fixes for PR #5961 (Per-Fusion statement tracking):
removeStatementsOwnedBywithstd::erase_ifnumExprs()/numVals()to return per-Fusion counts instead of globalTests
All tests pass: