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. 413c99441eSJan Vesely AMDGPUAAResult::ASAliasRulesTy::ASAliasRulesTy(AMDGPUAS AS_, Triple::ArchType Arch_) 423c99441eSJan 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] = { 55*76ae47cbSYaxun Liu /* Flat Global Constant Group Region Private */ 561a14bfa0SYaxun Liu /* Flat */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias}, 571a14bfa0SYaxun Liu /* Global */ {MayAlias, MayAlias, NoAlias , NoAlias , NoAlias , NoAlias}, 58*76ae47cbSYaxun Liu /* Constant */ {MayAlias, NoAlias , MayAlias, NoAlias , NoAlias, NoAlias}, 591a14bfa0SYaxun Liu /* Group */ {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias}, 60*76ae47cbSYaxun Liu /* Region */ {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 && 66*76ae47cbSYaxun Liu AS.REGION_ADDRESS == 4 && 671a14bfa0SYaxun Liu AS.LOCAL_ADDRESS == 3 && 68*76ae47cbSYaxun Liu AS.CONSTANT_ADDRESS == 2 && 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 { 843c99441eSJan Vesely if (AS1 > AS.MAX_COMMON_ADDRESS || AS2 > AS.MAX_COMMON_ADDRESS) { 853c99441eSJan Vesely if (Arch == Triple::amdgcn) 861a14bfa0SYaxun Liu report_fatal_error("Pointer address space out of range"); 873c99441eSJan Vesely return AS1 == AS2 ? MayAlias : NoAlias; 883c99441eSJan Vesely } 893c99441eSJan 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 // Forward the query to the next alias analysis. 1028e45acfcSStanislav Mekhanoshin return AAResultBase::alias(LocA, LocB); 1038e45acfcSStanislav Mekhanoshin } 1048e45acfcSStanislav Mekhanoshin 1058e45acfcSStanislav Mekhanoshin bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc, 1068e45acfcSStanislav Mekhanoshin bool OrLocal) { 1078e45acfcSStanislav Mekhanoshin const Value *Base = GetUnderlyingObject(Loc.Ptr, DL); 1088e45acfcSStanislav Mekhanoshin 1091a14bfa0SYaxun Liu if (Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS) { 1108e45acfcSStanislav Mekhanoshin return true; 1118e45acfcSStanislav Mekhanoshin } 1128e45acfcSStanislav Mekhanoshin 1138e45acfcSStanislav Mekhanoshin if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) { 1148e45acfcSStanislav Mekhanoshin if (GV->isConstant()) 1158e45acfcSStanislav Mekhanoshin return true; 1168e45acfcSStanislav Mekhanoshin } else if (const Argument *Arg = dyn_cast<Argument>(Base)) { 1178e45acfcSStanislav Mekhanoshin const Function *F = Arg->getParent(); 1188e45acfcSStanislav Mekhanoshin 1198e45acfcSStanislav Mekhanoshin // Only assume constant memory for arguments on kernels. 1208e45acfcSStanislav Mekhanoshin switch (F->getCallingConv()) { 1218e45acfcSStanislav Mekhanoshin default: 1228e45acfcSStanislav Mekhanoshin return AAResultBase::pointsToConstantMemory(Loc, OrLocal); 1238e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_VS: 1248e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_GS: 1258e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_PS: 1268e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_CS: 1278e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_KERNEL: 1288e45acfcSStanislav Mekhanoshin case CallingConv::SPIR_KERNEL: 1298e45acfcSStanislav Mekhanoshin break; 1308e45acfcSStanislav Mekhanoshin } 1318e45acfcSStanislav Mekhanoshin 1328e45acfcSStanislav Mekhanoshin unsigned ArgNo = Arg->getArgNo(); 1338e45acfcSStanislav Mekhanoshin /* On an argument, ReadOnly attribute indicates that the function does 1348e45acfcSStanislav Mekhanoshin not write through this pointer argument, even though it may write 1358e45acfcSStanislav Mekhanoshin to the memory that the pointer points to. 1368e45acfcSStanislav Mekhanoshin On an argument, ReadNone attribute indicates that the function does 1378e45acfcSStanislav Mekhanoshin not dereference that pointer argument, even though it may read or write 1388e45acfcSStanislav Mekhanoshin the memory that the pointer points to if accessed through other pointers. 1398e45acfcSStanislav Mekhanoshin */ 1408e45acfcSStanislav Mekhanoshin if (F->getAttributes().hasAttribute(ArgNo + 1, Attribute::NoAlias) && 1418e45acfcSStanislav Mekhanoshin (F->getAttributes().hasAttribute(ArgNo + 1, Attribute::ReadNone) || 1428e45acfcSStanislav Mekhanoshin F->getAttributes().hasAttribute(ArgNo + 1, Attribute::ReadOnly))) { 1438e45acfcSStanislav Mekhanoshin return true; 1448e45acfcSStanislav Mekhanoshin } 1458e45acfcSStanislav Mekhanoshin } 1468e45acfcSStanislav Mekhanoshin return AAResultBase::pointsToConstantMemory(Loc, OrLocal); 1478e45acfcSStanislav Mekhanoshin } 148