xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUAliasAnalysis.cpp (revision 7ef62cebc2f965b0f640263e179276928885e33d)
1 //===- AMDGPUAliasAnalysis ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This is the AMGPU address space based alias analysis pass.
10 //===----------------------------------------------------------------------===//
11 
12 #include "AMDGPUAliasAnalysis.h"
13 #include "AMDGPU.h"
14 #include "llvm/Analysis/ValueTracking.h"
15 #include "llvm/IR/Instructions.h"
16 
17 using namespace llvm;
18 
19 #define DEBUG_TYPE "amdgpu-aa"
20 
21 AnalysisKey AMDGPUAA::Key;
22 
23 // Register this pass...
24 char AMDGPUAAWrapperPass::ID = 0;
25 char AMDGPUExternalAAWrapper::ID = 0;
26 
27 INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
28                 "AMDGPU Address space based Alias Analysis", false, true)
29 
30 INITIALIZE_PASS(AMDGPUExternalAAWrapper, "amdgpu-aa-wrapper",
31                 "AMDGPU Address space based Alias Analysis Wrapper", false, true)
32 
33 ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
34   return new AMDGPUAAWrapperPass();
35 }
36 
37 ImmutablePass *llvm::createAMDGPUExternalAAWrapperPass() {
38   return new AMDGPUExternalAAWrapper();
39 }
40 
41 AMDGPUAAWrapperPass::AMDGPUAAWrapperPass() : ImmutablePass(ID) {
42   initializeAMDGPUAAWrapperPassPass(*PassRegistry::getPassRegistry());
43 }
44 
45 void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
46   AU.setPreservesAll();
47 }
48 
49 static AliasResult getAliasResult(unsigned AS1, unsigned AS2) {
50   static_assert(AMDGPUAS::MAX_AMDGPU_ADDRESS <= 7, "Addr space out of range");
51 
52   if (AS1 > AMDGPUAS::MAX_AMDGPU_ADDRESS || AS2 > AMDGPUAS::MAX_AMDGPU_ADDRESS)
53     return AliasResult::MayAlias;
54 
55 #define ASMay AliasResult::MayAlias
56 #define ASNo AliasResult::NoAlias
57   // This array is indexed by address space value enum elements 0 ... to 7
58   static const AliasResult ASAliasRules[8][8] = {
59     /*                    Flat    Global Region Group  Constant Private Const32 Buf Fat Ptr */
60     /* Flat     */        {ASMay, ASMay, ASNo,  ASMay, ASMay,   ASMay,  ASMay,  ASMay},
61     /* Global   */        {ASMay, ASMay, ASNo,  ASNo,  ASMay,   ASNo,   ASMay,  ASMay},
62     /* Region   */        {ASNo,  ASNo,  ASMay, ASNo,  ASNo,    ASNo,   ASNo,   ASNo},
63     /* Group    */        {ASMay, ASNo,  ASNo,  ASMay, ASNo,    ASNo,   ASNo,   ASNo},
64     /* Constant */        {ASMay, ASMay, ASNo,  ASNo,  ASNo,    ASNo,   ASMay,  ASMay},
65     /* Private  */        {ASMay, ASNo,  ASNo,  ASNo,  ASNo,    ASMay,  ASNo,   ASNo},
66     /* Constant 32-bit */ {ASMay, ASMay, ASNo,  ASNo,  ASMay,   ASNo,   ASNo,   ASMay},
67     /* Buffer Fat Ptr  */ {ASMay, ASMay, ASNo,  ASNo,  ASMay,   ASNo,   ASMay,  ASMay}
68   };
69 #undef ASMay
70 #undef ASNo
71 
72   return ASAliasRules[AS1][AS2];
73 }
74 
75 AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
76                                   const MemoryLocation &LocB, AAQueryInfo &AAQI,
77                                   const Instruction *) {
78   unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
79   unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
80 
81   AliasResult Result = getAliasResult(asA, asB);
82   if (Result == AliasResult::NoAlias)
83     return Result;
84 
85   // In general, FLAT (generic) pointers could be aliased to LOCAL or PRIVATE
86   // pointers. However, as LOCAL or PRIVATE pointers point to local objects, in
87   // certain cases, it's still viable to check whether a FLAT pointer won't
88   // alias to a LOCAL or PRIVATE pointer.
89   MemoryLocation A = LocA;
90   MemoryLocation B = LocB;
91   // Canonicalize the location order to simplify the following alias check.
92   if (asA != AMDGPUAS::FLAT_ADDRESS) {
93     std::swap(asA, asB);
94     std::swap(A, B);
95   }
96   if (asA == AMDGPUAS::FLAT_ADDRESS &&
97       (asB == AMDGPUAS::LOCAL_ADDRESS || asB == AMDGPUAS::PRIVATE_ADDRESS)) {
98     const auto *ObjA =
99         getUnderlyingObject(A.Ptr->stripPointerCastsForAliasAnalysis());
100     if (const LoadInst *LI = dyn_cast<LoadInst>(ObjA)) {
101       // If a generic pointer is loaded from the constant address space, it
102       // could only be a GLOBAL or CONSTANT one as that address space is solely
103       // prepared on the host side, where only GLOBAL or CONSTANT variables are
104       // visible. Note that this even holds for regular functions.
105       if (LI->getPointerAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS)
106         return AliasResult::NoAlias;
107     } else if (const Argument *Arg = dyn_cast<Argument>(ObjA)) {
108       const Function *F = Arg->getParent();
109       switch (F->getCallingConv()) {
110       case CallingConv::AMDGPU_KERNEL:
111         // In the kernel function, kernel arguments won't alias to (local)
112         // variables in shared or private address space.
113         return AliasResult::NoAlias;
114       default:
115         // TODO: In the regular function, if that local variable in the
116         // location B is not captured, that argument pointer won't alias to it
117         // as well.
118         break;
119       }
120     }
121   }
122 
123   // Forward the query to the next alias analysis.
124   return AAResultBase::alias(LocA, LocB, AAQI, nullptr);
125 }
126 
127 ModRefInfo AMDGPUAAResult::getModRefInfoMask(const MemoryLocation &Loc,
128                                              AAQueryInfo &AAQI,
129                                              bool IgnoreLocals) {
130   unsigned AS = Loc.Ptr->getType()->getPointerAddressSpace();
131   if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
132       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
133     return ModRefInfo::NoModRef;
134 
135   const Value *Base = getUnderlyingObject(Loc.Ptr);
136   AS = Base->getType()->getPointerAddressSpace();
137   if (AS == AMDGPUAS::CONSTANT_ADDRESS ||
138       AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
139     return ModRefInfo::NoModRef;
140 
141   return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals);
142 }
143