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:
121 if (
any(AS & SIAtomicAddrSpace::GLOBAL))
122 OS <<
LS <<
"global";
123 if (
any(AS & SIAtomicAddrSpace::LDS))
125 if (
any(AS & SIAtomicAddrSpace::SCRATCH))
126 OS <<
LS <<
"scratch";
127 if (
any(AS & SIAtomicAddrSpace::GDS))
129 if (
any(AS & SIAtomicAddrSpace::OTHER))
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;
151 unsigned CFSBits = 0;
155 const GCNSubtarget &ST,
157 SIAtomicScope Scope = SIAtomicScope::SYSTEM,
158 SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::ATOMIC,
159 SIAtomicAddrSpace InstrAddrSpace = SIAtomicAddrSpace::ALL,
160 bool IsCrossAddressSpaceOrdering =
true,
161 AtomicOrdering FailureOrdering = AtomicOrdering::SequentiallyConsistent,
162 bool IsVolatile =
false,
bool IsNonTemporal =
false,
163 bool IsLastUse =
false,
bool IsCooperative =
false,
bool IsAVNone =
false,
164 bool CanDemoteWorkgroupToWavefront =
false,
unsigned CFSBits = 0)
165 : Ordering(Ordering), FailureOrdering(FailureOrdering), Scope(Scope),
166 OrderingAddrSpace(OrderingAddrSpace), InstrAddrSpace(InstrAddrSpace),
167 IsCrossAddressSpaceOrdering(IsCrossAddressSpaceOrdering),
168 IsVolatile(IsVolatile), IsNonTemporal(IsNonTemporal),
169 IsLastUse(IsLastUse), IsCooperative(IsCooperative), IsAVNone(IsAVNone),
172 if (Ordering == AtomicOrdering::NotAtomic) {
173 assert(!IsCooperative &&
"Cannot be cooperative & non-atomic!");
174 assert(Scope == SIAtomicScope::NONE && !
any(OrderingAddrSpace) &&
175 !IsCrossAddressSpaceOrdering &&
176 FailureOrdering == AtomicOrdering::NotAtomic);
180 assert(Scope != SIAtomicScope::NONE &&
181 any(OrderingAddrSpace & SIAtomicAddrSpace::ATOMIC) &&
182 any(InstrAddrSpace & SIAtomicAddrSpace::ATOMIC));
187 if ((OrderingAddrSpace == InstrAddrSpace) &&
189 this->IsCrossAddressSpaceOrdering =
false;
193 if (!(InstrAddrSpace & ~SIAtomicAddrSpace::SCRATCH)) {
194 this->Scope = std::min(Scope, SIAtomicScope::SINGLETHREAD);
195 }
else if (!(InstrAddrSpace &
196 ~(SIAtomicAddrSpace::SCRATCH | SIAtomicAddrSpace::LDS))) {
197 this->Scope = std::min(Scope, SIAtomicScope::WORKGROUP);
198 }
else if (!(InstrAddrSpace &
199 ~(SIAtomicAddrSpace::SCRATCH | SIAtomicAddrSpace::LDS |
200 SIAtomicAddrSpace::GDS))) {
201 this->Scope = std::min(Scope, SIAtomicScope::AGENT);
206 if (this->Scope == SIAtomicScope::CLUSTER && !
ST.hasClusters())
207 this->Scope = SIAtomicScope::AGENT;
209 if (CanDemoteWorkgroupToWavefront &&
210 this->Scope == SIAtomicScope::WORKGROUP)
211 this->Scope = SIAtomicScope::WAVEFRONT;
230 return FailureOrdering;
235 SIAtomicAddrSpace getInstrAddrSpace()
const {
236 return InstrAddrSpace;
241 SIAtomicAddrSpace getOrderingAddrSpace()
const {
242 return OrderingAddrSpace;
247 bool getIsCrossAddressSpaceOrdering()
const {
248 return IsCrossAddressSpaceOrdering;
253 bool isVolatile()
const {
259 bool isNonTemporal()
const {
260 return IsNonTemporal;
265 bool isLastUse()
const {
return IsLastUse; }
268 bool isCooperative()
const {
return IsCooperative; }
271 bool isAVNone()
const {
return IsAVNone; }
276 return Ordering != AtomicOrdering::NotAtomic;
280 unsigned getCFS()
const {
return CFSBits; }
283class SIMemOpAccess final {
285 const AMDGPUMachineModuleInfo *MMI =
nullptr;
286 const GCNSubtarget &ST;
287 const bool CanDemoteWorkgroupToWavefront;
291 const char *
Msg)
const;
297 std::optional<std::tuple<SIAtomicScope, SIAtomicAddrSpace, bool>>
298 toSIAtomicScope(
SyncScope::ID SSID, SIAtomicAddrSpace InstrAddrSpace)
const;
301 SIAtomicAddrSpace toSIAtomicAddrSpace(
unsigned AS)
const;
305 std::optional<SIMemOpInfo>
311 SIMemOpAccess(
const AMDGPUMachineModuleInfo &MMI,
const GCNSubtarget &ST,
315 std::optional<SIMemOpInfo>
320 std::optional<SIMemOpInfo>
325 std::optional<SIMemOpInfo>
330 std::optional<SIMemOpInfo>
336 std::optional<SIMemOpInfo>
340class SICacheControl {
344 const GCNSubtarget &ST;
347 const SIInstrInfo *TII =
nullptr;
357 SICacheControl(
const GCNSubtarget &ST,
bool TgSplit);
362 unsigned Bits)
const;
366 bool canAffectGlobalAddrSpace(SIAtomicAddrSpace AS)
const;
372 static std::unique_ptr<SICacheControl> create(
const GCNSubtarget &ST,
380 SIAtomicAddrSpace AddrSpace)
const = 0;
387 SIAtomicAddrSpace AddrSpace)
const = 0;
394 SIAtomicAddrSpace AddrSpace)
const = 0;
400 SIAtomicAddrSpace AddrSpace,
401 SIMemOp
Op,
bool IsVolatile,
403 bool IsLastUse =
false)
const = 0;
410 virtual bool finalizeStore(MachineInstr &
MI,
bool Atomic)
const {
420 virtual bool handleCooperativeAtomic(MachineInstr &
MI)
const {
422 "cooperative atomics are not available on this architecture");
435 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
436 bool IsCrossAddrSpaceOrdering, Position Pos,
446 SIAtomicAddrSpace AddrSpace,
447 Position Pos)
const = 0;
455 SIAtomicScope Scope, SIAtomicAddrSpace AddrSpace,
456 Position Pos)
const = 0;
460 SIAtomicAddrSpace AddrSpace,
bool IsCrossAddrSpaceOrdering,
461 Position Pos,
bool IsAVNone)
const {
462 bool Changed = !IsAVNone && insertWriteback(
MI, Scope, AddrSpace, Pos);
463 Changed |= insertWait(
MI, Scope, AddrSpace, SIMemOp::LOAD | SIMemOp::STORE,
464 IsCrossAddrSpaceOrdering, Pos,
465 AtomicOrdering::Release,
false);
471 virtual bool handleNonVolatile(MachineInstr &
MI)
const {
return false; }
474 unsigned CFSBits = 0)
const {
479 virtual ~SICacheControl() =
default;
484class SIGfx6CacheControl final :
public SICacheControl {
486 SIGfx6CacheControl(
const GCNSubtarget &ST,
bool TgSplit)
487 : SICacheControl(
ST, TgSplit) {}
491 SIAtomicAddrSpace AddrSpace)
const override;
495 SIAtomicAddrSpace AddrSpace)
const override;
499 SIAtomicAddrSpace AddrSpace)
const override;
502 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
503 bool IsVolatile,
bool IsNonTemporal,
504 bool IsLastUse)
const override;
507 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
508 bool IsCrossAddrSpaceOrdering, Position Pos,
513 SIAtomicAddrSpace AddrSpace,
514 Position Pos)
const override;
517 SIAtomicAddrSpace AddrSpace,
518 Position Pos)
const override;
522class SIGfx10CacheControl final :
public SICacheControl {
524 SIGfx10CacheControl(
const GCNSubtarget &ST,
bool TgSplit)
525 : SICacheControl(
ST, TgSplit) {}
529 SIAtomicAddrSpace AddrSpace)
const override;
533 SIAtomicAddrSpace AddrSpace)
const override {
539 SIAtomicAddrSpace AddrSpace)
const override {
544 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
545 bool IsVolatile,
bool IsNonTemporal,
546 bool IsLastUse)
const override;
549 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
550 bool IsCrossAddrSpaceOrdering, Position Pos,
554 SIAtomicAddrSpace AddrSpace, Position Pos)
const override;
557 SIAtomicAddrSpace AddrSpace,
558 Position Pos)
const override {
563class SIGfx12CacheControl final :
public SICacheControl {
585 SIAtomicScope Scope, SIAtomicAddrSpace AddrSpace)
const;
588 SIGfx12CacheControl(
const GCNSubtarget &ST,
bool TgSplit)
589 : SICacheControl(
ST, TgSplit) {
592 assert(!
ST.hasGFX1250Insts() ||
ST.hasGFX13Insts() ||
ST.isCuModeEnabled());
596 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
597 bool IsCrossAddrSpaceOrdering, Position Pos,
601 SIAtomicAddrSpace AddrSpace, Position Pos)
const override;
604 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
605 bool IsVolatile,
bool IsNonTemporal,
606 bool IsLastUse)
const override;
608 bool finalizeStore(MachineInstr &
MI,
bool Atomic)
const override;
612 bool handleCooperativeAtomic(MachineInstr &
MI)
const override;
615 SIAtomicAddrSpace AddrSpace,
616 Position Pos)
const override;
620 SIAtomicAddrSpace AddrSpace)
const override {
621 return setAtomicScope(
MI, Scope, AddrSpace);
626 SIAtomicAddrSpace AddrSpace)
const override {
627 return setAtomicScope(
MI, Scope, AddrSpace);
632 SIAtomicAddrSpace AddrSpace)
const override {
633 return setAtomicScope(
MI, Scope, AddrSpace);
636 bool handleNonVolatile(MachineInstr &
MI)
const override;
639 unsigned CFSBits)
const override;
642class SIMemoryLegalizer final {
644 const MachineModuleInfo &MMI;
646 std::unique_ptr<SICacheControl> CC =
nullptr;
649 std::list<MachineBasicBlock::iterator> AtomicPseudoMIs;
659 bool removeAtomicPseudoMIs();
663 bool expandLoad(
const SIMemOpInfo &MOI,
667 bool expandStore(
const SIMemOpInfo &MOI,
671 bool expandAtomicFence(
const SIMemOpInfo &MOI,
675 bool expandAtomicCmpxchgOrRmw(
const SIMemOpInfo &MOI,
682 SIMemoryLegalizer(
const MachineModuleInfo &MMI) : MMI(MMI) {};
690 SIMemoryLegalizerLegacy() : MachineFunctionPass(ID) {}
692 void getAnalysisUsage(AnalysisUsage &AU)
const override {
697 StringRef getPassName()
const override {
705 {
"global", SIAtomicAddrSpace::GLOBAL},
706 {
"local", SIAtomicAddrSpace::LDS},
714 OS <<
"unknown address space '" << AS <<
"'; expected one of ";
716 for (
const auto &[Name, Val] : ASNames)
717 OS <<
LS <<
'\'' <<
Name <<
'\'';
725static std::optional<SIAtomicAddrSpace>
727 static constexpr StringLiteral FenceASPrefix =
"amdgpu-synchronize-as";
733 SIAtomicAddrSpace
Result = SIAtomicAddrSpace::NONE;
734 for (
const auto &[Prefix, Suffix] : MMRA) {
735 if (Prefix != FenceASPrefix)
738 if (
auto It = ASNames.find(Suffix); It != ASNames.end())
741 diagnoseUnknownMMRAASName(
MI, Suffix);
755 Fn,
Twine(
"unknown amdgcn-av metadata '") + Suffix +
Twine(
'\''),
763 bool TagFound =
false;
764 for (
const auto &[Prefix, Suffix] : MMRA) {
765 if (Prefix !=
"amdgcn-av")
767 if (Suffix ==
"none")
770 diagnoseUnknownAVMetadata(
MI, Suffix);
778 const char *
Msg)
const {
780 Func.getContext().diagnose(
781 DiagnosticInfoUnsupported(Func,
Msg,
MI->getDebugLoc()));
784std::optional<std::tuple<SIAtomicScope, SIAtomicAddrSpace, bool>>
786 SIAtomicAddrSpace InstrAddrSpace)
const {
788 return std::tuple(SIAtomicScope::SYSTEM, SIAtomicAddrSpace::ATOMIC,
true);
790 return std::tuple(SIAtomicScope::AGENT, SIAtomicAddrSpace::ATOMIC,
true);
792 return std::tuple(SIAtomicScope::CLUSTER, SIAtomicAddrSpace::ATOMIC,
true);
794 return std::tuple(SIAtomicScope::WORKGROUP, SIAtomicAddrSpace::ATOMIC,
797 return std::tuple(SIAtomicScope::WAVEFRONT, SIAtomicAddrSpace::ATOMIC,
800 return std::tuple(SIAtomicScope::SINGLETHREAD, SIAtomicAddrSpace::ATOMIC,
803 return std::tuple(SIAtomicScope::SYSTEM,
804 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
806 return std::tuple(SIAtomicScope::AGENT,
807 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
809 return std::tuple(SIAtomicScope::CLUSTER,
810 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
812 return std::tuple(SIAtomicScope::WORKGROUP,
813 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
815 return std::tuple(SIAtomicScope::WAVEFRONT,
816 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
818 return std::tuple(SIAtomicScope::SINGLETHREAD,
819 SIAtomicAddrSpace::ATOMIC & InstrAddrSpace,
false);
823SIAtomicAddrSpace SIMemOpAccess::toSIAtomicAddrSpace(
unsigned AS)
const {
825 return SIAtomicAddrSpace::FLAT;
827 return SIAtomicAddrSpace::GLOBAL;
829 return SIAtomicAddrSpace::LDS;
831 return SIAtomicAddrSpace::SCRATCH;
833 return SIAtomicAddrSpace::GDS;
836 return SIAtomicAddrSpace::GLOBAL;
838 return SIAtomicAddrSpace::OTHER;
844SIMemOpAccess::SIMemOpAccess(
const AMDGPUMachineModuleInfo &MMI_,
846 : MMI(&MMI_),
ST(
ST),
847 CanDemoteWorkgroupToWavefront(
849 MF.
getFunction().hasFnAttribute(
"amdgpu-no-lds-dma")) {}
851std::optional<SIMemOpInfo> SIMemOpAccess::constructFromMIWithMMO(
853 assert(
MI->getNumMemOperands() > 0);
855 std::optional<SyncScope::ID> MergedSSID;
858 SIAtomicAddrSpace InstrAddrSpace = SIAtomicAddrSpace::NONE;
859 bool IsNonTemporal =
true;
861 bool IsLastUse =
false;
862 bool IsCooperative =
false;
863 unsigned CFSBits = 0;
867 for (
const auto &MMO :
MI->memoperands()) {
868 IsNonTemporal &= MMO->isNonTemporal();
870 IsLastUse |= MMO->getFlags() &
MOLastUse;
873 InstrAddrSpace |= toSIAtomicAddrSpace(MMO->getPointerInfo().getAddrSpace());
875 if (OpOrdering != AtomicOrdering::NotAtomic) {
878 SyncScope::ID CurSSID = MergedSSID.value_or(MMO->getSyncScopeID());
885 MergedSSID = *Merged;
887 assert(MMO->getFailureOrdering() != AtomicOrdering::Release &&
888 MMO->getFailureOrdering() != AtomicOrdering::AcquireRelease);
900 Ordering = AtomicOrdering::Monotonic;
902 SIAtomicScope
Scope = SIAtomicScope::NONE;
903 SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::NONE;
904 bool IsCrossAddressSpaceOrdering =
false;
905 if (Ordering != AtomicOrdering::NotAtomic) {
906 auto ScopeOrNone = toSIAtomicScope(SSID, InstrAddrSpace);
911 std::tie(Scope, OrderingAddrSpace, IsCrossAddressSpaceOrdering) =
913 if (!OrderingAddrSpace ||
914 ((OrderingAddrSpace & SIAtomicAddrSpace::ATOMIC) !=
915 OrderingAddrSpace) ||
916 !(InstrAddrSpace & SIAtomicAddrSpace::ATOMIC)) {
921 return SIMemOpInfo(ST, Ordering, Scope, OrderingAddrSpace, InstrAddrSpace,
922 IsCrossAddressSpaceOrdering, FailureOrdering, IsVolatile,
923 IsNonTemporal, IsLastUse, IsCooperative,
924 hasAVNoneMMRA(*
MI), CanDemoteWorkgroupToWavefront,
928std::optional<SIMemOpInfo>
932 if (!(
MI->mayLoad() && !
MI->mayStore()))
936 if (
MI->getNumMemOperands() == 0)
937 return SIMemOpInfo(ST);
939 return constructFromMIWithMMO(
MI);
942std::optional<SIMemOpInfo>
946 if (!(!
MI->mayLoad() &&
MI->mayStore()))
950 if (
MI->getNumMemOperands() == 0)
951 return SIMemOpInfo(ST);
953 return constructFromMIWithMMO(
MI);
956std::optional<SIMemOpInfo>
960 if (
MI->getOpcode() != AMDGPU::ATOMIC_FENCE)
967 auto ScopeOrNone = toSIAtomicScope(SSID, SIAtomicAddrSpace::ATOMIC);
973 SIAtomicScope
Scope = SIAtomicScope::NONE;
974 SIAtomicAddrSpace OrderingAddrSpace = SIAtomicAddrSpace::NONE;
975 bool IsCrossAddressSpaceOrdering =
false;
976 std::tie(Scope, OrderingAddrSpace, IsCrossAddressSpaceOrdering) =
979 if (OrderingAddrSpace != SIAtomicAddrSpace::ATOMIC) {
988 auto SynchronizeAS = getSynchronizeAddrSpaceMD(*
MI);
990 OrderingAddrSpace = *SynchronizeAS;
992 return SIMemOpInfo(ST, Ordering, Scope, OrderingAddrSpace,
993 SIAtomicAddrSpace::ATOMIC, IsCrossAddressSpaceOrdering,
994 AtomicOrdering::NotAtomic,
false,
false,
false,
false,
995 hasAVNoneMMRA(*
MI), CanDemoteWorkgroupToWavefront);
998std::optional<SIMemOpInfo> SIMemOpAccess::getAtomicCmpxchgOrRmwInfo(
1002 if (!(
MI->mayLoad() &&
MI->mayStore()))
1003 return std::nullopt;
1006 if (
MI->getNumMemOperands() == 0)
1007 return SIMemOpInfo(ST);
1009 return constructFromMIWithMMO(
MI);
1012std::optional<SIMemOpInfo>
1017 return std::nullopt;
1019 return constructFromMIWithMMO(
MI);
1027 if (
MI.getNumMemOperands() == 0)
1030 return MMO->getFlags() & (MOThreadPrivate | MachineMemOperand::MOInvariant);
1034SICacheControl::SICacheControl(
const GCNSubtarget &ST,
bool TgSplit) :
ST(
ST) {
1035 TII =
ST.getInstrInfo();
1038 TgSplitEnabled = TgSplit;
1042 unsigned Bits)
const {
1043 MachineOperand *CPol =
TII->getNamedOperand(*
MI, AMDGPU::OpName::cpol);
1047 CPol->setImm(
CPol->getImm() | Bits);
1051bool SICacheControl::canAffectGlobalAddrSpace(SIAtomicAddrSpace AS)
const {
1052 assert((!
ST.hasGloballyAddressableScratch() ||
1053 any(AS & SIAtomicAddrSpace::GLOBAL) ||
1054 !(AS & SIAtomicAddrSpace::SCRATCH)) &&
1055 "scratch instructions should already be replaced by flat "
1056 "instructions if GloballyAddressableScratch is enabled");
1057 return any(AS & SIAtomicAddrSpace::GLOBAL);
1061std::unique_ptr<SICacheControl> SICacheControl::create(
const GCNSubtarget &ST,
1063 GCNSubtarget::Generation Generation =
ST.getGeneration();
1064 if (Generation < AMDGPUSubtarget::GFX10)
1065 return std::make_unique<SIGfx6CacheControl>(ST, TgSplit);
1066 if (Generation < AMDGPUSubtarget::GFX12)
1067 return std::make_unique<SIGfx10CacheControl>(ST, TgSplit);
1068 return std::make_unique<SIGfx12CacheControl>(ST, TgSplit);
1071bool SIGfx6CacheControl::enableLoadCacheBypass(
1073 SIAtomicScope Scope,
1074 SIAtomicAddrSpace AddrSpace)
const {
1077 if (!canAffectGlobalAddrSpace(AddrSpace)) {
1089 case SIAtomicScope::SYSTEM:
1090 if (
ST.hasGFX940Insts()) {
1096 case SIAtomicScope::AGENT:
1097 if (
ST.hasGFX940Insts()) {
1106 case SIAtomicScope::WORKGROUP:
1107 if (
ST.hasGFX940Insts()) {
1114 }
else if (
ST.hasGFX90AInsts()) {
1123 case SIAtomicScope::WAVEFRONT:
1124 case SIAtomicScope::SINGLETHREAD:
1134bool SIGfx6CacheControl::enableStoreCacheBypass(
1136 SIAtomicScope Scope,
1137 SIAtomicAddrSpace AddrSpace)
const {
1145 if (
ST.hasGFX940Insts() && canAffectGlobalAddrSpace(AddrSpace)) {
1147 case SIAtomicScope::SYSTEM:
1151 case SIAtomicScope::AGENT:
1155 case SIAtomicScope::WORKGROUP:
1159 case SIAtomicScope::WAVEFRONT:
1160 case SIAtomicScope::SINGLETHREAD:
1178bool SIGfx6CacheControl::enableRMWCacheBypass(
1180 SIAtomicScope Scope,
1181 SIAtomicAddrSpace AddrSpace)
const {
1191 if (
ST.hasGFX940Insts() && canAffectGlobalAddrSpace(AddrSpace)) {
1193 case SIAtomicScope::SYSTEM:
1197 case SIAtomicScope::AGENT:
1198 case SIAtomicScope::WORKGROUP:
1199 case SIAtomicScope::WAVEFRONT:
1200 case SIAtomicScope::SINGLETHREAD:
1214bool SIGfx6CacheControl::enableVolatileAndOrNonTemporal(
1216 bool IsVolatile,
bool IsNonTemporal,
bool IsLastUse =
false)
const {
1226 assert(
Op == SIMemOp::LOAD ||
Op == SIMemOp::STORE);
1231 if (
ST.hasGFX940Insts()) {
1234 }
else if (
Op == SIMemOp::LOAD) {
1246 Changed |= insertWait(
MI, SIAtomicScope::SYSTEM, AddrSpace,
Op,
false,
1247 Position::AFTER, AtomicOrdering::Unordered,
1253 if (IsNonTemporal) {
1254 if (
ST.hasGFX940Insts()) {
1268 SIAtomicScope Scope,
1269 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
1270 bool IsCrossAddrSpaceOrdering, Position Pos,
1272 bool AtomicsOnly)
const {
1278 if (Pos == Position::AFTER)
1282 if (
ST.hasGFX90AInsts() && TgSplitEnabled) {
1291 (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH |
1292 SIAtomicAddrSpace::GDS)) &&
1293 (Scope == SIAtomicScope::WORKGROUP)) {
1295 Scope = SIAtomicScope::AGENT;
1299 AddrSpace &= ~SIAtomicAddrSpace
::LDS;
1303 bool LGKMCnt =
false;
1306 (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH))) {
1308 case SIAtomicScope::SYSTEM:
1309 case SIAtomicScope::AGENT:
1312 case SIAtomicScope::WORKGROUP:
1313 case SIAtomicScope::WAVEFRONT:
1314 case SIAtomicScope::SINGLETHREAD:
1323 if (
any(AddrSpace & SIAtomicAddrSpace::LDS)) {
1325 case SIAtomicScope::SYSTEM:
1326 case SIAtomicScope::AGENT:
1327 case SIAtomicScope::WORKGROUP:
1334 LGKMCnt |= IsCrossAddrSpaceOrdering;
1336 case SIAtomicScope::WAVEFRONT:
1337 case SIAtomicScope::SINGLETHREAD:
1346 if (
any(AddrSpace & SIAtomicAddrSpace::GDS)) {
1348 case SIAtomicScope::SYSTEM:
1349 case SIAtomicScope::AGENT:
1356 LGKMCnt |= IsCrossAddrSpaceOrdering;
1358 case SIAtomicScope::WORKGROUP:
1359 case SIAtomicScope::WAVEFRONT:
1360 case SIAtomicScope::SINGLETHREAD:
1369 if (VMCnt || LGKMCnt) {
1370 unsigned WaitCntImmediate =
1376 .
addImm(WaitCntImmediate);
1384 Scope == SIAtomicScope::WORKGROUP &&
1385 any(AddrSpace & SIAtomicAddrSpace::LDS)) {
1390 if (Pos == Position::AFTER)
1399 return !ST.isAmdPalOS() && !ST.isMesa3DOS();
1403 SIAtomicScope Scope,
1404 SIAtomicAddrSpace AddrSpace,
1405 Position Pos)
const {
1406 if (!InsertCacheInv)
1414 if (Pos == Position::AFTER)
1418 ? AMDGPU::BUFFER_WBINVL1_VOL
1419 : AMDGPU::BUFFER_WBINVL1;
1421 if (canAffectGlobalAddrSpace(AddrSpace)) {
1423 case SIAtomicScope::SYSTEM:
1424 if (
ST.hasBufferInvInst()) {
1440 if (
ST.hasGFX90AInsts()) {
1455 case SIAtomicScope::AGENT:
1456 if (
ST.hasBufferInvInst()) {
1471 case SIAtomicScope::WORKGROUP:
1472 if (TgSplitEnabled) {
1473 if (
ST.hasBufferInvInst()) {
1492 }
else if (
ST.hasGFX90AInsts()) {
1498 case SIAtomicScope::WAVEFRONT:
1499 case SIAtomicScope::SINGLETHREAD:
1516 if (Pos == Position::AFTER)
1523 SIAtomicScope Scope,
1524 SIAtomicAddrSpace AddrSpace,
1525 Position Pos)
const {
1526 if (!
ST.hasGFX90AInsts())
1533 if (Pos == Position::AFTER)
1536 if (canAffectGlobalAddrSpace(AddrSpace)) {
1538 case SIAtomicScope::SYSTEM:
1550 case SIAtomicScope::AGENT:
1551 if (
ST.hasGFX940Insts()) {
1558 case SIAtomicScope::WORKGROUP:
1559 case SIAtomicScope::WAVEFRONT:
1560 case SIAtomicScope::SINGLETHREAD:
1570 if (Pos == Position::AFTER)
1576bool SIGfx10CacheControl::enableLoadCacheBypass(
1578 SIAtomicAddrSpace AddrSpace)
const {
1582 if (canAffectGlobalAddrSpace(AddrSpace)) {
1584 case SIAtomicScope::SYSTEM:
1585 case SIAtomicScope::AGENT:
1592 case SIAtomicScope::WORKGROUP:
1597 if (!
ST.isCuModeEnabled())
1600 case SIAtomicScope::WAVEFRONT:
1601 case SIAtomicScope::SINGLETHREAD:
1619bool SIGfx10CacheControl::enableVolatileAndOrNonTemporal(
1621 bool IsVolatile,
bool IsNonTemporal,
bool IsLastUse =
false)
const {
1632 assert(
Op == SIMemOp::LOAD ||
Op == SIMemOp::STORE);
1640 if (
Op == SIMemOp::LOAD) {
1653 Changed |= insertWait(
MI, SIAtomicScope::SYSTEM, AddrSpace,
Op,
false,
1654 Position::AFTER, AtomicOrdering::Unordered,
1659 if (IsNonTemporal) {
1664 if (
Op == SIMemOp::STORE)
1679 SIAtomicScope Scope,
1680 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
1681 bool IsCrossAddrSpaceOrdering,
1683 bool AtomicsOnly)
const {
1689 if (Pos == Position::AFTER)
1694 bool LGKMCnt =
false;
1697 (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH))) {
1699 case SIAtomicScope::SYSTEM:
1700 case SIAtomicScope::AGENT:
1701 if (
any(
Op & SIMemOp::LOAD))
1703 if (
any(
Op & SIMemOp::STORE))
1706 case SIAtomicScope::WORKGROUP:
1716 if (
any(
Op & SIMemOp::LOAD))
1718 if (
any(
Op & SIMemOp::STORE))
1722 case SIAtomicScope::WAVEFRONT:
1723 case SIAtomicScope::SINGLETHREAD:
1732 if (
any(AddrSpace & SIAtomicAddrSpace::LDS)) {
1734 case SIAtomicScope::SYSTEM:
1735 case SIAtomicScope::AGENT:
1736 case SIAtomicScope::WORKGROUP:
1743 LGKMCnt |= IsCrossAddrSpaceOrdering;
1745 case SIAtomicScope::WAVEFRONT:
1746 case SIAtomicScope::SINGLETHREAD:
1755 if (
any(AddrSpace & SIAtomicAddrSpace::GDS)) {
1757 case SIAtomicScope::SYSTEM:
1758 case SIAtomicScope::AGENT:
1765 LGKMCnt |= IsCrossAddrSpaceOrdering;
1767 case SIAtomicScope::WORKGROUP:
1768 case SIAtomicScope::WAVEFRONT:
1769 case SIAtomicScope::SINGLETHREAD:
1778 if (VMCnt || LGKMCnt) {
1779 unsigned WaitCntImmediate =
1785 .
addImm(WaitCntImmediate);
1793 Scope == SIAtomicScope::WORKGROUP &&
1794 any(AddrSpace & SIAtomicAddrSpace::LDS)) {
1801 .
addReg(AMDGPU::SGPR_NULL, RegState::Undef)
1806 if (Pos == Position::AFTER)
1813 SIAtomicScope Scope,
1814 SIAtomicAddrSpace AddrSpace,
1815 Position Pos)
const {
1816 if (!InsertCacheInv)
1824 if (Pos == Position::AFTER)
1827 if (canAffectGlobalAddrSpace(AddrSpace)) {
1829 case SIAtomicScope::SYSTEM:
1830 case SIAtomicScope::AGENT:
1838 case SIAtomicScope::WORKGROUP:
1843 if (!
ST.isCuModeEnabled()) {
1848 case SIAtomicScope::WAVEFRONT:
1849 case SIAtomicScope::SINGLETHREAD:
1864 if (Pos == Position::AFTER)
1872 MachineOperand *
CPol =
TII->getNamedOperand(*
MI, OpName::cpol);
1887 MachineOperand *
CPol =
TII->getNamedOperand(*
MI, OpName::cpol);
1900bool SIGfx12CacheControl::insertWaitsBeforeSystemScopeStore(
1908 if (
ST.hasImageInsts()) {
1910 if (
ST.hasAnyBVHInsts())
1920 SIAtomicScope Scope,
1921 SIAtomicAddrSpace AddrSpace, SIMemOp
Op,
1922 bool IsCrossAddrSpaceOrdering,
1924 bool AtomicsOnly)
const {
1930 bool LOADCnt =
false;
1932 bool STORECnt =
false;
1934 if (Pos == Position::AFTER)
1938 (SIAtomicAddrSpace::GLOBAL | SIAtomicAddrSpace::SCRATCH))) {
1940 case SIAtomicScope::SYSTEM:
1941 case SIAtomicScope::AGENT:
1942 case SIAtomicScope::CLUSTER:
1943 if (
any(
Op & SIMemOp::LOAD))
1945 if (
any(
Op & SIMemOp::STORE))
1948 case SIAtomicScope::WORKGROUP:
1965 if (!
ST.isCuModeEnabled() ||
ST.hasGFX1250Insts() ||
1967 if (
any(
Op & SIMemOp::LOAD))
1969 if (
any(
Op & SIMemOp::STORE))
1973 case SIAtomicScope::WAVEFRONT:
1974 case SIAtomicScope::SINGLETHREAD:
1983 if (
any(AddrSpace & SIAtomicAddrSpace::LDS)) {
1985 case SIAtomicScope::SYSTEM:
1986 case SIAtomicScope::AGENT:
1987 case SIAtomicScope::CLUSTER:
1988 case SIAtomicScope::WORKGROUP:
1995 DSCnt |= IsCrossAddrSpaceOrdering;
1997 case SIAtomicScope::WAVEFRONT:
1998 case SIAtomicScope::SINGLETHREAD:
2019 if (!AtomicsOnly &&
ST.hasImageInsts()) {
2020 if (
ST.hasAnyBVHInsts())
2038 if (Pos == Position::AFTER)
2045 SIAtomicScope Scope,
2046 SIAtomicAddrSpace AddrSpace,
2047 Position Pos)
const {
2048 if (!InsertCacheInv)
2060 if (!canAffectGlobalAddrSpace(AddrSpace))
2065 case SIAtomicScope::SYSTEM:
2071 case SIAtomicScope::AGENT:
2077 case SIAtomicScope::CLUSTER:
2080 case SIAtomicScope::WORKGROUP:
2088 if (
ST.isCuModeEnabled())
2093 case SIAtomicScope::WAVEFRONT:
2094 case SIAtomicScope::SINGLETHREAD:
2101 if (Pos == Position::AFTER)
2106 if (Pos == Position::AFTER)
2111 if (
ST.hasINVWBL2WaitCntRequirement() && Scope > SIAtomicScope::CLUSTER) {
2112 insertWait(
MI, Scope, AddrSpace, SIMemOp::LOAD,
2113 false, Pos, AtomicOrdering::Acquire,
2116 if (Pos == Position::AFTER)
2124 SIAtomicScope Scope,
2125 SIAtomicAddrSpace AddrSpace,
2126 Position Pos)
const {
2131 if (!canAffectGlobalAddrSpace(AddrSpace))
2138 if (Pos == Position::AFTER)
2150 std::optional<AMDGPU::CPol::CPol> NeedsWB;
2152 case SIAtomicScope::SYSTEM:
2153 if (!
ST.hasNoMTypeNC())
2156 case SIAtomicScope::AGENT:
2159 if (
ST.hasGFX1250Insts() && !
ST.hasNoMTypeNC())
2162 case SIAtomicScope::CLUSTER:
2163 case SIAtomicScope::WORKGROUP:
2164 case SIAtomicScope::WAVEFRONT:
2165 case SIAtomicScope::SINGLETHREAD:
2167 case SIAtomicScope::NONE:
2176 if (
ST.hasINVWBL2WaitCntRequirement()) {
2177 insertWait(
MI, Scope, AddrSpace, SIMemOp::LOAD | SIMemOp::STORE,
2179 AtomicOrdering::Release,
2187 if (Pos == Position::AFTER)
2193bool SIGfx12CacheControl::handleNonVolatile(MachineInstr &
MI)
const {
2195 if (!
ST.hasGFX1250Insts())
2197 MachineOperand *
CPol =
TII->getNamedOperand(
MI, OpName::cpol);
2204bool SIGfx12CacheControl::enableVolatileAndOrNonTemporal(
2206 bool IsVolatile,
bool IsNonTemporal,
bool IsLastUse =
false)
const {
2215 assert(
Op == SIMemOp::LOAD ||
Op == SIMemOp::STORE);
2222 }
else if (IsNonTemporal) {
2230 if (
ST.requiresWaitXCntForSingleAccessInstructions() &&
2242 Changed |= insertWait(
MI, SIAtomicScope::SYSTEM, AddrSpace,
Op,
false,
2243 Position::AFTER, AtomicOrdering::Unordered,
2250bool SIGfx12CacheControl::finalizeStore(MachineInstr &
MI,
bool Atomic)
const {
2251 assert(
MI.mayStore() &&
"Not a Store inst");
2252 const bool IsRMW = (
MI.mayLoad() &&
MI.mayStore());
2255 if (Atomic &&
ST.requiresWaitXCntForSingleAccessInstructions() &&
2266 MachineOperand *
CPol =
TII->getNamedOperand(
MI, OpName::cpol);
2272 if (
ST.requiresWaitsBeforeSystemScopeStores() && !Atomic &&
2274 Changed |= insertWaitsBeforeSystemScopeStore(
MI.getIterator());
2284 MachineOperand *
CPol =
TII->getNamedOperand(*
MI, AMDGPU::OpName::cpol);
2285 assert(CPol &&
"load_monitor must have a cpol operand");
2291bool SIGfx12CacheControl::handleCooperativeAtomic(MachineInstr &
MI)
const {
2292 if (!
ST.hasGFX1250Insts())
2296 MachineOperand *
CPol =
TII->getNamedOperand(
MI, OpName::cpol);
2297 assert(CPol &&
"No CPol operand?");
2305 SIAtomicScope Scope,
2306 SIAtomicAddrSpace AddrSpace)
const {
2309 if (canAffectGlobalAddrSpace(AddrSpace)) {
2311 case SIAtomicScope::SYSTEM:
2314 case SIAtomicScope::AGENT:
2317 case SIAtomicScope::CLUSTER:
2320 case SIAtomicScope::WORKGROUP:
2323 if (!
ST.isCuModeEnabled())
2326 case SIAtomicScope::WAVEFRONT:
2327 case SIAtomicScope::SINGLETHREAD:
2346 unsigned CFSBits)
const {
2347 if (!
ST.hasCacheFillSize())
2351 MachineOperand *
CPol =
TII->getNamedOperand(*CoreMI, OpName::cpol);
2366bool SIMemoryLegalizer::removeAtomicPseudoMIs() {
2367 if (AtomicPseudoMIs.empty())
2370 for (
auto &
MI : AtomicPseudoMIs)
2371 MI->eraseFromParent();
2373 AtomicPseudoMIs.clear();
2377bool SIMemoryLegalizer::expandLoad(
const SIMemOpInfo &MOI,
2385 if (MOI.isAtomic()) {
2387 <<
", scope=" <<
toString(MOI.getScope())
2388 <<
", ordering-AS=" << MOI.getOrderingAddrSpace()
2389 <<
", instr-AS=" << MOI.getInstrAddrSpace() <<
"\n");
2391 if (Order == AtomicOrdering::Monotonic ||
2392 Order == AtomicOrdering::Acquire ||
2393 Order == AtomicOrdering::SequentiallyConsistent) {
2394 Changed |=
CC->enableLoadCacheBypass(
MI, MOI.getScope(),
2395 MOI.getOrderingAddrSpace());
2400 if (MOI.isCooperative())
2403 if (Order == AtomicOrdering::SequentiallyConsistent)
2404 Changed |=
CC->insertWait(
MI, MOI.getScope(), MOI.getOrderingAddrSpace(),
2405 SIMemOp::LOAD | SIMemOp::STORE,
2406 MOI.getIsCrossAddressSpaceOrdering(),
2407 Position::BEFORE, Order,
false);
2409 if (Order == AtomicOrdering::Acquire ||
2410 Order == AtomicOrdering::SequentiallyConsistent) {
2413 CC->insertWait(
MI, MOI.getScope(), MOI.getInstrAddrSpace(),
2414 SIMemOp::LOAD, MOI.getIsCrossAddressSpaceOrdering(),
2415 Position::AFTER, Order,
true);
2416 if (!MOI.isAVNone()) {
2418 MI, MOI.getScope(), MOI.getOrderingAddrSpace(), Position::AFTER);
2430 Changed |=
CC->enableVolatileAndOrNonTemporal(
2431 MI, MOI.getInstrAddrSpace(), SIMemOp::LOAD, MOI.isVolatile(),
2432 MOI.isNonTemporal(), MOI.isLastUse());
2440bool SIMemoryLegalizer::expandStore(
const SIMemOpInfo &MOI,
2448 MachineInstr &StoreMI = *
MI;
2450 if (MOI.isAtomic()) {
2452 <<
", scope=" <<
toString(MOI.getScope())
2453 <<
", ordering-AS=" << MOI.getOrderingAddrSpace()
2454 <<
", instr-AS=" << MOI.getInstrAddrSpace() <<
"\n");
2455 if (MOI.getOrdering() == AtomicOrdering::Monotonic ||
2456 MOI.getOrdering() == AtomicOrdering::Release ||
2457 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) {
2458 Changed |=
CC->enableStoreCacheBypass(
MI, MOI.getScope(),
2459 MOI.getOrderingAddrSpace());
2464 if (MOI.isCooperative())
2467 if (MOI.getOrdering() == AtomicOrdering::Release ||
2468 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) {
2470 CC->insertRelease(
MI, MOI.getScope(), MOI.getOrderingAddrSpace(),
2471 MOI.getIsCrossAddressSpaceOrdering(),
2472 Position::BEFORE, MOI.isAVNone());
2475 Changed |=
CC->finalizeStore(StoreMI,
true);
2483 Changed |=
CC->enableVolatileAndOrNonTemporal(
2484 MI, MOI.getInstrAddrSpace(), SIMemOp::STORE, MOI.isVolatile(),
2485 MOI.isNonTemporal());
2489 Changed |=
CC->finalizeStore(StoreMI,
false);
2495bool SIMemoryLegalizer::expandAtomicFence(
const SIMemOpInfo &MOI,
2497 assert(
MI->getOpcode() == AMDGPU::ATOMIC_FENCE);
2501 AtomicPseudoMIs.push_back(
MI);
2504 const SIAtomicAddrSpace OrderingAddrSpace = MOI.getOrderingAddrSpace();
2506 if (MOI.isAtomic()) {
2508 <<
", scope=" <<
toString(MOI.getScope())
2509 <<
", ordering-AS=" << OrderingAddrSpace <<
"\n");
2511 if (Order == AtomicOrdering::Acquire) {
2513 Changed |=
CC->insertWait(
MI, MOI.getScope(), OrderingAddrSpace,
2514 SIMemOp::LOAD | SIMemOp::STORE,
2515 MOI.getIsCrossAddressSpaceOrdering(),
2516 Position::BEFORE, Order,
true);
2519 if (Order == AtomicOrdering::Release ||
2520 Order == AtomicOrdering::AcquireRelease ||
2521 Order == AtomicOrdering::SequentiallyConsistent) {
2529 Changed |=
CC->insertRelease(
MI, MOI.getScope(), OrderingAddrSpace,
2530 MOI.getIsCrossAddressSpaceOrdering(),
2531 Position::BEFORE, MOI.isAVNone());
2539 if ((Order == AtomicOrdering::Acquire ||
2540 Order == AtomicOrdering::AcquireRelease ||
2541 Order == AtomicOrdering::SequentiallyConsistent) &&
2543 Changed |=
CC->insertAcquire(
MI, MOI.getScope(), OrderingAddrSpace,
2553bool SIMemoryLegalizer::expandAtomicCmpxchgOrRmw(
const SIMemOpInfo &MOI,
2560 MachineInstr &RMWMI = *
MI;
2562 if (MOI.isAtomic()) {
2564 <<
", failure-ordering="
2566 <<
", scope=" <<
toString(MOI.getScope())
2567 <<
", ordering-AS=" << MOI.getOrderingAddrSpace()
2568 <<
", instr-AS=" << MOI.getInstrAddrSpace() <<
"\n");
2570 if (Order == AtomicOrdering::Monotonic ||
2571 Order == AtomicOrdering::Acquire || Order == AtomicOrdering::Release ||
2572 Order == AtomicOrdering::AcquireRelease ||
2573 Order == AtomicOrdering::SequentiallyConsistent) {
2574 Changed |=
CC->enableRMWCacheBypass(
MI, MOI.getScope(),
2575 MOI.getInstrAddrSpace());
2578 if (Order == AtomicOrdering::Release ||
2579 Order == AtomicOrdering::AcquireRelease ||
2580 Order == AtomicOrdering::SequentiallyConsistent ||
2581 MOI.getFailureOrdering() == AtomicOrdering::SequentiallyConsistent) {
2583 CC->insertRelease(
MI, MOI.getScope(), MOI.getOrderingAddrSpace(),
2584 MOI.getIsCrossAddressSpaceOrdering(),
2585 Position::BEFORE, MOI.isAVNone());
2588 if (Order == AtomicOrdering::Acquire ||
2589 Order == AtomicOrdering::AcquireRelease ||
2590 Order == AtomicOrdering::SequentiallyConsistent ||
2591 MOI.getFailureOrdering() == AtomicOrdering::Acquire ||
2592 MOI.getFailureOrdering() == AtomicOrdering::SequentiallyConsistent) {
2595 CC->insertWait(
MI, MOI.getScope(), MOI.getInstrAddrSpace(),
2597 MOI.getIsCrossAddressSpaceOrdering(), Position::AFTER,
2599 if (!MOI.isAVNone()) {
2601 MI, MOI.getScope(), MOI.getOrderingAddrSpace(), Position::AFTER);
2605 Changed |=
CC->finalizeStore(RMWMI,
true);
2614bool SIMemoryLegalizer::expandLDSDMA(
const SIMemOpInfo &MOI,
2628 bool Changed =
CC->enableVolatileAndOrNonTemporal(
2629 MI, MOI.getInstrAddrSpace(), OpKind, MOI.isVolatile(),
2630 MOI.isNonTemporal(), MOI.isLastUse());
2635bool SIMemoryLegalizerLegacy::runOnMachineFunction(
MachineFunction &MF) {
2636 const MachineModuleInfo &MMI =
2637 getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
2638 return SIMemoryLegalizer(MMI).run(MF);
2645 .getCachedResult<MachineModuleAnalysis>(
2647 assert(MMI &&
"MachineModuleAnalysis must be available");
2648 if (!SIMemoryLegalizer(MMI->getMMI()).run(MF))
2660 CC = SICacheControl::create(ST, TgSplit);
2662 for (
auto &
MBB : MF) {
2666 if (
MI->isBundle() &&
MI->mayLoadOrStore()) {
2669 I != E &&
I->isBundledWithPred(); ++
I) {
2670 I->unbundleFromPred();
2673 MO.setIsInternalRead(
false);
2676 MI =
MI->eraseFromParent();
2680 if (
const auto &MOI = MOA.getLoadInfo(
MI))
2682 else if (
const auto &MOI = MOA.getStoreInfo(
MI))
2684 else if (
const auto &MOI = MOA.getLDSDMAInfo(
MI))
2686 else if (
const auto &MOI = MOA.getAtomicFenceInfo(
MI))
2688 else if (
const auto &MOI = MOA.getAtomicCmpxchgOrRmwInfo(
MI))
2689 Changed |= expandAtomicCmpxchgOrRmw(*MOI,
MI);
2697 Changed |= removeAtomicPseudoMIs();
2703char SIMemoryLegalizerLegacy::ID = 0;
2707 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 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 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.
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 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.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the 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()
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()