blob: 9527c9f9884d68c5a56dc15137afaed56e44bac8 [file] [log] [blame]
Eugene Zelenkod16eff82017-08-08 23:53:55 +00001//===- AMDGPUAliasAnalysis ------------------------------------------------===//
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +00002//
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
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +000013#include "AMDGPUAliasAnalysis.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000014#include "AMDGPU.h"
Eugene Zelenkod16eff82017-08-08 23:53:55 +000015#include "llvm/ADT/Triple.h"
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +000016#include "llvm/Analysis/AliasAnalysis.h"
Eugene Zelenkod16eff82017-08-08 23:53:55 +000017#include "llvm/Analysis/MemoryLocation.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000018#include "llvm/Analysis/ValueTracking.h"
Eugene Zelenkod16eff82017-08-08 23:53:55 +000019#include "llvm/IR/Argument.h"
20#include "llvm/IR/Attributes.h"
21#include "llvm/IR/CallingConv.h"
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +000022#include "llvm/IR/Function.h"
Eugene Zelenkod16eff82017-08-08 23:53:55 +000023#include "llvm/IR/GlobalVariable.h"
24#include "llvm/IR/Type.h"
25#include "llvm/IR/Value.h"
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +000026#include "llvm/Pass.h"
Eugene Zelenkod16eff82017-08-08 23:53:55 +000027#include "llvm/Support/Casting.h"
28#include "llvm/Support/ErrorHandling.h"
29#include <cassert>
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +000030
31using namespace llvm;
32
33#define DEBUG_TYPE "amdgpu-aa"
34
35// Register this pass...
36char AMDGPUAAWrapperPass::ID = 0;
Eugene Zelenkod16eff82017-08-08 23:53:55 +000037
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +000038INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
39 "AMDGPU Address space based Alias Analysis", false, true)
40
41ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
42 return new AMDGPUAAWrapperPass();
43}
44
45void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
46 AU.setPreservesAll();
47}
48
Yaxun Liu1a14bfa2017-03-27 14:04:01 +000049// Must match the table in getAliasResult.
Jan Vesely3c994412017-03-31 19:26:23 +000050AMDGPUAAResult::ASAliasRulesTy::ASAliasRulesTy(AMDGPUAS AS_, Triple::ArchType Arch_)
51 : Arch(Arch_), AS(AS_) {
Yaxun Liu1a14bfa2017-03-27 14:04:01 +000052 // These arrarys are indexed by address space value
53 // enum elements 0 ... to 5
54 static const AliasResult ASAliasRulesPrivIsZero[6][6] = {
55 /* Private Global Constant Group Flat Region*/
56 /* Private */ {MayAlias, NoAlias , NoAlias , NoAlias , MayAlias, NoAlias},
57 /* Global */ {NoAlias , MayAlias, NoAlias , NoAlias , MayAlias, NoAlias},
58 /* Constant */ {NoAlias , NoAlias , MayAlias, NoAlias , MayAlias, NoAlias},
59 /* Group */ {NoAlias , NoAlias , NoAlias , MayAlias, MayAlias, NoAlias},
60 /* Flat */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias},
61 /* Region */ {NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, MayAlias}
62 };
63 static const AliasResult ASAliasRulesGenIsZero[6][6] = {
Yaxun Liu76ae47c2017-04-06 19:17:32 +000064 /* Flat Global Constant Group Region Private */
Yaxun Liu1a14bfa2017-03-27 14:04:01 +000065 /* Flat */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias},
66 /* Global */ {MayAlias, MayAlias, NoAlias , NoAlias , NoAlias , NoAlias},
Yaxun Liu76ae47c2017-04-06 19:17:32 +000067 /* Constant */ {MayAlias, NoAlias , MayAlias, NoAlias , NoAlias, NoAlias},
Yaxun Liu1a14bfa2017-03-27 14:04:01 +000068 /* Group */ {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias},
Yaxun Liu76ae47c2017-04-06 19:17:32 +000069 /* Region */ {MayAlias, NoAlias , NoAlias , NoAlias, MayAlias, NoAlias},
Yaxun Liu1a14bfa2017-03-27 14:04:01 +000070 /* Private */ {MayAlias, NoAlias , NoAlias , NoAlias , NoAlias , MayAlias}
71 };
72 assert(AS.MAX_COMMON_ADDRESS <= 5);
73 if (AS.FLAT_ADDRESS == 0) {
74 assert(AS.GLOBAL_ADDRESS == 1 &&
Yaxun Liu76ae47c2017-04-06 19:17:32 +000075 AS.REGION_ADDRESS == 4 &&
Yaxun Liu1a14bfa2017-03-27 14:04:01 +000076 AS.LOCAL_ADDRESS == 3 &&
Yaxun Liu76ae47c2017-04-06 19:17:32 +000077 AS.CONSTANT_ADDRESS == 2 &&
Yaxun Liu1a14bfa2017-03-27 14:04:01 +000078 AS.PRIVATE_ADDRESS == 5);
79 ASAliasRules = &ASAliasRulesGenIsZero;
80 } else {
81 assert(AS.PRIVATE_ADDRESS == 0 &&
82 AS.GLOBAL_ADDRESS == 1 &&
83 AS.CONSTANT_ADDRESS == 2 &&
84 AS.LOCAL_ADDRESS == 3 &&
85 AS.FLAT_ADDRESS == 4 &&
86 AS.REGION_ADDRESS == 5);
87 ASAliasRules = &ASAliasRulesPrivIsZero;
88 }
89}
90
91AliasResult AMDGPUAAResult::ASAliasRulesTy::getAliasResult(unsigned AS1,
92 unsigned AS2) const {
Jan Vesely3c994412017-03-31 19:26:23 +000093 if (AS1 > AS.MAX_COMMON_ADDRESS || AS2 > AS.MAX_COMMON_ADDRESS) {
94 if (Arch == Triple::amdgcn)
95 report_fatal_error("Pointer address space out of range");
96 return AS1 == AS2 ? MayAlias : NoAlias;
97 }
98
Yaxun Liu1a14bfa2017-03-27 14:04:01 +000099 return (*ASAliasRules)[AS1][AS2];
100}
101
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +0000102AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
103 const MemoryLocation &LocB) {
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +0000104 unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
105 unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +0000106
Yaxun Liu1a14bfa2017-03-27 14:04:01 +0000107 AliasResult Result = ASAliasRules.getAliasResult(asA, asB);
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +0000108 if (Result == NoAlias) return Result;
109
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +0000110 // Forward the query to the next alias analysis.
111 return AAResultBase::alias(LocA, LocB);
112}
113
114bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
115 bool OrLocal) {
116 const Value *Base = GetUnderlyingObject(Loc.Ptr, DL);
117
Yaxun Liu1a14bfa2017-03-27 14:04:01 +0000118 if (Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS) {
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +0000119 return true;
120 }
121
122 if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
123 if (GV->isConstant())
124 return true;
125 } else if (const Argument *Arg = dyn_cast<Argument>(Base)) {
126 const Function *F = Arg->getParent();
127
128 // Only assume constant memory for arguments on kernels.
129 switch (F->getCallingConv()) {
130 default:
131 return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
132 case CallingConv::AMDGPU_VS:
133 case CallingConv::AMDGPU_GS:
134 case CallingConv::AMDGPU_PS:
135 case CallingConv::AMDGPU_CS:
136 case CallingConv::AMDGPU_KERNEL:
137 case CallingConv::SPIR_KERNEL:
138 break;
139 }
140
141 unsigned ArgNo = Arg->getArgNo();
142 /* On an argument, ReadOnly attribute indicates that the function does
143 not write through this pointer argument, even though it may write
144 to the memory that the pointer points to.
145 On an argument, ReadNone attribute indicates that the function does
146 not dereference that pointer argument, even though it may read or write
147 the memory that the pointer points to if accessed through other pointers.
148 */
Reid Klecknerf021fab2017-04-13 23:12:13 +0000149 if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) &&
150 (F->hasParamAttribute(ArgNo, Attribute::ReadNone) ||
151 F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) {
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +0000152 return true;
153 }
154 }
155 return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
156}