1 //===- SIMemoryLegalizer.cpp ----------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// \file 11 /// \brief Memory legalizer - implements memory model. More information can be 12 /// found here: 13 /// http://llvm.org/docs/AMDGPUUsage.html#memory-model 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "AMDGPU.h" 18 #include "AMDGPUMachineModuleInfo.h" 19 #include "AMDGPUSubtarget.h" 20 #include "SIDefines.h" 21 #include "SIInstrInfo.h" 22 #include "Utils/AMDGPUBaseInfo.h" 23 #include "llvm/ADT/None.h" 24 #include "llvm/ADT/Optional.h" 25 #include "llvm/CodeGen/MachineBasicBlock.h" 26 #include "llvm/CodeGen/MachineFunction.h" 27 #include "llvm/CodeGen/MachineFunctionPass.h" 28 #include "llvm/CodeGen/MachineInstrBuilder.h" 29 #include "llvm/CodeGen/MachineMemOperand.h" 30 #include "llvm/CodeGen/MachineModuleInfo.h" 31 #include "llvm/CodeGen/MachineOperand.h" 32 #include "llvm/IR/DebugLoc.h" 33 #include "llvm/IR/DiagnosticInfo.h" 34 #include "llvm/IR/Function.h" 35 #include "llvm/IR/LLVMContext.h" 36 #include "llvm/MC/MCInstrDesc.h" 37 #include "llvm/Pass.h" 38 #include "llvm/Support/AtomicOrdering.h" 39 #include <cassert> 40 #include <list> 41 42 using namespace llvm; 43 using namespace llvm::AMDGPU; 44 45 #define DEBUG_TYPE "si-memory-legalizer" 46 #define PASS_NAME "SI Memory Legalizer" 47 48 namespace { 49 50 class SIMemOpInfo final { 51 private: 52 SyncScope::ID SSID = SyncScope::System; 53 AtomicOrdering Ordering = AtomicOrdering::NotAtomic; 54 AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic; 55 bool IsNonTemporal = false; 56 57 SIMemOpInfo(SyncScope::ID SSID, AtomicOrdering Ordering) 58 : SSID(SSID), Ordering(Ordering) {} 59 60 SIMemOpInfo(SyncScope::ID SSID, AtomicOrdering Ordering, 61 AtomicOrdering FailureOrdering, bool IsNonTemporal = false) 62 : SSID(SSID), Ordering(Ordering), FailureOrdering(FailureOrdering), 63 IsNonTemporal(IsNonTemporal) {} 64 65 /// \returns Info constructed from \p MI, which has at least machine memory 66 /// operand. 67 static Optional<SIMemOpInfo> constructFromMIWithMMO( 68 const MachineBasicBlock::iterator &MI); 69 70 public: 71 /// \returns Synchronization scope ID of the machine instruction used to 72 /// create this SIMemOpInfo. 73 SyncScope::ID getSSID() const { 74 return SSID; 75 } 76 /// \returns Ordering constraint of the machine instruction used to 77 /// create this SIMemOpInfo. 78 AtomicOrdering getOrdering() const { 79 return Ordering; 80 } 81 /// \returns Failure ordering constraint of the machine instruction used to 82 /// create this SIMemOpInfo. 83 AtomicOrdering getFailureOrdering() const { 84 return FailureOrdering; 85 } 86 /// \returns True if memory access of the machine instruction used to 87 /// create this SIMemOpInfo is non-temporal, false otherwise. 88 bool isNonTemporal() const { 89 return IsNonTemporal; 90 } 91 92 /// \returns True if ordering constraint of the machine instruction used to 93 /// create this SIMemOpInfo is unordered or higher, false otherwise. 94 bool isAtomic() const { 95 return Ordering != AtomicOrdering::NotAtomic; 96 } 97 98 /// \returns Load info if \p MI is a load operation, "None" otherwise. 99 static Optional<SIMemOpInfo> getLoadInfo( 100 const MachineBasicBlock::iterator &MI); 101 /// \returns Store info if \p MI is a store operation, "None" otherwise. 102 static Optional<SIMemOpInfo> getStoreInfo( 103 const MachineBasicBlock::iterator &MI); 104 /// \returns Atomic fence info if \p MI is an atomic fence operation, 105 /// "None" otherwise. 106 static Optional<SIMemOpInfo> getAtomicFenceInfo( 107 const MachineBasicBlock::iterator &MI); 108 /// \returns Atomic cmpxchg info if \p MI is an atomic cmpxchg operation, 109 /// "None" otherwise. 110 static Optional<SIMemOpInfo> getAtomicCmpxchgInfo( 111 const MachineBasicBlock::iterator &MI); 112 /// \returns Atomic rmw info if \p MI is an atomic rmw operation, 113 /// "None" otherwise. 114 static Optional<SIMemOpInfo> getAtomicRmwInfo( 115 const MachineBasicBlock::iterator &MI); 116 117 /// \brief Reports unknown synchronization scope used in \p MI to LLVM 118 /// context. 119 static void reportUnknownSyncScope( 120 const MachineBasicBlock::iterator &MI); 121 }; 122 123 class SIMemoryLegalizer final : public MachineFunctionPass { 124 private: 125 /// \brief Machine module info. 126 const AMDGPUMachineModuleInfo *MMI = nullptr; 127 128 /// \brief Instruction info. 129 const SIInstrInfo *TII = nullptr; 130 131 /// \brief Immediate for "vmcnt(0)". 132 unsigned Vmcnt0Immediate = 0; 133 134 /// \brief Opcode for cache invalidation instruction (L1). 135 unsigned Wbinvl1Opcode = 0; 136 137 /// \brief List of atomic pseudo instructions. 138 std::list<MachineBasicBlock::iterator> AtomicPseudoMIs; 139 140 /// \brief Sets named bit (BitName) to "true" if present in \p MI. Returns 141 /// true if \p MI is modified, false otherwise. 142 template <uint16_t BitName> 143 bool enableNamedBit(const MachineBasicBlock::iterator &MI) const { 144 int BitIdx = AMDGPU::getNamedOperandIdx(MI->getOpcode(), BitName); 145 if (BitIdx == -1) 146 return false; 147 148 MachineOperand &Bit = MI->getOperand(BitIdx); 149 if (Bit.getImm() != 0) 150 return false; 151 152 Bit.setImm(1); 153 return true; 154 } 155 156 /// \brief Sets GLC bit to "true" if present in \p MI. Returns true if \p MI 157 /// is modified, false otherwise. 158 bool enableGLCBit(const MachineBasicBlock::iterator &MI) const { 159 return enableNamedBit<AMDGPU::OpName::glc>(MI); 160 } 161 162 /// \brief Sets SLC bit to "true" if present in \p MI. Returns true if \p MI 163 /// is modified, false otherwise. 164 bool enableSLCBit(const MachineBasicBlock::iterator &MI) const { 165 return enableNamedBit<AMDGPU::OpName::slc>(MI); 166 } 167 168 /// \brief Inserts "buffer_wbinvl1_vol" instruction \p Before or after \p MI. 169 /// Always returns true. 170 bool insertBufferWbinvl1Vol(MachineBasicBlock::iterator &MI, 171 bool Before = true) const; 172 /// \brief Inserts "s_waitcnt vmcnt(0)" instruction \p Before or after \p MI. 173 /// Always returns true. 174 bool insertWaitcntVmcnt0(MachineBasicBlock::iterator &MI, 175 bool Before = true) const; 176 177 /// \brief Removes all processed atomic pseudo instructions from the current 178 /// function. Returns true if current function is modified, false otherwise. 179 bool removeAtomicPseudoMIs(); 180 181 /// \brief Expands load operation \p MI. Returns true if instructions are 182 /// added/deleted or \p MI is modified, false otherwise. 183 bool expandLoad(const SIMemOpInfo &MOI, 184 MachineBasicBlock::iterator &MI); 185 /// \brief Expands store operation \p MI. Returns true if instructions are 186 /// added/deleted or \p MI is modified, false otherwise. 187 bool expandStore(const SIMemOpInfo &MOI, 188 MachineBasicBlock::iterator &MI); 189 /// \brief Expands atomic fence operation \p MI. Returns true if 190 /// instructions are added/deleted or \p MI is modified, false otherwise. 191 bool expandAtomicFence(const SIMemOpInfo &MOI, 192 MachineBasicBlock::iterator &MI); 193 /// \brief Expands atomic cmpxchg operation \p MI. Returns true if 194 /// instructions are added/deleted or \p MI is modified, false otherwise. 195 bool expandAtomicCmpxchg(const SIMemOpInfo &MOI, 196 MachineBasicBlock::iterator &MI); 197 /// \brief Expands atomic rmw operation \p MI. Returns true if 198 /// instructions are added/deleted or \p MI is modified, false otherwise. 199 bool expandAtomicRmw(const SIMemOpInfo &MOI, 200 MachineBasicBlock::iterator &MI); 201 202 public: 203 static char ID; 204 205 SIMemoryLegalizer() : MachineFunctionPass(ID) {} 206 207 void getAnalysisUsage(AnalysisUsage &AU) const override { 208 AU.setPreservesCFG(); 209 MachineFunctionPass::getAnalysisUsage(AU); 210 } 211 212 StringRef getPassName() const override { 213 return PASS_NAME; 214 } 215 216 bool runOnMachineFunction(MachineFunction &MF) override; 217 }; 218 219 } // end namespace anonymous 220 221 /* static */ 222 Optional<SIMemOpInfo> SIMemOpInfo::constructFromMIWithMMO( 223 const MachineBasicBlock::iterator &MI) { 224 assert(MI->getNumMemOperands() > 0); 225 226 const MachineFunction *MF = MI->getParent()->getParent(); 227 const AMDGPUMachineModuleInfo *MMI = 228 &MF->getMMI().getObjFileInfo<AMDGPUMachineModuleInfo>(); 229 230 SyncScope::ID SSID = SyncScope::SingleThread; 231 AtomicOrdering Ordering = AtomicOrdering::NotAtomic; 232 AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic; 233 bool IsNonTemporal = true; 234 235 // Validator should check whether or not MMOs cover the entire set of 236 // locations accessed by the memory instruction. 237 for (const auto &MMO : MI->memoperands()) { 238 const auto &IsSyncScopeInclusion = 239 MMI->isSyncScopeInclusion(SSID, MMO->getSyncScopeID()); 240 if (!IsSyncScopeInclusion) { 241 reportUnknownSyncScope(MI); 242 return None; 243 } 244 245 SSID = IsSyncScopeInclusion.getValue() ? SSID : MMO->getSyncScopeID(); 246 Ordering = 247 isStrongerThan(Ordering, MMO->getOrdering()) ? 248 Ordering : MMO->getOrdering(); 249 FailureOrdering = 250 isStrongerThan(FailureOrdering, MMO->getFailureOrdering()) ? 251 FailureOrdering : MMO->getFailureOrdering(); 252 253 if (!(MMO->getFlags() & MachineMemOperand::MONonTemporal)) 254 IsNonTemporal = false; 255 } 256 257 return SIMemOpInfo(SSID, Ordering, FailureOrdering, IsNonTemporal); 258 } 259 260 /* static */ 261 Optional<SIMemOpInfo> SIMemOpInfo::getLoadInfo( 262 const MachineBasicBlock::iterator &MI) { 263 assert(MI->getDesc().TSFlags & SIInstrFlags::maybeAtomic); 264 265 if (!(MI->mayLoad() && !MI->mayStore())) 266 return None; 267 268 // Be conservative if there are no memory operands. 269 if (MI->getNumMemOperands() == 0) 270 return SIMemOpInfo(SyncScope::System, 271 AtomicOrdering::SequentiallyConsistent); 272 273 return SIMemOpInfo::constructFromMIWithMMO(MI); 274 } 275 276 /* static */ 277 Optional<SIMemOpInfo> SIMemOpInfo::getStoreInfo( 278 const MachineBasicBlock::iterator &MI) { 279 assert(MI->getDesc().TSFlags & SIInstrFlags::maybeAtomic); 280 281 if (!(!MI->mayLoad() && MI->mayStore())) 282 return None; 283 284 // Be conservative if there are no memory operands. 285 if (MI->getNumMemOperands() == 0) 286 return SIMemOpInfo(SyncScope::System, 287 AtomicOrdering::SequentiallyConsistent); 288 289 return SIMemOpInfo::constructFromMIWithMMO(MI); 290 } 291 292 /* static */ 293 Optional<SIMemOpInfo> SIMemOpInfo::getAtomicFenceInfo( 294 const MachineBasicBlock::iterator &MI) { 295 assert(MI->getDesc().TSFlags & SIInstrFlags::maybeAtomic); 296 297 if (MI->getOpcode() != AMDGPU::ATOMIC_FENCE) 298 return None; 299 300 SyncScope::ID SSID = 301 static_cast<SyncScope::ID>(MI->getOperand(1).getImm()); 302 AtomicOrdering Ordering = 303 static_cast<AtomicOrdering>(MI->getOperand(0).getImm()); 304 return SIMemOpInfo(SSID, Ordering); 305 } 306 307 /* static */ 308 Optional<SIMemOpInfo> SIMemOpInfo::getAtomicCmpxchgInfo( 309 const MachineBasicBlock::iterator &MI) { 310 assert(MI->getDesc().TSFlags & SIInstrFlags::maybeAtomic); 311 312 if (!(MI->mayLoad() && MI->mayStore())) 313 return None; 314 315 // Be conservative if there are no memory operands. 316 if (MI->getNumMemOperands() == 0) 317 return SIMemOpInfo(SyncScope::System, 318 AtomicOrdering::SequentiallyConsistent, 319 AtomicOrdering::SequentiallyConsistent); 320 321 return SIMemOpInfo::constructFromMIWithMMO(MI); 322 } 323 324 /* static */ 325 Optional<SIMemOpInfo> SIMemOpInfo::getAtomicRmwInfo( 326 const MachineBasicBlock::iterator &MI) { 327 assert(MI->getDesc().TSFlags & SIInstrFlags::maybeAtomic); 328 329 if (!(MI->mayLoad() && MI->mayStore())) 330 return None; 331 332 // Be conservative if there are no memory operands. 333 if (MI->getNumMemOperands() == 0) 334 return SIMemOpInfo(SyncScope::System, 335 AtomicOrdering::SequentiallyConsistent); 336 337 return SIMemOpInfo::constructFromMIWithMMO(MI); 338 } 339 340 /* static */ 341 void SIMemOpInfo::reportUnknownSyncScope( 342 const MachineBasicBlock::iterator &MI) { 343 DiagnosticInfoUnsupported Diag(MI->getParent()->getParent()->getFunction(), 344 "Unsupported synchronization scope"); 345 LLVMContext *CTX = &MI->getParent()->getParent()->getFunction().getContext(); 346 CTX->diagnose(Diag); 347 } 348 349 bool SIMemoryLegalizer::insertBufferWbinvl1Vol(MachineBasicBlock::iterator &MI, 350 bool Before) const { 351 MachineBasicBlock &MBB = *MI->getParent(); 352 DebugLoc DL = MI->getDebugLoc(); 353 354 if (!Before) 355 ++MI; 356 357 BuildMI(MBB, MI, DL, TII->get(Wbinvl1Opcode)); 358 359 if (!Before) 360 --MI; 361 362 return true; 363 } 364 365 bool SIMemoryLegalizer::insertWaitcntVmcnt0(MachineBasicBlock::iterator &MI, 366 bool Before) const { 367 MachineBasicBlock &MBB = *MI->getParent(); 368 DebugLoc DL = MI->getDebugLoc(); 369 370 if (!Before) 371 ++MI; 372 373 BuildMI(MBB, MI, DL, TII->get(AMDGPU::S_WAITCNT)).addImm(Vmcnt0Immediate); 374 375 if (!Before) 376 --MI; 377 378 return true; 379 } 380 381 bool SIMemoryLegalizer::removeAtomicPseudoMIs() { 382 if (AtomicPseudoMIs.empty()) 383 return false; 384 385 for (auto &MI : AtomicPseudoMIs) 386 MI->eraseFromParent(); 387 388 AtomicPseudoMIs.clear(); 389 return true; 390 } 391 392 bool SIMemoryLegalizer::expandLoad(const SIMemOpInfo &MOI, 393 MachineBasicBlock::iterator &MI) { 394 assert(MI->mayLoad() && !MI->mayStore()); 395 396 bool Changed = false; 397 398 if (MOI.isAtomic()) { 399 if (MOI.getSSID() == SyncScope::System || 400 MOI.getSSID() == MMI->getAgentSSID()) { 401 if (MOI.getOrdering() == AtomicOrdering::Monotonic || 402 MOI.getOrdering() == AtomicOrdering::Acquire || 403 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) 404 Changed |= enableGLCBit(MI); 405 406 if (MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) 407 Changed |= insertWaitcntVmcnt0(MI); 408 409 if (MOI.getOrdering() == AtomicOrdering::Acquire || 410 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) { 411 Changed |= insertWaitcntVmcnt0(MI, false); 412 Changed |= insertBufferWbinvl1Vol(MI, false); 413 } 414 415 return Changed; 416 } 417 418 if (MOI.getSSID() == SyncScope::SingleThread || 419 MOI.getSSID() == MMI->getWorkgroupSSID() || 420 MOI.getSSID() == MMI->getWavefrontSSID()) { 421 return Changed; 422 } 423 424 llvm_unreachable("Unsupported synchronization scope"); 425 } 426 427 // Atomic instructions do not have the nontemporal attribute. 428 if (MOI.isNonTemporal()) { 429 Changed |= enableGLCBit(MI); 430 Changed |= enableSLCBit(MI); 431 return Changed; 432 } 433 434 return Changed; 435 } 436 437 bool SIMemoryLegalizer::expandStore(const SIMemOpInfo &MOI, 438 MachineBasicBlock::iterator &MI) { 439 assert(!MI->mayLoad() && MI->mayStore()); 440 441 bool Changed = false; 442 443 if (MOI.isAtomic()) { 444 if (MOI.getSSID() == SyncScope::System || 445 MOI.getSSID() == MMI->getAgentSSID()) { 446 if (MOI.getOrdering() == AtomicOrdering::Release || 447 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) 448 Changed |= insertWaitcntVmcnt0(MI); 449 450 return Changed; 451 } 452 453 if (MOI.getSSID() == SyncScope::SingleThread || 454 MOI.getSSID() == MMI->getWorkgroupSSID() || 455 MOI.getSSID() == MMI->getWavefrontSSID()) { 456 return Changed; 457 } 458 459 llvm_unreachable("Unsupported synchronization scope"); 460 } 461 462 // Atomic instructions do not have the nontemporal attribute. 463 if (MOI.isNonTemporal()) { 464 Changed |= enableGLCBit(MI); 465 Changed |= enableSLCBit(MI); 466 return Changed; 467 } 468 469 return Changed; 470 } 471 472 bool SIMemoryLegalizer::expandAtomicFence(const SIMemOpInfo &MOI, 473 MachineBasicBlock::iterator &MI) { 474 assert(MI->getOpcode() == AMDGPU::ATOMIC_FENCE); 475 476 bool Changed = false; 477 478 if (MOI.isAtomic()) { 479 if (MOI.getSSID() == SyncScope::System || 480 MOI.getSSID() == MMI->getAgentSSID()) { 481 if (MOI.getOrdering() == AtomicOrdering::Acquire || 482 MOI.getOrdering() == AtomicOrdering::Release || 483 MOI.getOrdering() == AtomicOrdering::AcquireRelease || 484 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) 485 Changed |= insertWaitcntVmcnt0(MI); 486 487 if (MOI.getOrdering() == AtomicOrdering::Acquire || 488 MOI.getOrdering() == AtomicOrdering::AcquireRelease || 489 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) 490 Changed |= insertBufferWbinvl1Vol(MI); 491 492 AtomicPseudoMIs.push_back(MI); 493 return Changed; 494 } 495 496 if (MOI.getSSID() == SyncScope::SingleThread || 497 MOI.getSSID() == MMI->getWorkgroupSSID() || 498 MOI.getSSID() == MMI->getWavefrontSSID()) { 499 AtomicPseudoMIs.push_back(MI); 500 return Changed; 501 } 502 503 SIMemOpInfo::reportUnknownSyncScope(MI); 504 } 505 506 return Changed; 507 } 508 509 bool SIMemoryLegalizer::expandAtomicCmpxchg(const SIMemOpInfo &MOI, 510 MachineBasicBlock::iterator &MI) { 511 assert(MI->mayLoad() && MI->mayStore()); 512 513 bool Changed = false; 514 515 if (MOI.isAtomic()) { 516 if (MOI.getSSID() == SyncScope::System || 517 MOI.getSSID() == MMI->getAgentSSID()) { 518 if (MOI.getOrdering() == AtomicOrdering::Release || 519 MOI.getOrdering() == AtomicOrdering::AcquireRelease || 520 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent || 521 MOI.getFailureOrdering() == AtomicOrdering::SequentiallyConsistent) 522 Changed |= insertWaitcntVmcnt0(MI); 523 524 if (MOI.getOrdering() == AtomicOrdering::Acquire || 525 MOI.getOrdering() == AtomicOrdering::AcquireRelease || 526 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent || 527 MOI.getFailureOrdering() == AtomicOrdering::Acquire || 528 MOI.getFailureOrdering() == AtomicOrdering::SequentiallyConsistent) { 529 Changed |= insertWaitcntVmcnt0(MI, false); 530 Changed |= insertBufferWbinvl1Vol(MI, false); 531 } 532 533 return Changed; 534 } 535 536 if (MOI.getSSID() == SyncScope::SingleThread || 537 MOI.getSSID() == MMI->getWorkgroupSSID() || 538 MOI.getSSID() == MMI->getWavefrontSSID()) { 539 Changed |= enableGLCBit(MI); 540 return Changed; 541 } 542 543 llvm_unreachable("Unsupported synchronization scope"); 544 } 545 546 return Changed; 547 } 548 549 bool SIMemoryLegalizer::expandAtomicRmw(const SIMemOpInfo &MOI, 550 MachineBasicBlock::iterator &MI) { 551 assert(MI->mayLoad() && MI->mayStore()); 552 553 bool Changed = false; 554 555 if (MOI.isAtomic()) { 556 if (MOI.getSSID() == SyncScope::System || 557 MOI.getSSID() == MMI->getAgentSSID()) { 558 if (MOI.getOrdering() == AtomicOrdering::Release || 559 MOI.getOrdering() == AtomicOrdering::AcquireRelease || 560 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) 561 Changed |= insertWaitcntVmcnt0(MI); 562 563 if (MOI.getOrdering() == AtomicOrdering::Acquire || 564 MOI.getOrdering() == AtomicOrdering::AcquireRelease || 565 MOI.getOrdering() == AtomicOrdering::SequentiallyConsistent) { 566 Changed |= insertWaitcntVmcnt0(MI, false); 567 Changed |= insertBufferWbinvl1Vol(MI, false); 568 } 569 570 return Changed; 571 } 572 573 if (MOI.getSSID() == SyncScope::SingleThread || 574 MOI.getSSID() == MMI->getWorkgroupSSID() || 575 MOI.getSSID() == MMI->getWavefrontSSID()) { 576 Changed |= enableGLCBit(MI); 577 return Changed; 578 } 579 580 llvm_unreachable("Unsupported synchronization scope"); 581 } 582 583 return Changed; 584 } 585 586 bool SIMemoryLegalizer::runOnMachineFunction(MachineFunction &MF) { 587 bool Changed = false; 588 const SISubtarget &ST = MF.getSubtarget<SISubtarget>(); 589 const IsaInfo::IsaVersion IV = IsaInfo::getIsaVersion(ST.getFeatureBits()); 590 591 MMI = &MF.getMMI().getObjFileInfo<AMDGPUMachineModuleInfo>(); 592 TII = ST.getInstrInfo(); 593 594 Vmcnt0Immediate = 595 AMDGPU::encodeWaitcnt(IV, 0, getExpcntBitMask(IV), getLgkmcntBitMask(IV)); 596 Wbinvl1Opcode = ST.getGeneration() <= AMDGPUSubtarget::SOUTHERN_ISLANDS ? 597 AMDGPU::BUFFER_WBINVL1 : AMDGPU::BUFFER_WBINVL1_VOL; 598 599 for (auto &MBB : MF) { 600 for (auto MI = MBB.begin(); MI != MBB.end(); ++MI) { 601 if (!(MI->getDesc().TSFlags & SIInstrFlags::maybeAtomic)) 602 continue; 603 604 if (const auto &MOI = SIMemOpInfo::getLoadInfo(MI)) 605 Changed |= expandLoad(MOI.getValue(), MI); 606 else if (const auto &MOI = SIMemOpInfo::getStoreInfo(MI)) 607 Changed |= expandStore(MOI.getValue(), MI); 608 else if (const auto &MOI = SIMemOpInfo::getAtomicFenceInfo(MI)) 609 Changed |= expandAtomicFence(MOI.getValue(), MI); 610 else if (const auto &MOI = SIMemOpInfo::getAtomicCmpxchgInfo(MI)) 611 Changed |= expandAtomicCmpxchg(MOI.getValue(), MI); 612 else if (const auto &MOI = SIMemOpInfo::getAtomicRmwInfo(MI)) 613 Changed |= expandAtomicRmw(MOI.getValue(), MI); 614 } 615 } 616 617 Changed |= removeAtomicPseudoMIs(); 618 return Changed; 619 } 620 621 INITIALIZE_PASS(SIMemoryLegalizer, DEBUG_TYPE, PASS_NAME, false, false) 622 623 char SIMemoryLegalizer::ID = 0; 624 char &llvm::SIMemoryLegalizerID = SIMemoryLegalizer::ID; 625 626 FunctionPass *llvm::createSIMemoryLegalizerPass() { 627 return new SIMemoryLegalizer(); 628 } 629