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 */
59*a256b8b7SNicolai Haehnle   /* Flat     */        {MayAlias, MayAlias, NoAlias,  MayAlias, MayAlias, MayAlias, MayAlias,        MayAlias},
60523dab07SNeil Henning   /* Global   */        {MayAlias, MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , MayAlias,        MayAlias},
61*a256b8b7SNicolai Haehnle   /* Region   */        {NoAlias,  NoAlias , MayAlias, NoAlias , NoAlias,  NoAlias , NoAlias,         NoAlias},
62523dab07SNeil Henning   /* Group    */        {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias , NoAlias ,        NoAlias},
63*a256b8b7SNicolai Haehnle   /* Constant */        {MayAlias, MayAlias, NoAlias,  NoAlias , NoAlias , NoAlias , MayAlias,        MayAlias},
64523dab07SNeil Henning   /* Private  */        {MayAlias, NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, NoAlias ,        NoAlias},
65*a256b8b7SNicolai 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) {
948e45acfcSStanislav Mekhanoshin   const Value *Base = GetUnderlyingObject(Loc.Ptr, DL);
950da6350dSMatt Arsenault   unsigned AS = Base->getType()->getPointerAddressSpace();
960da6350dSMatt Arsenault   if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
970da6350dSMatt Arsenault       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) {
988e45acfcSStanislav Mekhanoshin     return true;
998e45acfcSStanislav Mekhanoshin   }
1008e45acfcSStanislav Mekhanoshin 
1018e45acfcSStanislav Mekhanoshin   if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
1028e45acfcSStanislav Mekhanoshin     if (GV->isConstant())
1038e45acfcSStanislav Mekhanoshin       return true;
1048e45acfcSStanislav Mekhanoshin   } else if (const Argument *Arg = dyn_cast<Argument>(Base)) {
1058e45acfcSStanislav Mekhanoshin     const Function *F = Arg->getParent();
1068e45acfcSStanislav Mekhanoshin 
1078e45acfcSStanislav Mekhanoshin     // Only assume constant memory for arguments on kernels.
1088e45acfcSStanislav Mekhanoshin     switch (F->getCallingConv()) {
1098e45acfcSStanislav Mekhanoshin     default:
110bfc779e4SAlina Sbirlea       return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal);
111ef1ae8ffSTim Renouf     case CallingConv::AMDGPU_LS:
112ef1ae8ffSTim Renouf     case CallingConv::AMDGPU_HS:
113ef1ae8ffSTim Renouf     case CallingConv::AMDGPU_ES:
1148e45acfcSStanislav Mekhanoshin     case CallingConv::AMDGPU_GS:
115ef1ae8ffSTim Renouf     case CallingConv::AMDGPU_VS:
1168e45acfcSStanislav Mekhanoshin     case CallingConv::AMDGPU_PS:
1178e45acfcSStanislav Mekhanoshin     case CallingConv::AMDGPU_CS:
1188e45acfcSStanislav Mekhanoshin     case CallingConv::AMDGPU_KERNEL:
1198e45acfcSStanislav Mekhanoshin     case CallingConv::SPIR_KERNEL:
1208e45acfcSStanislav Mekhanoshin       break;
1218e45acfcSStanislav Mekhanoshin     }
1228e45acfcSStanislav Mekhanoshin 
1238e45acfcSStanislav Mekhanoshin     unsigned ArgNo = Arg->getArgNo();
1248e45acfcSStanislav Mekhanoshin     /* On an argument, ReadOnly attribute indicates that the function does
1258e45acfcSStanislav Mekhanoshin        not write through this pointer argument, even though it may write
1268e45acfcSStanislav Mekhanoshin        to the memory that the pointer points to.
1278e45acfcSStanislav Mekhanoshin        On an argument, ReadNone attribute indicates that the function does
1288e45acfcSStanislav Mekhanoshin        not dereference that pointer argument, even though it may read or write
1298e45acfcSStanislav Mekhanoshin        the memory that the pointer points to if accessed through other pointers.
1308e45acfcSStanislav Mekhanoshin      */
131f021fab2SReid Kleckner     if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) &&
132f021fab2SReid Kleckner         (F->hasParamAttribute(ArgNo, Attribute::ReadNone) ||
133f021fab2SReid Kleckner          F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) {
1348e45acfcSStanislav Mekhanoshin       return true;
1358e45acfcSStanislav Mekhanoshin     }
1368e45acfcSStanislav Mekhanoshin   }
137bfc779e4SAlina Sbirlea   return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal);
1388e45acfcSStanislav Mekhanoshin }
139