285 Commits

Author SHA1 Message Date
Pankaj Dwivedi
28d4e33b65
[AMDGPU][SIInsertWaitCnt] Optimize loadcnt insertion at function boundaries (#169647)
On GFX12+, GLOBAL_INV increments the loadcnt counter but does not write
results to any VGPRs. Previously, we unconditionally inserted
s_wait_loadcnt 0 at function returns even when the only pending loadcnt
was from GLOBAL_INV instructions.

This patch optimizes waitcnt insertion by skipping the loadcnt wait at
function boundaries when no VGPRs have pending loads. This is determined
by checking if any VGPR has a score greater than the lower bound for
LOAD_CNT - if not, the pending loadcnt must be from non-VGPR-writing
instructions like GLOBAL_INV.

The optimization is limited to GFX12+ targets where GLOBAL_INV exists
and uses the extended wait count instructions.

This is a follow-up optimization to PR #135340 which added tracking for
GLOBAL_INV in the waitcnt pass.
2025-12-17 17:53:00 +05:30
Jay Foad
c1e829fc3d
[AMDGPU] Simplify waitcnt insertion on function entry. NFC. (#172461)
This pass runs way too late for PHI instructions.
2025-12-16 12:00:13 +00:00
Pankaj Dwivedi
e151434b0f
[AMDGPU][InsertWaitCnts][NFC] Merge VMEM_ACCESS and VMEM_READ_ACCESS into a single event type (#171973) 2025-12-12 18:26:40 +05:30
Pierre van Houtryve
025d0c0d1d
(reland) [AMDGPU][SIInsertWaitCnts] Use RegUnits-based tracking (#162077) (#171779)
Fixed a crash in Blender due to some weird control flow.
The issue was with the "merge" function which was only looking at the
keys of the "Other" VMem/SGPR maps. It needs to look at the keys of both
maps and merge them.

Original commit message below
----

The pass was already "reinventing" the concept just to deal with 16 bit
registers. Clean up the entire tracking logic to only use register
units.

There are no test changes because functionality didn't change, except:
- We can now track more LDS DMA IDs if we need it (up to `1 << 16`)
- The debug prints also changed a bit because we now talk in terms of
register units.

This also changes the tracking to use a DenseMap instead of a massive
fixed size table. This trades a bit of access speed for a smaller memory
footprint. Allocating and memsetting a huge table to zero caused a
non-negligible performance impact (I've observed up to 50% of the time
in the pass spent in the `memcpy` built-in on a big test file).

I also think we don't access these often enough to really justify using
a vector. We do a few accesses per instruction, but not much more. In a
huge 120MB LL file, I can barely see the trace of the DenseMap accesses.
2025-12-12 09:41:04 +01:00
Sameer Sahasrabuddhe
130fa98a29
[AMDGPU][NFC] dump Waitcnt using an ostream operator (#171251) 2025-12-10 20:45:49 +05:30
pvanhout
4572f4f5b1 Revert "[AMDGPU][SIInsertWaitCnts] Use RegUnits-based tracking (#162077)"
Fails on https://lab.llvm.org/buildbot/#/builders/123/builds/31922

This reverts commit bf9344099c63549b2f19f8ede29f883669b0baca.
2025-12-09 14:48:19 +01:00
Pierre van Houtryve
bf9344099c
[AMDGPU][SIInsertWaitCnts] Use RegUnits-based tracking (#162077)
The pass was already "reinventing" the concept just to deal with 16 bit
registers. Clean up the entire tracking logic to only use register
units.

There are no test changes because functionality didn't change, except:
- We can now track more LDS DMA IDs if we need it (up to `1 << 16`)
- The debug prints also changed a bit because we now talk in terms of
register units.

This also changes the tracking to use a DenseMap instead of a massive
fixed size table. This trades a bit of access speed for a smaller memory
footprint. Allocating and memsetting a huge table to zero caused a
non-negligible performance impact (I've observed up to 50% of the time
in the pass spent in the `memcpy` built-in on a big test file).

I also think we don't access these often enough to really justify using
a vector. We do a few accesses per instruction, but not much more. In a
huge 120MB LL file, I can barely see the trace of the DenseMap accesses.
2025-12-09 13:51:19 +01:00
Sameer Sahasrabuddhe
8c8196c802 [AMDGPU][NFC] cleanup whitespace in debug log of SIInsertWaitcnts 2025-12-09 07:42:37 +05:30
Sameer Sahasrabuddhe
1e33e12f25 [AMDGPU][NFC] fix function names in debug log for SIInsertWaitcnts 2025-12-09 07:36:31 +05:30
Sameer Sahasrabuddhe
1ae957515c [AMDGPU][NFC] Update a comment about FLAT v/s LDSDMA
The change in #170263 does not do justice to common knowledge in the backend.
Fix the comment to reflect the relation between FLAT encoding, flat pointer
access, and LDSDMA operations.
2025-12-08 20:49:19 +05:30
Pierre van Houtryve
8aa82eff56
[AMDGPU][SIInsertWaitcnts] Wait on all LDS DMA operations when no aliasing store is found (#170660)
Previously, we would miss inserting a wait if the ds_read had AA info,
but it didn't match
any LDS DMA op, for example if we didn't track the LDS DMA op it aliases
with because it exceeded the tracking limit.
2025-12-08 11:02:24 +01:00
Jay Foad
0ecac6d5b9
[AMDGPU] Inherit constructors from WaitcntGenerator. NFC. (#170845) 2025-12-05 13:38:00 +00:00
Jay Foad
64e3bcdd1f [AMDGPU] Add an assertion. NFCI. 2025-12-05 12:55:09 +00:00
Sameer Sahasrabuddhe
cb8ce283e1
[AMDGPU][Waitcnts] Don't create a pending flat event for LDS DMA (#170263)
Flat instructions need a waitcnt(0) on both VMEM and LDS accesses, but
only when the instruction really is using flat addressing. The LDS DMA
instructions (on GFX9) have the FLAT flag set, but they have very clear
semantics. These instructions update only VM_CNT (on GFX9), and hence do
not need to be treated like actual flat instructions.
2025-12-04 17:22:59 +05:30
Pierre van Houtryve
8feb6762ba
[AMDGPU] Take BUF instructions into account in mayAccessScratchThroughFlat (#170274)
BUF instructions can access the scratch address space, so
SIInsertWaitCnt needs to be able
to track the SCRATCH_WRITE_ACCESS event for such BUF instructions.

The release-vgprs.mir test had to be updated because BUF instructions
w/o a MMO are now
tracked as a SCRATCH_WRITE_ACCESS. I added a MMO that touches global to
keep the test result unchanged. I also added a couple of testcases with no MMO to test the corrected behavior.
2025-12-03 10:37:58 +01:00
Ryan Mitchell
5e4505d562
[AMDGPU][SIInsertWaitCnts] Gfx12.5 - Refactor xcnt optimization (#164357)
Refactor the XCnt optimization checks so that they can be checked when
applying a pre-existing waitcnt. This removes unnecessary xcnt waits
when taking a loop backedge.
2025-11-13 18:43:12 +00:00
Jay Foad
5e4f177142
[AMDGPU] Fix missing S_WAIT_XCNT with multiple pending VMEMs (#166779) 2025-11-12 09:44:08 +00:00
Aaditya
c8187f6539
[AMDGPU] Fix Xcnt handling between blocks (#165201)
For blocks with multiple predescessors, there
maybe `SMEM` and `VMEM` events active at the same time.
This patch handles these cases.
2025-11-01 16:48:48 +05:30
Aaditya
982c9e6ac5
[AMDGPU][NFC] Use getScoreUB for XCNT insertion. (#162448) 2025-10-13 11:07:05 +05:30
Aaditya
19cd5bd350
[AMDGPU] Account for implicit XCNT insertion (#160812)
Hardware inserts an implicit `S_WAIT_XCNT 0` between 
alternate SMEM and VMEM instructions, so there are 
never outstanding address translations for both SMEM 
and VMEM at the same time.
2025-10-03 13:38:37 +05:30
Pierre van Houtryve
a3f667bc08
[AMDGPU][SIInsertWaitCnts] Remove redundant TII/TRI/MRI arguments (NFC) (#161357)
WaitCntBrackets already has a pointer to its SIInsertWaitCnt instance.
With a small change, it can directly access TII/TRI/MRI that way.
This simplifies a lot of call sites which make the code easier to
follow.
2025-10-01 12:08:12 +02:00
Pierre van Houtryve
88c668d050
[AMDGPU][SIInsertWaitCnts] De-duplicate code (NFC) (#161161)
I'm reading through the pass over and over again to try and learn how it works. I noticed some code duplication here and there while doing that.
2025-10-01 10:53:32 +02:00
Pierre van Houtryve
14fcd81861
[AMDGPU][InsertWaitCnts] Refactor some helper functions, NFC (#161160)
- Remove one-line wrappers around a simple function call when they're
only used once or twice.
- Move very generic helpers into SIInstrInfo
- Delete unused functions

The goal is simply to reduce the noise in SIInsertWaitCnts without
hiding functionality. I focused on moving trivial helpers, or helpers
with very descriptive/verbose names (so it doesn't hide too much logic
away from the pass), and that have some reusability potential.

I'm also trying to make the code style more consistent. It doesn't make
sense to see a function call `TII->isXXX` then suddenly call a random
`isY` method that just wraps around `TII->isY`.

The context of this work is that I'm trying to learn how this pass
works, and while going through the code I noticed some little things
here and there that I thought would be good to fix.
2025-10-01 10:51:00 +02:00
Jay Foad
8cd917bc80
[AMDGPU] Skip debug uses in SIInsertWaitcnts::shouldFlushVmCnt (#160818) 2025-09-26 08:39:11 +01:00
Petar Avramovic
2ec7959b96
[AMDGPU][SIInsertWaitcnts] Track SCC. Insert KM_CNT waits for SCC writes. (#157843)
Add new event SCC_WRITE for s_barrier_signal_isfirst and s_barrier_leave,
instructions that write to SCC, counter is KM_CNT.
Also start tracking SCC for reads and writes.
s_barrier_wait on the same barrier guarantees that the SCC write from
s_barrier_signal_isfirst has landed, no need to insert s_wait_kmcnt.
2025-09-18 14:41:01 +02:00
Brox Chen
2b2b580c8d
[AMDGPU][CodeGen][True16] Track waitcnt as vgpr32 instead of vgpr16 for D16 Instructions in GFX11 (#157795)
It seems the VMEM access on hi/lo half could interfere the other half.
Track waitcnt of vgpr32 instead of vgpr16 for 16bit reg in GFX11.

---------

Co-authored-by: Joe Nash <joseph.nash@amd.com>
2025-09-17 10:09:06 -04:00
choikwa
ef7de8d144
[AMDGPU] Remove scope check in SIInsertWaitcnts::generateWaitcntInstBefore (#157821)
This change was motivated by CK where many VMCNT(0)'s were generated due
to instructions lacking !alias.scope metadata. The two causes of this
were:
1) LowerLDSModule not tacking on scope metadata on a single LDS variable
2) IPSCCP pass before inliner replacing noalias ptr derivative with a
global value, which made inliner unable to track it back to the noalias
   ptr argument.

However, it turns out that IPSCCP losing the scope information was
largely ineffectual as ScopedNoAliasAA was able to handle asymmetric
condition, where one MemLoc was missing scope, and still return NoAlias
result.

AMDGPU however was checking for existence of scope in SIInsertWaitcnts
and conservatively treating it as aliasing all and inserted VMCNT(0)
before DS_READs, forcing it to wait for all previous LDS DMA
instructions.

Since we know that ScopedNoAliasAA can handle asymmetry, we should also
allow AA query to determine if two MIs may alias.

Passed PSDB.

Previous attempt to address the issue in IPSCCP, likely stalled:
https://github.com/llvm/llvm-project/pull/154522
This solution may be preferrable over that as issue only affects AMDGPU.
2025-09-12 14:51:36 -04:00
Stanislav Mekhanoshin
6aebbb0a85
[AMDGPU] Define 1024 VGPRs on gfx1250 (#156765)
This is a baseline support, it is not useable yet.
2025-09-03 16:25:18 -07:00
Nicolai Hähnle
46762421c3
AMDGPU/GFX12: Do not wait unnecessarily before barriers (#154970)
The barrier intrinsic itself should not have memory semantics. Frontends
should use appropriate fence instructions for memory effects, and some
frontends want to rely on that for performance (e.g. wait only for LDS
before a barrier).

See the code comment for more detail.
2025-08-23 00:07:59 -07:00
Ivan Kosarev
faca8c9ed4
[AMDGPU][NFC] Only include CodeGenPassBuilder.h where needed. (#154769)
Saves around 125-210 MB of compilation memory usage per source for
roughly one third of our backend sources, ~60 MB on average.
2025-08-22 10:05:06 +01:00
Stanislav Mekhanoshin
d0ee82040c
[AMDGPU] Add s_barrier_init|join|leave instructions (#153296) 2025-08-12 15:07:07 -07:00
Sameer Sahasrabuddhe
8f187c74b3
[AMDGPU] introduce S_WAITCNT_LDS_DIRECT in the memory legalizer (#150887)
The new instruction represents the unknown number of waitcnts needed at a
release operation to ensure that prior direct loads to LDS (formerly called LDS
DMA) are completed. The instruction is replaced in SIInsertWaitcnts with a
suitable value for vmcnt().

Co-authored-by: Austin Kerbow <austin.kerbow@amd.com>.
2025-07-30 11:23:28 +05:30
Pierre van Houtryve
2ad4e93ded
[AMDGPU][gfx1250] Use SCOPE_SE for stores that may hit scratch (#150586) 2025-07-28 11:40:56 +02:00
Stanislav Mekhanoshin
9deb7f6062
[AMDGPU] gfx1250 vmem prefetch target intrinsics and builtins (#150466) 2025-07-24 12:13:59 -07:00
Diana Picus
20d8398825
[AMDGPU] ISel & PEI for whole wave functions (#145858)
Whole wave functions are functions that will run with a full EXEC mask.
They will not be invoked directly, but instead will be launched by way
of a new intrinsic, `llvm.amdgcn.call.whole.wave` (to be added in
a future patch). These functions are meant as an alternative to the
`llvm.amdgcn.init.whole.wave` or `llvm.amdgcn.strict.wwm` intrinsics.

Whole wave functions will set EXEC to -1 in the prologue and restore the
original value of EXEC in the epilogue. They must have a special first
argument, `i1 %active`, that is going to be mapped to EXEC. They may
have either the default calling convention or amdgpu_gfx. The inactive
lanes need to be preserved for all registers used, active lanes only for
the CSRs.

At the IR level, arguments to a whole wave function (other than
`%active`) contain poison in their inactive lanes. Likewise, the return
value for the inactive lanes is poison.

This patch contains the following work:
* 2 new pseudos, SI_SETUP_WHOLE_WAVE_FUNC and SI_WHOLE_WAVE_FUNC_RETURN
  used for managing the EXEC mask. SI_SETUP_WHOLE_WAVE_FUNC will return
  a SReg_1 representing `%active`, which needs to be passed into
  SI_WHOLE_WAVE_FUNC_RETURN.
* SelectionDAG support for generating these 2 new pseudos and the
  special handling of %active. Since the return may be in a different
  basic block, it's difficult to add the virtual reg for %active to
  SI_WHOLE_WAVE_FUNC_RETURN, so we initially generate an IMPLICIT_DEF
  which is later replaced via a custom inserter.
* Expansion of the 2 pseudos during prolog/epilog insertion. PEI also
  marks any used VGPRs as WWM registers, which are then spilled and
  restored with the usual logic.

Future patches will include the `llvm.amdgcn.call.whole.wave` intrinsic
and a lot of optimization work (especially in order to reduce spills
around function calls).

---------

Co-authored-by: Matt Arsenault <Matthew.Arsenault@amd.com>
Co-authored-by: Shilei Tian <i@tianshilei.me>
2025-07-21 10:39:09 +02:00
Jay Foad
ab25de7dec
[AMDGPU] Move common fields out of WaitcntBrackets. NFC. (#148864)
WaitcntBrackets holds per-basic-block information about the state of
wait counters. It also held a bunch of fields that are constant
throughout a run of the pass. This patch moves them out into the
SIInsertWaitcnts class, for better logical separation and to save a tiny
bit of memory.
2025-07-17 15:20:24 +01:00
Jay Foad
359dca0dad [AMDGPU] Move class WaitcntBrackets after class SIInsertWaitcnts. NFC.
This is a prerequisite for "[AMDGPU] Move common fields out of WaitcntBrackets. NFC. (#148864)"
2025-07-17 13:58:41 +01:00
Jay Foad
ad715beca1
[AMDGPU] Remove HasSampler variable. NFC. (#146682)
Putting the complex condition in a variable does not help readability.
It is simpler to use separate `if`s.
2025-07-02 15:44:32 +01:00
Jay Foad
2b03efc7fb
[AMDGPU] Use isImage. NFC. (#146677) 2025-07-02 14:18:42 +01:00
Sameer Sahasrabuddhe
a34a024812
[AMDGPU][SIInsertWaitCnts] skip meta instructions early (#145720)
When iterating over a block, meta instructions have no effect on wait counts,
but their presence drops the reference to earlier waitcnt instructions before
they are processed. This results in spurious wait counts, which do not affect
correctness, but are also not required in the resulting program. Skipping meta
instructions as soon as they are seen cleans this up.
2025-07-01 22:02:48 +05:30
Sameer Sahasrabuddhe
67302b2e6f
[AMDGPU][NFC] rename some constants for readability (#145870) 2025-06-26 20:00:26 +05:30
Jay Foad
b6b08117bd
[AMDGPU] Simplify S_WAIT_XCNT insertion. NFC. (#145682) 2025-06-25 20:56:41 +01:00
Sameer Sahasrabuddhe
81e07996aa
[AMDGPU][SIInsertWaitcnts] don't crash when printing messages at end of block (#145694) 2025-06-25 20:59:55 +05:30
Christudasan Devadasan
08b8d467d4
[AMDGPU][GFX1250] Insert S_WAIT_XCNT for SMEM and VMEM load-stores (#145566)
This patch tracks the register operands of both VMEM (FLAT, MUBUF,
MTBUF) and SMEM load-store operations and inserts a S_WAIT_XCNT
instruction with sufficient wait-count before potentially redefining
them. For VMEM instructions, XNACK is returned in the same order as
they were issued and hence non-zero counter values can be inserted.
However, SMEM execution is out-of-order and so is their XNACK reception.
Thus, only zero counter value can be inserted to capture SMEM dependencies.
2025-06-25 10:40:36 +05:30
Diana Picus
a201f8872a
[AMDGPU] Replace dynamic VGPR feature with attribute (#133444)
Use a function attribute (amdgpu-dynamic-vgpr) instead of a subtarget
feature, as requested in #130030.
2025-06-24 11:09:36 +02:00
Stanislav Mekhanoshin
0c2191b3a7
[AMDGPU] Omit image waits in function prologue on gfx1250 (#145097) 2025-06-20 14:11:29 -07:00
Sameer Sahasrabuddhe
62fe5e428a
[NFC][AMDGPU] print more info when debugging SIInsertWaitcnts pass (#144629) 2025-06-19 13:47:37 +05:30
Carl Ritson
34b6285735
[AMDGPU] Treat image_msaa_load as a sampler operation (#141726)
While image_msaa_load does not take a sampler, it can behave as if it
does on some hardware. This has implications for wait counting and
clausing.
2025-05-28 19:56:05 +09:00
Kazu Hirata
cc78177e8f
[llvm] Use *Map::try_emplace (NFC) (#141190)
try_emplace can default-construct values, so we do not need to do so
on our own.  Plus, try_emplace(Key) is much simpler/shorter than
insert({Key, LongValueType()}).
2025-05-22 23:50:58 -07:00
Robert Imschweiler
e55172f139
[AMDGPU] Classify FLAT instructions as VMEM (#137148)
Also adapt hazard and wait handling.
2025-05-07 09:20:52 +02:00