• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- AMDGPUAliasAnalysis ------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This is the AMGPU address space based alias analysis pass.
11 //===----------------------------------------------------------------------===//
12 
13 #include "AMDGPUAliasAnalysis.h"
14 #include "AMDGPU.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/Analysis/AliasAnalysis.h"
17 #include "llvm/Analysis/MemoryLocation.h"
18 #include "llvm/Analysis/ValueTracking.h"
19 #include "llvm/IR/Argument.h"
20 #include "llvm/IR/Attributes.h"
21 #include "llvm/IR/CallingConv.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/IR/GlobalVariable.h"
24 #include "llvm/IR/Type.h"
25 #include "llvm/IR/Value.h"
26 #include "llvm/Pass.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include <cassert>
30 
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "amdgpu-aa"
34 
35 // Register this pass...
36 char AMDGPUAAWrapperPass::ID = 0;
37 
38 INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
39                 "AMDGPU Address space based Alias Analysis", false, true)
40 
createAMDGPUAAWrapperPass()41 ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
42   return new AMDGPUAAWrapperPass();
43 }
44 
getAnalysisUsage(AnalysisUsage & AU) const45 void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
46   AU.setPreservesAll();
47 }
48 
49 // Must match the table in getAliasResult.
ASAliasRulesTy(AMDGPUAS AS_,Triple::ArchType Arch_)50 AMDGPUAAResult::ASAliasRulesTy::ASAliasRulesTy(AMDGPUAS AS_, Triple::ArchType Arch_)
51   : Arch(Arch_), AS(AS_) {
52   // These arrarys are indexed by address space value
53   // enum elements 0 ... to 6
54   static const AliasResult ASAliasRulesPrivIsZero[7][7] = {
55   /*                    Private    Global    Constant  Group     Flat      Region    Constant 32-bit */
56   /* Private  */        {MayAlias, NoAlias , NoAlias , NoAlias , MayAlias, NoAlias , NoAlias},
57   /* Global   */        {NoAlias , MayAlias, MayAlias, NoAlias , MayAlias, NoAlias , MayAlias},
58   /* Constant */        {NoAlias , MayAlias, MayAlias, NoAlias , MayAlias, NoAlias , MayAlias},
59   /* Group    */        {NoAlias , NoAlias , NoAlias , MayAlias, MayAlias, NoAlias , NoAlias},
60   /* Flat     */        {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias},
61   /* Region   */        {NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, MayAlias, NoAlias},
62   /* Constant 32-bit */ {NoAlias , MayAlias, MayAlias, NoAlias , MayAlias, NoAlias , MayAlias}
63   };
64   static const AliasResult ASAliasRulesGenIsZero[7][7] = {
65   /*                    Flat       Global    Region    Group     Constant  Private   Constant 32-bit */
66   /* Flat     */        {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias},
67   /* Global   */        {MayAlias, MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , MayAlias},
68   /* Region   */        {MayAlias, NoAlias , NoAlias , NoAlias,  MayAlias, NoAlias , MayAlias},
69   /* Group    */        {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias , NoAlias},
70   /* Constant */        {MayAlias, MayAlias, MayAlias, NoAlias , NoAlias,  NoAlias , MayAlias},
71   /* Private  */        {MayAlias, NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, NoAlias},
72   /* Constant 32-bit */ {MayAlias, MayAlias, MayAlias, NoAlias , MayAlias, NoAlias , NoAlias}
73   };
74   static_assert(AMDGPUAS::MAX_AMDGPU_ADDRESS <= 6, "Addr space out of range");
75   if (AS.FLAT_ADDRESS == 0) {
76     assert(AS.GLOBAL_ADDRESS         == 1 &&
77            AS.REGION_ADDRESS         == 2 &&
78            AS.LOCAL_ADDRESS          == 3 &&
79            AS.CONSTANT_ADDRESS       == 4 &&
80            AS.PRIVATE_ADDRESS        == 5 &&
81            AS.CONSTANT_ADDRESS_32BIT == 6);
82     ASAliasRules = &ASAliasRulesGenIsZero;
83   } else {
84     assert(AS.PRIVATE_ADDRESS        == 0 &&
85            AS.GLOBAL_ADDRESS         == 1 &&
86            AS.CONSTANT_ADDRESS       == 2 &&
87            AS.LOCAL_ADDRESS          == 3 &&
88            AS.FLAT_ADDRESS           == 4 &&
89            AS.REGION_ADDRESS         == 5 &&
90            AS.CONSTANT_ADDRESS_32BIT == 6);
91     ASAliasRules = &ASAliasRulesPrivIsZero;
92   }
93 }
94 
getAliasResult(unsigned AS1,unsigned AS2) const95 AliasResult AMDGPUAAResult::ASAliasRulesTy::getAliasResult(unsigned AS1,
96     unsigned AS2) const {
97   if (AS1 > AS.MAX_AMDGPU_ADDRESS || AS2 > AS.MAX_AMDGPU_ADDRESS) {
98     if (Arch == Triple::amdgcn)
99       report_fatal_error("Pointer address space out of range");
100     return AS1 == AS2 ? MayAlias : NoAlias;
101   }
102 
103   return (*ASAliasRules)[AS1][AS2];
104 }
105 
alias(const MemoryLocation & LocA,const MemoryLocation & LocB)106 AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
107                                   const MemoryLocation &LocB) {
108   unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
109   unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
110 
111   AliasResult Result = ASAliasRules.getAliasResult(asA, asB);
112   if (Result == NoAlias) return Result;
113 
114   // Forward the query to the next alias analysis.
115   return AAResultBase::alias(LocA, LocB);
116 }
117 
pointsToConstantMemory(const MemoryLocation & Loc,bool OrLocal)118 bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
119                                             bool OrLocal) {
120   const Value *Base = GetUnderlyingObject(Loc.Ptr, DL);
121 
122   if (Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS ||
123       Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS_32BIT) {
124     return true;
125   }
126 
127   if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
128     if (GV->isConstant())
129       return true;
130   } else if (const Argument *Arg = dyn_cast<Argument>(Base)) {
131     const Function *F = Arg->getParent();
132 
133     // Only assume constant memory for arguments on kernels.
134     switch (F->getCallingConv()) {
135     default:
136       return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
137     case CallingConv::AMDGPU_LS:
138     case CallingConv::AMDGPU_HS:
139     case CallingConv::AMDGPU_ES:
140     case CallingConv::AMDGPU_GS:
141     case CallingConv::AMDGPU_VS:
142     case CallingConv::AMDGPU_PS:
143     case CallingConv::AMDGPU_CS:
144     case CallingConv::AMDGPU_KERNEL:
145     case CallingConv::SPIR_KERNEL:
146       break;
147     }
148 
149     unsigned ArgNo = Arg->getArgNo();
150     /* On an argument, ReadOnly attribute indicates that the function does
151        not write through this pointer argument, even though it may write
152        to the memory that the pointer points to.
153        On an argument, ReadNone attribute indicates that the function does
154        not dereference that pointer argument, even though it may read or write
155        the memory that the pointer points to if accessed through other pointers.
156      */
157     if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) &&
158         (F->hasParamAttribute(ArgNo, Attribute::ReadNone) ||
159          F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) {
160       return true;
161     }
162   }
163   return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
164 }
165