35#define DEBUG_TYPE "si-memory-legalizer"
36#define PASS_NAME "SI Memory Legalizer"
40 cl::desc(
"Use this to skip inserting cache invalidating instructions."));
62enum class SIAtomicScope {
74enum class SIAtomicAddrSpace {
86 ATOMIC = GLOBAL |
LDS | SCRATCH | GDS,
89 ALL = GLOBAL |
LDS | SCRATCH | GDS | OTHER,
97 case SIAtomicScope::NONE:
99 case SIAtomicScope::SINGLETHREAD:
100 return "singlethread";
101 case SIAtomicScope::WAVEFRONT:
103 case SIAtomicScope::WORKGROUP:
105 case SIAtomicScope::CLUSTER:
107 case SIAtomicScope::AGENT:
109 case SIAtomicScope::SYSTEM:
116 if (AS == SIAtomicAddrSpace::NONE) {
121 if ((AS & SIAtomicAddrSpace::GLOBAL) != SIAtomicAddrSpace::NONE)
122 OS <<
LS <<
"global";
123 if ((AS & SIAtomicAddrSpace::LDS) != SIAtomicAddrSpace::NONE)
125 if ((AS & SIAtomicAddrSpace::SCRATCH) != SIAtomicAddrSpace::NONE)
126 OS <<
LS <<
"scratch";
127 if ((AS & SIAtomicAddrSpace::GDS) != SIAtomicAddrSpace::NONE)
129 if ((AS & SIAtomicAddrSpace::OTHER) != SIAtomicAddrSpace::NONE)
135class SIMemOpInfo final {
138 friend class SIMemOpAccess;
142 SIAtomicScope Scope = SIAtomicScope::SYSTEM;
143 SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::NONE;
144 SIAtomicAddrSpace InstrAddrSpace = SIAtomicAddrSpace::NONE;
145 bool IsCrossAddressSpaceOrdering =
false;
146 bool IsVolatile =
false;
147 bool IsNonTemporal =
false;
148 bool IsLastUse =
false;
149 bool IsCooperative =
false;
150 bool IsAVNone =
false;
154 const GCNSubtarget &ST,
156 SIAtomicScope Scope = SIAtomicScope::SYSTEM,
157 SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::ATOMIC,
158 SIAtomicAddrSpace InstrAddrSpace = SIAtomicAddrSpace::ALL,
159 bool IsCrossAddressSpaceOrdering =
true,
160 AtomicOrdering FailureOrdering = AtomicOrdering::SequentiallyConsistent,
161 bool IsVolatile =
false,
bool IsNonTemporal =
false,
162 bool IsLastUse =
false,
bool IsCooperative =
false,
bool IsAVNone =
false)
163 : Ordering(Ordering), FailureOrdering(FailureOrdering), Scope(Scope),
164 OrderingAddrSpace(OrderingAddrSpace), InstrAddrSpace(InstrAddrSpace),
165 IsCrossAddressSpaceOrdering(IsCrossAddressSpaceOrdering),
166 IsVolatile(IsVolatile), IsNonTemporal(IsNonTemporal),
167 IsLastUse(IsLastUse), IsCooperative(IsCooperative), IsAVNone(IsAVNone) {
169 if (Ordering == AtomicOrdering::NotAtomic) {
170 assert(!IsCooperative &&
"Cannot be cooperative & non-atomic!");
171 assert(Scope == SIAtomicScope::NONE &&
172 OrderingAddrSpace == SIAtomicAddrSpace::NONE &&
173 !IsCrossAddressSpaceOrdering &&
174 FailureOrdering == AtomicOrdering::NotAtomic);
178 assert(Scope != SIAtomicScope::NONE &&
179 (OrderingAddrSpace & SIAtomicAddrSpace::ATOMIC) !=
180 SIAtomicAddrSpace::NONE &&
181 (InstrAddrSpace & SIAtomicAddrSpace::ATOMIC) !=
182 SIAtomicAddrSpace::NONE);
187 if ((OrderingAddrSpace == InstrAddrSpace) &&
189 this->IsCrossAddressSpaceOrdering =
false;
193 if ((InstrAddrSpace & ~SIAtomicAddrSpace::SCRATCH) ==
194 SIAtomicAddrSpace::NONE) {
195 this->Scope = std::min(Scope, SIAtomicScope::SINGLETHREAD);
196 }
else if ((InstrAddrSpace &
197 ~(SIAtomicAddrSpace::SCRATCH | SIAtomicAddrSpace::LDS)) ==
198 SIAtomicAddrSpace::NONE) {
199 this->Scope = std::min(Scope, SIAtomicScope::WORKGROUP);
200 }
else if ((InstrAddrSpace &
201 ~(SIAtomicAddrSpace::SCRATCH | SIAtomicAddrSpace::LDS |
202 SIAtomicAddrSpace::GDS)) == SIAtomicAddrSpace::NONE) {
203 this->Scope = std::min(Scope, SIAtomicScope::AGENT);
208 if (this->Scope == SIAtomicScope::CLUSTER && !
ST.hasClusters())
209 this->Scope = SIAtomicScope::AGENT;
228 return FailureOrdering;
233 SIAtomicAddrSpace getInstrAddrSpace()
const {
234 return InstrAddrSpace;
239 SIAtomicAddrSpace getOrderingAddrSpace()
const {
240 return OrderingAddrSpace;
245 bool getIsCrossAddressSpaceOrdering()
const {
246 return IsCrossAddressSpaceOrdering;
251 bool isVolatile()
const {
257 bool isNonTemporal()
const {
258 return IsNonTemporal;
263 bool isLastUse()
const {
return IsLastUse; }
266 bool isCooperative()
const {
return IsCooperative; }
269 bool isAVNone()
const {
return IsAVNone; }
274 return Ordering != AtomicOrdering::NotAtomic;
279class SIMemOpAccess final {
281 const AMDGPUMachineModuleInfo *MMI =
nullptr;
282 const GCNSubtarget &ST;
286 const char *
Msg)
const;
292 std::optional<std::tuple<SIAtomicScope, SIAtomicAddrSpace, bool>>
293 toSIAtomicScope(
SyncScope::ID SSID, SIAtomicAddrSpace InstrAddrSpace)
const;
296 SIAtomicAddrSpace toSIAtomicAddrSpace(
unsigned AS)
const;
300 std::optional<SIMemOpInfo>
306 SIMemOpAccess(
const AMDGPUMachineModuleInfo &MMI,
const GCNSubtarget &ST);
309 std::optional<SIMemOpInfo>
314 std::optional<SIMemOpInfo>
319 std::optional<SIMemOpInfo>
324 std::optional<SIMemOpInfo>
330 std::optional<SIMemOpInfo>
334class SICacheControl {
338 const GCNSubtarget &ST;
341 const SIInstrInfo *TII =
nullptr;
351 SICacheControl(
const GCNSubtarget &ST,
bool TgSplit);
356 unsigned Bits)
const;
360 bool canAffectGlobalAddrSpace(SIAtomicAddrSpace AS)
const;
366 static std::unique_ptr<SICacheControl> create(
const GCNSubtarget &ST,
374 SIAtomicAddrSpace AddrSpace)
const = 0;
381 SIAtomicAddrSpace AddrSpace)
const = 0;
388 SIAtomicAddrSpace AddrSpace)
const = 0;
394 SIAtomicAddrSpace AddrSpace,
395 SIMemOp
Op,
bool IsVolatile,
397 bool IsLastUse =
false)
const = 0;
404 virtual bool finalizeStore(MachineInstr &
MI,
bool Atomic)
const {
414 virtual bool handleCooperativeAtomic(MachineInstr &
MI)
const {
416 "cooperative atomics are not available on this architecture");
429 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
430 bool IsCrossAddrSpaceOrdering, Position Pos,
440 SIAtomicAddrSpace AddrSpace,
441 Position Pos)
const = 0;
449 SIAtomicScope Scope, SIAtomicAddrSpace AddrSpace,
450 Position Pos)
const = 0;
454 SIAtomicAddrSpace AddrSpace,
bool IsCrossAddrSpaceOrdering,
455 Position Pos,
bool IsAVNone)
const {
456 bool Changed = !IsAVNone && insertWriteback(
MI, Scope, AddrSpace, Pos);
457 Changed |= insertWait(
MI, Scope, AddrSpace, SIMemOp::LOAD | SIMemOp::STORE,
458 IsCrossAddrSpaceOrdering, Pos,
459 AtomicOrdering::Release,
false);
465 virtual bool handleNonVolatile(MachineInstr &
MI)
const {
return false; }
468 virtual ~SICacheControl() =
default;
473class SIGfx6CacheControl final :
public SICacheControl {
475 SIGfx6CacheControl(
const GCNSubtarget &ST,
bool TgSplit)
476 : SICacheControl(
ST, TgSplit) {}
480 SIAtomicAddrSpace AddrSpace)
const override;
484 SIAtomicAddrSpace AddrSpace)
const override;
488 SIAtomicAddrSpace AddrSpace)
const override;
491 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
492 bool IsVolatile,
bool IsNonTemporal,
493 bool IsLastUse)
const override;
496 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
497 bool IsCrossAddrSpaceOrdering, Position Pos,
502 SIAtomicAddrSpace AddrSpace,
503 Position Pos)
const override;
506 SIAtomicAddrSpace AddrSpace,
507 Position Pos)
const override;
511class SIGfx10CacheControl final :
public SICacheControl {
513 SIGfx10CacheControl(
const GCNSubtarget &ST,
bool TgSplit)
514 : SICacheControl(
ST, TgSplit) {}
518 SIAtomicAddrSpace AddrSpace)
const override;
522 SIAtomicAddrSpace AddrSpace)
const override {
528 SIAtomicAddrSpace AddrSpace)
const override {
533 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
534 bool IsVolatile,
bool IsNonTemporal,
535 bool IsLastUse)
const override;
538 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
539 bool IsCrossAddrSpaceOrdering, Position Pos,
543 SIAtomicAddrSpace AddrSpace, Position Pos)
const override;
546 SIAtomicAddrSpace AddrSpace,
547 Position Pos)
const override {
552class SIGfx12CacheControl final :
public SICacheControl {
574 SIAtomicScope Scope, SIAtomicAddrSpace AddrSpace)
const;
577 SIGfx12CacheControl(
const GCNSubtarget &ST,
bool TgSplit)
578 : SICacheControl(
ST, TgSplit) {
581 assert(!
ST.hasGFX1250Insts() ||
ST.hasGFX13Insts() ||
ST.isCuModeEnabled());
585 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
586 bool IsCrossAddrSpaceOrdering, Position Pos,
590 SIAtomicAddrSpace AddrSpace, Position Pos)
const override;
593 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
594 bool IsVolatile,
bool IsNonTemporal,
595 bool IsLastUse)
const override;
597 bool finalizeStore(MachineInstr &
MI,
bool Atomic)
const override;
601 bool handleCooperativeAtomic(MachineInstr &
MI)
const override;
604 SIAtomicAddrSpace AddrSpace,
605 Position Pos)
const override;
609 SIAtomicAddrSpace AddrSpace)
const override {
610 return setAtomicScope(
MI, Scope, AddrSpace);
615 SIAtomicAddrSpace AddrSpace)
const override {
616 return setAtomicScope(
MI, Scope, AddrSpace);
621 SIAtomicAddrSpace AddrSpace)
const override {
622 return setAtomicScope(
MI, Scope, AddrSpace);
625 bool handleNonVolatile(MachineInstr &
MI)
const override;
628class SIMemoryLegalizer final {
630 const MachineModuleInfo &MMI;
632 std::unique_ptr<SICacheControl> CC =
nullptr;
635 std::list<MachineBasicBlock::iterator> AtomicPseudoMIs;
645 bool removeAtomicPseudoMIs();
649 bool expandLoad(
const SIMemOpInfo &MOI,
653 bool expandStore(
const SIMemOpInfo &MOI,
657 bool expandAtomicFence(
const SIMemOpInfo &MOI,
661 bool expandAtomicCmpxchgOrRmw(
const SIMemOpInfo &MOI,
668 SIMemoryLegalizer(
const MachineModuleInfo &MMI) : MMI(MMI) {};
676 SIMemoryLegalizerLegacy() : MachineFunctionPass(ID) {}
678 void getAnalysisUsage(AnalysisUsage &AU)
const override {
683 StringRef getPassName()
const override {
691 {
"global", SIAtomicAddrSpace::GLOBAL},
692 {
"local", SIAtomicAddrSpace::LDS},
700 OS <<
"unknown address space '" << AS <<
"'; expected one of ";
702 for (
const auto &[Name, Val] : ASNames)
703 OS <<
LS <<
'\'' <<
Name <<
'\'';
711static std::optional<SIAtomicAddrSpace>
713 static constexpr StringLiteral FenceASPrefix =
"amdgpu-synchronize-as";
719 SIAtomicAddrSpace
Result = SIAtomicAddrSpace::NONE;
720 for (
const auto &[Prefix, Suffix] : MMRA) {
721 if (Prefix != FenceASPrefix)
724 if (
auto It = ASNames.find(Suffix); It != ASNames.end())
727 diagnoseUnknownMMRAASName(
MI, Suffix);
730 if (Result == SIAtomicAddrSpace::NONE)
741 Fn,
Twine(
"unknown amdgcn-av metadata '") + Suffix +
Twine(
'\''),
749 bool TagFound =
false;
750 for (
const auto &[Prefix, Suffix] : MMRA) {
751 if (Prefix !=
"amdgcn-av")
753 if (Suffix ==
"none")
756 diagnoseUnknownAVMetadata(
MI, Suffix);
764 const char *
Msg)
const {
766 Func.getContext().diagnose(
767 DiagnosticInfoUnsupported(Func,
Msg,
MI->getDebugLoc()));
770std::optional<std::tuple<SIAtomicScope, SIAtomicAddrSpace, bool>>
772 SIAtomicAddrSpace InstrAddrSpace)
const {
774 return std::tuple(SIAtomicScope::SYSTEM, SIAtomicAddrSpace::ATOMIC,
true);
776 return std::tuple(SIAtomicScope::AGENT, SIAtomicAddrSpace::ATOMIC,
true);
778 return std::tuple(SIAtomicScope::CLUSTER, SIAtomicAddrSpace::ATOMIC,
true);
780 return std::tuple(SIAtomicScope::WORKGROUP, SIAtomicAddrSpace::ATOMIC,
783 return std::tuple(SIAtomicScope::WAVEFRONT, SIAtomicAddrSpace::ATOMIC,
786 return std::tuple(SIAtomicScope::SINGLETHREAD, SIAtomicAddrSpace::ATOMIC,
789 return std::tuple(SIAtomicScope::SYSTEM,
790 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
792 return std::tuple(SIAtomicScope::AGENT,
793 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
795 return std::tuple(SIAtomicScope::CLUSTER,
796 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
798 return std::tuple(SIAtomicScope::WORKGROUP,
799 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
801 return std::tuple(SIAtomicScope::WAVEFRONT,
802 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
804 return std::tuple(SIAtomicScope::SINGLETHREAD,
805 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
809SIAtomicAddrSpace SIMemOpAccess::toSIAtomicAddrSpace(
unsigned AS)
const {
811 return SIAtomicAddrSpace::FLAT;
813 return SIAtomicAddrSpace::GLOBAL;
815 return SIAtomicAddrSpace::LDS;
817 return SIAtomicAddrSpace::SCRATCH;
819 return SIAtomicAddrSpace::GDS;
822 return SIAtomicAddrSpace::GLOBAL;
824 return SIAtomicAddrSpace::OTHER;
827SIMemOpAccess::SIMemOpAccess(
const AMDGPUMachineModuleInfo &MMI_,
828 const GCNSubtarget &ST)
829 : MMI(&MMI_),
ST(
ST) {}
831std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
833 assert(
MI->getNumMemOperands() > 0);
835 std::optional<SyncScope::ID> MergedSSID;
838 SIAtomicAddrSpace InstrAddrSpace = SIAtomicAddrSpace::NONE;
839 bool IsNonTemporal =
true;
841 bool IsLastUse =
false;
842 bool IsCooperative =
false;
846 for (
const auto &MMO :
MI->memoperands()) {
847 IsNonTemporal &= MMO->isNonTemporal();
849 IsLastUse |= MMO->getFlags() &
MOLastUse;
851 InstrAddrSpace |= toSIAtomicAddrSpace(MMO->getPointerInfo().getAddrSpace());
853 if (OpOrdering != AtomicOrdering::NotAtomic) {
856 SyncScope::ID CurSSID = MergedSSID.value_or(MMO->getSyncScopeID());
860 reportUnsupported(
MI,
"Unsupported atomic synchronization scope");
863 MergedSSID = *Merged;
865 assert(MMO->getFailureOrdering() != AtomicOrdering::Release &&
866 MMO->getFailureOrdering() != AtomicOrdering::AcquireRelease);
878 Ordering = AtomicOrdering::Monotonic;
880 SIAtomicScope
Scope = SIAtomicScope::NONE;
881 SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::NONE;
882 bool IsCrossAddressSpaceOrdering =
false;
883 if (Ordering != AtomicOrdering::NotAtomic) {
884 auto ScopeOrNone = toSIAtomicScope(SSID, InstrAddrSpace);
886 reportUnsupported(
MI,
"Unsupported atomic synchronization scope");
889 std::tie(Scope, OrderingAddrSpace, IsCrossAddressSpaceOrdering) =
891 if ((OrderingAddrSpace == SIAtomicAddrSpace::NONE) ||
892 ((OrderingAddrSpace & SIAtomicAddrSpace::ATOMIC) != OrderingAddrSpace) ||
893 ((InstrAddrSpace & SIAtomicAddrSpace::ATOMIC) == SIAtomicAddrSpace::NONE)) {
894 reportUnsupported(
MI,
"Unsupported atomic address space");
898 return SIMemOpInfo(ST, Ordering, Scope, OrderingAddrSpace, InstrAddrSpace,
899 IsCrossAddressSpaceOrdering, FailureOrdering, IsVolatile,
900 IsNonTemporal, IsLastUse, IsCooperative,
904std::optional<SIMemOpInfo>
908 if (!(
MI->mayLoad() && !
MI->mayStore()))
912 if (
MI->getNumMemOperands() == 0)
913 return SIMemOpInfo(ST);
915 return constructFromMIWithMMO(
MI);
918std::optional<SIMemOpInfo>
922 if (!(!
MI->mayLoad() &&
MI->mayStore()))
926 if (
MI->getNumMemOperands() == 0)
927 return SIMemOpInfo(ST);
929 return constructFromMIWithMMO(
MI);
932std::optional<SIMemOpInfo>
936 if (
MI->getOpcode() != AMDGPU::ATOMIC_FENCE)
943 auto ScopeOrNone = toSIAtomicScope(SSID, SIAtomicAddrSpace::ATOMIC);
945 reportUnsupported(
MI,
"Unsupported atomic synchronization scope");
949 SIAtomicScope
Scope = SIAtomicScope::NONE;
950 SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::NONE;
951 bool IsCrossAddressSpaceOrdering =
false;
952 std::tie(Scope, OrderingAddrSpace, IsCrossAddressSpaceOrdering) =
955 if (OrderingAddrSpace != SIAtomicAddrSpace::ATOMIC) {
960 reportUnsupported(
MI,
"Unsupported atomic address space");
964 auto SynchronizeAS = getSynchronizeAddrSpaceMD(*
MI);
966 OrderingAddrSpace = *SynchronizeAS;
968 return SIMemOpInfo(ST, Ordering, Scope, OrderingAddrSpace,
969 SIAtomicAddrSpace::ATOMIC, IsCrossAddressSpaceOrdering,
970 AtomicOrdering::NotAtomic,
false,
false,
false,
false,
974std::optional<SIMemOpInfo> SIMemOpAccess::getAtomicCmpxchgOrRmwInfo(
978 if (!(
MI->mayLoad() &&
MI->mayStore()))
982 if (
MI->getNumMemOperands() == 0)
983 return SIMemOpInfo(ST);
985 return constructFromMIWithMMO(
MI);
988std::optional<SIMemOpInfo>
995 return constructFromMIWithMMO(
MI);
1003 if (
MI.getNumMemOperands() == 0)
1006 return MMO->getFlags() & (MOThreadPrivate | MachineMemOperand::MOInvariant);
1010SICacheControl::SICacheControl(
const GCNSubtarget &ST,
bool TgSplit) :
ST(
ST) {
1011 TII =
ST.getInstrInfo();
1014 TgSplitEnabled = TgSplit;
1018 unsigned Bits)
const {
1019 MachineOperand *CPol =
TII->getNamedOperand(*
MI, AMDGPU::OpName::cpol);
1023 CPol->setImm(
CPol->getImm() | Bits);
1027bool SICacheControl::canAffectGlobalAddrSpace(SIAtomicAddrSpace AS)
const {
1028 assert((!
ST.hasGloballyAddressableScratch() ||
1029 (AS & SIAtomicAddrSpace::GLOBAL) != SIAtomicAddrSpace::NONE ||
1030 (AS & SIAtomicAddrSpace::SCRATCH) == SIAtomicAddrSpace::NONE) &&
1031 "scratch instructions should already be replaced by flat "
1032 "instructions if GloballyAddressableScratch is enabled");
1033 return (AS & SIAtomicAddrSpace::GLOBAL) != SIAtomicAddrSpace::NONE;
1037std::unique_ptr<SICacheControl> SICacheControl::create(
const GCNSubtarget &ST,
1039 GCNSubtarget::Generation Generation =
ST.getGeneration();
1040 if (Generation < AMDGPUSubtarget::GFX10)
1041 return std::make_unique<SIGfx6CacheControl>(ST, TgSplit);
1042 if (Generation < AMDGPUSubtarget::GFX12)
1043 return std::make_unique<SIGfx10CacheControl>(ST, TgSplit);
1044 return std::make_unique<SIGfx12CacheControl>(ST, TgSplit);
1047bool SIGfx6CacheControl::enableLoadCacheBypass(
1049 SIAtomicScope Scope,
1050 SIAtomicAddrSpace AddrSpace)
const {
1053 if (!canAffectGlobalAddrSpace(AddrSpace)) {
1065 case SIAtomicScope::SYSTEM:
1066 if (
ST.hasGFX940Insts()) {
1072 case SIAtomicScope::AGENT:
1073 if (
ST.hasGFX940Insts()) {
1082 case SIAtomicScope::WORKGROUP:
1083 if (
ST.hasGFX940Insts()) {
1090 }
else if (
ST.hasGFX90AInsts()) {
1099 case SIAtomicScope::WAVEFRONT:
1100 case SIAtomicScope::SINGLETHREAD:
1110bool SIGfx6CacheControl::enableStoreCacheBypass(
1112 SIAtomicScope Scope,
1113 SIAtomicAddrSpace AddrSpace)
const {
1121 if (
ST.hasGFX940Insts() && canAffectGlobalAddrSpace(AddrSpace)) {
1123 case SIAtomicScope::SYSTEM:
1127 case SIAtomicScope::AGENT:
1131 case SIAtomicScope::WORKGROUP:
1135 case SIAtomicScope::WAVEFRONT:
1136 case SIAtomicScope::SINGLETHREAD:
1154bool SIGfx6CacheControl::enableRMWCacheBypass(
1156 SIAtomicScope Scope,
1157 SIAtomicAddrSpace AddrSpace)
const {
1167 if (
ST.hasGFX940Insts() && canAffectGlobalAddrSpace(AddrSpace)) {
1169 case SIAtomicScope::SYSTEM:
1173 case SIAtomicScope::AGENT:
1174 case SIAtomicScope::WORKGROUP:
1175 case SIAtomicScope::WAVEFRONT:
1176 case SIAtomicScope::SINGLETHREAD:
1190bool SIGfx6CacheControl::enableVolatileAndOrNonTemporal(
1192 bool IsVolatile,
bool IsNonTemporal,
bool IsLastUse =
false)
const {
1202 assert(
Op == SIMemOp::LOAD ||
Op == SIMemOp::STORE);
1207 if (
ST.hasGFX940Insts()) {
1210 }
else if (
Op == SIMemOp::LOAD) {
1222 Changed |= insertWait(
MI, SIAtomicScope::SYSTEM, AddrSpace,
Op,
false,
1223 Position::AFTER, AtomicOrdering::Unordered,
1229 if (IsNonTemporal) {
1230 if (
ST.hasGFX940Insts()) {
1244 SIAtomicScope Scope,
1245 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
1246 bool IsCrossAddrSpaceOrdering, Position Pos,
1248 bool AtomicsOnly)
const {
1254 if (Pos == Position::AFTER)
1258 if (
ST.hasGFX90AInsts() && TgSplitEnabled) {
1266 if (((AddrSpace & (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH |
1267 SIAtomicAddrSpace::GDS)) != SIAtomicAddrSpace::NONE) &&
1268 (Scope == SIAtomicScope::WORKGROUP)) {
1270 Scope = SIAtomicScope::AGENT;
1274 AddrSpace &= ~SIAtomicAddrSpace
::LDS;
1278 bool LGKMCnt =
false;
1280 if ((AddrSpace & (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH)) !=
1281 SIAtomicAddrSpace::NONE) {
1283 case SIAtomicScope::SYSTEM:
1284 case SIAtomicScope::AGENT:
1287 case SIAtomicScope::WORKGROUP:
1288 case SIAtomicScope::WAVEFRONT:
1289 case SIAtomicScope::SINGLETHREAD:
1298 if ((AddrSpace & SIAtomicAddrSpace::LDS) != SIAtomicAddrSpace::NONE) {
1300 case SIAtomicScope::SYSTEM:
1301 case SIAtomicScope::AGENT:
1302 case SIAtomicScope::WORKGROUP:
1309 LGKMCnt |= IsCrossAddrSpaceOrdering;
1311 case SIAtomicScope::WAVEFRONT:
1312 case SIAtomicScope::SINGLETHREAD:
1321 if ((AddrSpace & SIAtomicAddrSpace::GDS) != SIAtomicAddrSpace::NONE) {
1323 case SIAtomicScope::SYSTEM:
1324 case SIAtomicScope::AGENT:
1331 LGKMCnt |= IsCrossAddrSpaceOrdering;
1333 case SIAtomicScope::WORKGROUP:
1334 case SIAtomicScope::WAVEFRONT:
1335 case SIAtomicScope::SINGLETHREAD:
1344 if (VMCnt || LGKMCnt) {
1345 unsigned WaitCntImmediate =
1351 .
addImm(WaitCntImmediate);
1359 Scope == SIAtomicScope::WORKGROUP &&
1360 (AddrSpace & SIAtomicAddrSpace::LDS) != SIAtomicAddrSpace::NONE) {
1365 if (Pos == Position::AFTER)
1374 return !ST.isAmdPalOS() && !ST.isMesa3DOS();
1378 SIAtomicScope Scope,
1379 SIAtomicAddrSpace AddrSpace,
1380 Position Pos)
const {
1381 if (!InsertCacheInv)
1389 if (Pos == Position::AFTER)
1393 ? AMDGPU::BUFFER_WBINVL1_VOL
1394 : AMDGPU::BUFFER_WBINVL1;
1396 if (canAffectGlobalAddrSpace(AddrSpace)) {
1398 case SIAtomicScope::SYSTEM:
1399 if (
ST.hasGFX940Insts()) {
1415 if (
ST.hasGFX90AInsts()) {
1430 case SIAtomicScope::AGENT:
1431 if (
ST.hasGFX940Insts()) {
1446 case SIAtomicScope::WORKGROUP:
1447 if (TgSplitEnabled) {
1448 if (
ST.hasGFX940Insts()) {
1467 }
else if (
ST.hasGFX90AInsts()) {
1473 case SIAtomicScope::WAVEFRONT:
1474 case SIAtomicScope::SINGLETHREAD:
1491 if (Pos == Position::AFTER)
1498 SIAtomicScope Scope,
1499 SIAtomicAddrSpace AddrSpace,
1500 Position Pos)
const {
1501 if (!
ST.hasGFX90AInsts())
1508 if (Pos == Position::AFTER)
1511 if (canAffectGlobalAddrSpace(AddrSpace)) {
1513 case SIAtomicScope::SYSTEM:
1525 case SIAtomicScope::AGENT:
1526 if (
ST.hasGFX940Insts()) {
1533 case SIAtomicScope::WORKGROUP:
1534 case SIAtomicScope::WAVEFRONT:
1535 case SIAtomicScope::SINGLETHREAD:
1545 if (Pos == Position::AFTER)
1551bool SIGfx10CacheControl::enableLoadCacheBypass(
1553 SIAtomicAddrSpace AddrSpace)
const {
1557 if (canAffectGlobalAddrSpace(AddrSpace)) {
1559 case SIAtomicScope::SYSTEM:
1560 case SIAtomicScope::AGENT:
1567 case SIAtomicScope::WORKGROUP:
1572 if (!
ST.isCuModeEnabled())
1575 case SIAtomicScope::WAVEFRONT:
1576 case SIAtomicScope::SINGLETHREAD:
1594bool SIGfx10CacheControl::enableVolatileAndOrNonTemporal(
1596 bool IsVolatile,
bool IsNonTemporal,
bool IsLastUse =
false)
const {
1607 assert(
Op == SIMemOp::LOAD ||
Op == SIMemOp::STORE);
1615 if (
Op == SIMemOp::LOAD) {
1628 Changed |= insertWait(
MI, SIAtomicScope::SYSTEM, AddrSpace,
Op,
false,
1629 Position::AFTER, AtomicOrdering::Unordered,
1634 if (IsNonTemporal) {
1639 if (
Op == SIMemOp::STORE)
1654 SIAtomicScope Scope,
1655 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
1656 bool IsCrossAddrSpaceOrdering,
1658 bool AtomicsOnly)
const {
1664 if (Pos == Position::AFTER)
1669 bool LGKMCnt =
false;
1671 if ((AddrSpace & (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH)) !=
1672 SIAtomicAddrSpace::NONE) {
1674 case SIAtomicScope::SYSTEM:
1675 case SIAtomicScope::AGENT:
1676 if ((
Op & SIMemOp::LOAD) != SIMemOp::NONE)
1678 if ((
Op & SIMemOp::STORE) != SIMemOp::NONE)
1681 case SIAtomicScope::WORKGROUP:
1691 if ((
Op & SIMemOp::LOAD) != SIMemOp::NONE)
1693 if ((
Op & SIMemOp::STORE) != SIMemOp::NONE)
1697 case SIAtomicScope::WAVEFRONT:
1698 case SIAtomicScope::SINGLETHREAD:
1707 if ((AddrSpace & SIAtomicAddrSpace::LDS) != SIAtomicAddrSpace::NONE) {
1709 case SIAtomicScope::SYSTEM:
1710 case SIAtomicScope::AGENT:
1711 case SIAtomicScope::WORKGROUP:
1718 LGKMCnt |= IsCrossAddrSpaceOrdering;
1720 case SIAtomicScope::WAVEFRONT:
1721 case SIAtomicScope::SINGLETHREAD:
1730 if ((AddrSpace & SIAtomicAddrSpace::GDS) != SIAtomicAddrSpace::NONE) {
1732 case SIAtomicScope::SYSTEM:
1733 case SIAtomicScope::AGENT:
1740 LGKMCnt |= IsCrossAddrSpaceOrdering;
1742 case SIAtomicScope::WORKGROUP:
1743 case SIAtomicScope::WAVEFRONT:
1744 case SIAtomicScope::SINGLETHREAD:
1753 if (VMCnt || LGKMCnt) {
1754 unsigned WaitCntImmediate =
1760 .
addImm(WaitCntImmediate);
1768 Scope == SIAtomicScope::WORKGROUP &&
1769 (AddrSpace & SIAtomicAddrSpace::LDS) != SIAtomicAddrSpace::NONE) {
1776 .
addReg(AMDGPU::SGPR_NULL, RegState::Undef)
1781 if (Pos == Position::AFTER)
1788 SIAtomicScope Scope,
1789 SIAtomicAddrSpace AddrSpace,
1790 Position Pos)
const {
1791 if (!InsertCacheInv)
1799 if (Pos == Position::AFTER)
1802 if (canAffectGlobalAddrSpace(AddrSpace)) {
1804 case SIAtomicScope::SYSTEM:
1805 case SIAtomicScope::AGENT:
1813 case SIAtomicScope::WORKGROUP:
1818 if (!
ST.isCuModeEnabled()) {
1823 case SIAtomicScope::WAVEFRONT:
1824 case SIAtomicScope::SINGLETHREAD:
1839 if (Pos == Position::AFTER)
1847 MachineOperand *
CPol =
TII->getNamedOperand(*
MI, OpName::cpol);
1862 MachineOperand *
CPol =
TII->getNamedOperand(*
MI, OpName::cpol);
1875bool SIGfx12CacheControl::insertWaitsBeforeSystemScopeStore(
1883 if (
ST.hasImageInsts()) {
1894 SIAtomicScope Scope,
1895 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
1896 bool IsCrossAddrSpaceOrdering,
1898 bool AtomicsOnly)
const {
1904 bool LOADCnt =
false;
1906 bool STORECnt =
false;
1908 if (Pos == Position::AFTER)
1911 if ((AddrSpace & (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH)) !=
1912 SIAtomicAddrSpace::NONE) {
1914 case SIAtomicScope::SYSTEM:
1915 case SIAtomicScope::AGENT:
1916 case SIAtomicScope::CLUSTER:
1917 if ((
Op & SIMemOp::LOAD) != SIMemOp::NONE)
1919 if ((
Op & SIMemOp::STORE) != SIMemOp::NONE)
1922 case SIAtomicScope::WORKGROUP:
1939 if (!
ST.isCuModeEnabled() ||
ST.hasGFX1250Insts() ||
1941 if ((
Op & SIMemOp::LOAD) != SIMemOp::NONE)
1943 if ((
Op & SIMemOp::STORE) != SIMemOp::NONE)
1947 case SIAtomicScope::WAVEFRONT:
1948 case SIAtomicScope::SINGLETHREAD:
1957 if ((AddrSpace & SIAtomicAddrSpace::LDS) != SIAtomicAddrSpace::NONE) {
1959 case SIAtomicScope::SYSTEM:
1960 case SIAtomicScope::AGENT:
1961 case SIAtomicScope::CLUSTER:
1962 case SIAtomicScope::WORKGROUP:
1969 DSCnt |= IsCrossAddrSpaceOrdering;
1971 case SIAtomicScope::WAVEFRONT:
1972 case SIAtomicScope::SINGLETHREAD:
1993 if (!AtomicsOnly &&
ST.hasImageInsts()) {
2011 if (Pos == Position::AFTER)
2018 SIAtomicScope Scope,
2019 SIAtomicAddrSpace AddrSpace,
2020 Position Pos)
const {
2021 if (!InsertCacheInv)
2033 if (!canAffectGlobalAddrSpace(AddrSpace))
2038 case SIAtomicScope::SYSTEM:
2041 case SIAtomicScope::AGENT:
2044 case SIAtomicScope::CLUSTER:
2047 case SIAtomicScope::WORKGROUP:
2055 if (
ST.isCuModeEnabled())
2060 case SIAtomicScope::WAVEFRONT:
2061 case SIAtomicScope::SINGLETHREAD:
2068 if (Pos == Position::AFTER)
2073 if (Pos == Position::AFTER)
2078 if (
ST.hasINVWBL2WaitCntRequirement() && Scope > SIAtomicScope::CLUSTER) {
2079 insertWait(
MI, Scope, AddrSpace, SIMemOp::LOAD,
2080 false, Pos, AtomicOrdering::Acquire,
2083 if (Pos == Position::AFTER)
2091 SIAtomicScope Scope,
2092 SIAtomicAddrSpace AddrSpace,
2093 Position Pos)
const {
2098 if (!canAffectGlobalAddrSpace(AddrSpace))
2105 if (Pos == Position::AFTER)
2114 std::optional<AMDGPU::CPol::CPol> NeedsWB;
2116 case SIAtomicScope::SYSTEM:
2119 case SIAtomicScope::AGENT:
2121 if (
ST.hasGFX1250Insts())
2124 case SIAtomicScope::CLUSTER:
2125 case SIAtomicScope::WORKGROUP:
2126 case SIAtomicScope::WAVEFRONT:
2127 case SIAtomicScope::SINGLETHREAD:
2129 case SIAtomicScope::NONE:
2138 if (
ST.hasINVWBL2WaitCntRequirement()) {
2139 insertWait(
MI, Scope, AddrSpace, SIMemOp::LOAD | SIMemOp::STORE,
2141 AtomicOrdering::Release,
2149 if (Pos == Position::AFTER)
2155bool SIGfx12CacheControl::handleNonVolatile(MachineInstr &
MI)
const {
2157 if (!
ST.hasGFX1250Insts())
2159 MachineOperand *
CPol =
TII->getNamedOperand(
MI, OpName::cpol);
2166bool SIGfx12CacheControl::enableVolatileAndOrNonTemporal(
2168 bool IsVolatile,
bool IsNonTemporal,
bool IsLastUse =
false)
const {
2177 assert(
Op == SIMemOp::LOAD ||
Op == SIMemOp::STORE);
2184 }
else if (IsNonTemporal) {
2192 if (
ST.requiresWaitXCntForSingleAccessInstructions() &&
2204 Changed |= insertWait(
MI, SIAtomicScope::SYSTEM, AddrSpace,
Op,
false,
2205 Position::AFTER, AtomicOrdering::Unordered,
2212bool SIGfx12CacheControl::finalizeStore(MachineInstr &
MI,
bool Atomic)
const {
2213 assert(
MI.mayStore() &&
"Not a Store inst");
2214 const bool IsRMW = (
MI.mayLoad() &&
MI.mayStore());
2217 if (Atomic &&
ST.requiresWaitXCntForSingleAccessInstructions() &&
2228 MachineOperand *
CPol =
TII->getNamedOperand(
MI, OpName::cpol);
2234 if (
ST.requiresWaitsBeforeSystemScopeStores() && !Atomic &&
2236 Changed |= insertWaitsBeforeSystemScopeStore(
MI.getIterator());
2246 MachineOperand *
CPol =
TII->getNamedOperand(*
MI, AMDGPU::OpName::cpol);
2247 assert(CPol &&
"load_monitor must have a cpol operand");
2253bool SIGfx12CacheControl::handleCooperativeAtomic(MachineInstr &
MI)
const {
2254 if (!
ST.hasGFX1250Insts())
2258 MachineOperand *
CPol =
TII->getNamedOperand(
MI, OpName::cpol);
2259 assert(CPol &&
"No CPol operand?");
2267 SIAtomicScope Scope,
2268 SIAtomicAddrSpace AddrSpace)
const {
2271 if (canAffectGlobalAddrSpace(AddrSpace)) {
2273 case SIAtomicScope::SYSTEM:
2276 case SIAtomicScope::AGENT:
2279 case SIAtomicScope::CLUSTER:
2282 case SIAtomicScope::WORKGROUP:
2285 if (!
ST.isCuModeEnabled())
2288 case SIAtomicScope::WAVEFRONT:
2289 case SIAtomicScope::SINGLETHREAD:
2307bool SIMemoryLegalizer::removeAtomicPseudoMIs() {
2308 if (AtomicPseudoMIs.empty())
2311 for (
auto &
MI : AtomicPseudoMIs)
2312 MI->eraseFromParent();
2314 AtomicPseudoMIs.clear();
2318bool SIMemoryLegalizer::expandLoad(
const SIMemOpInfo &MOI,
2326 if (MOI.isAtomic()) {
2328 <<
", scope=" <<
toString(MOI.getScope())
2329 <<
", ordering-AS=" << MOI.getOrderingAddrSpace()
2330 <<
", instr-AS=" << MOI.getInstrAddrSpace() <<
"\n");
2332 if (Order == AtomicOrdering::Monotonic ||
2333 Order == AtomicOrdering::Acquire ||
2334 Order == AtomicOrdering::SequentiallyConsistent) {
2335 Changed |= CC->enableLoadCacheBypass(
MI, MOI.getScope(),
2336 MOI.getOrderingAddrSpace());
2341 if (MOI.isCooperative())
2342 Changed |= CC->handleCooperativeAtomic(*
MI);
2344 if (Order == AtomicOrdering::SequentiallyConsistent)
2345 Changed |= CC->insertWait(
MI, MOI.getScope(), MOI.getOrderingAddrSpace(),
2346 SIMemOp::LOAD | SIMemOp::STORE,
2347 MOI.getIsCrossAddressSpaceOrdering(),
2348 Position::BEFORE, Order,
false);
2350 if (Order == AtomicOrdering::Acquire ||
2351 Order == AtomicOrdering::SequentiallyConsistent) {
2354 CC->insertWait(
MI, MOI.getScope(), MOI.getInstrAddrSpace(),
2355 SIMemOp::LOAD, MOI.getIsCrossAddressSpaceOrdering(),
2356 Position::AFTER, Order,
true);
2357 if (!MOI.isAVNone()) {
2359 MI, MOI.getScope(), MOI.getOrderingAddrSpace(), Position::AFTER);
2370 Changed |= CC->enableVolatileAndOrNonTemporal(
2371 MI, MOI.getInstrAddrSpace(), SIMemOp::LOAD, MOI.isVolatile(),
2372 MOI.isNonTemporal(), MOI.isLastUse());
2378bool SIMemoryLegalizer::expandStore(
const SIMemOpInfo &MOI,
2386 MachineInstr &StoreMI = *
MI;
2388 if (MOI.isAtomic()) {
2390 <<
", scope=" <<
toString(MOI.getScope())
2391 <<
", ordering-AS=" << MOI.getOrderingAddrSpace()
2392 <<
", instr-AS=" << MOI.getInstrAddrSpace() <<
"\n");
2393 if (MOI.getOrdering() == AtomicOrdering::Monotonic ||
2394 MOI.getOrdering() == AtomicOrdering::Release ||
2395 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) {
2396 Changed |= CC->enableStoreCacheBypass(
MI, MOI.getScope(),
2397 MOI.getOrderingAddrSpace());
2402 if (MOI.isCooperative())
2403 Changed |= CC->handleCooperativeAtomic(*
MI);
2405 if (MOI.getOrdering() == AtomicOrdering::Release ||
2406 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) {
2408 CC->insertRelease(
MI, MOI.getScope(), MOI.getOrderingAddrSpace(),
2409 MOI.getIsCrossAddressSpaceOrdering(),
2410 Position::BEFORE, MOI.isAVNone());
2413 Changed |= CC->finalizeStore(StoreMI,
true);
2420 Changed |= CC->enableVolatileAndOrNonTemporal(
2421 MI, MOI.getInstrAddrSpace(), SIMemOp::STORE, MOI.isVolatile(),
2422 MOI.isNonTemporal());
2426 Changed |= CC->finalizeStore(StoreMI,
false);
2430bool SIMemoryLegalizer::expandAtomicFence(
const SIMemOpInfo &MOI,
2432 assert(
MI->getOpcode() == AMDGPU::ATOMIC_FENCE);
2436 AtomicPseudoMIs.push_back(
MI);
2439 const SIAtomicAddrSpace OrderingAddrSpace = MOI.getOrderingAddrSpace();
2441 if (MOI.isAtomic()) {
2443 <<
", scope=" <<
toString(MOI.getScope())
2444 <<
", ordering-AS=" << OrderingAddrSpace <<
"\n");
2446 if (Order == AtomicOrdering::Acquire) {
2448 Changed |= CC->insertWait(
MI, MOI.getScope(), OrderingAddrSpace,
2449 SIMemOp::LOAD | SIMemOp::STORE,
2450 MOI.getIsCrossAddressSpaceOrdering(),
2451 Position::BEFORE, Order,
true);
2454 if (Order == AtomicOrdering::Release ||
2455 Order == AtomicOrdering::AcquireRelease ||
2456 Order == AtomicOrdering::SequentiallyConsistent) {
2464 Changed |= CC->insertRelease(
MI, MOI.getScope(), OrderingAddrSpace,
2465 MOI.getIsCrossAddressSpaceOrdering(),
2466 Position::BEFORE, MOI.isAVNone());
2474 if ((Order == AtomicOrdering::Acquire ||
2475 Order == AtomicOrdering::AcquireRelease ||
2476 Order == AtomicOrdering::SequentiallyConsistent) &&
2478 Changed |= CC->insertAcquire(
MI, MOI.getScope(), OrderingAddrSpace,
2488bool SIMemoryLegalizer::expandAtomicCmpxchgOrRmw(
const SIMemOpInfo &MOI,
2495 MachineInstr &RMWMI = *
MI;
2497 if (MOI.isAtomic()) {
2499 <<
", failure-ordering="
2501 <<
", scope=" <<
toString(MOI.getScope())
2502 <<
", ordering-AS=" << MOI.getOrderingAddrSpace()
2503 <<
", instr-AS=" << MOI.getInstrAddrSpace() <<
"\n");
2505 if (Order == AtomicOrdering::Monotonic ||
2506 Order == AtomicOrdering::Acquire || Order == AtomicOrdering::Release ||
2507 Order == AtomicOrdering::AcquireRelease ||
2508 Order == AtomicOrdering::SequentiallyConsistent) {
2509 Changed |= CC->enableRMWCacheBypass(
MI, MOI.getScope(),
2510 MOI.getInstrAddrSpace());
2513 if (Order == AtomicOrdering::Release ||
2514 Order == AtomicOrdering::AcquireRelease ||
2515 Order == AtomicOrdering::SequentiallyConsistent ||
2516 MOI.getFailureOrdering() == AtomicOrdering::SequentiallyConsistent) {
2518 CC->insertRelease(
MI, MOI.getScope(), MOI.getOrderingAddrSpace(),
2519 MOI.getIsCrossAddressSpaceOrdering(),
2520 Position::BEFORE, MOI.isAVNone());
2523 if (Order == AtomicOrdering::Acquire ||
2524 Order == AtomicOrdering::AcquireRelease ||
2525 Order == AtomicOrdering::SequentiallyConsistent ||
2526 MOI.getFailureOrdering() == AtomicOrdering::Acquire ||
2527 MOI.getFailureOrdering() == AtomicOrdering::SequentiallyConsistent) {
2530 CC->insertWait(
MI, MOI.getScope(), MOI.getInstrAddrSpace(),
2532 MOI.getIsCrossAddressSpaceOrdering(), Position::AFTER,
2534 if (!MOI.isAVNone()) {
2536 MI, MOI.getScope(), MOI.getOrderingAddrSpace(), Position::AFTER);
2540 Changed |= CC->finalizeStore(RMWMI,
true);
2547bool SIMemoryLegalizer::expandLDSDMA(
const SIMemOpInfo &MOI,
2561 return CC->enableVolatileAndOrNonTemporal(
2562 MI, MOI.getInstrAddrSpace(), OpKind, MOI.isVolatile(),
2563 MOI.isNonTemporal(), MOI.isLastUse());
2566bool SIMemoryLegalizerLegacy::runOnMachineFunction(
MachineFunction &MF) {
2567 const MachineModuleInfo &MMI =
2568 getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
2569 return SIMemoryLegalizer(MMI).run(MF);
2576 .getCachedResult<MachineModuleAnalysis>(
2578 assert(MMI &&
"MachineModuleAnalysis must be available");
2579 if (!SIMemoryLegalizer(MMI->getMMI()).run(MF))
2591 CC = SICacheControl::create(ST, TgSplit);
2593 for (
auto &
MBB : MF) {
2597 if (
MI->isBundle() &&
MI->mayLoadOrStore()) {
2600 I != E &&
I->isBundledWithPred(); ++
I) {
2601 I->unbundleFromPred();
2604 MO.setIsInternalRead(
false);
2607 MI =
MI->eraseFromParent();
2611 if (
const auto &MOI = MOA.getLoadInfo(
MI))
2613 else if (
const auto &MOI = MOA.getStoreInfo(
MI))
2615 else if (
const auto &MOI = MOA.getLDSDMAInfo(
MI))
2617 else if (
const auto &MOI = MOA.getAtomicFenceInfo(
MI))
2619 else if (
const auto &MOI = MOA.getAtomicCmpxchgOrRmwInfo(
MI))
2620 Changed |= expandAtomicCmpxchgOrRmw(*MOI,
MI);
2628 Changed |= removeAtomicPseudoMIs();
2634char SIMemoryLegalizerLegacy::ID = 0;
2638 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.
This file provides utility for Memory Model Relaxation Annotations (MMRAs).
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static cl::opt< bool > AmdgcnSkipCacheInvalidations("amdgcn-skip-cache-invalidations", cl::init(false), cl::Hidden, cl::desc("Use this to skip inserting cache invalidating instructions."))
static bool isNonVolatileMemoryAccess(const MachineInstr &MI)
static bool canUseBUFFER_WBINVL1_VOL(const GCNSubtarget &ST)
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.
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.
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.
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",...
Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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 isAtomicRet(const T &...O)
constexpr bool isMaybeAtomic(const T &...O)
constexpr bool isAtomic(const T &...O)
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
@ System
Synchronized with respect to all concurrently executing threads.
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
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()
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.
FunctionPass * createSIMemoryLegalizerPass()