10b57cec5SDimitry Andric //===- AMDGPUAliasAnalysis ------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// \file 90b57cec5SDimitry Andric /// This is the AMGPU address space based alias analysis pass. 100b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "AMDGPUAliasAnalysis.h" 13349cc55cSDimitry Andric #include "AMDGPU.h" 140b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 15e8d8bef9SDimitry Andric #include "llvm/IR/Instructions.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric using namespace llvm; 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #define DEBUG_TYPE "amdgpu-aa" 200b57cec5SDimitry Andric 21e8d8bef9SDimitry Andric AnalysisKey AMDGPUAA::Key; 22e8d8bef9SDimitry Andric 230b57cec5SDimitry Andric // Register this pass... 240b57cec5SDimitry Andric char AMDGPUAAWrapperPass::ID = 0; 250b57cec5SDimitry Andric char AMDGPUExternalAAWrapper::ID = 0; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa", 280b57cec5SDimitry Andric "AMDGPU Address space based Alias Analysis", false, true) 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric INITIALIZE_PASS(AMDGPUExternalAAWrapper, "amdgpu-aa-wrapper", 310b57cec5SDimitry Andric "AMDGPU Address space based Alias Analysis Wrapper", false, true) 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric ImmutablePass *llvm::createAMDGPUAAWrapperPass() { 340b57cec5SDimitry Andric return new AMDGPUAAWrapperPass(); 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric ImmutablePass *llvm::createAMDGPUExternalAAWrapperPass() { 380b57cec5SDimitry Andric return new AMDGPUExternalAAWrapper(); 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric 41349cc55cSDimitry Andric AMDGPUAAWrapperPass::AMDGPUAAWrapperPass() : ImmutablePass(ID) { 42349cc55cSDimitry Andric initializeAMDGPUAAWrapperPassPass(*PassRegistry::getPassRegistry()); 43349cc55cSDimitry Andric } 44349cc55cSDimitry Andric 450b57cec5SDimitry Andric void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 460b57cec5SDimitry Andric AU.setPreservesAll(); 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA, 50bdd1243dSDimitry Andric const MemoryLocation &LocB, AAQueryInfo &AAQI, 51bdd1243dSDimitry Andric const Instruction *) { 520b57cec5SDimitry Andric unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace(); 530b57cec5SDimitry Andric unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace(); 540b57cec5SDimitry Andric 5506c3fb27SDimitry Andric if (!AMDGPU::addrspacesMayAlias(asA, asB)) 5606c3fb27SDimitry Andric return AliasResult::NoAlias; 570b57cec5SDimitry Andric 58e8d8bef9SDimitry Andric // In general, FLAT (generic) pointers could be aliased to LOCAL or PRIVATE 59e8d8bef9SDimitry Andric // pointers. However, as LOCAL or PRIVATE pointers point to local objects, in 60e8d8bef9SDimitry Andric // certain cases, it's still viable to check whether a FLAT pointer won't 61e8d8bef9SDimitry Andric // alias to a LOCAL or PRIVATE pointer. 62e8d8bef9SDimitry Andric MemoryLocation A = LocA; 63e8d8bef9SDimitry Andric MemoryLocation B = LocB; 64e8d8bef9SDimitry Andric // Canonicalize the location order to simplify the following alias check. 65e8d8bef9SDimitry Andric if (asA != AMDGPUAS::FLAT_ADDRESS) { 66e8d8bef9SDimitry Andric std::swap(asA, asB); 67e8d8bef9SDimitry Andric std::swap(A, B); 68e8d8bef9SDimitry Andric } 69e8d8bef9SDimitry Andric if (asA == AMDGPUAS::FLAT_ADDRESS && 70e8d8bef9SDimitry Andric (asB == AMDGPUAS::LOCAL_ADDRESS || asB == AMDGPUAS::PRIVATE_ADDRESS)) { 71e8d8bef9SDimitry Andric const auto *ObjA = 72fe6060f1SDimitry Andric getUnderlyingObject(A.Ptr->stripPointerCastsForAliasAnalysis()); 73e8d8bef9SDimitry Andric if (const LoadInst *LI = dyn_cast<LoadInst>(ObjA)) { 74e8d8bef9SDimitry Andric // If a generic pointer is loaded from the constant address space, it 75349cc55cSDimitry Andric // could only be a GLOBAL or CONSTANT one as that address space is solely 76e8d8bef9SDimitry Andric // prepared on the host side, where only GLOBAL or CONSTANT variables are 77e8d8bef9SDimitry Andric // visible. Note that this even holds for regular functions. 78e8d8bef9SDimitry Andric if (LI->getPointerAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS) 79fe6060f1SDimitry Andric return AliasResult::NoAlias; 80e8d8bef9SDimitry Andric } else if (const Argument *Arg = dyn_cast<Argument>(ObjA)) { 81e8d8bef9SDimitry Andric const Function *F = Arg->getParent(); 82e8d8bef9SDimitry Andric switch (F->getCallingConv()) { 83e8d8bef9SDimitry Andric case CallingConv::AMDGPU_KERNEL: 84e8d8bef9SDimitry Andric // In the kernel function, kernel arguments won't alias to (local) 85e8d8bef9SDimitry Andric // variables in shared or private address space. 86fe6060f1SDimitry Andric return AliasResult::NoAlias; 87e8d8bef9SDimitry Andric default: 88e8d8bef9SDimitry Andric // TODO: In the regular function, if that local variable in the 89e8d8bef9SDimitry Andric // location B is not captured, that argument pointer won't alias to it 90e8d8bef9SDimitry Andric // as well. 91e8d8bef9SDimitry Andric break; 92e8d8bef9SDimitry Andric } 93e8d8bef9SDimitry Andric } 94e8d8bef9SDimitry Andric } 95e8d8bef9SDimitry Andric 96*5f757f3fSDimitry Andric return AliasResult::MayAlias; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 99bdd1243dSDimitry Andric ModRefInfo AMDGPUAAResult::getModRefInfoMask(const MemoryLocation &Loc, 100bdd1243dSDimitry Andric AAQueryInfo &AAQI, 101bdd1243dSDimitry Andric bool IgnoreLocals) { 1025ffd83dbSDimitry Andric unsigned AS = Loc.Ptr->getType()->getPointerAddressSpace(); 1030b57cec5SDimitry Andric if (AS == AMDGPUAS::CONSTANT_ADDRESS || 1045ffd83dbSDimitry Andric AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) 105bdd1243dSDimitry Andric return ModRefInfo::NoModRef; 1065ffd83dbSDimitry Andric 107e8d8bef9SDimitry Andric const Value *Base = getUnderlyingObject(Loc.Ptr); 1085ffd83dbSDimitry Andric AS = Base->getType()->getPointerAddressSpace(); 1095ffd83dbSDimitry Andric if (AS == AMDGPUAS::CONSTANT_ADDRESS || 1105ffd83dbSDimitry Andric AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) 111bdd1243dSDimitry Andric return ModRefInfo::NoModRef; 1120b57cec5SDimitry Andric 113*5f757f3fSDimitry Andric return ModRefInfo::ModRef; 1140b57cec5SDimitry Andric } 115