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