xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- AMDGPUAliasAnalysis ------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric /// This is the AMGPU address space based alias analysis pass.
100b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "AMDGPUAliasAnalysis.h"
13349cc55cSDimitry Andric #include "AMDGPU.h"
140b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
15e8d8bef9SDimitry Andric #include "llvm/IR/Instructions.h"
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric using namespace llvm;
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #define DEBUG_TYPE "amdgpu-aa"
200b57cec5SDimitry Andric 
21e8d8bef9SDimitry Andric AnalysisKey AMDGPUAA::Key;
22e8d8bef9SDimitry Andric 
230b57cec5SDimitry Andric // Register this pass...
240b57cec5SDimitry Andric char AMDGPUAAWrapperPass::ID = 0;
250b57cec5SDimitry Andric char AMDGPUExternalAAWrapper::ID = 0;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
280b57cec5SDimitry Andric                 "AMDGPU Address space based Alias Analysis", false, true)
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric INITIALIZE_PASS(AMDGPUExternalAAWrapper, "amdgpu-aa-wrapper",
310b57cec5SDimitry Andric                 "AMDGPU Address space based Alias Analysis Wrapper", false, true)
320b57cec5SDimitry Andric 
createAMDGPUAAWrapperPass()330b57cec5SDimitry Andric ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
340b57cec5SDimitry Andric   return new AMDGPUAAWrapperPass();
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric 
createAMDGPUExternalAAWrapperPass()370b57cec5SDimitry Andric ImmutablePass *llvm::createAMDGPUExternalAAWrapperPass() {
380b57cec5SDimitry Andric   return new AMDGPUExternalAAWrapper();
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric 
AMDGPUAAWrapperPass()41349cc55cSDimitry Andric AMDGPUAAWrapperPass::AMDGPUAAWrapperPass() : ImmutablePass(ID) {
42349cc55cSDimitry Andric   initializeAMDGPUAAWrapperPassPass(*PassRegistry::getPassRegistry());
43349cc55cSDimitry Andric }
44349cc55cSDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const450b57cec5SDimitry Andric void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
460b57cec5SDimitry Andric   AU.setPreservesAll();
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric 
alias(const MemoryLocation & LocA,const MemoryLocation & LocB,AAQueryInfo & AAQI,const Instruction *)490b57cec5SDimitry Andric AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
50bdd1243dSDimitry Andric                                   const MemoryLocation &LocB, AAQueryInfo &AAQI,
51bdd1243dSDimitry Andric                                   const Instruction *) {
520b57cec5SDimitry Andric   unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
530b57cec5SDimitry Andric   unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
540b57cec5SDimitry Andric 
5506c3fb27SDimitry Andric   if (!AMDGPU::addrspacesMayAlias(asA, asB))
5606c3fb27SDimitry Andric     return AliasResult::NoAlias;
570b57cec5SDimitry Andric 
58e8d8bef9SDimitry Andric   // In general, FLAT (generic) pointers could be aliased to LOCAL or PRIVATE
59e8d8bef9SDimitry Andric   // pointers. However, as LOCAL or PRIVATE pointers point to local objects, in
60e8d8bef9SDimitry Andric   // certain cases, it's still viable to check whether a FLAT pointer won't
61e8d8bef9SDimitry Andric   // alias to a LOCAL or PRIVATE pointer.
62e8d8bef9SDimitry Andric   MemoryLocation A = LocA;
63e8d8bef9SDimitry Andric   MemoryLocation B = LocB;
64e8d8bef9SDimitry Andric   // Canonicalize the location order to simplify the following alias check.
65e8d8bef9SDimitry Andric   if (asA != AMDGPUAS::FLAT_ADDRESS) {
66e8d8bef9SDimitry Andric     std::swap(asA, asB);
67e8d8bef9SDimitry Andric     std::swap(A, B);
68e8d8bef9SDimitry Andric   }
69e8d8bef9SDimitry Andric   if (asA == AMDGPUAS::FLAT_ADDRESS &&
70e8d8bef9SDimitry Andric       (asB == AMDGPUAS::LOCAL_ADDRESS || asB == AMDGPUAS::PRIVATE_ADDRESS)) {
71e8d8bef9SDimitry Andric     const auto *ObjA =
72fe6060f1SDimitry Andric         getUnderlyingObject(A.Ptr->stripPointerCastsForAliasAnalysis());
73e8d8bef9SDimitry Andric     if (const LoadInst *LI = dyn_cast<LoadInst>(ObjA)) {
74e8d8bef9SDimitry Andric       // If a generic pointer is loaded from the constant address space, it
75349cc55cSDimitry Andric       // could only be a GLOBAL or CONSTANT one as that address space is solely
76e8d8bef9SDimitry Andric       // prepared on the host side, where only GLOBAL or CONSTANT variables are
77e8d8bef9SDimitry Andric       // visible. Note that this even holds for regular functions.
78e8d8bef9SDimitry Andric       if (LI->getPointerAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS)
79fe6060f1SDimitry Andric         return AliasResult::NoAlias;
80e8d8bef9SDimitry Andric     } else if (const Argument *Arg = dyn_cast<Argument>(ObjA)) {
81e8d8bef9SDimitry Andric       const Function *F = Arg->getParent();
82e8d8bef9SDimitry Andric       switch (F->getCallingConv()) {
83e8d8bef9SDimitry Andric       case CallingConv::AMDGPU_KERNEL:
84e8d8bef9SDimitry Andric         // In the kernel function, kernel arguments won't alias to (local)
85e8d8bef9SDimitry Andric         // variables in shared or private address space.
86fe6060f1SDimitry Andric         return AliasResult::NoAlias;
87e8d8bef9SDimitry Andric       default:
88e8d8bef9SDimitry Andric         // TODO: In the regular function, if that local variable in the
89e8d8bef9SDimitry Andric         // location B is not captured, that argument pointer won't alias to it
90e8d8bef9SDimitry Andric         // as well.
91e8d8bef9SDimitry Andric         break;
92e8d8bef9SDimitry Andric       }
93e8d8bef9SDimitry Andric     }
94e8d8bef9SDimitry Andric   }
95e8d8bef9SDimitry Andric 
96*5f757f3fSDimitry Andric   return AliasResult::MayAlias;
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric 
getModRefInfoMask(const MemoryLocation & Loc,AAQueryInfo & AAQI,bool IgnoreLocals)99bdd1243dSDimitry Andric ModRefInfo AMDGPUAAResult::getModRefInfoMask(const MemoryLocation &Loc,
100bdd1243dSDimitry Andric                                              AAQueryInfo &AAQI,
101bdd1243dSDimitry Andric                                              bool IgnoreLocals) {
1025ffd83dbSDimitry Andric   unsigned AS = Loc.Ptr->getType()->getPointerAddressSpace();
1030b57cec5SDimitry Andric   if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
1045ffd83dbSDimitry Andric       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
105bdd1243dSDimitry Andric     return ModRefInfo::NoModRef;
1065ffd83dbSDimitry Andric 
107e8d8bef9SDimitry Andric   const Value *Base = getUnderlyingObject(Loc.Ptr);
1085ffd83dbSDimitry Andric   AS = Base->getType()->getPointerAddressSpace();
1095ffd83dbSDimitry Andric   if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
1105ffd83dbSDimitry Andric       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
111bdd1243dSDimitry Andric     return ModRefInfo::NoModRef;
1120b57cec5SDimitry Andric 
113*5f757f3fSDimitry Andric   return ModRefInfo::ModRef;
1140b57cec5SDimitry Andric }
115