LoopGeneratorsGOMP.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. //===------ LoopGeneratorsGOMP.cpp - IR helper to create loops ------------===//
  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. // This file contains functions to create parallel loops as LLVM-IR.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "polly/CodeGen/LoopGeneratorsGOMP.h"
  13. #include "llvm/IR/Dominators.h"
  14. #include "llvm/IR/Module.h"
  15. using namespace llvm;
  16. using namespace polly;
  17. void ParallelLoopGeneratorGOMP::createCallSpawnThreads(Value *SubFn,
  18. Value *SubFnParam,
  19. Value *LB, Value *UB,
  20. Value *Stride) {
  21. const std::string Name = "GOMP_parallel_loop_runtime_start";
  22. Function *F = M->getFunction(Name);
  23. // If F is not available, declare it.
  24. if (!F) {
  25. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  26. Type *Params[] = {PointerType::getUnqual(FunctionType::get(
  27. Builder.getVoidTy(), Builder.getInt8PtrTy(), false)),
  28. Builder.getInt8PtrTy(),
  29. Builder.getInt32Ty(),
  30. LongType,
  31. LongType,
  32. LongType};
  33. FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
  34. F = Function::Create(Ty, Linkage, Name, M);
  35. }
  36. Value *Args[] = {SubFn, SubFnParam, Builder.getInt32(PollyNumThreads),
  37. LB, UB, Stride};
  38. CallInst *Call = Builder.CreateCall(F, Args);
  39. Call->setDebugLoc(DLGenerated);
  40. }
  41. void ParallelLoopGeneratorGOMP::deployParallelExecution(Function *SubFn,
  42. Value *SubFnParam,
  43. Value *LB, Value *UB,
  44. Value *Stride) {
  45. // Tell the runtime we start a parallel loop
  46. createCallSpawnThreads(SubFn, SubFnParam, LB, UB, Stride);
  47. CallInst *Call = Builder.CreateCall(SubFn, SubFnParam);
  48. Call->setDebugLoc(DLGenerated);
  49. createCallJoinThreads();
  50. }
  51. Function *ParallelLoopGeneratorGOMP::prepareSubFnDefinition(Function *F) const {
  52. FunctionType *FT =
  53. FunctionType::get(Builder.getVoidTy(), {Builder.getInt8PtrTy()}, false);
  54. Function *SubFn = Function::Create(FT, Function::InternalLinkage,
  55. F->getName() + "_polly_subfn", M);
  56. // Name the function's arguments
  57. SubFn->arg_begin()->setName("polly.par.userContext");
  58. return SubFn;
  59. }
  60. // Create a subfunction of the following (preliminary) structure:
  61. //
  62. // PrevBB
  63. // |
  64. // v
  65. // HeaderBB
  66. // | _____
  67. // v v |
  68. // CheckNextBB PreHeaderBB
  69. // |\ |
  70. // | \______/
  71. // |
  72. // v
  73. // ExitBB
  74. //
  75. // HeaderBB will hold allocations and loading of variables.
  76. // CheckNextBB will check for more work.
  77. // If there is more work to do: go to PreHeaderBB, otherwise go to ExitBB.
  78. // PreHeaderBB loads the new boundaries (& will lead to the loop body later on).
  79. // ExitBB marks the end of the parallel execution.
  80. std::tuple<Value *, Function *>
  81. ParallelLoopGeneratorGOMP::createSubFn(Value *Stride, AllocaInst *StructData,
  82. SetVector<Value *> Data,
  83. ValueMapT &Map) {
  84. if (PollyScheduling != OMPGeneralSchedulingType::Runtime) {
  85. // User tried to influence the scheduling type (currently not supported)
  86. errs() << "warning: Polly's GNU OpenMP backend solely "
  87. "supports the scheduling type 'runtime'.\n";
  88. }
  89. if (PollyChunkSize != 0) {
  90. // User tried to influence the chunk size (currently not supported)
  91. errs() << "warning: Polly's GNU OpenMP backend solely "
  92. "supports the default chunk size.\n";
  93. }
  94. Function *SubFn = createSubFnDefinition();
  95. LLVMContext &Context = SubFn->getContext();
  96. // Store the previous basic block.
  97. BasicBlock *PrevBB = Builder.GetInsertBlock();
  98. // Create basic blocks.
  99. BasicBlock *HeaderBB = BasicBlock::Create(Context, "polly.par.setup", SubFn);
  100. BasicBlock *ExitBB = BasicBlock::Create(Context, "polly.par.exit", SubFn);
  101. BasicBlock *CheckNextBB =
  102. BasicBlock::Create(Context, "polly.par.checkNext", SubFn);
  103. BasicBlock *PreHeaderBB =
  104. BasicBlock::Create(Context, "polly.par.loadIVBounds", SubFn);
  105. DT.addNewBlock(HeaderBB, PrevBB);
  106. DT.addNewBlock(ExitBB, HeaderBB);
  107. DT.addNewBlock(CheckNextBB, HeaderBB);
  108. DT.addNewBlock(PreHeaderBB, HeaderBB);
  109. // Fill up basic block HeaderBB.
  110. Builder.SetInsertPoint(HeaderBB);
  111. Value *LBPtr = Builder.CreateAlloca(LongType, nullptr, "polly.par.LBPtr");
  112. Value *UBPtr = Builder.CreateAlloca(LongType, nullptr, "polly.par.UBPtr");
  113. Value *UserContext = Builder.CreateBitCast(
  114. &*SubFn->arg_begin(), StructData->getType(), "polly.par.userContext");
  115. extractValuesFromStruct(Data, StructData->getAllocatedType(), UserContext,
  116. Map);
  117. Builder.CreateBr(CheckNextBB);
  118. // Add code to check if another set of iterations will be executed.
  119. Builder.SetInsertPoint(CheckNextBB);
  120. Value *Next = createCallGetWorkItem(LBPtr, UBPtr);
  121. Value *HasNextSchedule = Builder.CreateTrunc(
  122. Next, Builder.getInt1Ty(), "polly.par.hasNextScheduleBlock");
  123. Builder.CreateCondBr(HasNextSchedule, PreHeaderBB, ExitBB);
  124. // Add code to load the iv bounds for this set of iterations.
  125. Builder.SetInsertPoint(PreHeaderBB);
  126. Value *LB = Builder.CreateLoad(LongType, LBPtr, "polly.par.LB");
  127. Value *UB = Builder.CreateLoad(LongType, UBPtr, "polly.par.UB");
  128. // Subtract one as the upper bound provided by OpenMP is a < comparison
  129. // whereas the codegenForSequential function creates a <= comparison.
  130. UB = Builder.CreateSub(UB, ConstantInt::get(LongType, 1),
  131. "polly.par.UBAdjusted");
  132. Builder.CreateBr(CheckNextBB);
  133. Builder.SetInsertPoint(&*--Builder.GetInsertPoint());
  134. BasicBlock *AfterBB;
  135. Value *IV =
  136. createLoop(LB, UB, Stride, Builder, LI, DT, AfterBB, ICmpInst::ICMP_SLE,
  137. nullptr, true, /* UseGuard */ false);
  138. BasicBlock::iterator LoopBody = Builder.GetInsertPoint();
  139. // Add code to terminate this subfunction.
  140. Builder.SetInsertPoint(ExitBB);
  141. createCallCleanupThread();
  142. Builder.CreateRetVoid();
  143. Builder.SetInsertPoint(&*LoopBody);
  144. return std::make_tuple(IV, SubFn);
  145. }
  146. Value *ParallelLoopGeneratorGOMP::createCallGetWorkItem(Value *LBPtr,
  147. Value *UBPtr) {
  148. const std::string Name = "GOMP_loop_runtime_next";
  149. Function *F = M->getFunction(Name);
  150. // If F is not available, declare it.
  151. if (!F) {
  152. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  153. Type *Params[] = {LongType->getPointerTo(), LongType->getPointerTo()};
  154. FunctionType *Ty = FunctionType::get(Builder.getInt8Ty(), Params, false);
  155. F = Function::Create(Ty, Linkage, Name, M);
  156. }
  157. Value *Args[] = {LBPtr, UBPtr};
  158. CallInst *Call = Builder.CreateCall(F, Args);
  159. Call->setDebugLoc(DLGenerated);
  160. Value *Return = Builder.CreateICmpNE(
  161. Call, Builder.CreateZExt(Builder.getFalse(), Call->getType()));
  162. return Return;
  163. }
  164. void ParallelLoopGeneratorGOMP::createCallJoinThreads() {
  165. const std::string Name = "GOMP_parallel_end";
  166. Function *F = M->getFunction(Name);
  167. // If F is not available, declare it.
  168. if (!F) {
  169. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  170. FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
  171. F = Function::Create(Ty, Linkage, Name, M);
  172. }
  173. CallInst *Call = Builder.CreateCall(F, {});
  174. Call->setDebugLoc(DLGenerated);
  175. }
  176. void ParallelLoopGeneratorGOMP::createCallCleanupThread() {
  177. const std::string Name = "GOMP_loop_end_nowait";
  178. Function *F = M->getFunction(Name);
  179. // If F is not available, declare it.
  180. if (!F) {
  181. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  182. FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
  183. F = Function::Create(Ty, Linkage, Name, M);
  184. }
  185. CallInst *Call = Builder.CreateCall(F, {});
  186. Call->setDebugLoc(DLGenerated);
  187. }