Skip to content

[BugFix] Add FirstOwningBlockCollector to map allocated buffers to their declaring blocks - #2007

Closed
Rachmanino wants to merge 2 commits into
tile-ai:mainfrom
Rachmanino:fix-barrier-init
Closed

Rachmanino wants to merge 2 commits into
tile-ai:mainfrom
Rachmanino:fix-barrier-init

Conversation

@Rachmanino

@Rachmanino Rachmanino commented Apr 1, 2026 •

Copy link
Copy Markdown
Collaborator

This fixes missing barrier init attr when TMA is disabled.

This change introduces the FirstOwningBlockCollector class, which collects the first Block that declares each allocated buffer variable. The BufferAllocationLocator is updated to utilize this new collector, ensuring that shared barriers remain associated with their declaring blocks during buffer allocation. This enhancement improves the management of buffer allocations and addresses potential issues with opaque child blocks in pipelined For loops.

Summary by CodeRabbit

  • Refactor
    • Improved buffer allocation tracking and resource management logic to enhance consistency and efficiency across different execution contexts.

@github-actions

github-actions Bot commented Apr 1, 2026

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the TileLang project.

Please remember to run pre-commit run --all-files in the root directory of the project to ensure your changes are properly linted and formatted. This will help ensure your contribution passes the format check.

We appreciate you taking this step! Our team will review your contribution, and we look forward to your awesome work! 🚀

@coderabbitai

coderabbitai Bot commented Apr 1, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This change introduces a new FirstOwningBlockCollector to map buffer data variables to their first declaring blocks, then restructures the buffer allocation relocation loop to associate barrier/shared buffers with their owning blocks instead of using prior skip/continue behavior, while unifying argument-bound buffer handling earlier in the loop.

Changes

Cohort / File(s) Summary
Buffer Allocation Refactoring
src/transform/plan_update_buffer_allocation_location.cc
Added FirstOwningBlockCollector to track block ownership of buffer allocations. Restructured main allocation loop to check argument-bound buffers unconditionally at the start, then conditionally record barrier/shared allocations under their owning blocks with ICHECK validation, removing duplicate skip logic downstream.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~35 minutes

Possibly related PRs

Suggested reviewers

  • LeiWang1999

Poem

🐰 A rabbit hops through buffers bright,
FirstOwningBlockCollector held tight,
Barrier blocks now find their place,
In owning maps with gentle grace—
Control flow dances left and right! 🎯

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: introducing FirstOwningBlockCollector to map allocated buffers to their declaring blocks, which directly addresses the buffer allocation relocation logic modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…ring blocks

This change introduces the FirstOwningBlockCollector class, which collects the first Block that declares each allocated buffer variable. The BufferAllocationLocator is updated to utilize this new collector, ensuring that shared barriers remain associated with their declaring blocks during buffer allocation. This enhancement improves the management of buffer allocations and addresses potential issues with opaque child blocks in pipelined For loops.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/transform/plan_update_buffer_allocation_location.cc`:
- Around line 178-188: The constructor currently pushes barrier buffers into
alloc_buffers_ (using managed_allocations_, owning_block and alloc_buffers_)
which causes duplicates because VisitStmt_(const BlockNode*) already preserves
barrier buffers from op->alloc_buffers; change the constructor logic to skip any
buffer where buffer.scope() indicates a barrier (or where
IsBarrierBuffer(buffer) would be true) so you do not insert barrier buffers into
alloc_buffers_ (leave VisitStmt_ to handle them), i.e., add a guard before
alloc_buffers_[ob->second].push_back(buffer) to continue if the buffer is a
barrier or remove that push entirely for barrier-scoped buffers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 47ff5ca2-7020-4d47-95ae-dcd48fe0307b

📥 Commits

Reviewing files that changed from the base of the PR and between a82fa71 and 2077fe9.

📒 Files selected for processing (1)
  • src/transform/plan_update_buffer_allocation_location.cc

Comment on lines +178 to 188
if (buffer.scope() == "shared.barrier" ||
buffer.scope() == "shared.cluster_barrier") {
if (managed_allocations_.count(buffer->data.get())) {
auto ob = owning_block.find(buffer->data.get());
ICHECK(ob != owning_block.end())
<< "PlanAndUpdateBufferAllocationLocation: barrier buffer "
<< buffer->name << " has no owning Block";
alloc_buffers_[ob->second].push_back(buffer);
}
continue;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Barrier buffers will be allocated twice in their owning block.

The constructor now adds barrier buffers to alloc_buffers_[owning_block] (line 185). However, VisitStmt_(const BlockNode*) at lines 294-300 also preserves barrier buffers from the original op->alloc_buffers:

for (const Buffer &buf : op->alloc_buffers) {
  if (IsBarrierBuffer(buf)) {
    alloc_buffers.push_back(buf);  // First addition
    ...
  }
}
auto it = alloc_buffers_.find(op);
if (it != alloc_buffers_.end()) {
  for (const Buffer &buf : it->second) {
    alloc_buffers.push_back(buf);  // Second addition (same barrier buffer)
    ...
  }
}

When visiting the owning block, the same barrier buffer is added from both sources, resulting in duplicate allocations.

Proposed fix: Skip barrier buffers from alloc_buffers_ since they're already preserved from op->alloc_buffers
 auto it = alloc_buffers_.find(op);
 if (it != alloc_buffers_.end()) {
   for (const Buffer &buf : it->second) {
+    // Barrier buffers are already preserved from op->alloc_buffers above
+    if (IsBarrierBuffer(buf)) {
+      continue;
+    }
     alloc_buffers.push_back(buf);
     PushBinding(buf->data, buf);
   }
 }

Alternatively, revert to the original behavior where barrier buffers are not added to alloc_buffers_ at all, since VisitStmt_ already preserves them from their declaring block's op->alloc_buffers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/transform/plan_update_buffer_allocation_location.cc` around lines 178 -
188, The constructor currently pushes barrier buffers into alloc_buffers_ (using
managed_allocations_, owning_block and alloc_buffers_) which causes duplicates
because VisitStmt_(const BlockNode*) already preserves barrier buffers from
op->alloc_buffers; change the constructor logic to skip any buffer where
buffer.scope() indicates a barrier (or where IsBarrierBuffer(buffer) would be
true) so you do not insert barrier buffers into alloc_buffers_ (leave VisitStmt_
to handle them), i.e., add a guard before
alloc_buffers_[ob->second].push_back(buffer) to continue if the buffer is a
barrier or remove that push entirely for barrier-scoped buffers.

@LeiWang1999

Copy link
Copy Markdown
Member

would you mind providing a test to reproduce?

@Rachmanino

Copy link
Copy Markdown
Collaborator Author

closed as already fixed in pr #1971

@Rachmanino Rachmanino closed this Apr 3, 2026
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.

3 participants