12cab237bSDimitry Andric //===- AMDGPUAliasAnalysis ------------------------------------------------===//
27a7e6055SDimitry Andric //
37a7e6055SDimitry Andric // The LLVM Compiler Infrastructure
47a7e6055SDimitry Andric //
57a7e6055SDimitry Andric // This file is distributed under the University of Illinois Open Source
67a7e6055SDimitry Andric // License. See LICENSE.TXT for details.
77a7e6055SDimitry Andric //
87a7e6055SDimitry Andric //===----------------------------------------------------------------------===//
97a7e6055SDimitry Andric /// \file
107a7e6055SDimitry Andric /// This is the AMGPU address space based alias analysis pass.
117a7e6055SDimitry Andric //===----------------------------------------------------------------------===//
127a7e6055SDimitry Andric
137a7e6055SDimitry Andric #include "AMDGPUAliasAnalysis.h"
14db17bf38SDimitry Andric #include "AMDGPU.h"
152cab237bSDimitry Andric #include "llvm/ADT/Triple.h"
167a7e6055SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
172cab237bSDimitry Andric #include "llvm/Analysis/MemoryLocation.h"
18db17bf38SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
192cab237bSDimitry Andric #include "llvm/IR/Argument.h"
202cab237bSDimitry Andric #include "llvm/IR/Attributes.h"
212cab237bSDimitry Andric #include "llvm/IR/CallingConv.h"
227a7e6055SDimitry Andric #include "llvm/IR/Function.h"
232cab237bSDimitry Andric #include "llvm/IR/GlobalVariable.h"
242cab237bSDimitry Andric #include "llvm/IR/Type.h"
252cab237bSDimitry Andric #include "llvm/IR/Value.h"
267a7e6055SDimitry Andric #include "llvm/Pass.h"
272cab237bSDimitry Andric #include "llvm/Support/Casting.h"
282cab237bSDimitry Andric #include "llvm/Support/ErrorHandling.h"
292cab237bSDimitry Andric #include <cassert>
307a7e6055SDimitry Andric
317a7e6055SDimitry Andric using namespace llvm;
327a7e6055SDimitry Andric
337a7e6055SDimitry Andric #define DEBUG_TYPE "amdgpu-aa"
347a7e6055SDimitry Andric
357a7e6055SDimitry Andric // Register this pass...
367a7e6055SDimitry Andric char AMDGPUAAWrapperPass::ID = 0;
37*b5893f02SDimitry Andric char AMDGPUExternalAAWrapper::ID = 0;
382cab237bSDimitry Andric
397a7e6055SDimitry Andric INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
407a7e6055SDimitry Andric "AMDGPU Address space based Alias Analysis", false, true)
417a7e6055SDimitry Andric
42*b5893f02SDimitry Andric INITIALIZE_PASS(AMDGPUExternalAAWrapper, "amdgpu-aa-wrapper",
43*b5893f02SDimitry Andric "AMDGPU Address space based Alias Analysis Wrapper", false, true)
44*b5893f02SDimitry Andric
createAMDGPUAAWrapperPass()457a7e6055SDimitry Andric ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
467a7e6055SDimitry Andric return new AMDGPUAAWrapperPass();
477a7e6055SDimitry Andric }
487a7e6055SDimitry Andric
createAMDGPUExternalAAWrapperPass()49*b5893f02SDimitry Andric ImmutablePass *llvm::createAMDGPUExternalAAWrapperPass() {
50*b5893f02SDimitry Andric return new AMDGPUExternalAAWrapper();
51*b5893f02SDimitry Andric }
52*b5893f02SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const537a7e6055SDimitry Andric void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
547a7e6055SDimitry Andric AU.setPreservesAll();
557a7e6055SDimitry Andric }
567a7e6055SDimitry Andric
57*b5893f02SDimitry Andric // These arrays are indexed by address space value enum elements 0 ... to 6
58*b5893f02SDimitry Andric static const AliasResult ASAliasRules[7][7] = {
594ba319b5SDimitry Andric /* Flat Global Region Group Constant Private Constant 32-bit */
604ba319b5SDimitry Andric /* Flat */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias},
614ba319b5SDimitry Andric /* Global */ {MayAlias, MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , MayAlias},
624ba319b5SDimitry Andric /* Region */ {MayAlias, NoAlias , NoAlias , NoAlias, MayAlias, NoAlias , MayAlias},
634ba319b5SDimitry Andric /* Group */ {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias , NoAlias},
644ba319b5SDimitry Andric /* Constant */ {MayAlias, MayAlias, MayAlias, NoAlias , NoAlias, NoAlias , MayAlias},
654ba319b5SDimitry Andric /* Private */ {MayAlias, NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, NoAlias},
664ba319b5SDimitry Andric /* Constant 32-bit */ {MayAlias, MayAlias, MayAlias, NoAlias , MayAlias, NoAlias , NoAlias}
677a7e6055SDimitry Andric };
68*b5893f02SDimitry Andric
getAliasResult(unsigned AS1,unsigned AS2)69*b5893f02SDimitry Andric static AliasResult getAliasResult(unsigned AS1, unsigned AS2) {
704ba319b5SDimitry Andric static_assert(AMDGPUAS::MAX_AMDGPU_ADDRESS <= 6, "Addr space out of range");
717a7e6055SDimitry Andric
72*b5893f02SDimitry Andric if (AS1 > AMDGPUAS::MAX_AMDGPU_ADDRESS || AS2 > AMDGPUAS::MAX_AMDGPU_ADDRESS)
73*b5893f02SDimitry Andric return MayAlias;
747a7e6055SDimitry Andric
75*b5893f02SDimitry Andric return ASAliasRules[AS1][AS2];
767a7e6055SDimitry Andric }
777a7e6055SDimitry Andric
alias(const MemoryLocation & LocA,const MemoryLocation & LocB)787a7e6055SDimitry Andric AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
797a7e6055SDimitry Andric const MemoryLocation &LocB) {
807a7e6055SDimitry Andric unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
817a7e6055SDimitry Andric unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
827a7e6055SDimitry Andric
83*b5893f02SDimitry Andric AliasResult Result = getAliasResult(asA, asB);
84*b5893f02SDimitry Andric if (Result == NoAlias)
85*b5893f02SDimitry Andric return Result;
867a7e6055SDimitry Andric
877a7e6055SDimitry Andric // Forward the query to the next alias analysis.
887a7e6055SDimitry Andric return AAResultBase::alias(LocA, LocB);
897a7e6055SDimitry Andric }
907a7e6055SDimitry Andric
pointsToConstantMemory(const MemoryLocation & Loc,bool OrLocal)917a7e6055SDimitry Andric bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
927a7e6055SDimitry Andric bool OrLocal) {
937a7e6055SDimitry Andric const Value *Base = GetUnderlyingObject(Loc.Ptr, DL);
94*b5893f02SDimitry Andric unsigned AS = Base->getType()->getPointerAddressSpace();
95*b5893f02SDimitry Andric if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
96*b5893f02SDimitry Andric AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT) {
977a7e6055SDimitry Andric return true;
987a7e6055SDimitry Andric }
997a7e6055SDimitry Andric
1007a7e6055SDimitry Andric if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
1017a7e6055SDimitry Andric if (GV->isConstant())
1027a7e6055SDimitry Andric return true;
1037a7e6055SDimitry Andric } else if (const Argument *Arg = dyn_cast<Argument>(Base)) {
1047a7e6055SDimitry Andric const Function *F = Arg->getParent();
1057a7e6055SDimitry Andric
1067a7e6055SDimitry Andric // Only assume constant memory for arguments on kernels.
1077a7e6055SDimitry Andric switch (F->getCallingConv()) {
1087a7e6055SDimitry Andric default:
1097a7e6055SDimitry Andric return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
1102cab237bSDimitry Andric case CallingConv::AMDGPU_LS:
1112cab237bSDimitry Andric case CallingConv::AMDGPU_HS:
1122cab237bSDimitry Andric case CallingConv::AMDGPU_ES:
1137a7e6055SDimitry Andric case CallingConv::AMDGPU_GS:
1142cab237bSDimitry Andric case CallingConv::AMDGPU_VS:
1157a7e6055SDimitry Andric case CallingConv::AMDGPU_PS:
1167a7e6055SDimitry Andric case CallingConv::AMDGPU_CS:
1177a7e6055SDimitry Andric case CallingConv::AMDGPU_KERNEL:
1187a7e6055SDimitry Andric case CallingConv::SPIR_KERNEL:
1197a7e6055SDimitry Andric break;
1207a7e6055SDimitry Andric }
1217a7e6055SDimitry Andric
1227a7e6055SDimitry Andric unsigned ArgNo = Arg->getArgNo();
1237a7e6055SDimitry Andric /* On an argument, ReadOnly attribute indicates that the function does
1247a7e6055SDimitry Andric not write through this pointer argument, even though it may write
1257a7e6055SDimitry Andric to the memory that the pointer points to.
1267a7e6055SDimitry Andric On an argument, ReadNone attribute indicates that the function does
1277a7e6055SDimitry Andric not dereference that pointer argument, even though it may read or write
1287a7e6055SDimitry Andric the memory that the pointer points to if accessed through other pointers.
1297a7e6055SDimitry Andric */
1307a7e6055SDimitry Andric if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) &&
1317a7e6055SDimitry Andric (F->hasParamAttribute(ArgNo, Attribute::ReadNone) ||
1327a7e6055SDimitry Andric F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) {
1337a7e6055SDimitry Andric return true;
1347a7e6055SDimitry Andric }
1357a7e6055SDimitry Andric }
1367a7e6055SDimitry Andric return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
1377a7e6055SDimitry Andric }
138