1 //===- AMDGPUAliasAnalysis ---------------------------------------*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// This is the AMGPU address space based alias analysis pass.
11 //===----------------------------------------------------------------------===//
14 #include "AMDGPUAliasAnalysis.h"
15 #include "llvm/Analysis/AliasAnalysis.h"
16 #include "llvm/Analysis/ValueTracking.h"
17 #include "llvm/Analysis/Passes.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/IR/Function.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/Pass.h"
25 #define DEBUG_TYPE "amdgpu-aa"
27 // Register this pass...
28 char AMDGPUAAWrapperPass::ID = 0;
29 INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
30 "AMDGPU Address space based Alias Analysis", false, true)
32 ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
33 return new AMDGPUAAWrapperPass();
36 void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
40 // Must match the table in getAliasResult.
41 AMDGPUAAResult::ASAliasRulesTy::ASAliasRulesTy(AMDGPUAS AS_) : AS(AS_) {
42 // These arrarys are indexed by address space value
43 // enum elements 0 ... to 5
44 static const AliasResult ASAliasRulesPrivIsZero[6][6] = {
45 /* Private Global Constant Group Flat Region*/
46 /* Private */ {MayAlias, NoAlias , NoAlias , NoAlias , MayAlias, NoAlias},
47 /* Global */ {NoAlias , MayAlias, NoAlias , NoAlias , MayAlias, NoAlias},
48 /* Constant */ {NoAlias , NoAlias , MayAlias, NoAlias , MayAlias, NoAlias},
49 /* Group */ {NoAlias , NoAlias , NoAlias , MayAlias, MayAlias, NoAlias},
50 /* Flat */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias},
51 /* Region */ {NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, MayAlias}
53 static const AliasResult ASAliasRulesGenIsZero[6][6] = {
54 /* Flat Global Region Group Constant Private */
55 /* Flat */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias},
56 /* Global */ {MayAlias, MayAlias, NoAlias , NoAlias , NoAlias , NoAlias},
57 /* Region */ {NoAlias , NoAlias , MayAlias, NoAlias, NoAlias , MayAlias},
58 /* Group */ {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias},
59 /* Constant */ {MayAlias, NoAlias , NoAlias , NoAlias , MayAlias, NoAlias},
60 /* Private */ {MayAlias, NoAlias , NoAlias , NoAlias , NoAlias , MayAlias}
62 assert(AS.MAX_COMMON_ADDRESS <= 5);
63 if (AS.FLAT_ADDRESS == 0) {
64 assert(AS.GLOBAL_ADDRESS == 1 &&
65 AS.REGION_ADDRESS == 2 &&
66 AS.LOCAL_ADDRESS == 3 &&
67 AS.CONSTANT_ADDRESS == 4 &&
68 AS.PRIVATE_ADDRESS == 5);
69 ASAliasRules = &ASAliasRulesGenIsZero;
71 assert(AS.PRIVATE_ADDRESS == 0 &&
72 AS.GLOBAL_ADDRESS == 1 &&
73 AS.CONSTANT_ADDRESS == 2 &&
74 AS.LOCAL_ADDRESS == 3 &&
75 AS.FLAT_ADDRESS == 4 &&
76 AS.REGION_ADDRESS == 5);
77 ASAliasRules = &ASAliasRulesPrivIsZero;
81 AliasResult AMDGPUAAResult::ASAliasRulesTy::getAliasResult(unsigned AS1,
83 if (AS1 > AS.MAX_COMMON_ADDRESS || AS2 > AS.MAX_COMMON_ADDRESS)
84 report_fatal_error("Pointer address space out of range");
85 return (*ASAliasRules)[AS1][AS2];
88 AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
89 const MemoryLocation &LocB) {
90 unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
91 unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
93 AliasResult Result = ASAliasRules.getAliasResult(asA, asB);
94 if (Result == NoAlias) return Result;
96 if (isa<Argument>(LocA.Ptr) && isa<Argument>(LocB.Ptr)) {
97 Type *T1 = cast<PointerType>(LocA.Ptr->getType())->getElementType();
98 Type *T2 = cast<PointerType>(LocB.Ptr->getType())->getElementType();
100 if ((T1->isVectorTy() && !T2->isVectorTy()) ||
101 (T2->isVectorTy() && !T1->isVectorTy()))
104 // Forward the query to the next alias analysis.
105 return AAResultBase::alias(LocA, LocB);
108 bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
110 const Value *Base = GetUnderlyingObject(Loc.Ptr, DL);
112 if (Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS) {
116 if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
117 if (GV->isConstant())
119 } else if (const Argument *Arg = dyn_cast<Argument>(Base)) {
120 const Function *F = Arg->getParent();
122 // Only assume constant memory for arguments on kernels.
123 switch (F->getCallingConv()) {
125 return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
126 case CallingConv::AMDGPU_VS:
127 case CallingConv::AMDGPU_GS:
128 case CallingConv::AMDGPU_PS:
129 case CallingConv::AMDGPU_CS:
130 case CallingConv::AMDGPU_KERNEL:
131 case CallingConv::SPIR_KERNEL:
135 unsigned ArgNo = Arg->getArgNo();
136 /* On an argument, ReadOnly attribute indicates that the function does
137 not write through this pointer argument, even though it may write
138 to the memory that the pointer points to.
139 On an argument, ReadNone attribute indicates that the function does
140 not dereference that pointer argument, even though it may read or write
141 the memory that the pointer points to if accessed through other pointers.
143 if (F->getAttributes().hasAttribute(ArgNo + 1, Attribute::NoAlias) &&
144 (F->getAttributes().hasAttribute(ArgNo + 1, Attribute::ReadNone) ||
145 F->getAttributes().hasAttribute(ArgNo + 1, Attribute::ReadOnly))) {
149 return AAResultBase::pointsToConstantMemory(Loc, OrLocal);