137c9b8e0STobias Grosser //===------ PollyIRBuilder.cpp --------------------------------------------===//
237c9b8e0STobias Grosser //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
637c9b8e0STobias Grosser //
737c9b8e0STobias Grosser //===----------------------------------------------------------------------===//
837c9b8e0STobias Grosser //
937c9b8e0STobias Grosser // The Polly IRBuilder file contains Polly specific extensions for the IRBuilder
1037c9b8e0STobias Grosser // that are used e.g. to emit the llvm.loop.parallel metadata.
1137c9b8e0STobias Grosser //
1237c9b8e0STobias Grosser //===----------------------------------------------------------------------===//
1337c9b8e0STobias Grosser
1437c9b8e0STobias Grosser #include "polly/CodeGen/IRBuilder.h"
15ecdf263cSJohannes Doerfert #include "polly/ScopInfo.h"
16ecdf263cSJohannes Doerfert #include "polly/Support/ScopHelper.h"
174a07bbe3STobias Grosser #include "llvm/ADT/SmallVector.h"
1837c9b8e0STobias Grosser #include "llvm/IR/Metadata.h"
1937c9b8e0STobias Grosser
2037c9b8e0STobias Grosser using namespace llvm;
2137c9b8e0STobias Grosser using namespace polly;
2237c9b8e0STobias Grosser
23696a1ee9STobias Grosser static const int MaxArraysInAliasScops = 10;
24696a1ee9STobias Grosser
25c80d6979STobias Grosser /// Get a self referencing id metadata node.
26c7b719fcSJohannes Doerfert ///
27ecdf263cSJohannes Doerfert /// The MDNode looks like this (if arg0/arg1 are not null):
28c7b719fcSJohannes Doerfert ///
29d4c667c9SDuncan P. N. Exon Smith /// '!n = distinct !{!n, arg0, arg1}'
30c7b719fcSJohannes Doerfert ///
31ecdf263cSJohannes Doerfert /// @return The self referencing id metadata node.
getID(LLVMContext & Ctx,Metadata * arg0=nullptr,Metadata * arg1=nullptr)32bd8f3c1fSTobias Grosser static MDNode *getID(LLVMContext &Ctx, Metadata *arg0 = nullptr,
33bd8f3c1fSTobias Grosser Metadata *arg1 = nullptr) {
34ecdf263cSJohannes Doerfert MDNode *ID;
35bd8f3c1fSTobias Grosser SmallVector<Metadata *, 3> Args;
36a4817871SDavid Peixotto // Reserve operand 0 for loop id self reference.
37d4c667c9SDuncan P. N. Exon Smith Args.push_back(nullptr);
38ecdf263cSJohannes Doerfert
39ecdf263cSJohannes Doerfert if (arg0)
40ecdf263cSJohannes Doerfert Args.push_back(arg0);
41ecdf263cSJohannes Doerfert if (arg1)
42ecdf263cSJohannes Doerfert Args.push_back(arg1);
43ecdf263cSJohannes Doerfert
44d4c667c9SDuncan P. N. Exon Smith ID = MDNode::getDistinct(Ctx, Args);
45ecdf263cSJohannes Doerfert ID->replaceOperandWith(0, ID);
46ecdf263cSJohannes Doerfert return ID;
47ecdf263cSJohannes Doerfert }
48ecdf263cSJohannes Doerfert
ScopAnnotator()493f170eb1SMichael Kruse ScopAnnotator::ScopAnnotator() : SE(nullptr), AliasScopeDomain(nullptr) {
503f170eb1SMichael Kruse // Push an empty staging BandAttr.
513f170eb1SMichael Kruse LoopAttrEnv.emplace_back();
523f170eb1SMichael Kruse }
533f170eb1SMichael Kruse
~ScopAnnotator()543f170eb1SMichael Kruse ScopAnnotator::~ScopAnnotator() {
553f170eb1SMichael Kruse assert(LoopAttrEnv.size() == 1 && "Loop stack imbalance");
563f170eb1SMichael Kruse assert(!getStagingAttrEnv() && "Forgot to clear staging attr env");
573f170eb1SMichael Kruse }
58ecdf263cSJohannes Doerfert
buildAliasScopes(Scop & S)5951d1c74dSJohannes Doerfert void ScopAnnotator::buildAliasScopes(Scop &S) {
60ecdf263cSJohannes Doerfert SE = S.getSE();
61ecdf263cSJohannes Doerfert
62ecdf263cSJohannes Doerfert LLVMContext &Ctx = SE->getContext();
63ecdf263cSJohannes Doerfert AliasScopeDomain = getID(Ctx, MDString::get(Ctx, "polly.alias.scope.domain"));
64ecdf263cSJohannes Doerfert
65ecdf263cSJohannes Doerfert AliasScopeMap.clear();
66ecdf263cSJohannes Doerfert OtherAliasScopeListMap.clear();
67ecdf263cSJohannes Doerfert
684a07bbe3STobias Grosser // We are only interested in arrays, but no scalar references. Scalars should
694a07bbe3STobias Grosser // be handled easily by basicaa.
704a07bbe3STobias Grosser SmallVector<ScopArrayInfo *, 10> Arrays;
714a07bbe3STobias Grosser for (ScopArrayInfo *Array : S.arrays())
724a07bbe3STobias Grosser if (Array->isArrayKind())
734a07bbe3STobias Grosser Arrays.push_back(Array);
744a07bbe3STobias Grosser
75696a1ee9STobias Grosser // The construction of alias scopes is quadratic in the number of arrays
76696a1ee9STobias Grosser // involved. In case of too many arrays, skip the construction of alias
77696a1ee9STobias Grosser // information to avoid quadratic increases in compile time and code size.
784a07bbe3STobias Grosser if (Arrays.size() > MaxArraysInAliasScops)
79696a1ee9STobias Grosser return;
80696a1ee9STobias Grosser
81ecdf263cSJohannes Doerfert std::string AliasScopeStr = "polly.alias.scope.";
824a07bbe3STobias Grosser for (const ScopArrayInfo *Array : Arrays) {
83214deb79SMichael Kruse assert(Array->getBasePtr() && "Base pointer must be present");
844553463bSTobias Grosser AliasScopeMap[Array->getBasePtr()] =
854553463bSTobias Grosser getID(Ctx, AliasScopeDomain,
864553463bSTobias Grosser MDString::get(Ctx, (AliasScopeStr + Array->getName()).c_str()));
87214deb79SMichael Kruse }
88ecdf263cSJohannes Doerfert
894a07bbe3STobias Grosser for (const ScopArrayInfo *Array : Arrays) {
90ecdf263cSJohannes Doerfert MDNode *AliasScopeList = MDNode::get(Ctx, {});
91ecdf263cSJohannes Doerfert for (const auto &AliasScopePair : AliasScopeMap) {
924553463bSTobias Grosser if (Array->getBasePtr() == AliasScopePair.first)
93ecdf263cSJohannes Doerfert continue;
94ecdf263cSJohannes Doerfert
95bd8f3c1fSTobias Grosser Metadata *Args = {AliasScopePair.second};
96ecdf263cSJohannes Doerfert AliasScopeList =
97ecdf263cSJohannes Doerfert MDNode::concatenate(AliasScopeList, MDNode::get(Ctx, Args));
98ecdf263cSJohannes Doerfert }
99ecdf263cSJohannes Doerfert
1004553463bSTobias Grosser OtherAliasScopeListMap[Array->getBasePtr()] = AliasScopeList;
101ecdf263cSJohannes Doerfert }
10237c9b8e0STobias Grosser }
10337c9b8e0STobias Grosser
pushLoop(Loop * L,bool IsParallel)10451d1c74dSJohannes Doerfert void ScopAnnotator::pushLoop(Loop *L, bool IsParallel) {
105c7b719fcSJohannes Doerfert ActiveLoops.push_back(L);
10637c9b8e0STobias Grosser
107b85c98b4SMichael Kruse if (IsParallel) {
108b85c98b4SMichael Kruse LLVMContext &Ctx = SE->getContext();
109b85c98b4SMichael Kruse MDNode *AccessGroup = MDNode::getDistinct(Ctx, {});
110b85c98b4SMichael Kruse ParallelLoops.push_back(AccessGroup);
111b85c98b4SMichael Kruse }
1123f170eb1SMichael Kruse
1133f170eb1SMichael Kruse // Open an empty BandAttr context for loops nested in this one.
1143f170eb1SMichael Kruse LoopAttrEnv.emplace_back();
115c7b719fcSJohannes Doerfert }
116c7b719fcSJohannes Doerfert
popLoop(bool IsParallel)11751d1c74dSJohannes Doerfert void ScopAnnotator::popLoop(bool IsParallel) {
118c7b719fcSJohannes Doerfert ActiveLoops.pop_back();
11937c9b8e0STobias Grosser
120b85c98b4SMichael Kruse if (IsParallel) {
121c7b719fcSJohannes Doerfert assert(!ParallelLoops.empty() && "Expected a parallel loop to pop");
122c7b719fcSJohannes Doerfert ParallelLoops.pop_back();
12337c9b8e0STobias Grosser }
1243f170eb1SMichael Kruse
1253f170eb1SMichael Kruse // Exit the subloop context.
1263f170eb1SMichael Kruse assert(!getStagingAttrEnv() && "Forgot to clear staging attr env");
1273f170eb1SMichael Kruse assert(LoopAttrEnv.size() >= 2 && "Popped too many");
1283f170eb1SMichael Kruse LoopAttrEnv.pop_back();
129b85c98b4SMichael Kruse }
130c7b719fcSJohannes Doerfert
annotateLoopLatch(BranchInst * B,Loop * L,bool IsParallel,bool IsLoopVectorizerDisabled) const1310956a606SRoman Gareev void ScopAnnotator::annotateLoopLatch(BranchInst *B, Loop *L, bool IsParallel,
1320956a606SRoman Gareev bool IsLoopVectorizerDisabled) const {
133b85c98b4SMichael Kruse LLVMContext &Ctx = SE->getContext();
134b85c98b4SMichael Kruse SmallVector<Metadata *, 3> Args;
135b85c98b4SMichael Kruse
136b85c98b4SMichael Kruse // For the LoopID self-reference.
137b85c98b4SMichael Kruse Args.push_back(nullptr);
138c7b719fcSJohannes Doerfert
1393f170eb1SMichael Kruse // Add the user-defined loop properties to the annotation, if any. Any
1403f170eb1SMichael Kruse // additional properties are appended.
1413f170eb1SMichael Kruse // FIXME: What to do if these conflict?
1423f170eb1SMichael Kruse MDNode *MData = nullptr;
1433f170eb1SMichael Kruse if (BandAttr *AttrEnv = getActiveAttrEnv()) {
1443f170eb1SMichael Kruse MData = AttrEnv->Metadata;
1453f170eb1SMichael Kruse if (MData)
1463f170eb1SMichael Kruse llvm::append_range(Args, drop_begin(MData->operands(), 1));
1473f170eb1SMichael Kruse }
1483f170eb1SMichael Kruse
1490956a606SRoman Gareev if (IsLoopVectorizerDisabled) {
150b85c98b4SMichael Kruse MDString *PropName = MDString::get(Ctx, "llvm.loop.vectorize.enable");
151b85c98b4SMichael Kruse ConstantInt *FalseValue = ConstantInt::get(Type::getInt1Ty(Ctx), 0);
152b85c98b4SMichael Kruse ValueAsMetadata *PropValue = ValueAsMetadata::get(FalseValue);
153b85c98b4SMichael Kruse Args.push_back(MDNode::get(Ctx, {PropName, PropValue}));
1540956a606SRoman Gareev }
1550956a606SRoman Gareev
1560956a606SRoman Gareev if (IsParallel) {
157b85c98b4SMichael Kruse MDString *PropName = MDString::get(Ctx, "llvm.loop.parallel_accesses");
158b85c98b4SMichael Kruse MDNode *AccGroup = ParallelLoops.back();
159b85c98b4SMichael Kruse Args.push_back(MDNode::get(Ctx, {PropName, AccGroup}));
1600956a606SRoman Gareev }
1610956a606SRoman Gareev
162b85c98b4SMichael Kruse // No metadata to annotate.
1633f170eb1SMichael Kruse if (!MData && Args.size() <= 1)
164b85c98b4SMichael Kruse return;
165b85c98b4SMichael Kruse
1663f170eb1SMichael Kruse // Reuse the MData node if possible, this will avoid having to create another
1673f170eb1SMichael Kruse // one that cannot be merged because LoopIDs are 'distinct'. However, we have
1683f170eb1SMichael Kruse // to create a new one if we add properties.
1693f170eb1SMichael Kruse if (!MData || Args.size() > MData->getNumOperands()) {
1703f170eb1SMichael Kruse MData = MDNode::getDistinct(Ctx, Args);
171b85c98b4SMichael Kruse MData->replaceOperandWith(0, MData);
1723f170eb1SMichael Kruse }
173b85c98b4SMichael Kruse B->setMetadata(LLVMContext::MD_loop, MData);
17437c9b8e0STobias Grosser }
175c7b719fcSJohannes Doerfert
176cdfb57dcSRoman Gareev /// Get the pointer operand
177cdfb57dcSRoman Gareev ///
178cdfb57dcSRoman Gareev /// @param Inst The instruction to be analyzed.
179cdfb57dcSRoman Gareev /// @return the pointer operand in case @p Inst is a memory access
180cdfb57dcSRoman Gareev /// instruction and nullptr otherwise.
getMemAccInstPointerOperand(Instruction * Inst)181cdfb57dcSRoman Gareev static llvm::Value *getMemAccInstPointerOperand(Instruction *Inst) {
182cdfb57dcSRoman Gareev auto MemInst = MemAccInst::dyn_cast(Inst);
183cdfb57dcSRoman Gareev if (!MemInst)
184cdfb57dcSRoman Gareev return nullptr;
185cdfb57dcSRoman Gareev
186cdfb57dcSRoman Gareev return MemInst.getPointerOperand();
187cdfb57dcSRoman Gareev }
188cdfb57dcSRoman Gareev
1896249bfeeSMichael Kruse /// Find the base pointer of an array access.
1906249bfeeSMichael Kruse ///
1916249bfeeSMichael Kruse /// This should be equivalent to ScalarEvolution::getPointerBase, which we
1926249bfeeSMichael Kruse /// cannot use here the IR is still under construction which ScalarEvolution
1936249bfeeSMichael Kruse /// assumes to not be modified.
findBasePtr(Value * Val)1946249bfeeSMichael Kruse static Value *findBasePtr(Value *Val) {
1956249bfeeSMichael Kruse while (true) {
1966249bfeeSMichael Kruse if (auto *Gep = dyn_cast<GEPOperator>(Val)) {
1976249bfeeSMichael Kruse Val = Gep->getPointerOperand();
1986249bfeeSMichael Kruse continue;
1996249bfeeSMichael Kruse }
2006249bfeeSMichael Kruse if (auto *Cast = dyn_cast<BitCastOperator>(Val)) {
2016249bfeeSMichael Kruse Val = Cast->getOperand(0);
2026249bfeeSMichael Kruse continue;
2036249bfeeSMichael Kruse }
2046249bfeeSMichael Kruse
2056249bfeeSMichael Kruse break;
2066249bfeeSMichael Kruse }
2076249bfeeSMichael Kruse
2086249bfeeSMichael Kruse return Val;
2096249bfeeSMichael Kruse }
2106249bfeeSMichael Kruse
annotate(Instruction * Inst)21151d1c74dSJohannes Doerfert void ScopAnnotator::annotate(Instruction *Inst) {
212ecdf263cSJohannes Doerfert if (!Inst->mayReadOrWriteMemory())
213ecdf263cSJohannes Doerfert return;
214ecdf263cSJohannes Doerfert
215b85c98b4SMichael Kruse switch (ParallelLoops.size()) {
216b85c98b4SMichael Kruse case 0:
217b85c98b4SMichael Kruse // Not parallel to anything: no access group needed.
218b85c98b4SMichael Kruse break;
219b85c98b4SMichael Kruse case 1:
220b85c98b4SMichael Kruse // Single parallel loop: use directly.
221b85c98b4SMichael Kruse Inst->setMetadata(LLVMContext::MD_access_group,
222b85c98b4SMichael Kruse cast<MDNode>(ParallelLoops.front()));
223b85c98b4SMichael Kruse break;
224b85c98b4SMichael Kruse default:
225b85c98b4SMichael Kruse // Parallel to multiple loops: refer to list of access groups.
226b85c98b4SMichael Kruse Inst->setMetadata(LLVMContext::MD_access_group,
227b85c98b4SMichael Kruse MDNode::get(SE->getContext(),
228b85c98b4SMichael Kruse ArrayRef<Metadata *>(
229b85c98b4SMichael Kruse (Metadata *const *)ParallelLoops.data(),
230b85c98b4SMichael Kruse ParallelLoops.size())));
231b85c98b4SMichael Kruse break;
232b85c98b4SMichael Kruse }
233ecdf263cSJohannes Doerfert
23473725b8bSTobias Grosser // TODO: Use the ScopArrayInfo once available here.
23573725b8bSTobias Grosser if (!AliasScopeDomain)
23673725b8bSTobias Grosser return;
23773725b8bSTobias Grosser
238271deb17SMichael Kruse // Do not apply annotations on memory operations that take more than one
239271deb17SMichael Kruse // pointer. It would be ambiguous to which pointer the annotation applies.
240271deb17SMichael Kruse // FIXME: How can we specify annotations for all pointer arguments?
241271deb17SMichael Kruse if (isa<CallInst>(Inst) && !isa<MemSetInst>(Inst))
242271deb17SMichael Kruse return;
243271deb17SMichael Kruse
244cdfb57dcSRoman Gareev auto *Ptr = getMemAccInstPointerOperand(Inst);
245a7920980SJohannes Doerfert if (!Ptr)
246a7920980SJohannes Doerfert return;
247a7920980SJohannes Doerfert
2486249bfeeSMichael Kruse Value *BasePtr = findBasePtr(Ptr);
24973725b8bSTobias Grosser if (!BasePtr)
25073725b8bSTobias Grosser return;
25173725b8bSTobias Grosser
2526bab9f80STobias Grosser auto AliasScope = AliasScopeMap.lookup(BasePtr);
253b0da42fbSTobias Grosser
2546bab9f80STobias Grosser if (!AliasScope) {
2556bab9f80STobias Grosser BasePtr = AlternativeAliasBases.lookup(BasePtr);
2566bab9f80STobias Grosser if (!BasePtr)
257d79cb037STobias Grosser return;
258b0da42fbSTobias Grosser
2596bab9f80STobias Grosser AliasScope = AliasScopeMap.lookup(BasePtr);
2606bab9f80STobias Grosser if (!AliasScope)
261d79cb037STobias Grosser return;
262d79cb037STobias Grosser }
263d79cb037STobias Grosser
264d79cb037STobias Grosser assert(OtherAliasScopeListMap.count(BasePtr) &&
265d79cb037STobias Grosser "BasePtr either expected in AliasScopeMap and OtherAlias...Map");
266b0da42fbSTobias Grosser auto *OtherAliasScopeList = OtherAliasScopeListMap[BasePtr];
267b0da42fbSTobias Grosser
268*53720f74SNikita Popov Inst->setMetadata("alias.scope", MDNode::get(SE->getContext(), AliasScope));
269b0da42fbSTobias Grosser Inst->setMetadata("noalias", OtherAliasScopeList);
270ecdf263cSJohannes Doerfert }
271