xref: /src/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1044eb2f6SDimitry Andric //===- AMDGPUAliasAnalysis ------------------------------------------------===//
271d5a254SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
671d5a254SDimitry Andric //
771d5a254SDimitry Andric //===----------------------------------------------------------------------===//
871d5a254SDimitry Andric /// \file
971d5a254SDimitry Andric /// This is the AMGPU address space based alias analysis pass.
1071d5a254SDimitry Andric //===----------------------------------------------------------------------===//
1171d5a254SDimitry Andric 
1271d5a254SDimitry Andric #include "AMDGPUAliasAnalysis.h"
13c0981da4SDimitry Andric #include "AMDGPU.h"
147ab83427SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
15b60736ecSDimitry Andric #include "llvm/IR/Instructions.h"
1671d5a254SDimitry Andric 
1771d5a254SDimitry Andric using namespace llvm;
1871d5a254SDimitry Andric 
1971d5a254SDimitry Andric #define DEBUG_TYPE "amdgpu-aa"
2071d5a254SDimitry Andric 
21b60736ecSDimitry Andric AnalysisKey AMDGPUAA::Key;
22b60736ecSDimitry Andric 
2371d5a254SDimitry Andric // Register this pass...
2471d5a254SDimitry Andric char AMDGPUAAWrapperPass::ID = 0;
25d8e91e46SDimitry Andric char AMDGPUExternalAAWrapper::ID = 0;
26044eb2f6SDimitry Andric 
2771d5a254SDimitry Andric INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
2871d5a254SDimitry Andric                 "AMDGPU Address space based Alias Analysis", false, true)
2971d5a254SDimitry Andric 
30d8e91e46SDimitry Andric INITIALIZE_PASS(AMDGPUExternalAAWrapper, "amdgpu-aa-wrapper",
31d8e91e46SDimitry Andric                 "AMDGPU Address space based Alias Analysis Wrapper", false, true)
32d8e91e46SDimitry Andric 
createAMDGPUAAWrapperPass()3371d5a254SDimitry Andric ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
3471d5a254SDimitry Andric   return new AMDGPUAAWrapperPass();
3571d5a254SDimitry Andric }
3671d5a254SDimitry Andric 
createAMDGPUExternalAAWrapperPass()37d8e91e46SDimitry Andric ImmutablePass *llvm::createAMDGPUExternalAAWrapperPass() {
38d8e91e46SDimitry Andric   return new AMDGPUExternalAAWrapper();
39d8e91e46SDimitry Andric }
40d8e91e46SDimitry Andric 
AMDGPUAAWrapperPass()41c0981da4SDimitry Andric AMDGPUAAWrapperPass::AMDGPUAAWrapperPass() : ImmutablePass(ID) {
42c0981da4SDimitry Andric   initializeAMDGPUAAWrapperPassPass(*PassRegistry::getPassRegistry());
43c0981da4SDimitry Andric }
44c0981da4SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const4571d5a254SDimitry Andric void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
4671d5a254SDimitry Andric   AU.setPreservesAll();
4771d5a254SDimitry Andric }
4871d5a254SDimitry Andric 
alias(const MemoryLocation & LocA,const MemoryLocation & LocB,AAQueryInfo & AAQI,const Instruction *)4971d5a254SDimitry Andric AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
50e3b55780SDimitry Andric                                   const MemoryLocation &LocB, AAQueryInfo &AAQI,
51e3b55780SDimitry Andric                                   const Instruction *) {
5271d5a254SDimitry Andric   unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
5371d5a254SDimitry Andric   unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
5471d5a254SDimitry Andric 
557fa27ce4SDimitry Andric   if (!AMDGPU::addrspacesMayAlias(asA, asB))
567fa27ce4SDimitry Andric     return AliasResult::NoAlias;
5771d5a254SDimitry Andric 
58b60736ecSDimitry Andric   // In general, FLAT (generic) pointers could be aliased to LOCAL or PRIVATE
59b60736ecSDimitry Andric   // pointers. However, as LOCAL or PRIVATE pointers point to local objects, in
60b60736ecSDimitry Andric   // certain cases, it's still viable to check whether a FLAT pointer won't
61b60736ecSDimitry Andric   // alias to a LOCAL or PRIVATE pointer.
62b60736ecSDimitry Andric   MemoryLocation A = LocA;
63b60736ecSDimitry Andric   MemoryLocation B = LocB;
64b60736ecSDimitry Andric   // Canonicalize the location order to simplify the following alias check.
65b60736ecSDimitry Andric   if (asA != AMDGPUAS::FLAT_ADDRESS) {
66b60736ecSDimitry Andric     std::swap(asA, asB);
67b60736ecSDimitry Andric     std::swap(A, B);
68b60736ecSDimitry Andric   }
69b60736ecSDimitry Andric   if (asA == AMDGPUAS::FLAT_ADDRESS &&
70b60736ecSDimitry Andric       (asB == AMDGPUAS::LOCAL_ADDRESS || asB == AMDGPUAS::PRIVATE_ADDRESS)) {
71b60736ecSDimitry Andric     const auto *ObjA =
72344a3780SDimitry Andric         getUnderlyingObject(A.Ptr->stripPointerCastsForAliasAnalysis());
73b60736ecSDimitry Andric     if (const LoadInst *LI = dyn_cast<LoadInst>(ObjA)) {
74b60736ecSDimitry Andric       // If a generic pointer is loaded from the constant address space, it
75c0981da4SDimitry Andric       // could only be a GLOBAL or CONSTANT one as that address space is solely
76b60736ecSDimitry Andric       // prepared on the host side, where only GLOBAL or CONSTANT variables are
77b60736ecSDimitry Andric       // visible. Note that this even holds for regular functions.
78b60736ecSDimitry Andric       if (LI->getPointerAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS)
79344a3780SDimitry Andric         return AliasResult::NoAlias;
80b60736ecSDimitry Andric     } else if (const Argument *Arg = dyn_cast<Argument>(ObjA)) {
81b60736ecSDimitry Andric       const Function *F = Arg->getParent();
82b60736ecSDimitry Andric       switch (F->getCallingConv()) {
83b60736ecSDimitry Andric       case CallingConv::AMDGPU_KERNEL:
84b60736ecSDimitry Andric         // In the kernel function, kernel arguments won't alias to (local)
85b60736ecSDimitry Andric         // variables in shared or private address space.
86344a3780SDimitry Andric         return AliasResult::NoAlias;
87b60736ecSDimitry Andric       default:
88b60736ecSDimitry Andric         // TODO: In the regular function, if that local variable in the
89b60736ecSDimitry Andric         // location B is not captured, that argument pointer won't alias to it
90b60736ecSDimitry Andric         // as well.
91b60736ecSDimitry Andric         break;
92b60736ecSDimitry Andric       }
93b60736ecSDimitry Andric     }
94b60736ecSDimitry Andric   }
95b60736ecSDimitry Andric 
96b1c73532SDimitry Andric   return AliasResult::MayAlias;
9771d5a254SDimitry Andric }
9871d5a254SDimitry Andric 
getModRefInfoMask(const MemoryLocation & Loc,AAQueryInfo & AAQI,bool IgnoreLocals)99e3b55780SDimitry Andric ModRefInfo AMDGPUAAResult::getModRefInfoMask(const MemoryLocation &Loc,
100e3b55780SDimitry Andric                                              AAQueryInfo &AAQI,
101e3b55780SDimitry Andric                                              bool IgnoreLocals) {
102cfca06d7SDimitry Andric   unsigned AS = Loc.Ptr->getType()->getPointerAddressSpace();
103d8e91e46SDimitry Andric   if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
104cfca06d7SDimitry Andric       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
105e3b55780SDimitry Andric     return ModRefInfo::NoModRef;
106cfca06d7SDimitry Andric 
107b60736ecSDimitry Andric   const Value *Base = getUnderlyingObject(Loc.Ptr);
108cfca06d7SDimitry Andric   AS = Base->getType()->getPointerAddressSpace();
109cfca06d7SDimitry Andric   if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
110cfca06d7SDimitry Andric       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
111e3b55780SDimitry Andric     return ModRefInfo::NoModRef;
11271d5a254SDimitry Andric 
113b1c73532SDimitry Andric   return ModRefInfo::ModRef;
11471d5a254SDimitry Andric }
115