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 static AliasResult getAliasResult(unsigned AS1, unsigned AS2) { 500b57cec5SDimitry Andric static_assert(AMDGPUAS::MAX_AMDGPU_ADDRESS <= 7, "Addr space out of range"); 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric if (AS1 > AMDGPUAS::MAX_AMDGPU_ADDRESS || AS2 > AMDGPUAS::MAX_AMDGPU_ADDRESS) 53fe6060f1SDimitry Andric return AliasResult::MayAlias; 54fe6060f1SDimitry Andric 55fe6060f1SDimitry Andric #define ASMay AliasResult::MayAlias 56fe6060f1SDimitry Andric #define ASNo AliasResult::NoAlias 57fe6060f1SDimitry Andric // This array is indexed by address space value enum elements 0 ... to 7 58fe6060f1SDimitry Andric static const AliasResult ASAliasRules[8][8] = { 59fe6060f1SDimitry Andric /* Flat Global Region Group Constant Private Const32 Buf Fat Ptr */ 60fe6060f1SDimitry Andric /* Flat */ {ASMay, ASMay, ASNo, ASMay, ASMay, ASMay, ASMay, ASMay}, 61fe6060f1SDimitry Andric /* Global */ {ASMay, ASMay, ASNo, ASNo, ASMay, ASNo, ASMay, ASMay}, 62fe6060f1SDimitry Andric /* Region */ {ASNo, ASNo, ASMay, ASNo, ASNo, ASNo, ASNo, ASNo}, 63fe6060f1SDimitry Andric /* Group */ {ASMay, ASNo, ASNo, ASMay, ASNo, ASNo, ASNo, ASNo}, 64fe6060f1SDimitry Andric /* Constant */ {ASMay, ASMay, ASNo, ASNo, ASNo, ASNo, ASMay, ASMay}, 65fe6060f1SDimitry Andric /* Private */ {ASMay, ASNo, ASNo, ASNo, ASNo, ASMay, ASNo, ASNo}, 66fe6060f1SDimitry Andric /* Constant 32-bit */ {ASMay, ASMay, ASNo, ASNo, ASMay, ASNo, ASNo, ASMay}, 67fe6060f1SDimitry Andric /* Buffer Fat Ptr */ {ASMay, ASMay, ASNo, ASNo, ASMay, ASNo, ASMay, ASMay} 68fe6060f1SDimitry Andric }; 69fe6060f1SDimitry Andric #undef ASMay 70fe6060f1SDimitry Andric #undef ASNo 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric return ASAliasRules[AS1][AS2]; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA, 76*bdd1243dSDimitry Andric const MemoryLocation &LocB, AAQueryInfo &AAQI, 77*bdd1243dSDimitry Andric const Instruction *) { 780b57cec5SDimitry Andric unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace(); 790b57cec5SDimitry Andric unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace(); 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric AliasResult Result = getAliasResult(asA, asB); 82fe6060f1SDimitry Andric if (Result == AliasResult::NoAlias) 830b57cec5SDimitry Andric return Result; 840b57cec5SDimitry Andric 85e8d8bef9SDimitry Andric // In general, FLAT (generic) pointers could be aliased to LOCAL or PRIVATE 86e8d8bef9SDimitry Andric // pointers. However, as LOCAL or PRIVATE pointers point to local objects, in 87e8d8bef9SDimitry Andric // certain cases, it's still viable to check whether a FLAT pointer won't 88e8d8bef9SDimitry Andric // alias to a LOCAL or PRIVATE pointer. 89e8d8bef9SDimitry Andric MemoryLocation A = LocA; 90e8d8bef9SDimitry Andric MemoryLocation B = LocB; 91e8d8bef9SDimitry Andric // Canonicalize the location order to simplify the following alias check. 92e8d8bef9SDimitry Andric if (asA != AMDGPUAS::FLAT_ADDRESS) { 93e8d8bef9SDimitry Andric std::swap(asA, asB); 94e8d8bef9SDimitry Andric std::swap(A, B); 95e8d8bef9SDimitry Andric } 96e8d8bef9SDimitry Andric if (asA == AMDGPUAS::FLAT_ADDRESS && 97e8d8bef9SDimitry Andric (asB == AMDGPUAS::LOCAL_ADDRESS || asB == AMDGPUAS::PRIVATE_ADDRESS)) { 98e8d8bef9SDimitry Andric const auto *ObjA = 99fe6060f1SDimitry Andric getUnderlyingObject(A.Ptr->stripPointerCastsForAliasAnalysis()); 100e8d8bef9SDimitry Andric if (const LoadInst *LI = dyn_cast<LoadInst>(ObjA)) { 101e8d8bef9SDimitry Andric // If a generic pointer is loaded from the constant address space, it 102349cc55cSDimitry Andric // could only be a GLOBAL or CONSTANT one as that address space is solely 103e8d8bef9SDimitry Andric // prepared on the host side, where only GLOBAL or CONSTANT variables are 104e8d8bef9SDimitry Andric // visible. Note that this even holds for regular functions. 105e8d8bef9SDimitry Andric if (LI->getPointerAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS) 106fe6060f1SDimitry Andric return AliasResult::NoAlias; 107e8d8bef9SDimitry Andric } else if (const Argument *Arg = dyn_cast<Argument>(ObjA)) { 108e8d8bef9SDimitry Andric const Function *F = Arg->getParent(); 109e8d8bef9SDimitry Andric switch (F->getCallingConv()) { 110e8d8bef9SDimitry Andric case CallingConv::AMDGPU_KERNEL: 111e8d8bef9SDimitry Andric // In the kernel function, kernel arguments won't alias to (local) 112e8d8bef9SDimitry Andric // variables in shared or private address space. 113fe6060f1SDimitry Andric return AliasResult::NoAlias; 114e8d8bef9SDimitry Andric default: 115e8d8bef9SDimitry Andric // TODO: In the regular function, if that local variable in the 116e8d8bef9SDimitry Andric // location B is not captured, that argument pointer won't alias to it 117e8d8bef9SDimitry Andric // as well. 118e8d8bef9SDimitry Andric break; 119e8d8bef9SDimitry Andric } 120e8d8bef9SDimitry Andric } 121e8d8bef9SDimitry Andric } 122e8d8bef9SDimitry Andric 1230b57cec5SDimitry Andric // Forward the query to the next alias analysis. 124*bdd1243dSDimitry Andric return AAResultBase::alias(LocA, LocB, AAQI, nullptr); 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 127*bdd1243dSDimitry Andric ModRefInfo AMDGPUAAResult::getModRefInfoMask(const MemoryLocation &Loc, 128*bdd1243dSDimitry Andric AAQueryInfo &AAQI, 129*bdd1243dSDimitry Andric bool IgnoreLocals) { 1305ffd83dbSDimitry Andric unsigned AS = Loc.Ptr->getType()->getPointerAddressSpace(); 1310b57cec5SDimitry Andric if (AS == AMDGPUAS::CONSTANT_ADDRESS || 1325ffd83dbSDimitry Andric AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) 133*bdd1243dSDimitry Andric return ModRefInfo::NoModRef; 1345ffd83dbSDimitry Andric 135e8d8bef9SDimitry Andric const Value *Base = getUnderlyingObject(Loc.Ptr); 1365ffd83dbSDimitry Andric AS = Base->getType()->getPointerAddressSpace(); 1375ffd83dbSDimitry Andric if (AS == AMDGPUAS::CONSTANT_ADDRESS || 1385ffd83dbSDimitry Andric AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) 139*bdd1243dSDimitry Andric return ModRefInfo::NoModRef; 1400b57cec5SDimitry Andric 141*bdd1243dSDimitry Andric return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals); 1420b57cec5SDimitry Andric } 143