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