Polly 24.0.0git
IRBuilder.cpp
Go to the documentation of this file.
1//===------ PollyIRBuilder.cpp --------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// The Polly IRBuilder file contains Polly specific extensions for the IRBuilder
10// that are used e.g. to emit the llvm.loop.parallel metadata.
11//
12//===----------------------------------------------------------------------===//
13
15#include "polly/ScopInfo.h"
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/IR/Metadata.h"
19
20using namespace llvm;
21using namespace polly;
22
23static const int MaxArraysInAliasScops = 10;
24
25/// Get a self referencing id metadata node.
26///
27/// The MDNode looks like this (if arg0/arg1 are not null):
28///
29/// '!n = distinct !{!n, arg0, arg1}'
30///
31/// @return The self referencing id metadata node.
32static MDNode *getID(LLVMContext &Ctx, Metadata *arg0 = nullptr,
33 Metadata *arg1 = nullptr) {
34 MDNode *ID;
35 SmallVector<Metadata *, 3> Args;
36 // Reserve operand 0 for loop id self reference.
37 Args.push_back(nullptr);
38
39 if (arg0)
40 Args.push_back(arg0);
41 if (arg1)
42 Args.push_back(arg1);
43
44 ID = MDNode::getDistinct(Ctx, Args);
45 ID->replaceOperandWith(0, ID);
46 return ID;
47}
48
50 // Push an empty staging BandAttr.
51 LoopAttrEnv.emplace_back();
52}
53
55 assert(LoopAttrEnv.size() == 1 && "Loop stack imbalance");
56 assert(!getStagingAttrEnv() && "Forgot to clear staging attr env");
57}
58
60 SE = S.getSE();
61
62 LLVMContext &Ctx = SE->getContext();
64 getID(Ctx, ConstantAsMetadata::get(ConstantInt::getFalse(Ctx)),
65 MDString::get(Ctx, "polly.alias.scope.domain"));
66
67 AliasScopeMap.clear();
69
70 // We are only interested in arrays, but no scalar references. Scalars should
71 // be handled easily by basicaa.
72 SmallVector<ScopArrayInfo *, 10> Arrays;
73 for (ScopArrayInfo *Array : S.arrays())
74 if (Array->isArrayKind())
75 Arrays.push_back(Array);
76
77 // The construction of alias scopes is quadratic in the number of arrays
78 // involved. In case of too many arrays, skip the construction of alias
79 // information to avoid quadratic increases in compile time and code size.
80 if (Arrays.size() > MaxArraysInAliasScops)
81 return;
82
83 std::string AliasScopeStr = "polly.alias.scope.";
84 for (const ScopArrayInfo *Array : Arrays) {
85 assert(Array->getBasePtr() && "Base pointer must be present");
86 AliasScopeMap[Array->getBasePtr()] =
88 MDString::get(Ctx, (AliasScopeStr + Array->getName()).c_str()));
89 }
90
91 for (const ScopArrayInfo *Array : Arrays) {
92 MDNode *AliasScopeList = MDNode::get(Ctx, {});
93 for (const auto &AliasScopePair : AliasScopeMap) {
94 if (Array->getBasePtr() == AliasScopePair.first)
95 continue;
96
97 Metadata *Args = {AliasScopePair.second};
98 AliasScopeList =
99 MDNode::concatenate(AliasScopeList, MDNode::get(Ctx, Args));
100 }
101
102 OtherAliasScopeListMap[Array->getBasePtr()] = AliasScopeList;
103 }
104}
105
106void ScopAnnotator::pushLoop(Loop *L, bool IsParallel) {
107 ActiveLoops.push_back(L);
108
109 if (IsParallel) {
110 LLVMContext &Ctx = SE->getContext();
111 MDNode *AccessGroup = MDNode::getDistinct(Ctx, {});
112 ParallelLoops.push_back(AccessGroup);
113 }
114
115 // Open an empty BandAttr context for loops nested in this one.
116 LoopAttrEnv.emplace_back();
117}
118
119void ScopAnnotator::popLoop(bool IsParallel) {
120 ActiveLoops.pop_back();
121
122 if (IsParallel) {
123 assert(!ParallelLoops.empty() && "Expected a parallel loop to pop");
124 ParallelLoops.pop_back();
125 }
126
127 // Exit the subloop context.
128 assert(!getStagingAttrEnv() && "Forgot to clear staging attr env");
129 assert(LoopAttrEnv.size() >= 2 && "Popped too many");
130 LoopAttrEnv.pop_back();
131}
132
133static void addVectorizeMetadata(LLVMContext &Ctx,
134 SmallVector<Metadata *, 3> *Args,
135 bool EnableLoopVectorizer) {
136 MDString *PropName =
137 MDString::get(Ctx, EnableLoopVectorizer ? "llvm.loop.vectorize.enable"
138 : "llvm.loop.vectorize.disable");
139 Args->push_back(MDNode::get(Ctx, {PropName}));
140}
141
142void addParallelMetadata(LLVMContext &Ctx, SmallVector<Metadata *, 3> *Args,
143 llvm::SmallVector<llvm::MDNode *, 8> ParallelLoops) {
144 MDString *PropName = MDString::get(Ctx, "llvm.loop.parallel_accesses");
145 MDNode *AccGroup = ParallelLoops.back();
146 Args->push_back(MDNode::get(Ctx, {PropName, AccGroup}));
147}
148
150 CondBrInst *B, bool IsParallel,
151 std::optional<bool> EnableVectorizeMetadata) const {
152 LLVMContext &Ctx = SE->getContext();
153 SmallVector<Metadata *, 3> Args;
154
155 // For the LoopID self-reference.
156 Args.push_back(nullptr);
157
158 // Add the user-defined loop properties to the annotation, if any. Any
159 // additional properties are appended.
160 // FIXME: What to do if these conflict?
161 MDNode *MData = nullptr;
162 if (BandAttr *AttrEnv = getActiveAttrEnv()) {
163 MData = AttrEnv->Metadata;
164 if (MData)
165 llvm::append_range(Args, drop_begin(MData->operands(), 1));
166 }
167 if (IsParallel)
169 if (EnableVectorizeMetadata.has_value())
170 addVectorizeMetadata(Ctx, &Args, *EnableVectorizeMetadata);
171
172 // No metadata to annotate.
173 if (!MData && Args.size() <= 1)
174 return;
175
176 // Reuse the MData node if possible, this will avoid having to create another
177 // one that cannot be merged because LoopIDs are 'distinct'. However, we have
178 // to create a new one if we add properties.
179 if (!MData || Args.size() > MData->getNumOperands()) {
180 MData = MDNode::getDistinct(Ctx, Args);
181 MData->replaceOperandWith(0, MData);
182 }
183 B->setMetadata(LLVMContext::MD_loop, MData);
184}
185
186/// Get the pointer operand
187///
188/// @param Inst The instruction to be analyzed.
189/// @return the pointer operand in case @p Inst is a memory access
190/// instruction and nullptr otherwise.
191static llvm::Value *getMemAccInstPointerOperand(Instruction *Inst) {
192 auto MemInst = MemAccInst::dyn_cast(Inst);
193 if (!MemInst)
194 return nullptr;
195
196 return MemInst.getPointerOperand();
197}
198
199/// Find the base pointer of an array access.
200///
201/// This should be equivalent to ScalarEvolution::getPointerBase, which we
202/// cannot use here the IR is still under construction which ScalarEvolution
203/// assumes to not be modified.
204static Value *findBasePtr(Value *Val) {
205 while (true) {
206 if (auto *Gep = dyn_cast<GEPOperator>(Val)) {
207 Val = Gep->getPointerOperand();
208 continue;
209 }
210 if (auto *Cast = dyn_cast<BitCastOperator>(Val)) {
211 Val = Cast->getOperand(0);
212 continue;
213 }
214
215 break;
216 }
217
218 return Val;
219}
220
221void ScopAnnotator::annotate(Instruction *Inst) {
222 if (!Inst->mayReadOrWriteMemory())
223 return;
224
225 switch (ParallelLoops.size()) {
226 case 0:
227 // Not parallel to anything: no access group needed.
228 break;
229 case 1:
230 // Single parallel loop: use directly.
231 Inst->setMetadata(LLVMContext::MD_access_group,
232 cast<MDNode>(ParallelLoops.front()));
233 break;
234 default:
235 // Parallel to multiple loops: refer to list of access groups.
236 Inst->setMetadata(LLVMContext::MD_access_group,
237 MDNode::get(SE->getContext(),
238 ArrayRef<Metadata *>(
239 (Metadata *const *)ParallelLoops.data(),
240 ParallelLoops.size())));
241 break;
242 }
243
244 // TODO: Use the ScopArrayInfo once available here.
245 if (!AliasScopeDomain)
246 return;
247
248 // Do not apply annotations on memory operations that take more than one
249 // pointer. It would be ambiguous to which pointer the annotation applies.
250 // FIXME: How can we specify annotations for all pointer arguments?
251 if (isa<CallInst>(Inst) && !isa<MemSetInst>(Inst))
252 return;
253
254 auto *Ptr = getMemAccInstPointerOperand(Inst);
255 if (!Ptr)
256 return;
257
258 Value *BasePtr = findBasePtr(Ptr);
259 if (!BasePtr)
260 return;
261
262 auto AliasScope = AliasScopeMap.lookup(BasePtr);
263
264 if (!AliasScope) {
265 BasePtr = AlternativeAliasBases.lookup(BasePtr);
266 if (!BasePtr)
267 return;
268
269 AliasScope = AliasScopeMap.lookup(BasePtr);
270 if (!AliasScope)
271 return;
272 }
273
274 assert(OtherAliasScopeListMap.count(BasePtr) &&
275 "BasePtr either expected in AliasScopeMap and OtherAlias...Map");
276 auto *OtherAliasScopeList = OtherAliasScopeListMap[BasePtr];
277
278 Inst->setMetadata("alias.scope", MDNode::get(SE->getContext(), AliasScope));
279 Inst->setMetadata("noalias", OtherAliasScopeList);
280}
static MDNode * getID(LLVMContext &Ctx, Metadata *arg0=nullptr, Metadata *arg1=nullptr)
Get a self referencing id metadata node.
Definition IRBuilder.cpp:32
static void addVectorizeMetadata(LLVMContext &Ctx, SmallVector< Metadata *, 3 > *Args, bool EnableLoopVectorizer)
void addParallelMetadata(LLVMContext &Ctx, SmallVector< Metadata *, 3 > *Args, llvm::SmallVector< llvm::MDNode *, 8 > ParallelLoops)
static Value * findBasePtr(Value *Val)
Find the base pointer of an array access.
static llvm::Value * getMemAccInstPointerOperand(Instruction *Inst)
Get the pointer operand.
static const int MaxArraysInAliasScops
Definition IRBuilder.cpp:23
static MemAccInst dyn_cast(llvm::Value &V)
Definition ScopHelper.h:179
llvm::SmallVector< BandAttr *, 8 > LoopAttrEnv
Stack for surrounding BandAttr annotations.
Definition IRBuilder.h:89
llvm::SmallVector< llvm::MDNode *, 8 > ParallelLoops
Access groups for the parallel loops currently under construction.
Definition IRBuilder.h:103
void annotateLoopLatch(llvm::CondBrInst *B, bool IsParallel, std::optional< bool > EnableVectorizeMetadata=std::nullopt) const
Annotate the loop latch B.
llvm::DenseMap< llvm::AssertingVH< llvm::Value >, llvm::MDNode * > OtherAliasScopeListMap
A map from base pointers to an alias scope list of other pointers.
Definition IRBuilder.h:113
BandAttr *& getStagingAttrEnv()
Definition IRBuilder.h:90
void buildAliasScopes(Scop &S)
Build all alias scopes for the given SCoP.
Definition IRBuilder.cpp:59
void annotate(llvm::Instruction *I)
Annotate the new instruction I for all parallel loops.
llvm::MapVector< llvm::AssertingVH< llvm::Value >, llvm::MDNode * > AliasScopeMap
A map from base pointers to its alias scope.
Definition IRBuilder.h:109
llvm::ScalarEvolution * SE
The ScalarEvolution analysis we use to find base pointers.
Definition IRBuilder.h:97
llvm::DenseMap< llvm::AssertingVH< llvm::Value >, llvm::AssertingVH< llvm::Value > > AlternativeAliasBases
Definition IRBuilder.h:116
void pushLoop(llvm::Loop *L, bool IsParallel)
Add a new loop L which is parallel if IsParallel is true.
llvm::SmallVector< llvm::Loop *, 8 > ActiveLoops
All loops currently under construction.
Definition IRBuilder.h:100
void popLoop(bool isParallel)
Remove the last added loop.
BandAttr * getActiveAttrEnv() const
Definition IRBuilder.h:91
llvm::MDNode * AliasScopeDomain
The alias scope domain for the current SCoP.
Definition IRBuilder.h:106
A class to store information about arrays in the SCoP.
Definition ScopInfo.h:216
Static Control Part.
Definition ScopInfo.h:1627
B()
const char * arg1
Definition isl_test.c:871
#define assert(exp)
@ Array
MemoryKind::Array: Models a one or multi-dimensional array.
Definition ScopInfo.h:112
@ Value
MemoryKind::Value: Models an llvm::Value.
Definition ScopInfo.h:151
Represent the attributes of a loop.
Definition ScopHelper.h:538
static TupleKindPtr Ctx