1 //===------ LoopGenerators.cpp - IR helper to create loops ---------------===// 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 // This file contains functions to create scalar and OpenMP parallel loops 11 // as LLVM-IR. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "polly/ScopDetection.h" 16 #include "polly/CodeGen/LoopGenerators.h" 17 18 #include "llvm/Module.h" 19 #include "llvm/Analysis/Dominators.h" 20 #include "llvm/DataLayout.h" 21 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 22 23 using namespace llvm; 24 using namespace polly; 25 26 Value *polly::createLoop(Value *LB, Value *UB, Value *Stride, 27 IRBuilder<> &Builder, Pass *P, 28 BasicBlock *&AfterBlock, 29 ICmpInst::Predicate Predicate) { 30 DominatorTree &DT = P->getAnalysis<DominatorTree>(); 31 Function *F = Builder.GetInsertBlock()->getParent(); 32 LLVMContext &Context = F->getContext(); 33 34 BasicBlock *PreheaderBB = Builder.GetInsertBlock(); 35 BasicBlock *HeaderBB = BasicBlock::Create(Context, "polly.loop_header", F); 36 BasicBlock *BodyBB = BasicBlock::Create(Context, "polly.loop_body", F); 37 BasicBlock *AfterBB = SplitBlock(PreheaderBB, Builder.GetInsertPoint()++, P); 38 AfterBB->setName("polly.loop_after"); 39 40 PreheaderBB->getTerminator()->setSuccessor(0, HeaderBB); 41 DT.addNewBlock(HeaderBB, PreheaderBB); 42 43 Builder.SetInsertPoint(HeaderBB); 44 45 // Use the type of upper and lower bound. 46 assert(LB->getType() == UB->getType() 47 && "Different types for upper and lower bound."); 48 49 IntegerType *LoopIVType = dyn_cast<IntegerType>(UB->getType()); 50 assert(LoopIVType && "UB is not integer?"); 51 52 // IV 53 PHINode *IV = Builder.CreatePHI(LoopIVType, 2, "polly.loopiv"); 54 IV->addIncoming(LB, PreheaderBB); 55 56 Stride = Builder.CreateZExtOrBitCast(Stride, LoopIVType); 57 Value *IncrementedIV = Builder.CreateNSWAdd(IV, Stride, "polly.next_loopiv"); 58 59 // Exit condition. 60 Value *CMP; 61 CMP = Builder.CreateICmp(Predicate, IV, UB); 62 63 Builder.CreateCondBr(CMP, BodyBB, AfterBB); 64 DT.addNewBlock(BodyBB, HeaderBB); 65 66 Builder.SetInsertPoint(BodyBB); 67 Builder.CreateBr(HeaderBB); 68 IV->addIncoming(IncrementedIV, BodyBB); 69 DT.changeImmediateDominator(AfterBB, HeaderBB); 70 71 Builder.SetInsertPoint(BodyBB->begin()); 72 AfterBlock = AfterBB; 73 74 return IV; 75 } 76 77 void OMPGenerator::createCallParallelLoopStart(Value *SubFunction, 78 Value *SubfunctionParam, 79 Value *NumberOfThreads, 80 Value *LowerBound, 81 Value *UpperBound, 82 Value *Stride) { 83 Module *M = getModule(); 84 const char *Name = "GOMP_parallel_loop_runtime_start"; 85 Function *F = M->getFunction(Name); 86 87 // If F is not available, declare it. 88 if (!F) { 89 Type *LongTy = getIntPtrTy(); 90 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage; 91 92 Type *Params[] = { 93 PointerType::getUnqual(FunctionType::get(Builder.getVoidTy(), 94 Builder.getInt8PtrTy(), 95 false)), 96 Builder.getInt8PtrTy(), 97 Builder.getInt32Ty(), 98 LongTy, 99 LongTy, 100 LongTy, 101 }; 102 103 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false); 104 F = Function::Create(Ty, Linkage, Name, M); 105 } 106 107 Value *Args[] = { 108 SubFunction, 109 SubfunctionParam, 110 NumberOfThreads, 111 LowerBound, 112 UpperBound, 113 Stride, 114 }; 115 116 Builder.CreateCall(F, Args); 117 } 118 119 Value *OMPGenerator::createCallLoopNext(Value *LowerBoundPtr, 120 Value *UpperBoundPtr) { 121 Module *M = getModule(); 122 const char *Name = "GOMP_loop_runtime_next"; 123 Function *F = M->getFunction(Name); 124 125 // If F is not available, declare it. 126 if (!F) { 127 Type *LongPtrTy = PointerType::getUnqual(getIntPtrTy()); 128 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage; 129 130 Type *Params[] = { 131 LongPtrTy, 132 LongPtrTy, 133 }; 134 135 FunctionType *Ty = FunctionType::get(Builder.getInt8Ty(), Params, false); 136 F = Function::Create(Ty, Linkage, Name, M); 137 } 138 139 Value *Args[] = { 140 LowerBoundPtr, 141 UpperBoundPtr, 142 }; 143 144 Value *Return = Builder.CreateCall(F, Args); 145 Return = Builder.CreateICmpNE(Return, Builder.CreateZExt(Builder.getFalse(), 146 Return->getType())); 147 return Return; 148 } 149 150 void OMPGenerator::createCallParallelEnd() { 151 const char *Name = "GOMP_parallel_end"; 152 Module *M = getModule(); 153 Function *F = M->getFunction(Name); 154 155 // If F is not available, declare it. 156 if (!F) { 157 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage; 158 159 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false); 160 F = Function::Create(Ty, Linkage, Name, M); 161 } 162 163 Builder.CreateCall(F); 164 } 165 166 void OMPGenerator::createCallLoopEndNowait() { 167 const char *Name = "GOMP_loop_end_nowait"; 168 Module *M = getModule(); 169 Function *F = M->getFunction(Name); 170 171 // If F is not available, declare it. 172 if (!F) { 173 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage; 174 175 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false); 176 F = Function::Create(Ty, Linkage, Name, M); 177 } 178 179 Builder.CreateCall(F); 180 } 181 182 IntegerType *OMPGenerator::getIntPtrTy() { 183 return P->getAnalysis<DataLayout>().getIntPtrType(Builder.getContext()); 184 } 185 186 Module *OMPGenerator::getModule() { 187 return Builder.GetInsertBlock()->getParent()->getParent(); 188 } 189 190 Function *OMPGenerator::createSubfunctionDefinition() { 191 Module *M = getModule(); 192 Function *F = Builder.GetInsertBlock()->getParent(); 193 std::vector<Type*> Arguments(1, Builder.getInt8PtrTy()); 194 FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false); 195 Function *FN = Function::Create(FT, Function::InternalLinkage, 196 F->getName() + ".omp_subfn", M); 197 // Do not run any polly pass on the new function. 198 P->getAnalysis<polly::ScopDetection>().markFunctionAsInvalid(FN); 199 200 Function::arg_iterator AI = FN->arg_begin(); 201 AI->setName("omp.userContext"); 202 203 return FN; 204 } 205 206 Value *OMPGenerator::loadValuesIntoStruct(SetVector<Value*> &Values) { 207 std::vector<Type*> Members; 208 209 for (unsigned i = 0; i < Values.size(); i++) 210 Members.push_back(Values[i]->getType()); 211 212 StructType *Ty = StructType::get(Builder.getContext(), Members); 213 Value *Struct = Builder.CreateAlloca(Ty, 0, "omp.userContext"); 214 215 for (unsigned i = 0; i < Values.size(); i++) { 216 Value *Address = Builder.CreateStructGEP(Struct, i); 217 Builder.CreateStore(Values[i], Address); 218 } 219 220 return Struct; 221 } 222 223 void OMPGenerator::extractValuesFromStruct(SetVector<Value*> OldValues, 224 Value *Struct, 225 ValueToValueMapTy &Map) { 226 for (unsigned i = 0; i < OldValues.size(); i++) { 227 Value *Address = Builder.CreateStructGEP(Struct, i); 228 Value *NewValue = Builder.CreateLoad(Address); 229 Map.insert(std::make_pair<Value*, Value*>(OldValues[i], NewValue)); 230 } 231 } 232 233 Value *OMPGenerator::createSubfunction(Value *Stride, Value *StructData, 234 SetVector<Value*> Data, 235 ValueToValueMapTy &Map, 236 Function **SubFunction) { 237 Function *FN = createSubfunctionDefinition(); 238 239 BasicBlock *PrevBB, *HeaderBB, *ExitBB, *CheckNextBB, *LoadIVBoundsBB, 240 *AfterBB; 241 Value *LowerBoundPtr, *UpperBoundPtr, *UserContext, *Ret1, *HasNextSchedule, 242 *LowerBound, *UpperBound, *IV; 243 Type *IntPtrTy = getIntPtrTy(); 244 LLVMContext &Context = FN->getContext(); 245 246 // Store the previous basic block. 247 PrevBB = Builder.GetInsertBlock(); 248 249 // Create basic blocks. 250 HeaderBB = BasicBlock::Create(Context, "omp.setup", FN); 251 ExitBB = BasicBlock::Create(Context, "omp.exit", FN); 252 CheckNextBB = BasicBlock::Create(Context, "omp.checkNext", FN); 253 LoadIVBoundsBB = BasicBlock::Create(Context, "omp.loadIVBounds", FN); 254 255 DominatorTree &DT = P->getAnalysis<DominatorTree>(); 256 DT.addNewBlock(HeaderBB, PrevBB); 257 DT.addNewBlock(ExitBB, HeaderBB); 258 DT.addNewBlock(CheckNextBB, HeaderBB); 259 DT.addNewBlock(LoadIVBoundsBB, HeaderBB); 260 261 // Fill up basic block HeaderBB. 262 Builder.SetInsertPoint(HeaderBB); 263 LowerBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.lowerBoundPtr"); 264 UpperBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.upperBoundPtr"); 265 UserContext = Builder.CreateBitCast(FN->arg_begin(), StructData->getType(), 266 "omp.userContext"); 267 268 extractValuesFromStruct(Data, UserContext, Map); 269 Builder.CreateBr(CheckNextBB); 270 271 // Add code to check if another set of iterations will be executed. 272 Builder.SetInsertPoint(CheckNextBB); 273 Ret1 = createCallLoopNext(LowerBoundPtr, UpperBoundPtr); 274 HasNextSchedule = Builder.CreateTrunc(Ret1, Builder.getInt1Ty(), 275 "omp.hasNextScheduleBlock"); 276 Builder.CreateCondBr(HasNextSchedule, LoadIVBoundsBB, ExitBB); 277 278 // Add code to to load the iv bounds for this set of iterations. 279 Builder.SetInsertPoint(LoadIVBoundsBB); 280 LowerBound = Builder.CreateLoad(LowerBoundPtr, "omp.lowerBound"); 281 UpperBound = Builder.CreateLoad(UpperBoundPtr, "omp.upperBound"); 282 283 // Subtract one as the upper bound provided by openmp is a < comparison 284 // whereas the codegenForSequential function creates a <= comparison. 285 UpperBound = Builder.CreateSub(UpperBound, ConstantInt::get(IntPtrTy, 1), 286 "omp.upperBoundAdjusted"); 287 288 Builder.CreateBr(CheckNextBB); 289 Builder.SetInsertPoint(--Builder.GetInsertPoint()); 290 IV = createLoop(LowerBound, UpperBound, Stride, Builder, P, AfterBB, 291 ICmpInst::ICMP_SLE); 292 293 BasicBlock::iterator LoopBody = Builder.GetInsertPoint(); 294 Builder.SetInsertPoint(AfterBB->begin()); 295 296 // Add code to terminate this openmp subfunction. 297 Builder.SetInsertPoint(ExitBB); 298 createCallLoopEndNowait(); 299 Builder.CreateRetVoid(); 300 301 Builder.SetInsertPoint(LoopBody); 302 *SubFunction = FN; 303 304 return IV; 305 } 306 307 Value *OMPGenerator::createParallelLoop(Value *LowerBound, Value *UpperBound, 308 Value *Stride, 309 SetVector<Value*> &Values, 310 ValueToValueMapTy &Map, 311 BasicBlock::iterator *LoopBody) { 312 Value *Struct, *IV, *SubfunctionParam, *NumberOfThreads; 313 Function *SubFunction; 314 315 Struct = loadValuesIntoStruct(Values); 316 317 BasicBlock::iterator PrevInsertPoint = Builder.GetInsertPoint(); 318 IV = createSubfunction(Stride, Struct, Values, Map, &SubFunction); 319 *LoopBody = Builder.GetInsertPoint(); 320 Builder.SetInsertPoint(PrevInsertPoint); 321 322 // Create call for GOMP_parallel_loop_runtime_start. 323 SubfunctionParam = Builder.CreateBitCast(Struct, Builder.getInt8PtrTy(), 324 "omp_data"); 325 326 NumberOfThreads = Builder.getInt32(0); 327 328 // Add one as the upper bound provided by openmp is a < comparison 329 // whereas the codegenForSequential function creates a <= comparison. 330 UpperBound = Builder.CreateAdd(UpperBound, 331 ConstantInt::get(getIntPtrTy(), 1)); 332 333 createCallParallelLoopStart(SubFunction, SubfunctionParam, NumberOfThreads, 334 LowerBound, UpperBound, Stride); 335 Builder.CreateCall(SubFunction, SubfunctionParam); 336 createCallParallelEnd(); 337 338 return IV; 339 } 340