Skip to content

[IR Container] Phase 2.3 Basic shared ptr#5960

Open
mdavis36 wants to merge 2 commits intomd/fusion-stmt-regfrom
md/phase2-shared-ptr
Open

[IR Container] Phase 2.3 Basic shared ptr#5960
mdavis36 wants to merge 2 commits intomd/fusion-stmt-regfrom
md/phase2-shared-ptr

Conversation

@mdavis36
Copy link
Collaborator

@mdavis36 mdavis36 commented Feb 12, 2026

Summary

Replace unique_ptr<IrContainer> with shared_ptr<IrContainer> in Fusion and add the container-side registration API that tracks which Fusions share a given container.

This is the foundational change of Phase 2. The pointer type change alone has no behavioral impact — single-Fusion containers behave identically under shared_ptr. The tracking infrastructure (sharing_fusions_, addFusion/removeFusion) lays the groundwork for all subsequent tasks.

Parallel compilation is disabled in-code via kPhase2DisableParallelCompile = true as a precaution during the transition. This ensures CI runs serial compilation for later PRs without requiring environment variables. Parallel compilation is restored in #5971 .

Relationship to Phase 2

This is the core type change that enables the shared container model:

Phase 1 (unique_ptr — exclusive ownership):
  Fusion A ──→ unique_ptr<IrContainer_A> ──→ {vals_A, exprs_A}
  Fusion B ──→ unique_ptr<IrContainer_B> ──→ {vals_B, exprs_B}

Phase 2 (shared_ptr — shared storage):
  Fusion A ─┐
             ├──→ shared_ptr<IrContainer> ──→ {vals_A, vals_B, exprs_A, exprs_B}
  Fusion B ─┘

  IrContainer tracks: sharing_fusions_ = {A, B}

Without this change, no subsequent Phase 2 work (per-Fusion tracking, shared-container copy/move, thread safety) is possible. The tracking API is the mechanism that makes container sharing safe — it allows the container to know its consumers, enabling correct cleanup when Fusions are destroyed.

CI Risk

Low. For single-Fusion containers (all existing usage), shared_ptr is behaviorally identical to unique_ptr. No accessor paths change. Parallel compilation is serialized by the in-code constant.

@mdavis36
Copy link
Collaborator Author

!test

@github-actions
Copy link

github-actions bot commented Feb 12, 2026

Review updated until commit c965408

Description

  • Replace unique_ptr<IrContainer> with shared_ptr<IrContainer> in Fusion class

  • Add Fusion tracking infrastructure to IrContainer (addFusion/removeFusion/transferFusion/sharingCount)

  • Remove IrContainer::parent_ backpointer since 1:1 relationship no longer holds

  • Disable parallel compilation during transition via kPhase2DisableParallelCompile constant

  • Update all related code paths to work with shared ownership model

Changes walkthrough

Relevant files
Enhancement
fusion.cpp
Update Fusion class for shared_ptr transition                       

csrc/fusion.cpp

  • Update Fusion constructor to use shared_ptr and call addFusion instead
    of setting parent_
  • Add removeFusion call in Fusion destructor for proper cleanup
  • Remove parent_ references from swap function and update comments
  • Pass destination fusion to IrContainer::copy method
  • Minor formatting improvements in removeExpr
  • +11/-14 
    container.cpp
    Implement Fusion tracking infrastructure in IrContainer   

    csrc/ir/container.cpp

  • Remove parent_ swapping from IrContainer::swap
  • Add dest_fusion parameter to IrContainer::copy and use it for IrCloner
  • Update inContainer to check sharing_fusions_ instead of parent_
  • Implement new Fusion tracking methods: addFusion, removeFusion,
    transferFusion, sharingCount, hasMultipleFusions, sharingFusions
  • +31/-5   
    fusion.h
    Update Fusion header for shared_ptr IrContainer                   

    csrc/fusion.h

  • Change ir_container_ from unique_ptr to shared_ptr
  • Add ir_container_ptr() method to access shared_ptr
  • Update comments to reflect shared ownership model
  • +5/-2     
    container.h
    Update IrContainer header with tracking API                           

    csrc/ir/container.h

  • Remove parent_ member variable and parent() method
  • Add Fusion tracking API methods (addFusion, removeFusion,
    transferFusion, etc.)
  • Update copy method signature to include dest_fusion parameter
  • Add sharing_fusions_ unordered_set for tracking
  • +11/-9   
    Configuration changes
    fusion_kernel_runtime.cpp
    Disable parallel compilation during shared_ptr transition

    csrc/runtime/fusion_kernel_runtime.cpp

  • Add kPhase2DisableParallelCompile constant to disable parallel
    compilation
  • Use constant in compileFusionParallel to conditionally disable
    parallel compilation
  • +7/-2     

    PR Reviewer Guide

    Here are some key observations to aid the review process:

    🧪 No relevant tests
    ⚡ Recommended focus areas for review
    Missing error handling

    In the Fusion destructor, there's a call to ir_container_->removeFusion(this) but no null check. While the constructor initializes ir_container_ with std::make_shared, there could be scenarios where the container becomes null during the fusion lifetime. Consider adding a null check for defensive programming.

    Fusion::~Fusion() {
      clear();
      if (ir_container_) {
        ir_container_->removeFusion(this);
      }
    }
    Potential race condition

    The sharing_fusions_ set is accessed in multiple methods (addFusion, removeFusion, transferFusion) but there's no synchronization mechanism. Since this is part of Phase 2 which mentions thread safety as a future concern, consider if thread-safe containers (like std::unordered_set with external locking or std::shared_mutex when available) should be used even at this foundational stage.

    void IrContainer::addFusion(Fusion* fusion) {
      sharing_fusions_.insert(fusion);
    }
    
    void IrContainer::removeFusion(Fusion* fusion) {
      sharing_fusions_.erase(fusion);
    }
    
    void IrContainer::transferFusion(Fusion* from, Fusion* to) {
      sharing_fusions_.erase(from);
      sharing_fusions_.insert(to);
    }
    
    size_t IrContainer::sharingCount() const {
      return sharing_fusions_.size();
    }
    
    bool IrContainer::hasMultipleFusions() const {
      return sharing_fusions_.size() > 1;
    }
    
    const std::unordered_set<Fusion*>& IrContainer::sharingFusions() const {
      return sharing_fusions_;
    }

    @mdavis36 mdavis36 force-pushed the md/phase2-shared-ptr branch from 3a199c8 to 53e5045 Compare February 12, 2026 22:09
    @mdavis36 mdavis36 changed the title [WIP] phase2 basic shared ptr [IR Container] Phase2 Basic shared ptr Feb 12, 2026
    @mdavis36 mdavis36 changed the title [IR Container] Phase2 Basic shared ptr [IR Container] Phase 2.3 Basic shared ptr Feb 18, 2026
    Change Fusion::ir_container_ from unique_ptr to shared_ptr to enable
    future container sharing between Fusions. Add Fusion tracking API to
    IrContainer (addFusion/removeFusion/transferFusion/sharingCount).
    Remove IrContainer::parent_ since the 1:1 relationship no longer holds.
    Disable parallel compilation during the shared_ptr transition.
    @mdavis36
    Copy link
    Collaborator Author

    !test

    @mdavis36 mdavis36 marked this pull request as ready for review February 18, 2026 06:37
    @greptile-apps
    Copy link
    Contributor

    greptile-apps bot commented Feb 18, 2026

    Greptile Summary

    This PR transitions IrContainer from exclusive ownership (unique_ptr) to shared ownership (shared_ptr) and replaces the 1:1 parent backpointer with a 1:many tracking infrastructure (sharing_fusions_ set).

    Key Changes:

    • Replaced unique_ptr<IrContainer> with shared_ptr<IrContainer> in Fusion
    • Removed parent_ pointer from IrContainer, added sharing_fusions_ set for tracking which Fusions share a container
    • Added registration API: addFusion(), removeFusion(), transferFusion()
    • Updated constructor to call addFusion(this) and destructor to call removeFusion(this)
    • Modified copy() signature to pass destination Fusion explicitly (since parent_ is removed)
    • Updated inContainer() to verify Fusion membership via sharing_fusions_ instead of parent pointer
    • Disabled parallel compilation via kPhase2DisableParallelCompile constant as precaution during transition

    Implementation Quality:
    The implementation correctly maintains the invariant that sharing_fusions_ accurately reflects container ownership:

    • Container content swapping (not pointer swapping) in Fusion::swap() preserves sharing_fusions_ correctness
    • Copy/move operations properly register and unregister Fusions
    • Statement::ir_container_ pointers are correctly updated after swap

    Future Work:
    Methods ir_container_ptr() and transferFusion() are defined but unused, laying groundwork for actual container sharing in subsequent PRs.

    Confidence Score: 5/5

    • This PR is safe to merge with minimal risk
    • The shared_ptr transition is well-executed with proper tracking infrastructure. All ownership invariants are maintained through swap/copy/move operations. For single-Fusion containers (current usage), behavior is identical to unique_ptr. Parallel compilation is intentionally disabled as a safety measure.
    • No files require special attention

    Important Files Changed

    Filename Overview
    csrc/fusion.h Changed ir_container_ from unique_ptr to shared_ptr, added ir_container_ptr() accessor for future container sharing support
    csrc/fusion.cpp Updated constructor/destructor to use addFusion/removeFusion API instead of parent pointer, updated copy() signature, removed stale parent pointer updates from swap()
    csrc/ir/container.h Replaced parent_ pointer with sharing_fusions_ set, added tracking API (addFusion, removeFusion, transferFusion) to support shared container model
    csrc/ir/container.cpp Implemented fusion tracking API, updated inContainer to check sharing_fusions_ membership, removed parent pointer from swap()
    csrc/runtime/fusion_kernel_runtime.cpp Added kPhase2DisableParallelCompile flag to serialize compilation during transition period as safety precaution

    Class Diagram

    %%{init: {'theme': 'neutral'}}%%
    classDiagram
        class Fusion {
            -shared_ptr~IrContainer~ ir_container_
            +Fusion()
            +~Fusion()
            +swap(Fusion& a, Fusion& b)
            +copy(Fusion* from, Fusion* to)
        }
        
        class IrContainer {
            -unordered_set~Fusion*~ sharing_fusions_
            +addFusion(Fusion* fusion)
            +removeFusion(Fusion* fusion)
            +transferFusion(Fusion* from, Fusion* to)
            +sharingCount() size_t
            +hasMultipleFusions() bool
            +swap(IrContainer& a, IrContainer& b)
        }
        
        class Statement {
            +Fusion* ir_container_
            +container() Fusion*
        }
        
        Fusion "1" --> "1" IrContainer : owns (shared_ptr)
        IrContainer "1" --> "*" Fusion : tracks (sharing_fusions_)
        Statement "*" --> "1" Fusion : belongs to
        
        note for IrContainer "Phase 2: Replaced parent_ pointer with sharing_fusions_ set to support multi-Fusion containers"
        note for Fusion "Phase 2: Changed from unique_ptr to shared_ptr for future container sharing"
    
    Loading

    Last reviewed commit: c965408

    Copy link
    Contributor

    @greptile-apps greptile-apps bot left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    5 files reviewed, 1 comment

    Edit Code Review Agent Settings | Greptile

    @greptile-apps
    Copy link
    Contributor

    greptile-apps bot commented Feb 18, 2026

    Additional Comments (1)

    csrc/fusion.cpp
    Stale comment references removed code

    These comments reference "parent backpointers" and say "each Fusion owns a different IrContainer", both of which are artifacts of the old parent_ pointer model. Since parent_ was removed and the comment no longer accurately describes the code, it should be updated. The actual purpose of the loop below is to update Statement::ir_container_ pointers so that statements point to the correct owning Fusion after the content swap.

      // After swapping container contents, update Statement::ir_container_
      // pointers so each Statement points to the Fusion whose container now
      // holds it.
    

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Labels

    None yet

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    1 participant