1d16eff81SEugene Zelenko //===- AMDGPUAliasAnalysis ------------------------------------------------===// 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 "AMDGPUAliasAnalysis.h" 146bda14b3SChandler Carruth #include "AMDGPU.h" 15d16eff81SEugene Zelenko #include "llvm/ADT/Triple.h" 168e45acfcSStanislav Mekhanoshin #include "llvm/Analysis/AliasAnalysis.h" 17d16eff81SEugene Zelenko #include "llvm/Analysis/MemoryLocation.h" 186bda14b3SChandler Carruth #include "llvm/Analysis/ValueTracking.h" 19d16eff81SEugene Zelenko #include "llvm/IR/Argument.h" 20d16eff81SEugene Zelenko #include "llvm/IR/Attributes.h" 21d16eff81SEugene Zelenko #include "llvm/IR/CallingConv.h" 228e45acfcSStanislav Mekhanoshin #include "llvm/IR/Function.h" 23d16eff81SEugene Zelenko #include "llvm/IR/GlobalVariable.h" 24d16eff81SEugene Zelenko #include "llvm/IR/Type.h" 25d16eff81SEugene Zelenko #include "llvm/IR/Value.h" 268e45acfcSStanislav Mekhanoshin #include "llvm/Pass.h" 27d16eff81SEugene Zelenko #include "llvm/Support/Casting.h" 28d16eff81SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 29d16eff81SEugene Zelenko #include <cassert> 308e45acfcSStanislav Mekhanoshin 318e45acfcSStanislav Mekhanoshin using namespace llvm; 328e45acfcSStanislav Mekhanoshin 338e45acfcSStanislav Mekhanoshin #define DEBUG_TYPE "amdgpu-aa" 348e45acfcSStanislav Mekhanoshin 358e45acfcSStanislav Mekhanoshin // Register this pass... 368e45acfcSStanislav Mekhanoshin char AMDGPUAAWrapperPass::ID = 0; 37d16eff81SEugene Zelenko 388e45acfcSStanislav Mekhanoshin INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa", 398e45acfcSStanislav Mekhanoshin "AMDGPU Address space based Alias Analysis", false, true) 408e45acfcSStanislav Mekhanoshin 418e45acfcSStanislav Mekhanoshin ImmutablePass *llvm::createAMDGPUAAWrapperPass() { 428e45acfcSStanislav Mekhanoshin return new AMDGPUAAWrapperPass(); 438e45acfcSStanislav Mekhanoshin } 448e45acfcSStanislav Mekhanoshin 458e45acfcSStanislav Mekhanoshin void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 468e45acfcSStanislav Mekhanoshin AU.setPreservesAll(); 478e45acfcSStanislav Mekhanoshin } 488e45acfcSStanislav Mekhanoshin 491a14bfa0SYaxun Liu // Must match the table in getAliasResult. 503c99441eSJan Vesely AMDGPUAAResult::ASAliasRulesTy::ASAliasRulesTy(AMDGPUAS AS_, Triple::ArchType Arch_) 513c99441eSJan Vesely : Arch(Arch_), AS(AS_) { 521a14bfa0SYaxun Liu // These arrarys are indexed by address space value 531a14bfa0SYaxun Liu // enum elements 0 ... to 5 541a14bfa0SYaxun Liu static const AliasResult ASAliasRulesPrivIsZero[6][6] = { 551a14bfa0SYaxun Liu /* Private Global Constant Group Flat Region*/ 561a14bfa0SYaxun Liu /* Private */ {MayAlias, NoAlias , NoAlias , NoAlias , MayAlias, NoAlias}, 571a14bfa0SYaxun Liu /* Global */ {NoAlias , MayAlias, NoAlias , NoAlias , MayAlias, NoAlias}, 581a14bfa0SYaxun Liu /* Constant */ {NoAlias , NoAlias , MayAlias, NoAlias , MayAlias, NoAlias}, 591a14bfa0SYaxun Liu /* Group */ {NoAlias , NoAlias , NoAlias , MayAlias, MayAlias, NoAlias}, 601a14bfa0SYaxun Liu /* Flat */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias}, 611a14bfa0SYaxun Liu /* Region */ {NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, MayAlias} 621a14bfa0SYaxun Liu }; 631a14bfa0SYaxun Liu static const AliasResult ASAliasRulesGenIsZero[6][6] = { 6476ae47cbSYaxun Liu /* Flat Global Constant Group Region Private */ 651a14bfa0SYaxun Liu /* Flat */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias}, 661a14bfa0SYaxun Liu /* Global */ {MayAlias, MayAlias, NoAlias , NoAlias , NoAlias , NoAlias}, 6776ae47cbSYaxun Liu /* Constant */ {MayAlias, NoAlias , MayAlias, NoAlias , NoAlias, NoAlias}, 681a14bfa0SYaxun Liu /* Group */ {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias}, 6976ae47cbSYaxun Liu /* Region */ {MayAlias, NoAlias , NoAlias , NoAlias, MayAlias, NoAlias}, 701a14bfa0SYaxun Liu /* Private */ {MayAlias, NoAlias , NoAlias , NoAlias , NoAlias , MayAlias} 711a14bfa0SYaxun Liu }; 721a14bfa0SYaxun Liu assert(AS.MAX_COMMON_ADDRESS <= 5); 731a14bfa0SYaxun Liu if (AS.FLAT_ADDRESS == 0) { 741a14bfa0SYaxun Liu assert(AS.GLOBAL_ADDRESS == 1 && 7576ae47cbSYaxun Liu AS.REGION_ADDRESS == 4 && 761a14bfa0SYaxun Liu AS.LOCAL_ADDRESS == 3 && 7776ae47cbSYaxun Liu AS.CONSTANT_ADDRESS == 2 && 781a14bfa0SYaxun Liu AS.PRIVATE_ADDRESS == 5); 791a14bfa0SYaxun Liu ASAliasRules = &ASAliasRulesGenIsZero; 801a14bfa0SYaxun Liu } else { 811a14bfa0SYaxun Liu assert(AS.PRIVATE_ADDRESS == 0 && 821a14bfa0SYaxun Liu AS.GLOBAL_ADDRESS == 1 && 831a14bfa0SYaxun Liu AS.CONSTANT_ADDRESS == 2 && 841a14bfa0SYaxun Liu AS.LOCAL_ADDRESS == 3 && 851a14bfa0SYaxun Liu AS.FLAT_ADDRESS == 4 && 861a14bfa0SYaxun Liu AS.REGION_ADDRESS == 5); 871a14bfa0SYaxun Liu ASAliasRules = &ASAliasRulesPrivIsZero; 881a14bfa0SYaxun Liu } 891a14bfa0SYaxun Liu } 901a14bfa0SYaxun Liu 911a14bfa0SYaxun Liu AliasResult AMDGPUAAResult::ASAliasRulesTy::getAliasResult(unsigned AS1, 921a14bfa0SYaxun Liu unsigned AS2) const { 933c99441eSJan Vesely if (AS1 > AS.MAX_COMMON_ADDRESS || AS2 > AS.MAX_COMMON_ADDRESS) { 943c99441eSJan Vesely if (Arch == Triple::amdgcn) 951a14bfa0SYaxun Liu report_fatal_error("Pointer address space out of range"); 963c99441eSJan Vesely return AS1 == AS2 ? MayAlias : NoAlias; 973c99441eSJan Vesely } 983c99441eSJan Vesely 991a14bfa0SYaxun Liu return (*ASAliasRules)[AS1][AS2]; 1001a14bfa0SYaxun Liu } 1011a14bfa0SYaxun Liu 1028e45acfcSStanislav Mekhanoshin AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA, 1038e45acfcSStanislav Mekhanoshin const MemoryLocation &LocB) { 1048e45acfcSStanislav Mekhanoshin unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace(); 1058e45acfcSStanislav Mekhanoshin unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace(); 1068e45acfcSStanislav Mekhanoshin 1071a14bfa0SYaxun Liu AliasResult Result = ASAliasRules.getAliasResult(asA, asB); 1088e45acfcSStanislav Mekhanoshin if (Result == NoAlias) return Result; 1098e45acfcSStanislav Mekhanoshin 1108e45acfcSStanislav Mekhanoshin // Forward the query to the next alias analysis. 1118e45acfcSStanislav Mekhanoshin return AAResultBase::alias(LocA, LocB); 1128e45acfcSStanislav Mekhanoshin } 1138e45acfcSStanislav Mekhanoshin 1148e45acfcSStanislav Mekhanoshin bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc, 1158e45acfcSStanislav Mekhanoshin bool OrLocal) { 1168e45acfcSStanislav Mekhanoshin const Value *Base = GetUnderlyingObject(Loc.Ptr, DL); 1178e45acfcSStanislav Mekhanoshin 1181a14bfa0SYaxun Liu if (Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS) { 1198e45acfcSStanislav Mekhanoshin return true; 1208e45acfcSStanislav Mekhanoshin } 1218e45acfcSStanislav Mekhanoshin 1228e45acfcSStanislav Mekhanoshin if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) { 1238e45acfcSStanislav Mekhanoshin if (GV->isConstant()) 1248e45acfcSStanislav Mekhanoshin return true; 1258e45acfcSStanislav Mekhanoshin } else if (const Argument *Arg = dyn_cast<Argument>(Base)) { 1268e45acfcSStanislav Mekhanoshin const Function *F = Arg->getParent(); 1278e45acfcSStanislav Mekhanoshin 1288e45acfcSStanislav Mekhanoshin // Only assume constant memory for arguments on kernels. 1298e45acfcSStanislav Mekhanoshin switch (F->getCallingConv()) { 1308e45acfcSStanislav Mekhanoshin default: 1318e45acfcSStanislav Mekhanoshin return AAResultBase::pointsToConstantMemory(Loc, OrLocal); 132*ef1ae8ffSTim Renouf case CallingConv::AMDGPU_LS: 133*ef1ae8ffSTim Renouf case CallingConv::AMDGPU_HS: 134*ef1ae8ffSTim Renouf case CallingConv::AMDGPU_ES: 1358e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_GS: 136*ef1ae8ffSTim Renouf case CallingConv::AMDGPU_VS: 1378e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_PS: 1388e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_CS: 1398e45acfcSStanislav Mekhanoshin case CallingConv::AMDGPU_KERNEL: 1408e45acfcSStanislav Mekhanoshin case CallingConv::SPIR_KERNEL: 1418e45acfcSStanislav Mekhanoshin break; 1428e45acfcSStanislav Mekhanoshin } 1438e45acfcSStanislav Mekhanoshin 1448e45acfcSStanislav Mekhanoshin unsigned ArgNo = Arg->getArgNo(); 1458e45acfcSStanislav Mekhanoshin /* On an argument, ReadOnly attribute indicates that the function does 1468e45acfcSStanislav Mekhanoshin not write through this pointer argument, even though it may write 1478e45acfcSStanislav Mekhanoshin to the memory that the pointer points to. 1488e45acfcSStanislav Mekhanoshin On an argument, ReadNone attribute indicates that the function does 1498e45acfcSStanislav Mekhanoshin not dereference that pointer argument, even though it may read or write 1508e45acfcSStanislav Mekhanoshin the memory that the pointer points to if accessed through other pointers. 1518e45acfcSStanislav Mekhanoshin */ 152f021fab2SReid Kleckner if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) && 153f021fab2SReid Kleckner (F->hasParamAttribute(ArgNo, Attribute::ReadNone) || 154f021fab2SReid Kleckner F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) { 1558e45acfcSStanislav Mekhanoshin return true; 1568e45acfcSStanislav Mekhanoshin } 1578e45acfcSStanislav Mekhanoshin } 1588e45acfcSStanislav Mekhanoshin return AAResultBase::pointsToConstantMemory(Loc, OrLocal); 1598e45acfcSStanislav Mekhanoshin } 160