OSDN Git Service

[IR] Make getParamAttributes take argument numbers, not ArgNo+1
[android-x86/external-llvm.git] / lib / Target / AMDGPU / AMDGPUAliasAnalysis.cpp
1 //===- AMDGPUAliasAnalysis ---------------------------------------*- C++ -*-==//
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 "AMDGPU.h"
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"
22
23 using namespace llvm;
24
25 #define DEBUG_TYPE "amdgpu-aa"
26
27 // Register this pass...
28 char AMDGPUAAWrapperPass::ID = 0;
29 INITIALIZE_PASS(AMDGPUAAWrapperPass, "amdgpu-aa",
30                 "AMDGPU Address space based Alias Analysis", false, true)
31
32 ImmutablePass *llvm::createAMDGPUAAWrapperPass() {
33   return new AMDGPUAAWrapperPass();
34 }
35
36 void AMDGPUAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
37   AU.setPreservesAll();
38 }
39
40 // Must match the table in getAliasResult.
41 AMDGPUAAResult::ASAliasRulesTy::ASAliasRulesTy(AMDGPUAS AS_, Triple::ArchType Arch_)
42   : Arch(Arch_), AS(AS_) {
43   // These arrarys are indexed by address space value
44   // enum elements 0 ... to 5
45   static const AliasResult ASAliasRulesPrivIsZero[6][6] = {
46   /*             Private    Global    Constant  Group     Flat      Region*/
47   /* Private  */ {MayAlias, NoAlias , NoAlias , NoAlias , MayAlias, NoAlias},
48   /* Global   */ {NoAlias , MayAlias, NoAlias , NoAlias , MayAlias, NoAlias},
49   /* Constant */ {NoAlias , NoAlias , MayAlias, NoAlias , MayAlias, NoAlias},
50   /* Group    */ {NoAlias , NoAlias , NoAlias , MayAlias, MayAlias, NoAlias},
51   /* Flat     */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias},
52   /* Region   */ {NoAlias , NoAlias , NoAlias , NoAlias , MayAlias, MayAlias}
53   };
54   static const AliasResult ASAliasRulesGenIsZero[6][6] = {
55   /*             Flat       Global    Constant  Group     Region    Private */
56   /* Flat     */ {MayAlias, MayAlias, MayAlias, MayAlias, MayAlias, MayAlias},
57   /* Global   */ {MayAlias, MayAlias, NoAlias , NoAlias , NoAlias , NoAlias},
58   /* Constant */ {MayAlias, NoAlias , MayAlias, NoAlias , NoAlias,  NoAlias},
59   /* Group    */ {MayAlias, NoAlias , NoAlias , MayAlias, NoAlias , NoAlias},
60   /* Region   */ {MayAlias, NoAlias , NoAlias , NoAlias,  MayAlias, NoAlias},
61   /* Private  */ {MayAlias, NoAlias , NoAlias , NoAlias , NoAlias , MayAlias}
62   };
63   assert(AS.MAX_COMMON_ADDRESS <= 5);
64   if (AS.FLAT_ADDRESS == 0) {
65     assert(AS.GLOBAL_ADDRESS   == 1 &&
66            AS.REGION_ADDRESS   == 4 &&
67            AS.LOCAL_ADDRESS    == 3 &&
68            AS.CONSTANT_ADDRESS == 2 &&
69            AS.PRIVATE_ADDRESS  == 5);
70     ASAliasRules = &ASAliasRulesGenIsZero;
71   } else {
72     assert(AS.PRIVATE_ADDRESS  == 0 &&
73            AS.GLOBAL_ADDRESS   == 1 &&
74            AS.CONSTANT_ADDRESS == 2 &&
75            AS.LOCAL_ADDRESS    == 3 &&
76            AS.FLAT_ADDRESS     == 4 &&
77            AS.REGION_ADDRESS   == 5);
78     ASAliasRules = &ASAliasRulesPrivIsZero;
79   }
80 }
81
82 AliasResult AMDGPUAAResult::ASAliasRulesTy::getAliasResult(unsigned AS1,
83     unsigned AS2) const {
84   if (AS1 > AS.MAX_COMMON_ADDRESS || AS2 > AS.MAX_COMMON_ADDRESS) {
85     if (Arch == Triple::amdgcn)
86       report_fatal_error("Pointer address space out of range");
87     return AS1 == AS2 ? MayAlias : NoAlias;
88   }
89
90   return (*ASAliasRules)[AS1][AS2];
91 }
92
93 AliasResult AMDGPUAAResult::alias(const MemoryLocation &LocA,
94                                   const MemoryLocation &LocB) {
95   unsigned asA = LocA.Ptr->getType()->getPointerAddressSpace();
96   unsigned asB = LocB.Ptr->getType()->getPointerAddressSpace();
97
98   AliasResult Result = ASAliasRules.getAliasResult(asA, asB);
99   if (Result == NoAlias) return Result;
100
101   // Forward the query to the next alias analysis.
102   return AAResultBase::alias(LocA, LocB);
103 }
104
105 bool AMDGPUAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
106                                             bool OrLocal) {
107   const Value *Base = GetUnderlyingObject(Loc.Ptr, DL);
108
109   if (Base->getType()->getPointerAddressSpace() == AS.CONSTANT_ADDRESS) {
110     return true;
111   }
112
113   if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Base)) {
114     if (GV->isConstant())
115       return true;
116   } else if (const Argument *Arg = dyn_cast<Argument>(Base)) {
117     const Function *F = Arg->getParent();
118
119     // Only assume constant memory for arguments on kernels.
120     switch (F->getCallingConv()) {
121     default:
122       return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
123     case CallingConv::AMDGPU_VS:
124     case CallingConv::AMDGPU_GS:
125     case CallingConv::AMDGPU_PS:
126     case CallingConv::AMDGPU_CS:
127     case CallingConv::AMDGPU_KERNEL:
128     case CallingConv::SPIR_KERNEL:
129       break;
130     }
131
132     unsigned ArgNo = Arg->getArgNo();
133     /* On an argument, ReadOnly attribute indicates that the function does
134        not write through this pointer argument, even though it may write
135        to the memory that the pointer points to.
136        On an argument, ReadNone attribute indicates that the function does
137        not dereference that pointer argument, even though it may read or write
138        the memory that the pointer points to if accessed through other pointers.
139      */
140     if (F->hasParamAttribute(ArgNo, Attribute::NoAlias) &&
141         (F->hasParamAttribute(ArgNo, Attribute::ReadNone) ||
142          F->hasParamAttribute(ArgNo, Attribute::ReadOnly))) {
143       return true;
144     }
145   }
146   return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
147 }