18e45acfcSStanislav Mekhanoshin //===- AMDGPUAliasAnalysis ---------------------------------------*- C++ -*-==// 28e45acfcSStanislav Mekhanoshin // 38e45acfcSStanislav Mekhanoshin // The LLVM Compiler Infrastructure 48e45acfcSStanislav Mekhanoshin // 58e45acfcSStanislav Mekhanoshin // This file is distributed under the University of Illinois Open Source 68e45acfcSStanislav Mekhanoshin // License. See LICENSE.TXT for details. 78e45acfcSStanislav Mekhanoshin // 88e45acfcSStanislav Mekhanoshin //===----------------------------------------------------------------------===// 98e45acfcSStanislav Mekhanoshin /// \file 108e45acfcSStanislav Mekhanoshin /// This is the AMGPU address space based alias analysis pass. 118e45acfcSStanislav Mekhanoshin //===----------------------------------------------------------------------===// 128e45acfcSStanislav Mekhanoshin 138e45acfcSStanislav Mekhanoshin #include "AMDGPU.h" 148e45acfcSStanislav Mekhanoshin #include "AMDGPUAliasAnalysis.h" 158e45acfcSStanislav Mekhanoshin #include "llvm/Analysis/AliasAnalysis.h" 168e45acfcSStanislav Mekhanoshin #include "llvm/Analysis/ValueTracking.h" 178e45acfcSStanislav Mekhanoshin #include "llvm/Analysis/Passes.h" 188e45acfcSStanislav Mekhanoshin #include "llvm/Support/raw_ostream.h" 198e45acfcSStanislav Mekhanoshin #include "llvm/IR/Function.h" 208e45acfcSStanislav Mekhanoshin #include "llvm/IR/Module.h" 218e45acfcSStanislav Mekhanoshin #include "llvm/Pass.h" 228e45acfcSStanislav Mekhanoshin 238e45acfcSStanislav Mekhanoshin using namespace llvm; 248e45acfcSStanislav Mekhanoshin 258e45acfcSStanislav Mekhanoshin #define DEBUG_TYPE "amdgpu-aa" 268e45acfcSStanislav Mekhanoshin 278e45acfcSStanislav Mekhanoshin // Register this pass... 288e45acfcSStanislav Mekhanoshin char AMDGPUAAWrapperPass::ID = 0; 298e45acfcSStanislav Mekhanoshin INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa", 308e45acfcSStanislav Mekhanoshin "AMDGPU Address space based Alias Analysis", false, true) 318e45acfcSStanislav Mekhanoshin 328e45acfcSStanislav Mekhanoshin ImmutablePass *llvm::createAMDGPUAAWrapperPass() { 338e45acfcSStanislav Mekhanoshin return new AMDGPUAAWrapperPass(); 348e45acfcSStanislav Mekhanoshin } 358e45acfcSStanislav Mekhanoshin 368e45acfcSStanislav Mekhanoshin void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 378e45acfcSStanislav Mekhanoshin AU.setPreservesAll(); 388e45acfcSStanislav Mekhanoshin } 398e45acfcSStanislav Mekhanoshin 401a14bfa0SYaxun Liu // Must match the table in getAliasResult. 41*3c99441eSJan Vesely AMDGPUAAResult::ASAliasRulesTy::ASAliasRulesTy(AMDGPUAS AS_, Triple::ArchType Arch_) 42*3c99441eSJan Vesely : Arch(Arch_), AS(AS_) { 431a14bfa0SYaxun Liu // These arrarys are indexed by address space value 441a14bfa0SYaxun Liu // enum elements 0 ... to 5 451a14bfa0SYaxun Liu static const AliasResult ASAliasRulesPrivIsZero[6][6] = { 461a14bfa0SYaxun Liu /* Private Global Constant Group Flat Region*/ 471a14bfa0SYaxun Liu /* Private */ {MayAlias, NoAlias , NoAlias , NoAlias , MayAlias, NoAlias}, 481a14bfa0SYaxun Liu /* Global */ {NoAlias , MayAlias, NoAlias , NoAlias , MayAlias, NoAlias}, 491a14bfa0SYaxun Liu /* Constant */ {NoAlias , NoAlias , MayAlias, NoAlias , MayAlias, NoAlias}, 501a14bfa0SYaxun Liu /* Group */ {NoAlias , NoAlias , NoAlias , MayAlias, MayAlias, NoAlias}, 511a14bfa0SYaxun Liu /* Flat */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias}, 521a14bfa0SYaxun Liu /* Region */ {NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, MayAlias} 531a14bfa0SYaxun Liu }; 541a14bfa0SYaxun Liu static const AliasResult ASAliasRulesGenIsZero[6][6] = { 551a14bfa0SYaxun Liu /* Flat Global Region Group Constant Private */ 561a14bfa0SYaxun Liu /* Flat */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias}, 571a14bfa0SYaxun Liu /* Global */ {MayAlias, MayAlias, NoAlias , NoAlias , NoAlias , NoAlias}, 581a14bfa0SYaxun Liu /* Region */ {NoAlias , NoAlias , MayAlias, NoAlias, NoAlias , MayAlias}, 591a14bfa0SYaxun Liu /* Group */ {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias}, 601a14bfa0SYaxun Liu /* Constant */ {MayAlias, NoAlias , NoAlias , NoAlias , MayAlias, NoAlias}, 611a14bfa0SYaxun Liu /* Private */ {MayAlias, NoAlias , NoAlias , NoAlias , NoAlias , MayAlias} 621a14bfa0SYaxun Liu }; 631a14bfa0SYaxun Liu assert(AS.MAX_COMMON_ADDRESS <= 5); 641a14bfa0SYaxun Liu if (AS.FLAT_ADDRESS == 0) { 651a14bfa0SYaxun Liu assert(AS.GLOBAL_ADDRESS == 1 && 661a14bfa0SYaxun Liu AS.REGION_ADDRESS == 2 && 671a14bfa0SYaxun Liu AS.LOCAL_ADDRESS == 3 && 681a14bfa0SYaxun Liu AS.CONSTANT_ADDRESS == 4 && 691a14bfa0SYaxun Liu AS.PRIVATE_ADDRESS == 5); 701a14bfa0SYaxun Liu ASAliasRules = &ASAliasRulesGenIsZero; 711a14bfa0SYaxun Liu } else { 721a14bfa0SYaxun Liu assert(AS.PRIVATE_ADDRESS == 0 && 731a14bfa0SYaxun Liu AS.GLOBAL_ADDRESS == 1 && 741a14bfa0SYaxun Liu AS.CONSTANT_ADDRESS == 2 && 751a14bfa0SYaxun Liu AS.LOCAL_ADDRESS == 3 && 761a14bfa0SYaxun Liu AS.FLAT_ADDRESS == 4 && 771a14bfa0SYaxun Liu AS.REGION_ADDRESS == 5); 781a14bfa0SYaxun Liu ASAliasRules = &ASAliasRulesPrivIsZero; 791a14bfa0SYaxun Liu } 801a14bfa0SYaxun Liu } 811a14bfa0SYaxun Liu 821a14bfa0SYaxun Liu AliasResult AMDGPUAAResult::ASAliasRulesTy::getAliasResult(unsigned AS1, 831a14bfa0SYaxun Liu unsigned AS2) const { 84*3c99441eSJan Vesely if (AS1 > AS.MAX_COMMON_ADDRESS || AS2 > AS.MAX_COMMON_ADDRESS) { 85*3c99441eSJan Vesely if (Arch == Triple::amdgcn) 861a14bfa0SYaxun Liu report_fatal_error("Pointer address space out of range"); 87*3c99441eSJan Vesely return AS1 == AS2 ? MayAlias : NoAlias; 88*3c99441eSJan Vesely } 89*3c99441eSJan Vesely 901a14bfa0SYaxun Liu return (*ASAliasRules)[AS1][AS2]; 911a14bfa0SYaxun Liu } 921a14bfa0SYaxun Liu 938e45acfcSStanislav Mekhanoshin AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA, 948e45acfcSStanislav Mekhanoshin const MemoryLocation &LocB) { 958e45acfcSStanislav Mekhanoshin unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace(); 968e45acfcSStanislav Mekhanoshin unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace(); 978e45acfcSStanislav Mekhanoshin 981a14bfa0SYaxun Liu AliasResult Result = ASAliasRules.getAliasResult(asA, asB); 998e45acfcSStanislav Mekhanoshin if (Result == NoAlias) return Result; 1008e45acfcSStanislav Mekhanoshin 1018e45acfcSStanislav Mekhanoshin if (isa<Argument>(LocA.Ptr) && isa<Argument>(LocB.Ptr)) { 1028e45acfcSStanislav Mekhanoshin Type *T1 = cast<PointerType>(LocA.Ptr->getType())->getElementType(); 1038e45acfcSStanislav Mekhanoshin Type *T2 = cast<PointerType>(LocB.Ptr->getType())->getElementType(); 1048e45acfcSStanislav Mekhanoshin 1058e45acfcSStanislav Mekhanoshin if ((T1->isVectorTy() && !T2->isVectorTy()) || 1068e45acfcSStanislav Mekhanoshin (T2->isVectorTy() && !T1->isVectorTy())) 1078e45acfcSStanislav Mekhanoshin return NoAlias; 1088e45acfcSStanislav Mekhanoshin } 1098e45acfcSStanislav Mekhanoshin // Forward the query to the next alias analysis. 1108e45acfcSStanislav Mekhanoshin return AAResultBase::alias(LocA, LocB); 1118e45acfcSStanislav Mekhanoshin } 1128e45acfcSStanislav Mekhanoshin 1138e45acfcSStanislav Mekhanoshin bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc, 1148e45acfcSStanislav Mekhanoshin bool OrLocal) { 1158e45acfcSStanislav Mekhanoshin const Value *Base = GetUnderlyingObject(Loc.Ptr, DL); 1168e45acfcSStanislav Mekhanoshin 1171a14bfa0SYaxun Liu if (Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS) { 1188e45acfcSStanislav Mekhanoshin return true; 1198e45acfcSStanislav Mekhanoshin } 1208e45acfcSStanislav Mekhanoshin 1218e45acfcSStanislav Mekhanoshin if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) { 1228e45acfcSStanislav Mekhanoshin if (GV->isConstant()) 1238e45acfcSStanislav Mekhanoshin return true; 1248e45acfcSStanislav Mekhanoshin } else if (const Argument *Arg = dyn_cast<Argument>(Base)) { 1258e45acfcSStanislav Mekhanoshin const Function *F = Arg->getParent(); 1268e45acfcSStanislav Mekhanoshin 1278e45acfcSStanislav Mekhanoshin // Only assume constant memory for arguments on kernels. 1288e45acfcSStanislav Mekhanoshin switch (F->getCallingConv()) { 1298e45acfcSStanislav Mekhanoshin default: 1308e45acfcSStanislav Mekhanoshin return AAResultBase::pointsToConstantMemory(Loc, OrLocal); 1318e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_VS: 1328e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_GS: 1338e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_PS: 1348e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_CS: 1358e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_KERNEL: 1368e45acfcSStanislav Mekhanoshin case CallingConv::SPIR_KERNEL: 1378e45acfcSStanislav Mekhanoshin break; 1388e45acfcSStanislav Mekhanoshin } 1398e45acfcSStanislav Mekhanoshin 1408e45acfcSStanislav Mekhanoshin unsigned ArgNo = Arg->getArgNo(); 1418e45acfcSStanislav Mekhanoshin /* On an argument, ReadOnly attribute indicates that the function does 1428e45acfcSStanislav Mekhanoshin not write through this pointer argument, even though it may write 1438e45acfcSStanislav Mekhanoshin to the memory that the pointer points to. 1448e45acfcSStanislav Mekhanoshin On an argument, ReadNone attribute indicates that the function does 1458e45acfcSStanislav Mekhanoshin not dereference that pointer argument, even though it may read or write 1468e45acfcSStanislav Mekhanoshin the memory that the pointer points to if accessed through other pointers. 1478e45acfcSStanislav Mekhanoshin */ 1488e45acfcSStanislav Mekhanoshin if (F->getAttributes().hasAttribute(ArgNo + 1, Attribute::NoAlias) && 1498e45acfcSStanislav Mekhanoshin (F->getAttributes().hasAttribute(ArgNo + 1, Attribute::ReadNone) || 1508e45acfcSStanislav Mekhanoshin F->getAttributes().hasAttribute(ArgNo + 1, Attribute::ReadOnly))) { 1518e45acfcSStanislav Mekhanoshin return true; 1528e45acfcSStanislav Mekhanoshin } 1538e45acfcSStanislav Mekhanoshin } 1548e45acfcSStanislav Mekhanoshin return AAResultBase::pointsToConstantMemory(Loc, OrLocal); 1558e45acfcSStanislav Mekhanoshin } 156