aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
diff options
context:
space:
mode:
authorPierre van Houtryve <pierre.vanhoutryve@amd.com>2025-09-04 11:19:25 +0200
committerGitHub <noreply@github.com>2025-09-04 09:19:25 +0000
commite2bd10cf16c3f90813de5b64f348ece035a6bb68 (patch)
tree4f0098f72aea9bda0fbca8672101ee6b702d86d2 /llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
parent3ec7b895be67f0d74613d35aa5aa1580a436aa05 (diff)
downloadllvm-e2bd10cf16c3f90813de5b64f348ece035a6bb68.zip
llvm-e2bd10cf16c3f90813de5b64f348ece035a6bb68.tar.gz
llvm-e2bd10cf16c3f90813de5b64f348ece035a6bb68.tar.bz2
[AMDGPU][gfx1250] Add 128B cooperative atomics (#156418)
- Add clang built-ins + sema/codegen - Add IR Intrinsic + verifier - Add DAG/GlobalISel codegen for the intrinsics - Add lowering in SIMemoryLegalizer using a MMO flag.
Diffstat (limited to 'llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp')
-rw-r--r--llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp44
1 files changed, 41 insertions, 3 deletions
diff --git a/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp b/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
index 3006eaf..6ab4eb4 100644
--- a/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
+++ b/llvm/lib/Target/AMDGPU/SIMemoryLegalizer.cpp
@@ -103,6 +103,7 @@ private:
bool IsVolatile = false;
bool IsNonTemporal = false;
bool IsLastUse = false;
+ bool IsCooperative = false;
SIMemOpInfo(
AtomicOrdering Ordering = AtomicOrdering::SequentiallyConsistent,
@@ -112,14 +113,15 @@ private:
bool IsCrossAddressSpaceOrdering = true,
AtomicOrdering FailureOrdering = AtomicOrdering::SequentiallyConsistent,
bool IsVolatile = false, bool IsNonTemporal = false,
- bool IsLastUse = false)
+ bool IsLastUse = false, bool IsCooperative = false)
: Ordering(Ordering), FailureOrdering(FailureOrdering), Scope(Scope),
OrderingAddrSpace(OrderingAddrSpace), InstrAddrSpace(InstrAddrSpace),
IsCrossAddressSpaceOrdering(IsCrossAddressSpaceOrdering),
IsVolatile(IsVolatile), IsNonTemporal(IsNonTemporal),
- IsLastUse(IsLastUse) {
+ IsLastUse(IsLastUse), IsCooperative(IsCooperative) {
if (Ordering == AtomicOrdering::NotAtomic) {
+ assert(!IsCooperative && "Cannot be cooperative & non-atomic!");
assert(Scope == SIAtomicScope::NONE &&
OrderingAddrSpace == SIAtomicAddrSpace::NONE &&
!IsCrossAddressSpaceOrdering &&
@@ -209,6 +211,9 @@ public:
/// create this SIMemOpInfo is last use, false otherwise.
bool isLastUse() const { return IsLastUse; }
+ /// \returns True if this is a cooperative load or store atomic.
+ bool isCooperative() const { return IsCooperative; }
+
/// \returns True if ordering constraint of the machine instruction used to
/// create this SIMemOpInfo is unordered or higher, false otherwise.
bool isAtomic() const {
@@ -325,6 +330,12 @@ public:
return false;
};
+ /// Handle cooperative load/store atomics.
+ virtual bool handleCooperativeAtomic(MachineInstr &MI) const {
+ llvm_unreachable(
+ "cooperative atomics are not available on this architecture");
+ }
+
/// Inserts any necessary instructions at position \p Pos relative
/// to instruction \p MI to ensure memory instructions before \p Pos of kind
/// \p Op associated with address spaces \p AddrSpace have completed. Used
@@ -612,6 +623,8 @@ public:
bool finalizeStore(MachineInstr &MI, bool Atomic) const override;
+ virtual bool handleCooperativeAtomic(MachineInstr &MI) const override;
+
bool insertRelease(MachineBasicBlock::iterator &MI, SIAtomicScope Scope,
SIAtomicAddrSpace AddrSpace, bool IsCrossAddrSpaceOrdering,
Position Pos) const override;
@@ -812,6 +825,7 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
bool IsNonTemporal = true;
bool IsVolatile = false;
bool IsLastUse = false;
+ bool IsCooperative = false;
// Validator should check whether or not MMOs cover the entire set of
// locations accessed by the memory instruction.
@@ -819,6 +833,7 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
IsNonTemporal &= MMO->isNonTemporal();
IsVolatile |= MMO->isVolatile();
IsLastUse |= MMO->getFlags() & MOLastUse;
+ IsCooperative |= MMO->getFlags() & MOCooperative;
InstrAddrSpace |=
toSIAtomicAddrSpace(MMO->getPointerInfo().getAddrSpace());
AtomicOrdering OpOrdering = MMO->getSuccessOrdering();
@@ -860,7 +875,7 @@ std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
}
return SIMemOpInfo(Ordering, Scope, OrderingAddrSpace, InstrAddrSpace,
IsCrossAddressSpaceOrdering, FailureOrdering, IsVolatile,
- IsNonTemporal, IsLastUse);
+ IsNonTemporal, IsLastUse, IsCooperative);
}
std::optional<SIMemOpInfo>
@@ -2615,6 +2630,19 @@ bool SIGfx12CacheControl::finalizeStore(MachineInstr &MI, bool Atomic) const {
return false;
}
+bool SIGfx12CacheControl::handleCooperativeAtomic(MachineInstr &MI) const {
+ if (!ST.hasGFX1250Insts())
+ return false;
+
+ // Cooperative atomics need to be SCOPE_DEV or higher.
+ MachineOperand *CPol = TII->getNamedOperand(MI, OpName::cpol);
+ assert(CPol && "No CPol operand?");
+ const unsigned Scope = CPol->getImm() & CPol::SCOPE;
+ if (Scope < CPol::SCOPE_DEV)
+ return setScope(MI, CPol::SCOPE_DEV);
+ return false;
+}
+
bool SIGfx12CacheControl::setAtomicScope(const MachineBasicBlock::iterator &MI,
SIAtomicScope Scope,
SIAtomicAddrSpace AddrSpace) const {
@@ -2679,6 +2707,11 @@ bool SIMemoryLegalizer::expandLoad(const SIMemOpInfo &MOI,
MOI.getOrderingAddrSpace());
}
+ // Handle cooperative atomics after cache bypass step, as it may override
+ // the scope of the instruction to a greater scope.
+ if (MOI.isCooperative())
+ Changed |= CC->handleCooperativeAtomic(*MI);
+
if (Order == AtomicOrdering::SequentiallyConsistent)
Changed |= CC->insertWait(MI, MOI.getScope(), MOI.getOrderingAddrSpace(),
SIMemOp::LOAD | SIMemOp::STORE,
@@ -2724,6 +2757,11 @@ bool SIMemoryLegalizer::expandStore(const SIMemOpInfo &MOI,
MOI.getOrderingAddrSpace());
}
+ // Handle cooperative atomics after cache bypass step, as it may override
+ // the scope of the instruction to a greater scope.
+ if (MOI.isCooperative())
+ Changed |= CC->handleCooperativeAtomic(*MI);
+
if (MOI.getOrdering() == AtomicOrdering::Release ||
MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent)
Changed |= CC->insertRelease(MI, MOI.getScope(),