35#define DEBUG_TYPE "si-memory-legalizer"
36#define PASS_NAME "SI Memory Legalizer"
58enum class SIAtomicScope {
70enum class SIAtomicAddrSpace {
82 ATOMIC = GLOBAL |
LDS | SCRATCH | GDS,
85 ALL = GLOBAL |
LDS | SCRATCH | GDS | OTHER,
93 case SIAtomicScope::NONE:
95 case SIAtomicScope::SINGLETHREAD:
96 return "singlethread";
97 case SIAtomicScope::WAVEFRONT:
99 case SIAtomicScope::WORKGROUP:
101 case SIAtomicScope::CLUSTER:
103 case SIAtomicScope::AGENT:
105 case SIAtomicScope::SYSTEM:
117 if (any(AS & SIAtomicAddrSpace::GLOBAL))
118 OS << LS <<
"global";
119 if (any(AS & SIAtomicAddrSpace::LDS))
121 if (any(AS & SIAtomicAddrSpace::SCRATCH))
122 OS << LS <<
"scratch";
123 if (any(AS & SIAtomicAddrSpace::GDS))
125 if (any(AS & SIAtomicAddrSpace::OTHER))
131class SIMemOpInfo final {
134 friend class SIMemOpAccess;
138 SIAtomicScope Scope = SIAtomicScope::SYSTEM;
139 SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::NONE;
140 SIAtomicAddrSpace InstrAddrSpace = SIAtomicAddrSpace::NONE;
141 bool IsCrossAddressSpaceOrdering =
false;
142 bool IsVolatile =
false;
143 bool IsNonTemporal =
false;
144 bool IsLastUse =
false;
145 bool IsCooperative =
false;
146 bool IsAVNone =
false;
147 unsigned CFSBits = 0;
153 SIAtomicScope Scope = SIAtomicScope::SYSTEM,
154 SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::ATOMIC,
155 SIAtomicAddrSpace InstrAddrSpace = SIAtomicAddrSpace::ALL,
156 bool IsCrossAddressSpaceOrdering =
true,
158 bool IsVolatile =
false,
bool IsNonTemporal =
false,
159 bool IsLastUse =
false,
bool IsCooperative =
false,
bool IsAVNone =
false,
160 bool CanDemoteWorkgroupToWavefront =
false,
unsigned CFSBits = 0)
161 : Ordering(Ordering), FailureOrdering(FailureOrdering), Scope(Scope),
162 OrderingAddrSpace(OrderingAddrSpace), InstrAddrSpace(InstrAddrSpace),
163 IsCrossAddressSpaceOrdering(IsCrossAddressSpaceOrdering),
164 IsVolatile(IsVolatile), IsNonTemporal(IsNonTemporal),
165 IsLastUse(IsLastUse), IsCooperative(IsCooperative), IsAVNone(IsAVNone),
169 assert(!IsCooperative &&
"Cannot be cooperative & non-atomic!");
170 assert(Scope == SIAtomicScope::NONE && !any(OrderingAddrSpace) &&
171 !IsCrossAddressSpaceOrdering &&
176 assert(Scope != SIAtomicScope::NONE &&
177 any(OrderingAddrSpace & SIAtomicAddrSpace::ATOMIC) &&
178 any(InstrAddrSpace & SIAtomicAddrSpace::ATOMIC));
183 if ((OrderingAddrSpace == InstrAddrSpace) &&
185 this->IsCrossAddressSpaceOrdering =
false;
189 if (!(InstrAddrSpace & ~SIAtomicAddrSpace::SCRATCH)) {
190 this->Scope = std::min(Scope, SIAtomicScope::SINGLETHREAD);
191 }
else if (!(InstrAddrSpace &
192 ~(SIAtomicAddrSpace::SCRATCH | SIAtomicAddrSpace::LDS))) {
193 this->Scope = std::min(Scope, SIAtomicScope::WORKGROUP);
194 }
else if (!(InstrAddrSpace &
195 ~(SIAtomicAddrSpace::SCRATCH | SIAtomicAddrSpace::LDS |
196 SIAtomicAddrSpace::GDS))) {
197 this->Scope = std::min(Scope, SIAtomicScope::AGENT);
202 if (this->Scope == SIAtomicScope::CLUSTER && !ST.hasClusters())
203 this->Scope = SIAtomicScope::AGENT;
205 if (CanDemoteWorkgroupToWavefront &&
206 this->Scope == SIAtomicScope::WORKGROUP)
207 this->Scope = SIAtomicScope::WAVEFRONT;
226 return FailureOrdering;
231 SIAtomicAddrSpace getInstrAddrSpace()
const {
232 return InstrAddrSpace;
237 SIAtomicAddrSpace getOrderingAddrSpace()
const {
238 return OrderingAddrSpace;
243 bool getIsCrossAddressSpaceOrdering()
const {
244 return IsCrossAddressSpaceOrdering;
249 bool isVolatile()
const {
255 bool isNonTemporal()
const {
256 return IsNonTemporal;
261 bool isLastUse()
const {
return IsLastUse; }
264 bool isCooperative()
const {
return IsCooperative; }
267 bool isAVNone()
const {
return IsAVNone; }
276 unsigned getCFS()
const {
return CFSBits; }
279class SIMemOpAccess final {
283 const bool CanDemoteWorkgroupToWavefront;
287 const char *
Msg)
const;
293 std::optional<std::tuple<SIAtomicScope, SIAtomicAddrSpace, bool>>
294 toSIAtomicScope(
SyncScope::ID SSID, SIAtomicAddrSpace InstrAddrSpace)
const;
297 SIAtomicAddrSpace toSIAtomicAddrSpace(
unsigned AS)
const;
301 std::optional<SIMemOpInfo>
311 std::optional<SIMemOpInfo>
316 std::optional<SIMemOpInfo>
321 std::optional<SIMemOpInfo>
326 std::optional<SIMemOpInfo>
332 std::optional<SIMemOpInfo>
336class SICacheControl {
358 unsigned Bits)
const;
362 bool canAffectGlobalAddrSpace(SIAtomicAddrSpace AS)
const;
368 static std::unique_ptr<SICacheControl> create(
const GCNSubtarget &ST,
376 SIAtomicAddrSpace AddrSpace)
const = 0;
383 SIAtomicAddrSpace AddrSpace)
const = 0;
390 SIAtomicAddrSpace AddrSpace)
const = 0;
396 SIAtomicAddrSpace AddrSpace,
397 SIMemOp
Op,
bool IsVolatile,
399 bool IsLastUse =
false)
const = 0;
418 "cooperative atomics are not available on this architecture");
431 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
432 bool IsCrossAddrSpaceOrdering, Position Pos,
442 SIAtomicAddrSpace AddrSpace,
443 Position Pos)
const = 0;
451 SIAtomicScope Scope, SIAtomicAddrSpace AddrSpace,
452 Position Pos)
const = 0;
456 SIAtomicAddrSpace AddrSpace,
bool IsCrossAddrSpaceOrdering,
457 Position Pos,
bool IsAVNone)
const {
458 bool Changed = !IsAVNone && insertWriteback(
MI, Scope, AddrSpace, Pos);
459 Changed |= insertWait(
MI, Scope, AddrSpace, SIMemOp::LOAD | SIMemOp::STORE,
460 IsCrossAddrSpaceOrdering, Pos,
467 virtual bool handleNonVolatile(
MachineInstr &
MI)
const {
return false; }
470 unsigned CFSBits = 0)
const {
475 virtual ~SICacheControl() =
default;
480class SIGfx6CacheControl final :
public SICacheControl {
482 SIGfx6CacheControl(
const GCNSubtarget &ST,
bool TgSplit)
483 : SICacheControl(ST, TgSplit) {}
487 SIAtomicAddrSpace AddrSpace)
const override;
491 SIAtomicAddrSpace AddrSpace)
const override;
495 SIAtomicAddrSpace AddrSpace)
const override;
498 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
499 bool IsVolatile,
bool IsNonTemporal,
500 bool IsLastUse)
const override;
503 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
504 bool IsCrossAddrSpaceOrdering, Position Pos,
509 SIAtomicAddrSpace AddrSpace,
510 Position Pos)
const override;
513 SIAtomicAddrSpace AddrSpace,
514 Position Pos)
const override;
518class SIGfx10CacheControl final :
public SICacheControl {
520 SIGfx10CacheControl(
const GCNSubtarget &ST,
bool TgSplit)
521 : SICacheControl(ST, TgSplit) {}
525 SIAtomicAddrSpace AddrSpace)
const override;
529 SIAtomicAddrSpace AddrSpace)
const override {
535 SIAtomicAddrSpace AddrSpace)
const override {
540 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
541 bool IsVolatile,
bool IsNonTemporal,
542 bool IsLastUse)
const override;
545 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
546 bool IsCrossAddrSpaceOrdering, Position Pos,
550 SIAtomicAddrSpace AddrSpace, Position Pos)
const override;
553 SIAtomicAddrSpace AddrSpace,
554 Position Pos)
const override {
559class SIGfx12CacheControl final :
public SICacheControl {
581 SIAtomicScope Scope, SIAtomicAddrSpace AddrSpace)
const;
584 SIGfx12CacheControl(
const GCNSubtarget &ST,
bool TgSplit)
585 : SICacheControl(ST, TgSplit) {
588 assert(!ST.hasGFX1250Insts() || ST.hasGFX13Insts() || ST.isCuModeEnabled());
592 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
593 bool IsCrossAddrSpaceOrdering, Position Pos,
597 SIAtomicAddrSpace AddrSpace, Position Pos)
const override;
600 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
601 bool IsVolatile,
bool IsNonTemporal,
602 bool IsLastUse)
const override;
611 SIAtomicAddrSpace AddrSpace,
612 Position Pos)
const override;
616 SIAtomicAddrSpace AddrSpace)
const override {
617 return setAtomicScope(
MI, Scope, AddrSpace);
622 SIAtomicAddrSpace AddrSpace)
const override {
623 return setAtomicScope(
MI, Scope, AddrSpace);
628 SIAtomicAddrSpace AddrSpace)
const override {
629 return setAtomicScope(
MI, Scope, AddrSpace);
635 unsigned CFSBits)
const override;
638class SIMemoryLegalizer final {
642 std::unique_ptr<SICacheControl>
CC =
nullptr;
645 std::list<MachineBasicBlock::iterator> AtomicPseudoMIs;
655 bool removeAtomicPseudoMIs();
659 bool expandLoad(
const SIMemOpInfo &MOI,
663 bool expandStore(
const SIMemOpInfo &MOI,
667 bool expandAtomicFence(
const SIMemOpInfo &MOI,
671 bool expandAtomicCmpxchgOrRmw(
const SIMemOpInfo &MOI,
701 {
"global", SIAtomicAddrSpace::GLOBAL},
702 {
"local", SIAtomicAddrSpace::LDS},
710 OS <<
"unknown address space '" << AS <<
"'; expected one of ";
712 for (
const auto &[Name, Val] : ASNames)
713 OS << LS <<
'\'' << Name <<
'\'';
721static std::optional<SIAtomicAddrSpace>
723 static constexpr StringLiteral FenceASPrefix =
"amdgpu-synchronize-as";
729 SIAtomicAddrSpace Result = SIAtomicAddrSpace::NONE;
730 for (
const auto &[Prefix, Suffix] : MMRA) {
731 if (Prefix != FenceASPrefix)
734 if (
auto It = ASNames.
find(Suffix); It != ASNames.
end())
735 Result |= It->second;
737 diagnoseUnknownMMRAASName(
MI, Suffix);
751 Fn,
Twine(
"unknown amdgcn-av metadata '") + Suffix +
Twine(
'\''),
759 bool TagFound =
false;
760 for (
const auto &[Prefix, Suffix] : MMRA) {
761 if (Prefix !=
"amdgcn-av")
763 if (Suffix ==
"none")
766 diagnoseUnknownAVMetadata(
MI, Suffix);
774 const char *
Msg)
const {
776 Func.getContext().diagnose(
777 DiagnosticInfoUnsupported(Func,
Msg,
MI->getDebugLoc()));
780std::optional<std::tuple<SIAtomicScope, SIAtomicAddrSpace, bool>>
782 SIAtomicAddrSpace InstrAddrSpace)
const {
784 return std::tuple(SIAtomicScope::SYSTEM, SIAtomicAddrSpace::ATOMIC,
true);
786 return std::tuple(SIAtomicScope::AGENT, SIAtomicAddrSpace::ATOMIC,
true);
788 return std::tuple(SIAtomicScope::CLUSTER, SIAtomicAddrSpace::ATOMIC,
true);
790 return std::tuple(SIAtomicScope::WORKGROUP, SIAtomicAddrSpace::ATOMIC,
793 return std::tuple(SIAtomicScope::WAVEFRONT, SIAtomicAddrSpace::ATOMIC,
796 return std::tuple(SIAtomicScope::SINGLETHREAD, SIAtomicAddrSpace::ATOMIC,
799 return std::tuple(SIAtomicScope::SYSTEM,
800 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
802 return std::tuple(SIAtomicScope::AGENT,
803 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
805 return std::tuple(SIAtomicScope::CLUSTER,
806 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
808 return std::tuple(SIAtomicScope::WORKGROUP,
809 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
811 return std::tuple(SIAtomicScope::WAVEFRONT,
812 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
814 return std::tuple(SIAtomicScope::SINGLETHREAD,
815 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
819SIAtomicAddrSpace SIMemOpAccess::toSIAtomicAddrSpace(
unsigned AS)
const {
821 return SIAtomicAddrSpace::FLAT;
823 return SIAtomicAddrSpace::GLOBAL;
825 return SIAtomicAddrSpace::LDS;
827 return SIAtomicAddrSpace::SCRATCH;
829 return SIAtomicAddrSpace::GDS;
832 return SIAtomicAddrSpace::GLOBAL;
834 return SIAtomicAddrSpace::OTHER;
840SIMemOpAccess::SIMemOpAccess(
const AMDGPUMachineModuleInfo &MMI_,
842 : MMI(&MMI_),
ST(
ST),
843 CanDemoteWorkgroupToWavefront(
845 MF.
getFunction().hasFnAttribute(
"amdgpu-no-lds-dma")) {}
847std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
849 assert(
MI->getNumMemOperands() > 0);
851 std::optional<SyncScope::ID> MergedSSID;
854 SIAtomicAddrSpace InstrAddrSpace = SIAtomicAddrSpace::NONE;
855 bool IsNonTemporal =
true;
857 bool IsLastUse =
false;
858 bool IsCooperative =
false;
859 unsigned CFSBits = 0;
863 for (
const auto &MMO :
MI->memoperands()) {
864 IsNonTemporal &= MMO->isNonTemporal();
866 IsLastUse |= MMO->getFlags() &
MOLastUse;
869 InstrAddrSpace |= toSIAtomicAddrSpace(MMO->getPointerInfo().getAddrSpace());
871 if (OpOrdering != AtomicOrdering::NotAtomic) {
874 SyncScope::ID CurSSID = MergedSSID.value_or(MMO->getSyncScopeID());
881 MergedSSID = *Merged;
883 assert(MMO->getFailureOrdering() != AtomicOrdering::Release &&
884 MMO->getFailureOrdering() != AtomicOrdering::AcquireRelease);
896 Ordering = AtomicOrdering::Monotonic;
898 SIAtomicScope
Scope = SIAtomicScope::NONE;
899 SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::NONE;
900 bool IsCrossAddressSpaceOrdering =
false;
901 if (Ordering != AtomicOrdering::NotAtomic) {
902 auto ScopeOrNone = toSIAtomicScope(SSID, InstrAddrSpace);
907 std::tie(Scope, OrderingAddrSpace, IsCrossAddressSpaceOrdering) =
909 if (!OrderingAddrSpace ||
910 ((OrderingAddrSpace & SIAtomicAddrSpace::ATOMIC) !=
911 OrderingAddrSpace) ||
912 !(InstrAddrSpace & SIAtomicAddrSpace::ATOMIC)) {
917 return SIMemOpInfo(ST, Ordering, Scope, OrderingAddrSpace, InstrAddrSpace,
918 IsCrossAddressSpaceOrdering, FailureOrdering, IsVolatile,
919 IsNonTemporal, IsLastUse, IsCooperative,
920 hasAVNoneMMRA(*
MI), CanDemoteWorkgroupToWavefront,
924std::optional<SIMemOpInfo>
928 if (!(
MI->mayLoad() && !
MI->mayStore()))
932 if (
MI->getNumMemOperands() == 0)
933 return SIMemOpInfo(ST);
935 return constructFromMIWithMMO(
MI);
938std::optional<SIMemOpInfo>
942 if (!(!
MI->mayLoad() &&
MI->mayStore()))
946 if (
MI->getNumMemOperands() == 0)
947 return SIMemOpInfo(ST);
949 return constructFromMIWithMMO(
MI);
952std::optional<SIMemOpInfo>
956 if (
MI->getOpcode() != AMDGPU::ATOMIC_FENCE)
963 auto ScopeOrNone = toSIAtomicScope(SSID, SIAtomicAddrSpace::ATOMIC);
969 SIAtomicScope
Scope = SIAtomicScope::NONE;
970 SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::NONE;
971 bool IsCrossAddressSpaceOrdering =
false;
972 std::tie(Scope, OrderingAddrSpace, IsCrossAddressSpaceOrdering) =
975 if (OrderingAddrSpace != SIAtomicAddrSpace::ATOMIC) {
984 auto SynchronizeAS = getSynchronizeAddrSpaceMD(*
MI);
986 OrderingAddrSpace = *SynchronizeAS;
988 return SIMemOpInfo(ST, Ordering, Scope, OrderingAddrSpace,
989 SIAtomicAddrSpace::ATOMIC, IsCrossAddressSpaceOrdering,
990 AtomicOrdering::NotAtomic,
false,
false,
false,
false,
991 hasAVNoneMMRA(*
MI), CanDemoteWorkgroupToWavefront);
994std::optional<SIMemOpInfo> SIMemOpAccess::getAtomicCmpxchgOrRmwInfo(
998 if (!(
MI->mayLoad() &&
MI->mayStore()))
1002 if (
MI->getNumMemOperands() == 0)
1003 return SIMemOpInfo(ST);
1005 return constructFromMIWithMMO(
MI);
1008std::optional<SIMemOpInfo>
1013 return std::nullopt;
1015 return constructFromMIWithMMO(
MI);
1023 if (
MI.getNumMemOperands() == 0)
1026 return MMO->getFlags() & (MOThreadPrivate | MachineMemOperand::MOInvariant);
1030SICacheControl::SICacheControl(
const GCNSubtarget &ST,
bool TgSplit) :
ST(
ST) {
1031 TII =
ST.getInstrInfo();
1033 InsertCacheInv = !
ST.getCLOpts().skip_cache_invalidations;
1034 TgSplitEnabled = TgSplit;
1038 unsigned Bits)
const {
1039 MachineOperand *CPol =
TII->getNamedOperand(*
MI, AMDGPU::OpName::cpol);
1043 CPol->setImm(
CPol->getImm() | Bits);
1047bool SICacheControl::canAffectGlobalAddrSpace(SIAtomicAddrSpace AS)
const {
1048 assert((!
ST.hasGloballyAddressableScratch() ||
1049 any(AS & SIAtomicAddrSpace::GLOBAL) ||
1050 !(AS & SIAtomicAddrSpace::SCRATCH)) &&
1051 "scratch instructions should already be replaced by flat "
1052 "instructions if GloballyAddressableScratch is enabled");
1053 return any(AS & SIAtomicAddrSpace::GLOBAL);
1057std::unique_ptr<SICacheControl> SICacheControl::create(
const GCNSubtarget &ST,
1059 GCNSubtarget::Generation Generation =
ST.getGeneration();
1060 if (Generation < AMDGPUSubtarget::GFX10)
1061 return std::make_unique<SIGfx6CacheControl>(ST, TgSplit);
1062 if (Generation < AMDGPUSubtarget::GFX12)
1063 return std::make_unique<SIGfx10CacheControl>(ST, TgSplit);
1064 return std::make_unique<SIGfx12CacheControl>(ST, TgSplit);
1067bool SIGfx6CacheControl::enableLoadCacheBypass(
1069 SIAtomicScope Scope,
1070 SIAtomicAddrSpace AddrSpace)
const {
1073 if (!canAffectGlobalAddrSpace(AddrSpace)) {
1085 case SIAtomicScope::SYSTEM:
1086 if (
ST.hasGFX940Insts()) {
1092 case SIAtomicScope::AGENT:
1093 if (
ST.hasGFX940Insts()) {
1102 case SIAtomicScope::WORKGROUP:
1103 if (
ST.hasGFX940Insts()) {
1110 }
else if (
ST.hasGFX90AInsts()) {
1119 case SIAtomicScope::WAVEFRONT:
1120 case SIAtomicScope::SINGLETHREAD:
1130bool SIGfx6CacheControl::enableStoreCacheBypass(
1132 SIAtomicScope Scope,
1133 SIAtomicAddrSpace AddrSpace)
const {
1141 if (
ST.hasGFX940Insts() && canAffectGlobalAddrSpace(AddrSpace)) {
1143 case SIAtomicScope::SYSTEM:
1147 case SIAtomicScope::AGENT:
1151 case SIAtomicScope::WORKGROUP:
1155 case SIAtomicScope::WAVEFRONT:
1156 case SIAtomicScope::SINGLETHREAD:
1174bool SIGfx6CacheControl::enableRMWCacheBypass(
1176 SIAtomicScope Scope,
1177 SIAtomicAddrSpace AddrSpace)
const {
1187 if (
ST.hasGFX940Insts() && canAffectGlobalAddrSpace(AddrSpace)) {
1189 case SIAtomicScope::SYSTEM:
1193 case SIAtomicScope::AGENT:
1194 case SIAtomicScope::WORKGROUP:
1195 case SIAtomicScope::WAVEFRONT:
1196 case SIAtomicScope::SINGLETHREAD:
1210bool SIGfx6CacheControl::enableVolatileAndOrNonTemporal(
1212 bool IsVolatile,
bool IsNonTemporal,
bool IsLastUse =
false)
const {
1222 assert(
Op == SIMemOp::LOAD ||
Op == SIMemOp::STORE);
1227 if (
ST.hasGFX940Insts()) {
1230 }
else if (
Op == SIMemOp::LOAD) {
1242 Changed |= insertWait(
MI, SIAtomicScope::SYSTEM, AddrSpace,
Op,
false,
1243 Position::AFTER, AtomicOrdering::Unordered,
1249 if (IsNonTemporal) {
1250 if (
ST.hasGFX940Insts()) {
1264 SIAtomicScope Scope,
1265 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
1266 bool IsCrossAddrSpaceOrdering, Position Pos,
1268 bool AtomicsOnly)
const {
1274 if (Pos == Position::AFTER)
1278 if (
ST.hasGFX90AInsts() && TgSplitEnabled) {
1287 (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH |
1288 SIAtomicAddrSpace::GDS)) &&
1289 (Scope == SIAtomicScope::WORKGROUP)) {
1291 Scope = SIAtomicScope::AGENT;
1295 AddrSpace &= ~SIAtomicAddrSpace
::LDS;
1299 bool LGKMCnt =
false;
1302 (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH))) {
1304 case SIAtomicScope::SYSTEM:
1305 case SIAtomicScope::AGENT:
1308 case SIAtomicScope::WORKGROUP:
1309 case SIAtomicScope::WAVEFRONT:
1310 case SIAtomicScope::SINGLETHREAD:
1319 if (
any(AddrSpace & SIAtomicAddrSpace::LDS)) {
1321 case SIAtomicScope::SYSTEM:
1322 case SIAtomicScope::AGENT:
1323 case SIAtomicScope::WORKGROUP:
1330 LGKMCnt |= IsCrossAddrSpaceOrdering;
1332 case SIAtomicScope::WAVEFRONT:
1333 case SIAtomicScope::SINGLETHREAD:
1342 if (
any(AddrSpace & SIAtomicAddrSpace::GDS)) {
1344 case SIAtomicScope::SYSTEM:
1345 case SIAtomicScope::AGENT:
1352 LGKMCnt |= IsCrossAddrSpaceOrdering;
1354 case SIAtomicScope::WORKGROUP:
1355 case SIAtomicScope::WAVEFRONT:
1356 case SIAtomicScope::SINGLETHREAD:
1365 if (VMCnt || LGKMCnt) {
1366 unsigned WaitCntImmediate =
1372 .
addImm(WaitCntImmediate);
1380 Scope == SIAtomicScope::WORKGROUP &&
1381 any(AddrSpace & SIAtomicAddrSpace::LDS)) {
1386 if (Pos == Position::AFTER)
1395 return !ST.isAmdPalOS() && !ST.isMesa3DOS();
1399 SIAtomicScope Scope,
1400 SIAtomicAddrSpace AddrSpace,
1401 Position Pos)
const {
1402 if (!InsertCacheInv)
1410 if (Pos == Position::AFTER)
1414 ? AMDGPU::BUFFER_WBINVL1_VOL
1415 : AMDGPU::BUFFER_WBINVL1;
1417 if (canAffectGlobalAddrSpace(AddrSpace)) {
1419 case SIAtomicScope::SYSTEM:
1420 if (
ST.hasBufferInvInst()) {
1436 if (
ST.hasGFX90AInsts()) {
1451 case SIAtomicScope::AGENT:
1452 if (
ST.hasBufferInvInst()) {
1467 case SIAtomicScope::WORKGROUP:
1468 if (TgSplitEnabled) {
1469 if (
ST.hasBufferInvInst()) {
1488 }
else if (
ST.hasGFX90AInsts()) {
1494 case SIAtomicScope::WAVEFRONT:
1495 case SIAtomicScope::SINGLETHREAD:
1512 if (Pos == Position::AFTER)
1519 SIAtomicScope Scope,
1520 SIAtomicAddrSpace AddrSpace,
1521 Position Pos)
const {
1522 if (!
ST.hasGFX90AInsts())
1529 if (Pos == Position::AFTER)
1532 if (canAffectGlobalAddrSpace(AddrSpace)) {
1534 case SIAtomicScope::SYSTEM:
1546 case SIAtomicScope::AGENT:
1547 if (
ST.hasGFX940Insts()) {
1554 case SIAtomicScope::WORKGROUP:
1555 case SIAtomicScope::WAVEFRONT:
1556 case SIAtomicScope::SINGLETHREAD:
1566 if (Pos == Position::AFTER)
1572bool SIGfx10CacheControl::enableLoadCacheBypass(
1574 SIAtomicAddrSpace AddrSpace)
const {
1578 if (canAffectGlobalAddrSpace(AddrSpace)) {
1580 case SIAtomicScope::SYSTEM:
1581 case SIAtomicScope::AGENT:
1588 case SIAtomicScope::WORKGROUP:
1593 if (!
ST.isCuModeEnabled())
1596 case SIAtomicScope::WAVEFRONT:
1597 case SIAtomicScope::SINGLETHREAD:
1615bool SIGfx10CacheControl::enableVolatileAndOrNonTemporal(
1617 bool IsVolatile,
bool IsNonTemporal,
bool IsLastUse =
false)
const {
1628 assert(
Op == SIMemOp::LOAD ||
Op == SIMemOp::STORE);
1636 if (
Op == SIMemOp::LOAD) {
1649 Changed |= insertWait(
MI, SIAtomicScope::SYSTEM, AddrSpace,
Op,
false,
1650 Position::AFTER, AtomicOrdering::Unordered,
1655 if (IsNonTemporal) {
1660 if (
Op == SIMemOp::STORE)
1675 SIAtomicScope Scope,
1676 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
1677 bool IsCrossAddrSpaceOrdering,
1679 bool AtomicsOnly)
const {
1685 if (Pos == Position::AFTER)
1690 bool LGKMCnt =
false;
1693 (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH))) {
1695 case SIAtomicScope::SYSTEM:
1696 case SIAtomicScope::AGENT:
1697 if (
any(
Op & SIMemOp::LOAD))
1699 if (
any(
Op & SIMemOp::STORE))
1702 case SIAtomicScope::WORKGROUP:
1712 if (
any(
Op & SIMemOp::LOAD))
1714 if (
any(
Op & SIMemOp::STORE))
1718 case SIAtomicScope::WAVEFRONT:
1719 case SIAtomicScope::SINGLETHREAD:
1728 if (
any(AddrSpace & SIAtomicAddrSpace::LDS)) {
1730 case SIAtomicScope::SYSTEM:
1731 case SIAtomicScope::AGENT:
1732 case SIAtomicScope::WORKGROUP:
1739 LGKMCnt |= IsCrossAddrSpaceOrdering;
1741 case SIAtomicScope::WAVEFRONT:
1742 case SIAtomicScope::SINGLETHREAD:
1751 if (
any(AddrSpace & SIAtomicAddrSpace::GDS)) {
1753 case SIAtomicScope::SYSTEM:
1754 case SIAtomicScope::AGENT:
1761 LGKMCnt |= IsCrossAddrSpaceOrdering;
1763 case SIAtomicScope::WORKGROUP:
1764 case SIAtomicScope::WAVEFRONT:
1765 case SIAtomicScope::SINGLETHREAD:
1774 if (VMCnt || LGKMCnt) {
1775 unsigned WaitCntImmediate =
1781 .
addImm(WaitCntImmediate);
1789 Scope == SIAtomicScope::WORKGROUP &&
1790 any(AddrSpace & SIAtomicAddrSpace::LDS)) {
1797 .
addReg(AMDGPU::SGPR_NULL, RegState::Undef)
1802 if (Pos == Position::AFTER)
1809 SIAtomicScope Scope,
1810 SIAtomicAddrSpace AddrSpace,
1811 Position Pos)
const {
1812 if (!InsertCacheInv)
1820 if (Pos == Position::AFTER)
1823 if (canAffectGlobalAddrSpace(AddrSpace)) {
1825 case SIAtomicScope::SYSTEM:
1826 case SIAtomicScope::AGENT:
1834 case SIAtomicScope::WORKGROUP:
1839 if (!
ST.isCuModeEnabled()) {
1844 case SIAtomicScope::WAVEFRONT:
1845 case SIAtomicScope::SINGLETHREAD:
1860 if (Pos == Position::AFTER)
1868 MachineOperand *
CPol =
TII->getNamedOperand(*
MI, OpName::cpol);
1883 MachineOperand *
CPol =
TII->getNamedOperand(*
MI, OpName::cpol);
1896bool SIGfx12CacheControl::insertWaitsBeforeSystemScopeStore(
1904 if (
ST.hasImageInsts()) {
1906 if (
ST.hasAnyBVHInsts())
1916 SIAtomicScope Scope,
1917 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
1918 bool IsCrossAddrSpaceOrdering,
1920 bool AtomicsOnly)
const {
1926 bool LOADCnt =
false;
1928 bool STORECnt =
false;
1930 if (Pos == Position::AFTER)
1934 (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH))) {
1936 case SIAtomicScope::SYSTEM:
1937 case SIAtomicScope::AGENT:
1938 case SIAtomicScope::CLUSTER:
1939 if (
any(
Op & SIMemOp::LOAD))
1941 if (
any(
Op & SIMemOp::STORE))
1944 case SIAtomicScope::WORKGROUP:
1961 if (!
ST.isCuModeEnabled() ||
ST.hasGFX1250Insts() ||
1963 if (
any(
Op & SIMemOp::LOAD))
1965 if (
any(
Op & SIMemOp::STORE))
1969 case SIAtomicScope::WAVEFRONT:
1970 case SIAtomicScope::SINGLETHREAD:
1979 if (
any(AddrSpace & SIAtomicAddrSpace::LDS)) {
1981 case SIAtomicScope::SYSTEM:
1982 case SIAtomicScope::AGENT:
1983 case SIAtomicScope::CLUSTER:
1984 case SIAtomicScope::WORKGROUP:
1991 DSCnt |= IsCrossAddrSpaceOrdering;
1993 case SIAtomicScope::WAVEFRONT:
1994 case SIAtomicScope::SINGLETHREAD:
2015 if (!AtomicsOnly &&
ST.hasImageInsts()) {
2016 if (
ST.hasAnyBVHInsts())
2034 if (Pos == Position::AFTER)
2041 SIAtomicScope Scope,
2042 SIAtomicAddrSpace AddrSpace,
2043 Position Pos)
const {
2044 if (!InsertCacheInv)
2056 if (!canAffectGlobalAddrSpace(AddrSpace))
2061 case SIAtomicScope::SYSTEM:
2067 case SIAtomicScope::AGENT:
2073 case SIAtomicScope::CLUSTER:
2076 case SIAtomicScope::WORKGROUP:
2084 if (
ST.isCuModeEnabled())
2089 case SIAtomicScope::WAVEFRONT:
2090 case SIAtomicScope::SINGLETHREAD:
2097 if (Pos == Position::AFTER)
2102 if (Pos == Position::AFTER)
2107 if (
ST.hasINVWBL2WaitCntRequirement() && Scope > SIAtomicScope::CLUSTER) {
2108 insertWait(
MI, Scope, AddrSpace, SIMemOp::LOAD,
2109 false, Pos, AtomicOrdering::Acquire,
2112 if (Pos == Position::AFTER)
2120 SIAtomicScope Scope,
2121 SIAtomicAddrSpace AddrSpace,
2122 Position Pos)
const {
2127 if (!canAffectGlobalAddrSpace(AddrSpace))
2134 if (Pos == Position::AFTER)
2146 std::optional<AMDGPU::CPol::CPol> NeedsWB;
2148 case SIAtomicScope::SYSTEM:
2149 if (!
ST.hasNoMTypeNC())
2152 case SIAtomicScope::AGENT:
2155 if (
ST.hasGFX1250Insts() && !
ST.hasNoMTypeNC())
2158 case SIAtomicScope::CLUSTER:
2159 case SIAtomicScope::WORKGROUP:
2160 case SIAtomicScope::WAVEFRONT:
2161 case SIAtomicScope::SINGLETHREAD:
2163 case SIAtomicScope::NONE:
2172 if (
ST.hasINVWBL2WaitCntRequirement()) {
2173 insertWait(
MI, Scope, AddrSpace, SIMemOp::LOAD | SIMemOp::STORE,
2175 AtomicOrdering::Release,
2183 if (Pos == Position::AFTER)
2189bool SIGfx12CacheControl::handleNonVolatile(MachineInstr &
MI)
const {
2191 if (!
ST.hasGFX1250Insts())
2193 MachineOperand *
CPol =
TII->getNamedOperand(
MI, OpName::cpol);
2200bool SIGfx12CacheControl::enableVolatileAndOrNonTemporal(
2202 bool IsVolatile,
bool IsNonTemporal,
bool IsLastUse =
false)
const {
2211 assert(
Op == SIMemOp::LOAD ||
Op == SIMemOp::STORE);
2218 }
else if (IsNonTemporal) {
2226 if (
ST.requiresWaitXCntForSingleAccessInstructions() &&
2238 Changed |= insertWait(
MI, SIAtomicScope::SYSTEM, AddrSpace,
Op,
false,
2239 Position::AFTER, AtomicOrdering::Unordered,
2246bool SIGfx12CacheControl::finalizeStore(MachineInstr &
MI,
bool Atomic)
const {
2247 assert(
MI.mayStore() &&
"Not a Store inst");
2248 const bool IsRMW = (
MI.mayLoad() &&
MI.mayStore());
2251 if (Atomic &&
ST.requiresWaitXCntForSingleAccessInstructions() &&
2262 MachineOperand *
CPol =
TII->getNamedOperand(
MI, OpName::cpol);
2268 if (
ST.requiresWaitsBeforeSystemScopeStores() && !Atomic &&
2270 Changed |= insertWaitsBeforeSystemScopeStore(
MI.getIterator());
2280 MachineOperand *
CPol =
TII->getNamedOperand(*
MI, AMDGPU::OpName::cpol);
2281 assert(CPol &&
"load_monitor must have a cpol operand");
2287bool SIGfx12CacheControl::handleCooperativeAtomic(MachineInstr &
MI)
const {
2288 if (!
ST.hasGFX1250Insts())
2292 MachineOperand *
CPol =
TII->getNamedOperand(
MI, OpName::cpol);
2293 assert(CPol &&
"No CPol operand?");
2301 SIAtomicScope Scope,
2302 SIAtomicAddrSpace AddrSpace)
const {
2305 if (canAffectGlobalAddrSpace(AddrSpace)) {
2307 case SIAtomicScope::SYSTEM:
2310 case SIAtomicScope::AGENT:
2313 case SIAtomicScope::CLUSTER:
2316 case SIAtomicScope::WORKGROUP:
2319 if (!
ST.isCuModeEnabled())
2322 case SIAtomicScope::WAVEFRONT:
2323 case SIAtomicScope::SINGLETHREAD:
2342 unsigned CFSBits)
const {
2343 if (!
ST.hasCacheFillSize())
2347 MachineOperand *
CPol =
TII->getNamedOperand(*CoreMI, OpName::cpol);
2362bool SIMemoryLegalizer::removeAtomicPseudoMIs() {
2363 if (AtomicPseudoMIs.empty())
2366 for (
auto &
MI : AtomicPseudoMIs)
2367 MI->eraseFromParent();
2369 AtomicPseudoMIs.clear();
2373bool SIMemoryLegalizer::expandLoad(
const SIMemOpInfo &MOI,
2381 if (MOI.isAtomic()) {
2383 <<
", scope=" <<
toString(MOI.getScope())
2384 <<
", ordering-AS=" << MOI.getOrderingAddrSpace()
2385 <<
", instr-AS=" << MOI.getInstrAddrSpace() <<
"\n");
2387 if (Order == AtomicOrdering::Monotonic ||
2388 Order == AtomicOrdering::Acquire ||
2389 Order == AtomicOrdering::SequentiallyConsistent) {
2390 Changed |=
CC->enableLoadCacheBypass(
MI, MOI.getScope(),
2391 MOI.getOrderingAddrSpace());
2396 if (MOI.isCooperative())
2402 if (Order == AtomicOrdering::SequentiallyConsistent)
2403 Changed |=
CC->insertWait(
MI, MOI.getScope(), MOI.getOrderingAddrSpace(),
2404 SIMemOp::LOAD | SIMemOp::STORE,
2405 MOI.getIsCrossAddressSpaceOrdering(),
2406 Position::BEFORE, Order,
false);
2408 if (Order == AtomicOrdering::Acquire ||
2409 Order == AtomicOrdering::SequentiallyConsistent) {
2412 CC->insertWait(
MI, MOI.getScope(), MOI.getInstrAddrSpace(),
2413 SIMemOp::LOAD, MOI.getIsCrossAddressSpaceOrdering(),
2414 Position::AFTER, Order,
true);
2415 if (!MOI.isAVNone()) {
2417 MI, MOI.getScope(), MOI.getOrderingAddrSpace(), Position::AFTER);
2427 Changed |=
CC->enableVolatileAndOrNonTemporal(
2428 MI, MOI.getInstrAddrSpace(), SIMemOp::LOAD, MOI.isVolatile(),
2429 MOI.isNonTemporal(), MOI.isLastUse());
2437bool SIMemoryLegalizer::expandStore(
const SIMemOpInfo &MOI,
2445 MachineInstr &StoreMI = *
MI;
2447 if (MOI.isAtomic()) {
2449 <<
", scope=" <<
toString(MOI.getScope())
2450 <<
", ordering-AS=" << MOI.getOrderingAddrSpace()
2451 <<
", instr-AS=" << MOI.getInstrAddrSpace() <<
"\n");
2452 if (MOI.getOrdering() == AtomicOrdering::Monotonic ||
2453 MOI.getOrdering() == AtomicOrdering::Release ||
2454 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) {
2455 Changed |=
CC->enableStoreCacheBypass(
MI, MOI.getScope(),
2456 MOI.getOrderingAddrSpace());
2461 if (MOI.isCooperative())
2464 if (MOI.getOrdering() == AtomicOrdering::Release ||
2465 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) {
2467 CC->insertRelease(
MI, MOI.getScope(), MOI.getOrderingAddrSpace(),
2468 MOI.getIsCrossAddressSpaceOrdering(),
2469 Position::BEFORE, MOI.isAVNone());
2472 Changed |=
CC->finalizeStore(StoreMI,
true);
2480 Changed |=
CC->enableVolatileAndOrNonTemporal(
2481 MI, MOI.getInstrAddrSpace(), SIMemOp::STORE, MOI.isVolatile(),
2482 MOI.isNonTemporal());
2486 Changed |=
CC->finalizeStore(StoreMI,
false);
2492bool SIMemoryLegalizer::expandAtomicFence(
const SIMemOpInfo &MOI,
2494 assert(
MI->getOpcode() == AMDGPU::ATOMIC_FENCE);
2498 AtomicPseudoMIs.push_back(
MI);
2501 const SIAtomicAddrSpace OrderingAddrSpace = MOI.getOrderingAddrSpace();
2503 if (MOI.isAtomic()) {
2505 <<
", scope=" <<
toString(MOI.getScope())
2506 <<
", ordering-AS=" << OrderingAddrSpace <<
"\n");
2508 if (Order == AtomicOrdering::Acquire) {
2510 Changed |=
CC->insertWait(
MI, MOI.getScope(), OrderingAddrSpace,
2511 SIMemOp::LOAD | SIMemOp::STORE,
2512 MOI.getIsCrossAddressSpaceOrdering(),
2513 Position::BEFORE, Order,
true);
2516 if (Order == AtomicOrdering::Release ||
2517 Order == AtomicOrdering::AcquireRelease ||
2518 Order == AtomicOrdering::SequentiallyConsistent) {
2526 Changed |=
CC->insertRelease(
MI, MOI.getScope(), OrderingAddrSpace,
2527 MOI.getIsCrossAddressSpaceOrdering(),
2528 Position::BEFORE, MOI.isAVNone());
2536 if ((Order == AtomicOrdering::Acquire ||
2537 Order == AtomicOrdering::AcquireRelease ||
2538 Order == AtomicOrdering::SequentiallyConsistent) &&
2540 Changed |=
CC->insertAcquire(
MI, MOI.getScope(), OrderingAddrSpace,
2550bool SIMemoryLegalizer::expandAtomicCmpxchgOrRmw(
const SIMemOpInfo &MOI,
2557 MachineInstr &RMWMI = *
MI;
2559 if (MOI.isAtomic()) {
2561 <<
", failure-ordering="
2563 <<
", scope=" <<
toString(MOI.getScope())
2564 <<
", ordering-AS=" << MOI.getOrderingAddrSpace()
2565 <<
", instr-AS=" << MOI.getInstrAddrSpace() <<
"\n");
2567 if (Order == AtomicOrdering::Monotonic ||
2568 Order == AtomicOrdering::Acquire || Order == AtomicOrdering::Release ||
2569 Order == AtomicOrdering::AcquireRelease ||
2570 Order == AtomicOrdering::SequentiallyConsistent) {
2571 Changed |=
CC->enableRMWCacheBypass(
MI, MOI.getScope(),
2572 MOI.getInstrAddrSpace());
2575 if (Order == AtomicOrdering::Release ||
2576 Order == AtomicOrdering::AcquireRelease ||
2577 Order == AtomicOrdering::SequentiallyConsistent ||
2578 MOI.getFailureOrdering() == AtomicOrdering::SequentiallyConsistent) {
2580 CC->insertRelease(
MI, MOI.getScope(), MOI.getOrderingAddrSpace(),
2581 MOI.getIsCrossAddressSpaceOrdering(),
2582 Position::BEFORE, MOI.isAVNone());
2585 if (Order == AtomicOrdering::Acquire ||
2586 Order == AtomicOrdering::AcquireRelease ||
2587 Order == AtomicOrdering::SequentiallyConsistent ||
2588 MOI.getFailureOrdering() == AtomicOrdering::Acquire ||
2589 MOI.getFailureOrdering() == AtomicOrdering::SequentiallyConsistent) {
2592 CC->insertWait(
MI, MOI.getScope(), MOI.getInstrAddrSpace(),
2594 MOI.getIsCrossAddressSpaceOrdering(), Position::AFTER,
2596 if (!MOI.isAVNone()) {
2598 MI, MOI.getScope(), MOI.getOrderingAddrSpace(), Position::AFTER);
2602 Changed |=
CC->finalizeStore(RMWMI,
true);
2611bool SIMemoryLegalizer::expandLDSDMA(
const SIMemOpInfo &MOI,
2625 bool Changed =
CC->enableVolatileAndOrNonTemporal(
2626 MI, MOI.getInstrAddrSpace(), OpKind, MOI.isVolatile(),
2627 MOI.isNonTemporal(), MOI.isLastUse());
2632bool SIMemoryLegalizerLegacy::runOnMachineFunction(
MachineFunction &MF) {
2633 const MachineModuleInfo &MMI =
2634 getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
2635 return SIMemoryLegalizer(MMI).run(MF);
2642 .getCachedResult<MachineModuleAnalysis>(
2644 assert(MMI &&
"MachineModuleAnalysis must be available");
2645 if (!SIMemoryLegalizer(MMI->getMMI()).run(MF))
2657 CC = SICacheControl::create(ST, TgSplit);
2659 for (
auto &
MBB : MF) {
2663 if (
MI->isBundle() &&
MI->mayLoadOrStore()) {
2666 I != E &&
I->isBundledWithPred(); ++
I) {
2667 I->unbundleFromPred();
2670 MO.setIsInternalRead(
false);
2673 MI =
MI->eraseFromParent();
2677 if (
const auto &MOI = MOA.getLoadInfo(
MI))
2679 else if (
const auto &MOI = MOA.getStoreInfo(
MI))
2681 else if (
const auto &MOI = MOA.getLDSDMAInfo(
MI))
2683 else if (
const auto &MOI = MOA.getAtomicFenceInfo(
MI))
2685 else if (
const auto &MOI = MOA.getAtomicCmpxchgOrRmwInfo(
MI))
2686 Changed |= expandAtomicCmpxchgOrRmw(*MOI,
MI);
2694 Changed |= removeAtomicPseudoMIs();
2700char SIMemoryLegalizerLegacy::ID = 0;
2704 return new SIMemoryLegalizerLegacy();
static std::optional< LoadInfo > getLoadInfo(const MachineInstr &MI)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
AMDGPU Machine Module Info.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Atomic ordering constants.
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
This header defines various interfaces for pass management in LLVM.
static bool isAtomic(MachineBasicBlock::iterator I)
This file provides utility for Memory Model Relaxation Annotations (MMRAs).
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool isNonVolatileMemoryAccess(const MachineInstr &MI)
static bool canUseBUFFER_WBINVL1_VOL(const GCNSubtarget &ST)
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
static const uint32_t IV[8]
SyncScope::ID getWorkgroupSSID() const
SyncScope::ID getWavefrontSSID() const
SyncScope::ID getAgentSSID() const
SyncScope::ID getClusterOneAddressSpaceSSID() const
SyncScope::ID getClusterSSID() const
SyncScope::ID getAgentOneAddressSpaceSSID() const
SyncScope::ID getSingleThreadOneAddressSpaceSSID() const
SyncScope::ID getWavefrontOneAddressSpaceSSID() const
std::optional< SyncScope::ID > getMergedSyncScopeID(SyncScope::ID A, SyncScope::ID B) const
In AMDGPU, synchronization scopes are inclusive: a larger scope is inclusive of a smaller one (e....
SyncScope::ID getSystemOneAddressSpaceSSID() const
SyncScope::ID getWorkgroupOneAddressSpaceSSID() const
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
Diagnostic information for unsupported feature in backend.
FunctionPass class - This class is used to implement most global optimizations.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Generation getGeneration() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
A helper class to return the specified delimiter string after the first invocation of operator String...
Instructions::iterator instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
A description of a memory reference used in the backend.
This class contains meta information specific to a module.
Ty & getObjFileInfo()
Keep track of various per-module pieces of information for backends that would like to do so.
MachineOperand class - Representation of each machine instruction operand.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
static bool isVMEM(const MachineInstr &MI)
static bool mayWriteLDSThroughDMA(const MachineInstr &MI)
static bool isBUF(const MachineInstr &MI)
static bool isAtomicRet(const MachineInstr &MI)
static bool isAtomic(const MachineInstr &MI)
static bool isLoadMonitor(unsigned Opc)
static bool isLDSDMA(const MachineInstr &MI)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
iterator find(StringRef Key)
Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ BUFFER_STRIDED_POINTER
Address space for 192-bit fat buffer pointers with an additional index.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ BUFFER_FAT_POINTER
Address space for 160-bit buffer fat pointers.
@ PRIVATE_ADDRESS
Address space for private memory.
@ BUFFER_RESOURCE
Address space for 128-bit buffer resources.
constexpr char IsVolatile[]
Key for Kernel::Arg::Metadata::mIsVolatile.
bool isGFX10(const MCSubtargetInfo &STI)
bool isGFX11(const MCSubtargetInfo &STI)
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
unsigned encodeWaitcnt(const IsaVersion &Version, const Waitcnt &Decoded)
bool isTgSplitEnabled(const Function &F)
unsigned getVmcntBitMask(const IsaVersion &Version)
unsigned getLgkmcntBitMask(const IsaVersion &Version)
unsigned getExpcntBitMask(const IsaVersion &Version)
constexpr bool any(E Val)
constexpr bool isAtomicRet(const T &...O)
constexpr bool isMaybeAtomic(const T &...O)
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
char & SIMemoryLegalizerID
@ LLVM_MARK_AS_BITMASK_ENUM
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
static void reportUnsupported(MachineIRBuilder &MIRBuilder, const Twine &Msg)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
bool isReleaseOrStronger(AtomicOrdering AO)
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
static const DIScope * getScope(const NodeT *N)
const char * toIRString(AtomicOrdering ao)
String used by LLVM IR to represent atomic ordering.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
AtomicOrdering getMergedAtomicOrdering(AtomicOrdering AO, AtomicOrdering Other)
Return a single atomic ordering that is at least as strong as both the AO and Other orderings for an ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static const MachineMemOperand::Flags MOCooperative
Mark the MMO of cooperative load/store atomics.
AtomicOrdering
Atomic ordering for LLVM's memory model.
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
static const MachineMemOperand::Flags MOLastUse
Mark the MMO of a load as the last use.
static const MachineMemOperand::Flags MOCFSB0
Use two MMO flags to encode the 2-bit cache fill size field for GFX13+.
FunctionPass * createSIMemoryLegalizerPass()
Instruction set architecture version.