Skip to content

[BugFix] Respect layouts in logical reductions - #2807

Open
lijinpei wants to merge 2 commits into
tile-ai:mainfrom
lijinpei:20260729-fix-issue-2714
Open

[BugFix] Respect layouts in logical reductions#2807
lijinpei wants to merge 2 commits into
tile-ai:mainfrom
lijinpei:20260729-fix-issue-2714

Conversation

@lijinpei

@lijinpei lijinpei commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

[BugFix] Respect layouts in logical reductions

The int8x2 cases are marked xfail on HIP: that backend cannot emit a vector
access to a buffer of packed elements, so the compile aborts before the
reduction is reached. CUDA is unaffected.

Fixes #2714

[BugFix] Verify parallel vector stores

The data race check proves that two iterations writing the same location
write the same value. For a vector-valued store that comparison is itself
vector-valued, which Or() rejects ("mismatched types"), so a T.Parallel
loop containing a vectorized store could not be compiled at all.

Compare the vectors lane by lane instead, so that nothing vector-valued
reaches arith::Analyzer: its Z3 backend models only scalar arithmetic and
aborts on a Ramp, Broadcast or Shuffle. Vector indices are constrained per
lane for the same reason -- dropping them would lose the injectivity of the
index map and report a spurious race on every vectorized copy. A lane that
does not reduce to a scalar falls back to the same-iteration check.

Summary

  • Added layout-aware logical reduction lowering and CUDA/HIP code generation, including scalar and vectorized reduction helpers.
  • Registered new tl.logical_reduce and tl.logical_reduce_index intrinsics.
  • Improved parallel-loop race verification by comparing vector store indices and values lane by lane, with safe fallback handling for non-scalarizable lanes.
  • Added regression coverage for swizzled/padded logical reductions and vector-valued parallel stores, including expected HIP failures for packed element types.

C++ style / lint notes

  • The PR changes C++ code but does not appear to modify rules documented in docs/developer_guide/cpp_style.md.
  • The C++ API Style Audit (warning only) remains advisory; any TLCPP003/TLCPP004 warnings should not block merging unless they indicate a concrete API, FFI, or maintainability risk.

The data race check proves that two iterations writing the same location
write the same value. For a vector-valued store that comparison is itself
vector-valued, which Or() rejects ("mismatched types"), so a T.Parallel
loop containing a vectorized store could not be compiled at all.

Compare the vectors lane by lane instead, so that nothing vector-valued
reaches arith::Analyzer: its Z3 backend models only scalar arithmetic and
aborts on a Ramp, Broadcast or Shuffle. Vector indices are constrained per
lane for the same reason -- dropping them would lose the injectivity of the
index map and report a spurious race on every vectorized copy. A lane that
does not reduce to a scalar falls back to the same-iteration check.
@github-actions

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 Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds layout-aware logical reduction lowering, CUDA/HIP code generation and templates, regression coverage for swizzled and padded layouts, and vector-aware parallel-loop race verification with corresponding tests.

Changes

Layout-aware logical reductions

Layer / File(s) Summary
Logical reduction lowering
src/op/builtin.*, src/transform/lower_tile_op.cc
Registers compiler-internal logical reduction intrinsics and rewrites tl.any_of/tl.all_of calls into layout-aware mapped reductions with derived vector widths.
Backend logical reduction emission
src/cuda/codegen/*, src/rocm/codegen/*, src/tl_templates/{cuda,hip}/common.h
Emits scalar or vector LogicalReduceMap calls for CUDA and HIP, including mapped lambdas and lane-wise short-circuit reduction helpers.
Layout-aware reduction regression coverage
testing/python/issue/test_tilelang_issue_2714.py
Tests CUDA/HIP reductions across swizzled and padded layouts, validates results against PyTorch, and checks generated vector-reduction code.

Vector parallel-loop verification

Layer / File(s) Summary
Vector-aware race constraints
src/transform/verify_parallel_loop.cc
Extracts scalar lanes from supported vector expressions and compares vector indices and stored values lane by lane during race analysis.
Vector store verification tests
testing/python/language/test_tilelang_language_parallel.py, testing/python/transform/test_tilelang_transform_verify_parallel_loop.py
Adds vector-store compilation coverage and tests accepted injective, rejected non-injective, and same-value vector-store cases.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TileLangKernel
  participant LowerTileOp
  participant CUDAorHIPCodegen
  participant LogicalReduceMap
  TileLangKernel->>LowerTileOp: emit tl.any_of or tl.all_of
  LowerTileOp->>LowerTileOp: derive layout mapping and vector width
  LowerTileOp->>CUDAorHIPCodegen: emit tl.logical_reduce
  CUDAorHIPCodegen->>LogicalReduceMap: generate scalar or vector mapped reduction
  LogicalReduceMap->>TileLangKernel: return logical reduction result
Loading

Possibly related issues

  • tile-ai/tilelang#2714 — The PR adds the layout-aware logical reduction lowering and backend code generation described by the issue.

Possibly related PRs

  • tile-ai/tilelang#2806 — Both PRs modify parallel-loop race analysis around BufferStoreNode handling in verify_parallel_loop.cc.

Suggested reviewers: siriusneo

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: logical reductions now respect layouts.
✨ 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.

@lijinpei
lijinpei force-pushed the 20260729-fix-issue-2714 branch from 96e4b7d to 24efb29 Compare July 29, 2026 16:14
The int8x2 cases are marked xfail on HIP: that backend cannot emit a
vector access to a buffer of packed elements, so the compile aborts
before the reduction is reached. CUDA is unaffected.

Fixes tile-ai#2714
@lijinpei
lijinpei force-pushed the 20260729-fix-issue-2714 branch from 24efb29 to 359d367 Compare July 29, 2026 16:18

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/transform/verify_parallel_loop.cc (1)

94-141: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Model and test cross-lane vector-store collisions. Matching only lane n with lane n misses aliases such as Ramp(j, 1, 2) between adjacent parallel iterations, allowing differing writes to the same scalar element.

  • src/transform/verify_parallel_loop.cc#L94-L141: evaluate collisions and stored-value equality for every relevant pair of vector lanes, not only corresponding lanes.
  • testing/python/transform/test_tilelang_transform_verify_parallel_loop.py#L53-L70: add an overlapping Ramp-index case with varying values that must emit Data race detected.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/transform/verify_parallel_loop.cc` around lines 94 - 141, Update
src/transform/verify_parallel_loop.cc lines 94-141 in the collision constraints
and same_value logic to compare every relevant pair of vector lanes, including
cross-lane aliases such as overlapping Ramp indices, rather than only matching
lane numbers; preserve scalar and scalable-vector behavior. Add an overlapping
Ramp-index case with differing stored values to
testing/python/transform/test_tilelang_transform_verify_parallel_loop.py lines
53-70 and assert that verification emits “Data race detected”.
🧹 Nitpick comments (5)
src/transform/lower_tile_op.cc (2)

869-918: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Two full HandleAccessPtrAndOffset remaps for one reduction. The first remap (Lines 874-880) exists only to feed SelectLogicalReductionVectorSize; the second recomputes the same layout math with chunk_offset. Consider selecting the vector size from the chunk-based mapping directly, or factoring the shared "remap access_ptr with symbolic offset" step into a small helper, to avoid duplicating the (non-trivial) index recomputation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/transform/lower_tile_op.cc` around lines 869 - 918, Avoid performing two
independent HandleAccessPtrAndOffset remaps in MakeMappedLogicalReduction. Reuse
a shared helper or derive SelectLogicalReductionVectorSize from the chunk-based
mapping so the access-pointer layout and index computation are performed once
while preserving the existing vector-size selection behavior.

920-947: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Extent sign check is one-sided. ICHECK_GE(extent_imm->value, 0) only fires for constant extents; a symbolic extent that evaluates negative silently yields vector_count <= 0 and the reduction returns !is_any. Consider analyzer_->CanProveGreaterEqual(extent, 0) or documenting that the frontend guarantees non-negativity.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/transform/lower_tile_op.cc` around lines 920 - 947, The extent validation
in TryRewriteLogicalReduction only rejects negative IntImm values and allows
symbolic extents that can be proven negative. Validate the simplified extent
with analyzer_->CanProveGreaterEqual(extent, 0), rejecting or reporting failure
when non-negativity cannot be established, while preserving the existing
reduction rewrite for valid extents.
testing/python/issue/test_tilelang_issue_2714.py (1)

193-194: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Loose type-name assertion. [A-Za-z_][A-Za-z0-9_]*{vector_words}\*\) matches any identifier ending in the word count (int4*, longlong4*, uint4*, …), so this can pass for an unintended vector type. Anchoring on the expected type per element_type would make the regression assertion meaningful.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@testing/python/issue/test_tilelang_issue_2714.py` around lines 193 - 194, The
assertion in the test around vector_words is too permissive because it accepts
any type name ending with the lane count. Derive the expected vector type from
element_type and update the regex to match that specific type, while preserving
the existing vector_words calculation and return-expression validation.
src/op/builtin.h (1)

232-238: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document the full argument list. The comment only describes arg 0; arg 1 (vector count) and arg 2 (is_any flag) are part of the contract enforced by both codegens.

📝 Suggested doc
 /*!
  * \brief Compiler-internal mapped logical reduction.
  *
  * Arg 0 is a Let binding the runtime vector index to the layout-remapped
  * load; codegen turns this into a LogicalReduceMap template call.
+ *
+ * logical_reduce(mapping_let, vector_count, is_any)
+ * - vector_count: number of chunks to scan.
+ * - is_any: Bool, true for any_of, false for all_of.
  */
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/op/builtin.h` around lines 232 - 238, Expand the documentation for
logical_reduce() to describe the complete argument contract: arg 0 is the Let
binding for the runtime vector index and layout-remapped load, arg 1 is the
vector count, and arg 2 is the is_any flag. Keep the existing codegen behavior
and declaration unchanged.
src/cuda/codegen/codegen_cuda.cc (1)

2407-2445: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

PrintLogicalReduce is duplicated byte-for-byte across the two backends. Both implementations perform the same validation, the same tl::Logical[Vector]ReduceMap<...> template-name construction, and the same var_idmap_ bookkeeping; any future change to the emission contract must be applied twice and will silently diverge otherwise.

  • src/cuda/codegen/codegen_cuda.cc#L2407-L2445: extract the shared validation + emission into a helper (e.g. in tl::codegen) parameterized on a PrintType/PrintExpr/AllocVarID callback set, and call it here.
  • src/rocm/codegen/codegen_hip.cc#L1169-L1207: replace the copied body with a call to that shared helper.

The same applies at a lower priority to the identical LogicalReduceMap/LogicalVectorReduceMap definitions in src/tl_templates/cuda/common.h and src/tl_templates/hip/common.h, though those follow the existing per-backend header convention.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cuda/codegen/codegen_cuda.cc` around lines 2407 - 2445, Extract the
duplicated logical-reduce validation and emission from
CodeGenTileLangCUDA::PrintLogicalReduce in
src/cuda/codegen/codegen_cuda.cc#L2407-L2445 and the corresponding
implementation in src/rocm/codegen/codegen_hip.cc#L1169-L1207 into a shared
tl::codegen helper parameterized by the backend printing and variable-allocation
callbacks. Replace both PrintLogicalReduce bodies with calls to that helper
while preserving validation, Logical[Vector]ReduceMap template construction,
expression emission, and var_idmap_ cleanup. The LogicalReduceMap definitions in
the template headers require no direct change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/transform/verify_parallel_loop.cc`:
- Around line 94-141: Update src/transform/verify_parallel_loop.cc lines 94-141
in the collision constraints and same_value logic to compare every relevant pair
of vector lanes, including cross-lane aliases such as overlapping Ramp indices,
rather than only matching lane numbers; preserve scalar and scalable-vector
behavior. Add an overlapping Ramp-index case with differing stored values to
testing/python/transform/test_tilelang_transform_verify_parallel_loop.py lines
53-70 and assert that verification emits “Data race detected”.

---

Nitpick comments:
In `@src/cuda/codegen/codegen_cuda.cc`:
- Around line 2407-2445: Extract the duplicated logical-reduce validation and
emission from CodeGenTileLangCUDA::PrintLogicalReduce in
src/cuda/codegen/codegen_cuda.cc#L2407-L2445 and the corresponding
implementation in src/rocm/codegen/codegen_hip.cc#L1169-L1207 into a shared
tl::codegen helper parameterized by the backend printing and variable-allocation
callbacks. Replace both PrintLogicalReduce bodies with calls to that helper
while preserving validation, Logical[Vector]ReduceMap template construction,
expression emission, and var_idmap_ cleanup. The LogicalReduceMap definitions in
the template headers require no direct change.

In `@src/op/builtin.h`:
- Around line 232-238: Expand the documentation for logical_reduce() to describe
the complete argument contract: arg 0 is the Let binding for the runtime vector
index and layout-remapped load, arg 1 is the vector count, and arg 2 is the
is_any flag. Keep the existing codegen behavior and declaration unchanged.

In `@src/transform/lower_tile_op.cc`:
- Around line 869-918: Avoid performing two independent HandleAccessPtrAndOffset
remaps in MakeMappedLogicalReduction. Reuse a shared helper or derive
SelectLogicalReductionVectorSize from the chunk-based mapping so the
access-pointer layout and index computation are performed once while preserving
the existing vector-size selection behavior.
- Around line 920-947: The extent validation in TryRewriteLogicalReduction only
rejects negative IntImm values and allows symbolic extents that can be proven
negative. Validate the simplified extent with
analyzer_->CanProveGreaterEqual(extent, 0), rejecting or reporting failure when
non-negativity cannot be established, while preserving the existing reduction
rewrite for valid extents.

In `@testing/python/issue/test_tilelang_issue_2714.py`:
- Around line 193-194: The assertion in the test around vector_words is too
permissive because it accepts any type name ending with the lane count. Derive
the expected vector type from element_type and update the regex to match that
specific type, while preserving the existing vector_words calculation and
return-expression validation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 32e93a10-895d-44f9-8dd1-a706d3d41a3f

📥 Commits

Reviewing files that changed from the base of the PR and between 6c3dd97 and 359d367.

📒 Files selected for processing (13)
  • src/cuda/codegen/codegen_cuda.cc
  • src/cuda/codegen/codegen_cuda.h
  • src/op/builtin.cc
  • src/op/builtin.h
  • src/rocm/codegen/codegen_hip.cc
  • src/rocm/codegen/codegen_hip.h
  • src/tl_templates/cuda/common.h
  • src/tl_templates/hip/common.h
  • src/transform/lower_tile_op.cc
  • src/transform/verify_parallel_loop.cc
  • testing/python/issue/test_tilelang_issue_2714.py
  • testing/python/language/test_tilelang_language_parallel.py
  • testing/python/transform/test_tilelang_transform_verify_parallel_loop.py

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

Labels

None yet

Projects

None yet

1 participant