1d16eff81SEugene Zelenko //===- AMDGPUAliasAnalysis ------------------------------------------------===//
28e45acfcSStanislav Mekhanoshin //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68e45acfcSStanislav Mekhanoshin //
78e45acfcSStanislav Mekhanoshin //===----------------------------------------------------------------------===//
88e45acfcSStanislav Mekhanoshin /// \file
98e45acfcSStanislav Mekhanoshin /// This is the AMGPU address space based alias analysis pass.
108e45acfcSStanislav Mekhanoshin //===----------------------------------------------------------------------===//
118e45acfcSStanislav Mekhanoshin 
128e45acfcSStanislav Mekhanoshin #include "AMDGPUAliasAnalysis.h"
136bda14b3SChandler Carruth #include "AMDGPU.h"
14d16eff81SEugene Zelenko #include "llvm/ADT/Triple.h"
158e45acfcSStanislav Mekhanoshin #include "llvm/Analysis/AliasAnalysis.h"
16d16eff81SEugene Zelenko #include "llvm/Analysis/MemoryLocation.h"
176bda14b3SChandler Carruth #include "llvm/Analysis/ValueTracking.h"
18d16eff81SEugene Zelenko #include "llvm/IR/Argument.h"
19d16eff81SEugene Zelenko #include "llvm/IR/Attributes.h"
20d16eff81SEugene Zelenko #include "llvm/IR/CallingConv.h"
218e45acfcSStanislav Mekhanoshin #include "llvm/IR/Function.h"
22d16eff81SEugene Zelenko #include "llvm/IR/GlobalVariable.h"
23d16eff81SEugene Zelenko #include "llvm/IR/Type.h"
24d16eff81SEugene Zelenko #include "llvm/IR/Value.h"
258e45acfcSStanislav Mekhanoshin #include "llvm/Pass.h"
26d16eff81SEugene Zelenko #include "llvm/Support/Casting.h"
27d16eff81SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
28d16eff81SEugene Zelenko #include <cassert>
298e45acfcSStanislav Mekhanoshin 
308e45acfcSStanislav Mekhanoshin using namespace llvm;
318e45acfcSStanislav Mekhanoshin 
328e45acfcSStanislav Mekhanoshin #define DEBUG_TYPE "amdgpu-aa"
338e45acfcSStanislav Mekhanoshin 
348e45acfcSStanislav Mekhanoshin // Register this pass...
358e45acfcSStanislav Mekhanoshin char AMDGPUAAWrapperPass::ID = 0;
368ba740a5SMatt Arsenault char AMDGPUExternalAAWrapper::ID = 0;
37d16eff81SEugene Zelenko 
388e45acfcSStanislav Mekhanoshin INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
398e45acfcSStanislav Mekhanoshin                 "AMDGPU Address space based Alias Analysis", false, true)
408e45acfcSStanislav Mekhanoshin 
418ba740a5SMatt Arsenault INITIALIZE_PASS(AMDGPUExternalAAWrapper, "amdgpu-aa-wrapper",
428ba740a5SMatt Arsenault                 "AMDGPU Address space based Alias Analysis Wrapper", false, true)
438ba740a5SMatt Arsenault 
448e45acfcSStanislav Mekhanoshin ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
458e45acfcSStanislav Mekhanoshin   return new AMDGPUAAWrapperPass();
468e45acfcSStanislav Mekhanoshin }
478e45acfcSStanislav Mekhanoshin 
488ba740a5SMatt Arsenault ImmutablePass *llvm::createAMDGPUExternalAAWrapperPass() {
498ba740a5SMatt Arsenault   return new AMDGPUExternalAAWrapper();
508ba740a5SMatt Arsenault }
518ba740a5SMatt Arsenault 
528e45acfcSStanislav Mekhanoshin void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
538e45acfcSStanislav Mekhanoshin   AU.setPreservesAll();
548e45acfcSStanislav Mekhanoshin }
558e45acfcSStanislav Mekhanoshin 
56523dab07SNeil Henning // These arrays are indexed by address space value enum elements 0 ... to 7
57523dab07SNeil Henning static const AliasResult ASAliasRules[8][8] = {
58523dab07SNeil Henning   /*                    Flat       Global    Region    Group     Constant  Private   Constant 32-bit  Buffer Fat Ptr */
59a256b8b7SNicolai Haehnle   /* Flat     */        {MayAlias, MayAlias, NoAlias,  MayAlias, MayAlias, MayAlias, MayAlias,        MayAlias},
60523dab07SNeil Henning   /* Global   */        {MayAlias, MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , MayAlias,        MayAlias},
61a256b8b7SNicolai Haehnle   /* Region   */        {NoAlias,  NoAlias , MayAlias, NoAlias , NoAlias,  NoAlias , NoAlias,         NoAlias},
62523dab07SNeil Henning   /* Group    */        {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias , NoAlias ,        NoAlias},
63a256b8b7SNicolai Haehnle   /* Constant */        {MayAlias, MayAlias, NoAlias,  NoAlias , NoAlias , NoAlias , MayAlias,        MayAlias},
64523dab07SNeil Henning   /* Private  */        {MayAlias, NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, NoAlias ,        NoAlias},
65a256b8b7SNicolai Haehnle   /* Constant 32-bit */ {MayAlias, MayAlias, NoAlias,  NoAlias , MayAlias, NoAlias , NoAlias ,        MayAlias},
66523dab07SNeil Henning   /* Buffer Fat Ptr  */ {MayAlias, MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , MayAlias,        MayAlias}
671a14bfa0SYaxun Liu };
680da6350dSMatt Arsenault 
69796b0e7aSMatt Arsenault static AliasResult getAliasResult(unsigned AS1, unsigned AS2) {
70523dab07SNeil Henning   static_assert(AMDGPUAS::MAX_AMDGPU_ADDRESS <= 7, "Addr space out of range");
710da6350dSMatt Arsenault 
72796b0e7aSMatt Arsenault   if (AS1 > AMDGPUAS::MAX_AMDGPU_ADDRESS || AS2 > AMDGPUAS::MAX_AMDGPU_ADDRESS)
73796b0e7aSMatt Arsenault     return MayAlias;
741a14bfa0SYaxun Liu 
75796b0e7aSMatt Arsenault   return ASAliasRules[AS1][AS2];
761a14bfa0SYaxun Liu }
771a14bfa0SYaxun Liu 
788e45acfcSStanislav Mekhanoshin AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
79bfc779e4SAlina Sbirlea                                   const MemoryLocation &LocB,
80bfc779e4SAlina Sbirlea                                   AAQueryInfo &AAQI) {
818e45acfcSStanislav Mekhanoshin   unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
828e45acfcSStanislav Mekhanoshin   unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
838e45acfcSStanislav Mekhanoshin 
84796b0e7aSMatt Arsenault   AliasResult Result = getAliasResult(asA, asB);
85796b0e7aSMatt Arsenault   if (Result == NoAlias)
86796b0e7aSMatt Arsenault     return Result;
878e45acfcSStanislav Mekhanoshin 
888e45acfcSStanislav Mekhanoshin   // Forward the query to the next alias analysis.
89bfc779e4SAlina Sbirlea   return AAResultBase::alias(LocA, LocB, AAQI);
908e45acfcSStanislav Mekhanoshin }
918e45acfcSStanislav Mekhanoshin 
928e45acfcSStanislav Mekhanoshin bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
93bfc779e4SAlina Sbirlea                                             AAQueryInfo &AAQI, bool OrLocal) {
94beda9d04SMatt Arsenault   unsigned AS = Loc.Ptr->getType()->getPointerAddressSpace();
950da6350dSMatt Arsenault   if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
96beda9d04SMatt Arsenault       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
978e45acfcSStanislav Mekhanoshin     return true;
98beda9d04SMatt Arsenault 
99*b0eb40caSVitaly Buka   const Value *Base = getUnderlyingObject(Loc.Ptr);
100beda9d04SMatt Arsenault   AS = Base->getType()->getPointerAddressSpace();
101beda9d04SMatt Arsenault   if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
102beda9d04SMatt Arsenault       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
103beda9d04SMatt Arsenault     return true;
1048e45acfcSStanislav Mekhanoshin 
1058e45acfcSStanislav Mekhanoshin   if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
1068e45acfcSStanislav Mekhanoshin     if (GV->isConstant())
1078e45acfcSStanislav Mekhanoshin       return true;
1088e45acfcSStanislav Mekhanoshin   } else if (const Argument *Arg = dyn_cast<Argument>(Base)) {
1098e45acfcSStanislav Mekhanoshin     const Function *F = Arg->getParent();
1108e45acfcSStanislav Mekhanoshin 
1118e45acfcSStanislav Mekhanoshin     // Only assume constant memory for arguments on kernels.
1128e45acfcSStanislav Mekhanoshin     switch (F->getCallingConv()) {
1138e45acfcSStanislav Mekhanoshin     default:
114bfc779e4SAlina Sbirlea       return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal);
115ef1ae8ffSTim Renouf     case CallingConv::AMDGPU_LS:
116ef1ae8ffSTim Renouf     case CallingConv::AMDGPU_HS:
117ef1ae8ffSTim Renouf     case CallingConv::AMDGPU_ES:
1188e45acfcSStanislav Mekhanoshin     case CallingConv::AMDGPU_GS:
119ef1ae8ffSTim Renouf     case CallingConv::AMDGPU_VS:
1208e45acfcSStanislav Mekhanoshin     case CallingConv::AMDGPU_PS:
1218e45acfcSStanislav Mekhanoshin     case CallingConv::AMDGPU_CS:
1228e45acfcSStanislav Mekhanoshin     case CallingConv::AMDGPU_KERNEL:
1238e45acfcSStanislav Mekhanoshin     case CallingConv::SPIR_KERNEL:
1248e45acfcSStanislav Mekhanoshin       break;
1258e45acfcSStanislav Mekhanoshin     }
1268e45acfcSStanislav Mekhanoshin 
1278e45acfcSStanislav Mekhanoshin     unsigned ArgNo = Arg->getArgNo();
1288e45acfcSStanislav Mekhanoshin     /* On an argument, ReadOnly attribute indicates that the function does
1298e45acfcSStanislav Mekhanoshin        not write through this pointer argument, even though it may write
1308e45acfcSStanislav Mekhanoshin        to the memory that the pointer points to.
1318e45acfcSStanislav Mekhanoshin        On an argument, ReadNone attribute indicates that the function does
1328e45acfcSStanislav Mekhanoshin        not dereference that pointer argument, even though it may read or write
1338e45acfcSStanislav Mekhanoshin        the memory that the pointer points to if accessed through other pointers.
1348e45acfcSStanislav Mekhanoshin      */
135f021fab2SReid Kleckner     if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) &&
136f021fab2SReid Kleckner         (F->hasParamAttribute(ArgNo, Attribute::ReadNone) ||
137f021fab2SReid Kleckner          F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) {
1388e45acfcSStanislav Mekhanoshin       return true;
1398e45acfcSStanislav Mekhanoshin     }
1408e45acfcSStanislav Mekhanoshin   }
141bfc779e4SAlina Sbirlea   return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal);
1428e45acfcSStanislav Mekhanoshin }
143