blob: fa52bbb9def8ca47c9b56f7c039ca75bed59d4e6 [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
Matt Arsenault923712b2018-02-09 16:57:57 +0000118 if (Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS ||
119 Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS_32BIT) {
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +0000120 return true;
121 }
122
123 if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
124 if (GV->isConstant())
125 return true;
126 } else if (const Argument *Arg = dyn_cast<Argument>(Base)) {
127 const Function *F = Arg->getParent();
128
129 // Only assume constant memory for arguments on kernels.
130 switch (F->getCallingConv()) {
131 default:
132 return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
Tim Renoufef1ae8f2017-09-29 09:51:22 +0000133 case CallingConv::AMDGPU_LS:
134 case CallingConv::AMDGPU_HS:
135 case CallingConv::AMDGPU_ES:
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +0000136 case CallingConv::AMDGPU_GS:
Tim Renoufef1ae8f2017-09-29 09:51:22 +0000137 case CallingConv::AMDGPU_VS:
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +0000138 case CallingConv::AMDGPU_PS:
139 case CallingConv::AMDGPU_CS:
140 case CallingConv::AMDGPU_KERNEL:
141 case CallingConv::SPIR_KERNEL:
142 break;
143 }
144
145 unsigned ArgNo = Arg->getArgNo();
146 /* On an argument, ReadOnly attribute indicates that the function does
147 not write through this pointer argument, even though it may write
148 to the memory that the pointer points to.
149 On an argument, ReadNone attribute indicates that the function does
150 not dereference that pointer argument, even though it may read or write
151 the memory that the pointer points to if accessed through other pointers.
152 */
Reid Klecknerf021fab2017-04-13 23:12:13 +0000153 if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) &&
154 (F->hasParamAttribute(ArgNo, Attribute::ReadNone) ||
155 F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) {
Stanislav Mekhanoshin8e45acf2017-03-17 23:56:58 +0000156 return true;
157 }
158 }
159 return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
160}