Files
TheRock/rocm-libraries/shared/stinkytofu/tools/waitcnt-check
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00
..

waitcnt-check

A standalone validator for s_wait_* (wait-count) insertion in STIR (StinkyTofu IR) dumps. It parses a STIR file, simulates the per-counter in-flight queues across the control-flow graph, and reports any consumer that reads the result of an asynchronous memory op that has not been drained by a preceding s_wait_*.

It is an independent cross-check of the compiler's StinkyWaitCntInsertionPass: the dataflow model here mirrors shared/stinkytofu/src/transforms/asm/waitcnt/WaitDataflow.cpp, so a STIR that the pass waited correctly should validate clean.

What it checks

Each tracked asynchronous memory op completes on one hardware counter, and each counter is drained by its own wait instruction:

Counter Producers Wait op
DS ds_read / ds_load / ds_write / ds_store / ds_atomic s_wait_dscnt
Buffer vector buffer / global / flat load + store s_wait_loadcnt
KM scalar s_load / s_buffer_load s_wait_kmcnt
Tensor tensor_load_to_lds s_wait_tensorcnt

The validator models, per counter:

  • Per-predecessor queues. Each block keeps one in-flight queue per CFG predecessor (not a single union), so a consumer at a join computes the strictest required wait as the min over paths. Queues are capped at the hardware in-flight window (64) so loops converge.
  • RAW (consumer reads a register/LDS token still in flight), WAR-on-LDS and barrier ordering against the DS FIFO, plus the conservative fallbacks used by the reference pass for untagged memtokens.
  • The tensor counter only needs to drain at a barrier (or when there is a single wave); see --num-waves.

When it finds a consumer whose producer is still in flight, it reports a MISSING violation: the wait the compiler should have emitted is absent (or too lenient / placed too late).

Usage

python3 waitcnt_check.py [options] <file.stir>

By default only violations are printed. Example:

python3 shared/stinkytofu/tools/waitcnt-check/waitcnt_check.py dump_function-after.stir

Options

Option Description
--num-waves N NumWaves tile config. 0 (default) = multi-wave: the tensor counter only drains at barriers. 1 = tensor drains at every consumer.
-v, --verbose Also print the Wait Instructions listing (what each s_wait_* drained) and Notes.
--quiet Print only the one-line summary per function.
-h, --help Show help.

Exit codes

Code Meaning
0 PASS — no violations
1 FAIL — at least one violation
2 Could not read or parse the input file

Reading a violation

Only the first violation per counter/queue is reported (one diagnostic per s_wait_* kind), each followed by a dump of the live queue state:

  MISSING: Consumer v_wmma_scale_f32_16x16x128_f8f6f4 @ line 1913 in ^label_LoopBeginL
           uses async producer ds_load_b128 @ line 1805 (s_wait_dscnt)
           still in-flight (queue depth=28, needs wait s_wait_dscnt 27)
    Queue dump for s_wait_dscnt at consumer ... in ^label_LoopBeginL:
      required (drains ALL 2 undrained producer(s) this consumer uses): s_wait_dscnt 26
      live queues (DS): 2 per-pred queue(s)
        queue[0] pred=^label_openLoopL_1 depth=28
          idx 0: ds_load_b128 @ line 1805 (drain with s_wait_dscnt 27)  <-- undrained producer
          idx 1: ds_load_b64  @ line 1806 (drain with s_wait_dscnt 26)  <-- undrained producer
          ...
  • needs wait <op> N in the headline is per producer: the keep value that drains just the op named there (for an op at index i in a queue of size n, that is n - i - 1).
  • required: <op> N is the single wait that drains every undrained producer the consumer reads — the min of the per-producer values. This is the value the compiler should have emitted before the consumer.
  • Each queue line shows its source predecessor and, per op, the keep value that would drain it; <-- undrained producer marks the offending ops.

Notes

  • The tool is dependency-free (Python 3 standard library only).
  • It reads a STIR text dump as produced by the StinkyTofu asm pipeline; it does not require building the compiler.