Skip to content

fix(hipblaslt): complete the K=64 prefetch in handwritten gfx950 kernels - #12679

Merged
newling merged 1 commit into
users/newling/fix-gfx950-custom-final-loop-waitfrom
users/newling/fix-gfx950-custom-single-prefetch
Sep 29, 2026
Merged

newling merged 1 commit into
users/newling/fix-gfx950-custom-final-loop-waitfrom
users/newling/fix-gfx950-custom-single-prefetch

Conversation

@newling

@newling newling commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

JIRA ID : AIHPBLAS-4866

Motivation

Three handwritten gfx950 BF16/FP16 kernels can read local data share (LDS) before its global-memory loads complete at K=64. Skipping the second prefetch leaves only 16 loads, but the existing vmcnt(24) and vmcnt(16) waits assume 32 and do not guarantee their completion.

Technical Details

Add s_waitcnt vmcnt(0) on the path that skips the second prefetch, before the existing barriers and first LDS reads. The path with two prefetches bypasses the new wait.

This follow-up is based on #12676, which fixes a separate LDS-to-register dependency in the final compute loop.

Test Plan

Compare baseline, fixed and same-size NOP controls in gfx950 functional emulation at M=N=256, K=64, batch=1, with alpha=1, beta=0 and GSU=1. Run the prefetch regressions and K=0/K=128/beta=1 controls.

Test Result

All three kernels go from 2 reports to 0; replacing the new wait with s_nop 0 restores both reports. All 19 emulator runs pass full-output numerical validation, and all nine focused regressions pass. Baseline numerical validation also passes; incorrect output was not reproduced.

Full detector trace, detailed results and reproduction commands.

Submission Checklist

Risk level

Medium: changes kernel synchronization. Physical gfx950 validation and performance remain unmeasured; waitcheck cannot complete this DirectToLDS control-flow analysis.

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

The code change is reasonable.
OK to merge this change.
(as long as we keep these custom kernels)

@codecov

codecov Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Additional details and impacted files
@@                                 Coverage Diff                                 @@
##           users/newling/fix-gfx950-custom-final-loop-wait   #12679      +/-   ##
===================================================================================
- Coverage                                            70.57%   70.43%   -0.14%     
===================================================================================
  Files                                                 2932     2932              
  Lines                                               482397   482397              
  Branches                                             69542    69542              
===================================================================================
- Hits                                                340429   339749     -680     
- Misses                                              118174   118787     +613     
- Partials                                             23794    23861      +67     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 48.82% <ø> (ø)
TensileLite-Unit 81.59% <ø> (-1.00%) ⬇️
hipBLAS 90.62% <ø> (ø) Carriedforward from aaea555
hipBLASLt 35.55% <ø> (ø) Carriedforward from aaea555
hipCUB 82.68% <ø> (ø) Carriedforward from aaea555
hipDNN 86.69% <ø> (ø) Carriedforward from aaea555
hipFFT 54.32% <ø> (ø) Carriedforward from aaea555
hipRAND 76.12% <ø> (ø) Carriedforward from aaea555
hipSOLVER 68.96% <ø> (ø) Carriedforward from aaea555
hipSPARSE 86.99% <ø> (ø) Carriedforward from aaea555
rocBLAS 48.25% <ø> (ø) Carriedforward from aaea555
rocFFT 46.67% <ø> (ø) Carriedforward from aaea555
rocRAND 57.42% <ø> (ø) Carriedforward from aaea555
rocSOLVER 76.83% <ø> (ø) Carriedforward from aaea555
rocSPARSE 74.76% <ø> (ø) Carriedforward from aaea555
rocThrust 78.34% <ø> (ø) Carriedforward from aaea555

*This pull request uses carry forward flags. Click here to find out more.
see 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@newling
newling merged commit dd28da3 into users/newling/fix-gfx950-custom-final-loop-wait Sep 29, 2026
213 of 227 checks passed
@newling
newling deleted the users/newling/fix-gfx950-custom-single-prefetch branch September 29, 2026 14:55
newling added a commit that referenced this pull request Sep 29, 2026
…els (#12679)

JIRA ID : AIHPBLAS-4866

## Motivation

Three handwritten gfx950 BF16/FP16 kernels can read local data share
(LDS) before its global-memory loads complete at `K=64`. Skipping the
second prefetch leaves only 16 loads, but the existing `vmcnt(24)` and
`vmcnt(16)` waits assume 32 and do not guarantee their completion.

## Technical Details

Add `s_waitcnt vmcnt(0)` on the path that skips the second prefetch,
before the existing barriers and first LDS reads. The path with two
prefetches bypasses the new wait.

This follow-up is based on
[#12676](#12676), which fixes
a separate LDS-to-register dependency in the final compute loop.

## Test Plan

Compare baseline, fixed and same-size NOP controls in gfx950 functional
emulation at `M=N=256, K=64, batch=1`, with `alpha=1`, `beta=0` and
`GSU=1`. Run the prefetch regressions and K=0/K=128/beta=1 controls.

## Test Result

All three kernels go from **2 reports to 0**; replacing the new wait
with `s_nop 0` restores both reports. All 19 emulator runs pass
full-output numerical validation, and all nine focused regressions pass.
Baseline numerical validation also passes; incorrect output was not
reproduced.

[Full detector trace, detailed results and reproduction
commands](https://gist.github.com/newling/e688488a90362116cddc26ebb0a61927).

## Submission Checklist

- [ ] Look over the contributing guidelines at
https://github.com/ROCm/TheRock/blob/main/GOVERNANCE.md#pull-requests.

## Risk level

Medium: changes kernel synchronization. Physical gfx950 validation and
performance remain unmeasured; waitcheck cannot complete this
DirectToLDS control-flow analysis.
newling added a commit that referenced this pull request Sep 29, 2026
…els (#12679)

JIRA ID : AIHPBLAS-4866

## Motivation

Three handwritten gfx950 BF16/FP16 kernels can read local data share
(LDS) before its global-memory loads complete at `K=64`. Skipping the
second prefetch leaves only 16 loads, but the existing `vmcnt(24)` and
`vmcnt(16)` waits assume 32 and do not guarantee their completion.

## Technical Details

Add `s_waitcnt vmcnt(0)` on the path that skips the second prefetch,
before the existing barriers and first LDS reads. The path with two
prefetches bypasses the new wait.

This follow-up is based on
[#12676](#12676), which fixes
a separate LDS-to-register dependency in the final compute loop.

## Test Plan

Compare baseline, fixed and same-size NOP controls in gfx950 functional
emulation at `M=N=256, K=64, batch=1`, with `alpha=1`, `beta=0` and
`GSU=1`. Run the prefetch regressions and K=0/K=128/beta=1 controls.

## Test Result

All three kernels go from **2 reports to 0**; replacing the new wait
with `s_nop 0` restores both reports. All 19 emulator runs pass
full-output numerical validation, and all nine focused regressions pass.
Baseline numerical validation also passes; incorrect output was not
reproduced.

[Full detector trace, detailed results and reproduction
commands](https://gist.github.com/newling/e688488a90362116cddc26ebb0a61927).

## Submission Checklist

- [ ] Look over the contributing guidelines at
https://github.com/ROCm/TheRock/blob/main/GOVERNANCE.md#pull-requests.

## Risk level

Medium: changes kernel synchronization. Physical gfx950 validation and
performance remain unmeasured; waitcheck cannot complete this
DirectToLDS control-flow analysis.
newling added a commit that referenced this pull request Oct 5, 2026
…els (#12679)

JIRA ID : AIHPBLAS-4866

## Motivation

Three handwritten gfx950 BF16/FP16 kernels can read local data share
(LDS) before its global-memory loads complete at `K=64`. Skipping the
second prefetch leaves only 16 loads, but the existing `vmcnt(24)` and
`vmcnt(16)` waits assume 32 and do not guarantee their completion.

## Technical Details

Add `s_waitcnt vmcnt(0)` on the path that skips the second prefetch,
before the existing barriers and first LDS reads. The path with two
prefetches bypasses the new wait.

This follow-up is based on
[#12676](#12676), which fixes
a separate LDS-to-register dependency in the final compute loop.

## Test Plan

Compare baseline, fixed and same-size NOP controls in gfx950 functional
emulation at `M=N=256, K=64, batch=1`, with `alpha=1`, `beta=0` and
`GSU=1`. Run the prefetch regressions and K=0/K=128/beta=1 controls.

## Test Result

All three kernels go from **2 reports to 0**; replacing the new wait
with `s_nop 0` restores both reports. All 19 emulator runs pass
full-output numerical validation, and all nine focused regressions pass.
Baseline numerical validation also passes; incorrect output was not
reproduced.

[Full detector trace, detailed results and reproduction
commands](https://gist.github.com/newling/e688488a90362116cddc26ebb0a61927).

## Submission Checklist

- [ ] Look over the contributing guidelines at
https://github.com/ROCm/TheRock/blob/main/GOVERNANCE.md#pull-requests.

## Risk level

Medium: changes kernel synchronization. Physical gfx950 validation and
performance remain unmeasured; waitcheck cannot complete this
DirectToLDS control-flow analysis.
newling added a commit that referenced this pull request Oct 7, 2026
…els (#12679)

JIRA ID : AIHPBLAS-4866

## Motivation

Three handwritten gfx950 BF16/FP16 kernels can read local data share
(LDS) before its global-memory loads complete at `K=64`. Skipping the
second prefetch leaves only 16 loads, but the existing `vmcnt(24)` and
`vmcnt(16)` waits assume 32 and do not guarantee their completion.

## Technical Details

Add `s_waitcnt vmcnt(0)` on the path that skips the second prefetch,
before the existing barriers and first LDS reads. The path with two
prefetches bypasses the new wait.

This follow-up is based on
[#12676](#12676), which fixes
a separate LDS-to-register dependency in the final compute loop.

## Test Plan

Compare baseline, fixed and same-size NOP controls in gfx950 functional
emulation at `M=N=256, K=64, batch=1`, with `alpha=1`, `beta=0` and
`GSU=1`. Run the prefetch regressions and K=0/K=128/beta=1 controls.

## Test Result

All three kernels go from **2 reports to 0**; replacing the new wait
with `s_nop 0` restores both reports. All 19 emulator runs pass
full-output numerical validation, and all nine focused regressions pass.
Baseline numerical validation also passes; incorrect output was not
reproduced.

[Full detector trace, detailed results and reproduction
commands](https://gist.github.com/newling/e688488a90362116cddc26ebb0a61927).

## Submission Checklist

- [ ] Look over the contributing guidelines at
https://github.com/ROCm/TheRock/blob/main/GOVERNANCE.md#pull-requests.

## Risk level

Medium: changes kernel synchronization. Physical gfx950 validation and
performance remain unmeasured; waitcheck cannot complete this
DirectToLDS control-flow analysis.
newling added a commit that referenced this pull request Oct 7, 2026
…ps (#12676)

Three handwritten gfx950 kernels in hipBLASLt's production solution
tables can consume matrix operands before their asynchronous loads are
guaranteed to have completed. The affected kernels are the two BF16 TN
variants and the FP16 TN variant with a 256×256×64 tile.

The optimized final loop runs for `alpha=1`, `beta=0`, an unsplit
reduction (`GSU=1`), and complete output tiles. The proposed update uses
`lgkmcnt(7)` before matrix fused multiply-add (MFMA) index 0 and
`lgkmcnt(8)` before index 8, matching the ordinary no-load loop. These
waits complete each group of operands before use while allowing later
reads to remain pending.

This PR also includes the K=64 fix from
[#12679](#12679). When the
second global-memory prefetch is skipped, `vmcnt(0)` completes the sole
prefetch before the barrier and subsequent local data share (LDS) reads.

RocJITsu reports ten final-loop hazards per kernel on develop and zero
with the two partial waits. Replacing both waits with NOPs restores ten
reports; removing either wait alone also restores reports. The K=64
controls give two reports before the fix and zero afterward. Tests cover
all three kernels, reduction-size and output-edge cases, padded strides,
and batch=1024; six fresh detector runs after the rebase also report
zero. All runs pass numerical validation, and the custom-kernel
regression tests pass. These are functional-emulation results; physical
gfx950 correctness and performance have not been measured.

[Complete detector trace, results, reproduction recipe and proposed
patch](https://gist.github.com/newling/d8ed49e5f33de16938482e5b2b61c13f).

**Publication status:** GitHub currently contains the earlier full-drain
version (`lgkmcnt(0)` at final-loop entry). The validated partial-wait
revision above is local at `2f2c2c80dc3` and awaits push; its exact
patch is in the linked gist.

JIRA ID : AIHPBLAS-4866
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants