LoopGeneratorsGOMP.cpp 8.0 KB

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