[CodeGen] Emit aliasing metadata for new arrays.
[polly-mirror.git] / lib / CodeGen / IRBuilder.cpp
blob7e8c3ad84d9802429ea41ca67bdac9ca8d28bd8c
1 //===------ PollyIRBuilder.cpp --------------------------------------------===//
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 //
10 // The Polly IRBuilder file contains Polly specific extensions for the IRBuilder
11 // that are used e.g. to emit the llvm.loop.parallel metadata.
13 //===----------------------------------------------------------------------===//
15 #include "polly/CodeGen/IRBuilder.h"
16 #include "polly/ScopInfo.h"
17 #include "polly/Support/ScopHelper.h"
18 #include "llvm/IR/Metadata.h"
19 #include "llvm/Support/Debug.h"
21 using namespace llvm;
22 using namespace polly;
24 static const int MaxArraysInAliasScops = 10;
26 /// Get a self referencing id metadata node.
27 ///
28 /// The MDNode looks like this (if arg0/arg1 are not null):
29 ///
30 /// '!n = metadata !{metadata !n, arg0, arg1}'
31 ///
32 /// @return The self referencing id metadata node.
33 static MDNode *getID(LLVMContext &Ctx, Metadata *arg0 = nullptr,
34 Metadata *arg1 = nullptr) {
35 MDNode *ID;
36 SmallVector<Metadata *, 3> Args;
37 // Use a temporary node to safely create a unique pointer for the first arg.
38 auto TempNode = MDNode::getTemporary(Ctx, None);
39 // Reserve operand 0 for loop id self reference.
40 Args.push_back(TempNode.get());
42 if (arg0)
43 Args.push_back(arg0);
44 if (arg1)
45 Args.push_back(arg1);
47 ID = MDNode::get(Ctx, Args);
48 ID->replaceOperandWith(0, ID);
49 return ID;
52 ScopAnnotator::ScopAnnotator() : SE(nullptr), AliasScopeDomain(nullptr) {}
54 void ScopAnnotator::buildAliasScopes(Scop &S) {
55 SE = S.getSE();
57 LLVMContext &Ctx = SE->getContext();
58 AliasScopeDomain = getID(Ctx, MDString::get(Ctx, "polly.alias.scope.domain"));
60 AliasScopeMap.clear();
61 OtherAliasScopeListMap.clear();
63 // The construction of alias scopes is quadratic in the number of arrays
64 // involved. In case of too many arrays, skip the construction of alias
65 // information to avoid quadratic increases in compile time and code size.
66 if (std::distance(S.array_begin(), S.array_end()) > MaxArraysInAliasScops)
67 return;
69 std::string AliasScopeStr = "polly.alias.scope.";
70 for (const ScopArrayInfo *Array : S.arrays()) {
71 assert(Array->getBasePtr() && "Base pointer must be present");
72 AliasScopeMap[Array->getBasePtr()] =
73 getID(Ctx, AliasScopeDomain,
74 MDString::get(Ctx, (AliasScopeStr + Array->getName()).c_str()));
77 for (const ScopArrayInfo *Array : S.arrays()) {
78 MDNode *AliasScopeList = MDNode::get(Ctx, {});
79 for (const auto &AliasScopePair : AliasScopeMap) {
80 if (Array->getBasePtr() == AliasScopePair.first)
81 continue;
83 Metadata *Args = {AliasScopePair.second};
84 AliasScopeList =
85 MDNode::concatenate(AliasScopeList, MDNode::get(Ctx, Args));
88 OtherAliasScopeListMap[Array->getBasePtr()] = AliasScopeList;
92 void ScopAnnotator::pushLoop(Loop *L, bool IsParallel) {
94 ActiveLoops.push_back(L);
95 if (!IsParallel)
96 return;
98 BasicBlock *Header = L->getHeader();
99 MDNode *Id = getID(Header->getContext());
100 assert(Id->getOperand(0) == Id && "Expected Id to be a self-reference");
101 assert(Id->getNumOperands() == 1 && "Unexpected extra operands in Id");
102 MDNode *Ids = ParallelLoops.empty()
103 ? Id
104 : MDNode::concatenate(ParallelLoops.back(), Id);
105 ParallelLoops.push_back(Ids);
108 void ScopAnnotator::popLoop(bool IsParallel) {
109 ActiveLoops.pop_back();
110 if (!IsParallel)
111 return;
113 assert(!ParallelLoops.empty() && "Expected a parallel loop to pop");
114 ParallelLoops.pop_back();
117 void ScopAnnotator::annotateLoopLatch(BranchInst *B, Loop *L,
118 bool IsParallel) const {
119 if (!IsParallel)
120 return;
122 assert(!ParallelLoops.empty() && "Expected a parallel loop to annotate");
123 MDNode *Ids = ParallelLoops.back();
124 MDNode *Id = cast<MDNode>(Ids->getOperand(Ids->getNumOperands() - 1));
125 B->setMetadata("llvm.loop", Id);
128 /// Get the pointer operand
130 /// @param Inst The instruction to be analyzed.
131 /// @return the pointer operand in case @p Inst is a memory access
132 /// instruction and nullptr otherwise.
133 static llvm::Value *getMemAccInstPointerOperand(Instruction *Inst) {
134 auto MemInst = MemAccInst::dyn_cast(Inst);
135 if (!MemInst)
136 return nullptr;
138 return MemInst.getPointerOperand();
141 void ScopAnnotator::annotateSecondLevel(llvm::Instruction *Inst,
142 llvm::Value *BasePtr) {
143 auto *Ptr = getMemAccInstPointerOperand(Inst);
144 if (!Ptr)
145 return;
146 auto SecondLevelAliasScope = SecondLevelAliasScopeMap.lookup(Ptr);
147 auto SecondLevelOtherAliasScopeList =
148 SecondLevelOtherAliasScopeListMap.lookup(Ptr);
149 if (!SecondLevelAliasScope) {
150 auto AliasScope = AliasScopeMap.lookup(BasePtr);
151 if (!AliasScope)
152 return;
153 LLVMContext &Ctx = SE->getContext();
154 SecondLevelAliasScope = getID(
155 Ctx, AliasScope, MDString::get(Ctx, "second level alias metadata"));
156 SecondLevelAliasScopeMap[Ptr] = SecondLevelAliasScope;
157 Metadata *Args = {SecondLevelAliasScope};
158 auto SecondLevelBasePtrAliasScopeList =
159 SecondLevelAliasScopeMap.lookup(BasePtr);
160 SecondLevelAliasScopeMap[BasePtr] = MDNode::concatenate(
161 SecondLevelBasePtrAliasScopeList, MDNode::get(Ctx, Args));
162 auto OtherAliasScopeList = OtherAliasScopeListMap.lookup(BasePtr);
163 SecondLevelOtherAliasScopeList = MDNode::concatenate(
164 OtherAliasScopeList, SecondLevelBasePtrAliasScopeList);
165 SecondLevelOtherAliasScopeListMap[Ptr] = SecondLevelOtherAliasScopeList;
167 Inst->setMetadata("alias.scope", SecondLevelAliasScope);
168 Inst->setMetadata("noalias", SecondLevelOtherAliasScopeList);
171 void ScopAnnotator::annotate(Instruction *Inst) {
172 if (!Inst->mayReadOrWriteMemory())
173 return;
175 if (!ParallelLoops.empty())
176 Inst->setMetadata("llvm.mem.parallel_loop_access", ParallelLoops.back());
178 // TODO: Use the ScopArrayInfo once available here.
179 if (!AliasScopeDomain)
180 return;
182 auto *Ptr = getMemAccInstPointerOperand(Inst);
183 if (!Ptr)
184 return;
186 auto *PtrSCEV = SE->getSCEV(Ptr);
187 auto *BaseSCEV = SE->getPointerBase(PtrSCEV);
188 auto *SU = dyn_cast<SCEVUnknown>(BaseSCEV);
190 if (!SU)
191 return;
193 auto *BasePtr = SU->getValue();
195 if (!BasePtr)
196 return;
198 auto AliasScope = AliasScopeMap.lookup(BasePtr);
200 if (!AliasScope) {
201 BasePtr = AlternativeAliasBases.lookup(BasePtr);
202 if (!BasePtr)
203 return;
205 AliasScope = AliasScopeMap.lookup(BasePtr);
206 if (!AliasScope)
207 return;
210 assert(OtherAliasScopeListMap.count(BasePtr) &&
211 "BasePtr either expected in AliasScopeMap and OtherAlias...Map");
212 auto *OtherAliasScopeList = OtherAliasScopeListMap[BasePtr];
214 if (InterIterationAliasFreeBasePtrs.count(BasePtr)) {
215 annotateSecondLevel(Inst, BasePtr);
216 return;
219 Inst->setMetadata("alias.scope", AliasScope);
220 Inst->setMetadata("noalias", OtherAliasScopeList);
223 void ScopAnnotator::addInterIterationAliasFreeBasePtr(llvm::Value *BasePtr) {
224 if (!BasePtr)
225 return;
227 InterIterationAliasFreeBasePtrs.insert(BasePtr);