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 14 #include "polly/CodeGen/IRBuilder.h" 15 #include "polly/ScopInfo.h" 16 #include "polly/Support/ScopHelper.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/IR/Metadata.h" 19 20 using namespace llvm; 21 using namespace polly; 22 23 static 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. 32 static 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 49 ScopAnnotator::ScopAnnotator() : SE(nullptr), AliasScopeDomain(nullptr) { 50 // Push an empty staging BandAttr. 51 LoopAttrEnv.emplace_back(); 52 } 53 54 ScopAnnotator::~ScopAnnotator() { 55 assert(LoopAttrEnv.size() == 1 && "Loop stack imbalance"); 56 assert(!getStagingAttrEnv() && "Forgot to clear staging attr env"); 57 } 58 59 void ScopAnnotator::buildAliasScopes(Scop &S) { 60 SE = S.getSE(); 61 62 LLVMContext &Ctx = SE->getContext(); 63 AliasScopeDomain = getID(Ctx, MDString::get(Ctx, "polly.alias.scope.domain")); 64 65 AliasScopeMap.clear(); 66 OtherAliasScopeListMap.clear(); 67 68 // We are only interested in arrays, but no scalar references. Scalars should 69 // be handled easily by basicaa. 70 SmallVector<ScopArrayInfo *, 10> Arrays; 71 for (ScopArrayInfo *Array : S.arrays()) 72 if (Array->isArrayKind()) 73 Arrays.push_back(Array); 74 75 // The construction of alias scopes is quadratic in the number of arrays 76 // involved. In case of too many arrays, skip the construction of alias 77 // information to avoid quadratic increases in compile time and code size. 78 if (Arrays.size() > MaxArraysInAliasScops) 79 return; 80 81 std::string AliasScopeStr = "polly.alias.scope."; 82 for (const ScopArrayInfo *Array : Arrays) { 83 assert(Array->getBasePtr() && "Base pointer must be present"); 84 AliasScopeMap[Array->getBasePtr()] = 85 getID(Ctx, AliasScopeDomain, 86 MDString::get(Ctx, (AliasScopeStr + Array->getName()).c_str())); 87 } 88 89 for (const ScopArrayInfo *Array : Arrays) { 90 MDNode *AliasScopeList = MDNode::get(Ctx, {}); 91 for (const auto &AliasScopePair : AliasScopeMap) { 92 if (Array->getBasePtr() == AliasScopePair.first) 93 continue; 94 95 Metadata *Args = {AliasScopePair.second}; 96 AliasScopeList = 97 MDNode::concatenate(AliasScopeList, MDNode::get(Ctx, Args)); 98 } 99 100 OtherAliasScopeListMap[Array->getBasePtr()] = AliasScopeList; 101 } 102 } 103 104 void ScopAnnotator::pushLoop(Loop *L, bool IsParallel) { 105 ActiveLoops.push_back(L); 106 107 if (IsParallel) { 108 LLVMContext &Ctx = SE->getContext(); 109 MDNode *AccessGroup = MDNode::getDistinct(Ctx, {}); 110 ParallelLoops.push_back(AccessGroup); 111 } 112 113 // Open an empty BandAttr context for loops nested in this one. 114 LoopAttrEnv.emplace_back(); 115 } 116 117 void ScopAnnotator::popLoop(bool IsParallel) { 118 ActiveLoops.pop_back(); 119 120 if (IsParallel) { 121 assert(!ParallelLoops.empty() && "Expected a parallel loop to pop"); 122 ParallelLoops.pop_back(); 123 } 124 125 // Exit the subloop context. 126 assert(!getStagingAttrEnv() && "Forgot to clear staging attr env"); 127 assert(LoopAttrEnv.size() >= 2 && "Popped too many"); 128 LoopAttrEnv.pop_back(); 129 } 130 131 static void addVectorizeMetadata(LLVMContext &Ctx, 132 SmallVector<Metadata *, 3> *Args, 133 bool EnableLoopVectorizer) { 134 MDString *PropName = MDString::get(Ctx, "llvm.loop.vectorize.enable"); 135 ConstantInt *Value = 136 ConstantInt::get(Type::getInt1Ty(Ctx), EnableLoopVectorizer); 137 ValueAsMetadata *PropValue = ValueAsMetadata::get(Value); 138 Args->push_back(MDNode::get(Ctx, {PropName, PropValue})); 139 } 140 141 void addParallelMetadata(LLVMContext &Ctx, SmallVector<Metadata *, 3> *Args, 142 llvm::SmallVector<llvm::MDNode *, 8> ParallelLoops) { 143 MDString *PropName = MDString::get(Ctx, "llvm.loop.parallel_accesses"); 144 MDNode *AccGroup = ParallelLoops.back(); 145 Args->push_back(MDNode::get(Ctx, {PropName, AccGroup})); 146 } 147 148 void ScopAnnotator::annotateLoopLatch( 149 BranchInst *B, bool IsParallel, 150 std::optional<bool> EnableVectorizeMetadata) const { 151 LLVMContext &Ctx = SE->getContext(); 152 SmallVector<Metadata *, 3> Args; 153 154 // For the LoopID self-reference. 155 Args.push_back(nullptr); 156 157 // Add the user-defined loop properties to the annotation, if any. Any 158 // additional properties are appended. 159 // FIXME: What to do if these conflict? 160 MDNode *MData = nullptr; 161 if (BandAttr *AttrEnv = getActiveAttrEnv()) { 162 MData = AttrEnv->Metadata; 163 if (MData) 164 llvm::append_range(Args, drop_begin(MData->operands(), 1)); 165 } 166 if (IsParallel) 167 addParallelMetadata(Ctx, &Args, ParallelLoops); 168 if (EnableVectorizeMetadata.has_value()) 169 addVectorizeMetadata(Ctx, &Args, *EnableVectorizeMetadata); 170 171 // No metadata to annotate. 172 if (!MData && Args.size() <= 1) 173 return; 174 175 // Reuse the MData node if possible, this will avoid having to create another 176 // one that cannot be merged because LoopIDs are 'distinct'. However, we have 177 // to create a new one if we add properties. 178 if (!MData || Args.size() > MData->getNumOperands()) { 179 MData = MDNode::getDistinct(Ctx, Args); 180 MData->replaceOperandWith(0, MData); 181 } 182 B->setMetadata(LLVMContext::MD_loop, MData); 183 } 184 185 /// Get the pointer operand 186 /// 187 /// @param Inst The instruction to be analyzed. 188 /// @return the pointer operand in case @p Inst is a memory access 189 /// instruction and nullptr otherwise. 190 static llvm::Value *getMemAccInstPointerOperand(Instruction *Inst) { 191 auto MemInst = MemAccInst::dyn_cast(Inst); 192 if (!MemInst) 193 return nullptr; 194 195 return MemInst.getPointerOperand(); 196 } 197 198 /// Find the base pointer of an array access. 199 /// 200 /// This should be equivalent to ScalarEvolution::getPointerBase, which we 201 /// cannot use here the IR is still under construction which ScalarEvolution 202 /// assumes to not be modified. 203 static Value *findBasePtr(Value *Val) { 204 while (true) { 205 if (auto *Gep = dyn_cast<GEPOperator>(Val)) { 206 Val = Gep->getPointerOperand(); 207 continue; 208 } 209 if (auto *Cast = dyn_cast<BitCastOperator>(Val)) { 210 Val = Cast->getOperand(0); 211 continue; 212 } 213 214 break; 215 } 216 217 return Val; 218 } 219 220 void ScopAnnotator::annotate(Instruction *Inst) { 221 if (!Inst->mayReadOrWriteMemory()) 222 return; 223 224 switch (ParallelLoops.size()) { 225 case 0: 226 // Not parallel to anything: no access group needed. 227 break; 228 case 1: 229 // Single parallel loop: use directly. 230 Inst->setMetadata(LLVMContext::MD_access_group, 231 cast<MDNode>(ParallelLoops.front())); 232 break; 233 default: 234 // Parallel to multiple loops: refer to list of access groups. 235 Inst->setMetadata(LLVMContext::MD_access_group, 236 MDNode::get(SE->getContext(), 237 ArrayRef<Metadata *>( 238 (Metadata *const *)ParallelLoops.data(), 239 ParallelLoops.size()))); 240 break; 241 } 242 243 // TODO: Use the ScopArrayInfo once available here. 244 if (!AliasScopeDomain) 245 return; 246 247 // Do not apply annotations on memory operations that take more than one 248 // pointer. It would be ambiguous to which pointer the annotation applies. 249 // FIXME: How can we specify annotations for all pointer arguments? 250 if (isa<CallInst>(Inst) && !isa<MemSetInst>(Inst)) 251 return; 252 253 auto *Ptr = getMemAccInstPointerOperand(Inst); 254 if (!Ptr) 255 return; 256 257 Value *BasePtr = findBasePtr(Ptr); 258 if (!BasePtr) 259 return; 260 261 auto AliasScope = AliasScopeMap.lookup(BasePtr); 262 263 if (!AliasScope) { 264 BasePtr = AlternativeAliasBases.lookup(BasePtr); 265 if (!BasePtr) 266 return; 267 268 AliasScope = AliasScopeMap.lookup(BasePtr); 269 if (!AliasScope) 270 return; 271 } 272 273 assert(OtherAliasScopeListMap.count(BasePtr) && 274 "BasePtr either expected in AliasScopeMap and OtherAlias...Map"); 275 auto *OtherAliasScopeList = OtherAliasScopeListMap[BasePtr]; 276 277 Inst->setMetadata("alias.scope", MDNode::get(SE->getContext(), AliasScope)); 278 Inst->setMetadata("noalias", OtherAliasScopeList); 279 } 280