1 //===-- AMDGPUMemoryUtils.cpp - -------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "AMDGPUMemoryUtils.h" 10 #include "AMDGPU.h" 11 #include "llvm/ADT/SmallSet.h" 12 #include "llvm/Analysis/AliasAnalysis.h" 13 #include "llvm/Analysis/MemorySSA.h" 14 #include "llvm/IR/Instructions.h" 15 #include "llvm/IR/IntrinsicsAMDGPU.h" 16 #include "llvm/IR/IntrinsicInst.h" 17 18 #define DEBUG_TYPE "amdgpu-memory-utils" 19 20 using namespace llvm; 21 22 namespace llvm { 23 24 namespace AMDGPU { 25 26 bool isReallyAClobber(const Value *Ptr, MemoryDef *Def, AAResults *AA) { 27 Instruction *DefInst = Def->getMemoryInst(); 28 29 if (isa<FenceInst>(DefInst)) 30 return false; 31 32 if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(DefInst)) { 33 switch (II->getIntrinsicID()) { 34 case Intrinsic::amdgcn_s_barrier: 35 case Intrinsic::amdgcn_wave_barrier: 36 return false; 37 default: 38 break; 39 } 40 } 41 42 // Ignore atomics not aliasing with the original load, any atomic is a 43 // universal MemoryDef from MSSA's point of view too, just like a fence. 44 const auto checkNoAlias = [AA, Ptr](auto I) -> bool { 45 return I && AA->isNoAlias(I->getPointerOperand(), Ptr); 46 }; 47 48 if (checkNoAlias(dyn_cast<AtomicCmpXchgInst>(DefInst)) || 49 checkNoAlias(dyn_cast<AtomicRMWInst>(DefInst))) 50 return false; 51 52 return true; 53 } 54 55 bool isClobberedInFunction(const LoadInst *Load, MemorySSA *MSSA, 56 AAResults *AA) { 57 MemorySSAWalker *Walker = MSSA->getWalker(); 58 SmallVector<MemoryAccess *> WorkList{Walker->getClobberingMemoryAccess(Load)}; 59 SmallSet<MemoryAccess *, 8> Visited; 60 MemoryLocation Loc(MemoryLocation::get(Load)); 61 62 LLVM_DEBUG(dbgs() << "Checking clobbering of: " << *Load << '\n'); 63 64 // Start with a nearest dominating clobbering access, it will be either 65 // live on entry (nothing to do, load is not clobbered), MemoryDef, or 66 // MemoryPhi if several MemoryDefs can define this memory state. In that 67 // case add all Defs to WorkList and continue going up and checking all 68 // the definitions of this memory location until the root. When all the 69 // defs are exhausted and came to the entry state we have no clobber. 70 // Along the scan ignore barriers and fences which are considered clobbers 71 // by the MemorySSA, but not really writing anything into the memory. 72 while (!WorkList.empty()) { 73 MemoryAccess *MA = WorkList.pop_back_val(); 74 if (!Visited.insert(MA).second) 75 continue; 76 77 if (MSSA->isLiveOnEntryDef(MA)) 78 continue; 79 80 if (MemoryDef *Def = dyn_cast<MemoryDef>(MA)) { 81 LLVM_DEBUG(dbgs() << " Def: " << *Def->getMemoryInst() << '\n'); 82 83 if (isReallyAClobber(Load->getPointerOperand(), Def, AA)) { 84 LLVM_DEBUG(dbgs() << " -> load is clobbered\n"); 85 return true; 86 } 87 88 WorkList.push_back( 89 Walker->getClobberingMemoryAccess(Def->getDefiningAccess(), Loc)); 90 continue; 91 } 92 93 const MemoryPhi *Phi = cast<MemoryPhi>(MA); 94 for (auto &Use : Phi->incoming_values()) 95 WorkList.push_back(cast<MemoryAccess>(&Use)); 96 } 97 98 LLVM_DEBUG(dbgs() << " -> no clobber\n"); 99 return false; 100 } 101 102 } // end namespace AMDGPU 103 104 } // end namespace llvm 105