LoopGeneratorsKMP.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. //===------ LoopGeneratorsKMP.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/LoopGeneratorsKMP.h"
  13. #include "llvm/IR/Dominators.h"
  14. #include "llvm/IR/Module.h"
  15. using namespace llvm;
  16. using namespace polly;
  17. void ParallelLoopGeneratorKMP::createCallSpawnThreads(Value *SubFn,
  18. Value *SubFnParam,
  19. Value *LB, Value *UB,
  20. Value *Stride) {
  21. const std::string Name = "__kmpc_fork_call";
  22. Function *F = M->getFunction(Name);
  23. Type *KMPCMicroTy = StructType::getTypeByName(M->getContext(), "kmpc_micro");
  24. if (!KMPCMicroTy) {
  25. // void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid, ...)
  26. Type *MicroParams[] = {Builder.getInt32Ty()->getPointerTo(),
  27. Builder.getInt32Ty()->getPointerTo()};
  28. KMPCMicroTy = FunctionType::get(Builder.getVoidTy(), MicroParams, true);
  29. }
  30. // If F is not available, declare it.
  31. if (!F) {
  32. StructType *IdentTy =
  33. StructType::getTypeByName(M->getContext(), "struct.ident_t");
  34. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  35. Type *Params[] = {IdentTy->getPointerTo(), Builder.getInt32Ty(),
  36. KMPCMicroTy->getPointerTo()};
  37. FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, true);
  38. F = Function::Create(Ty, Linkage, Name, M);
  39. }
  40. Value *Task = Builder.CreatePointerBitCastOrAddrSpaceCast(
  41. SubFn, KMPCMicroTy->getPointerTo());
  42. Value *Args[] = {SourceLocationInfo,
  43. Builder.getInt32(4) /* Number of arguments (w/o Task) */,
  44. Task,
  45. LB,
  46. UB,
  47. Stride,
  48. SubFnParam};
  49. CallInst *Call = Builder.CreateCall(F, Args);
  50. Call->setDebugLoc(DLGenerated);
  51. }
  52. void ParallelLoopGeneratorKMP::deployParallelExecution(Function *SubFn,
  53. Value *SubFnParam,
  54. Value *LB, Value *UB,
  55. Value *Stride) {
  56. // Inform OpenMP runtime about the number of threads if greater than zero
  57. if (PollyNumThreads > 0) {
  58. Value *GlobalThreadID = createCallGlobalThreadNum();
  59. createCallPushNumThreads(GlobalThreadID, Builder.getInt32(PollyNumThreads));
  60. }
  61. // Tell the runtime we start a parallel loop
  62. createCallSpawnThreads(SubFn, SubFnParam, LB, UB, Stride);
  63. }
  64. Function *ParallelLoopGeneratorKMP::prepareSubFnDefinition(Function *F) const {
  65. std::vector<Type *> Arguments = {Builder.getInt32Ty()->getPointerTo(),
  66. Builder.getInt32Ty()->getPointerTo(),
  67. LongType,
  68. LongType,
  69. LongType,
  70. Builder.getInt8PtrTy()};
  71. FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false);
  72. Function *SubFn = Function::Create(FT, Function::InternalLinkage,
  73. F->getName() + "_polly_subfn", M);
  74. // Name the function's arguments
  75. Function::arg_iterator AI = SubFn->arg_begin();
  76. AI->setName("polly.kmpc.global_tid");
  77. std::advance(AI, 1);
  78. AI->setName("polly.kmpc.bound_tid");
  79. std::advance(AI, 1);
  80. AI->setName("polly.kmpc.lb");
  81. std::advance(AI, 1);
  82. AI->setName("polly.kmpc.ub");
  83. std::advance(AI, 1);
  84. AI->setName("polly.kmpc.inc");
  85. std::advance(AI, 1);
  86. AI->setName("polly.kmpc.shared");
  87. return SubFn;
  88. }
  89. // Create a subfunction of the following (preliminary) structure:
  90. //
  91. // PrevBB
  92. // |
  93. // v
  94. // HeaderBB
  95. // / | _____
  96. // / v v |
  97. // / PreHeaderBB |
  98. // | | |
  99. // | v |
  100. // | CheckNextBB |
  101. // \ | \_____/
  102. // \ |
  103. // v v
  104. // ExitBB
  105. //
  106. // HeaderBB will hold allocations, loading of variables and kmp-init calls.
  107. // CheckNextBB will check for more work (dynamic / static chunked) or will be
  108. // empty (static non chunked).
  109. // If there is more work to do: go to PreHeaderBB, otherwise go to ExitBB.
  110. // PreHeaderBB loads the new boundaries (& will lead to the loop body later on).
  111. // Just like CheckNextBB: PreHeaderBB is (preliminary) empty in the static non
  112. // chunked scheduling case. ExitBB marks the end of the parallel execution.
  113. // The possibly empty BasicBlocks will automatically be removed.
  114. std::tuple<Value *, Function *>
  115. ParallelLoopGeneratorKMP::createSubFn(Value *SequentialLoopStride,
  116. AllocaInst *StructData,
  117. SetVector<Value *> Data, ValueMapT &Map) {
  118. Function *SubFn = createSubFnDefinition();
  119. LLVMContext &Context = SubFn->getContext();
  120. // Store the previous basic block.
  121. BasicBlock *PrevBB = Builder.GetInsertBlock();
  122. // Create basic blocks.
  123. BasicBlock *HeaderBB = BasicBlock::Create(Context, "polly.par.setup", SubFn);
  124. BasicBlock *ExitBB = BasicBlock::Create(Context, "polly.par.exit", SubFn);
  125. BasicBlock *CheckNextBB =
  126. BasicBlock::Create(Context, "polly.par.checkNext", SubFn);
  127. BasicBlock *PreHeaderBB =
  128. BasicBlock::Create(Context, "polly.par.loadIVBounds", SubFn);
  129. DT.addNewBlock(HeaderBB, PrevBB);
  130. DT.addNewBlock(ExitBB, HeaderBB);
  131. DT.addNewBlock(CheckNextBB, HeaderBB);
  132. DT.addNewBlock(PreHeaderBB, HeaderBB);
  133. // Fill up basic block HeaderBB.
  134. Builder.SetInsertPoint(HeaderBB);
  135. Value *LBPtr = Builder.CreateAlloca(LongType, nullptr, "polly.par.LBPtr");
  136. Value *UBPtr = Builder.CreateAlloca(LongType, nullptr, "polly.par.UBPtr");
  137. Value *IsLastPtr = Builder.CreateAlloca(Builder.getInt32Ty(), nullptr,
  138. "polly.par.lastIterPtr");
  139. Value *StridePtr =
  140. Builder.CreateAlloca(LongType, nullptr, "polly.par.StridePtr");
  141. // Get iterator for retrieving the previously defined parameters.
  142. Function::arg_iterator AI = SubFn->arg_begin();
  143. // First argument holds "global thread ID".
  144. Value *IDPtr = &*AI;
  145. // Skip "bound thread ID" since it is not used (but had to be defined).
  146. std::advance(AI, 2);
  147. // Move iterator to: LB, UB, Stride, Shared variable struct.
  148. Value *LB = &*AI;
  149. std::advance(AI, 1);
  150. Value *UB = &*AI;
  151. std::advance(AI, 1);
  152. Value *Stride = &*AI;
  153. std::advance(AI, 1);
  154. Value *Shared = &*AI;
  155. Value *UserContext = Builder.CreateBitCast(Shared, StructData->getType(),
  156. "polly.par.userContext");
  157. extractValuesFromStruct(Data, StructData->getAllocatedType(), UserContext,
  158. Map);
  159. const auto Alignment = llvm::Align(is64BitArch() ? 8 : 4);
  160. Value *ID = Builder.CreateAlignedLoad(Builder.getInt32Ty(), IDPtr, Alignment,
  161. "polly.par.global_tid");
  162. Builder.CreateAlignedStore(LB, LBPtr, Alignment);
  163. Builder.CreateAlignedStore(UB, UBPtr, Alignment);
  164. Builder.CreateAlignedStore(Builder.getInt32(0), IsLastPtr, Alignment);
  165. Builder.CreateAlignedStore(Stride, StridePtr, Alignment);
  166. // Subtract one as the upper bound provided by openmp is a < comparison
  167. // whereas the codegenForSequential function creates a <= comparison.
  168. Value *AdjustedUB = Builder.CreateAdd(UB, ConstantInt::get(LongType, -1),
  169. "polly.indvar.UBAdjusted");
  170. Value *ChunkSize =
  171. ConstantInt::get(LongType, std::max<int>(PollyChunkSize, 1));
  172. OMPGeneralSchedulingType Scheduling =
  173. getSchedType(PollyChunkSize, PollyScheduling);
  174. switch (Scheduling) {
  175. case OMPGeneralSchedulingType::Dynamic:
  176. case OMPGeneralSchedulingType::Guided:
  177. case OMPGeneralSchedulingType::Runtime:
  178. // "DYNAMIC" scheduling types are handled below (including 'runtime')
  179. {
  180. UB = AdjustedUB;
  181. createCallDispatchInit(ID, LB, UB, Stride, ChunkSize);
  182. Value *HasWork =
  183. createCallDispatchNext(ID, IsLastPtr, LBPtr, UBPtr, StridePtr);
  184. Value *HasIteration =
  185. Builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_EQ, HasWork,
  186. Builder.getInt32(1), "polly.hasIteration");
  187. Builder.CreateCondBr(HasIteration, PreHeaderBB, ExitBB);
  188. Builder.SetInsertPoint(CheckNextBB);
  189. HasWork = createCallDispatchNext(ID, IsLastPtr, LBPtr, UBPtr, StridePtr);
  190. HasIteration =
  191. Builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_EQ, HasWork,
  192. Builder.getInt32(1), "polly.hasWork");
  193. Builder.CreateCondBr(HasIteration, PreHeaderBB, ExitBB);
  194. Builder.SetInsertPoint(PreHeaderBB);
  195. LB = Builder.CreateAlignedLoad(LongType, LBPtr, Alignment,
  196. "polly.indvar.LB");
  197. UB = Builder.CreateAlignedLoad(LongType, UBPtr, Alignment,
  198. "polly.indvar.UB");
  199. }
  200. break;
  201. case OMPGeneralSchedulingType::StaticChunked:
  202. case OMPGeneralSchedulingType::StaticNonChunked:
  203. // "STATIC" scheduling types are handled below
  204. {
  205. Builder.CreateAlignedStore(AdjustedUB, UBPtr, Alignment);
  206. createCallStaticInit(ID, IsLastPtr, LBPtr, UBPtr, StridePtr, ChunkSize);
  207. Value *ChunkedStride = Builder.CreateAlignedLoad(
  208. LongType, StridePtr, Alignment, "polly.kmpc.stride");
  209. LB = Builder.CreateAlignedLoad(LongType, LBPtr, Alignment,
  210. "polly.indvar.LB");
  211. UB = Builder.CreateAlignedLoad(LongType, UBPtr, Alignment,
  212. "polly.indvar.UB.temp");
  213. Value *UBInRange =
  214. Builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_SLE, UB, AdjustedUB,
  215. "polly.indvar.UB.inRange");
  216. UB = Builder.CreateSelect(UBInRange, UB, AdjustedUB, "polly.indvar.UB");
  217. Builder.CreateAlignedStore(UB, UBPtr, Alignment);
  218. Value *HasIteration = Builder.CreateICmp(
  219. llvm::CmpInst::Predicate::ICMP_SLE, LB, UB, "polly.hasIteration");
  220. Builder.CreateCondBr(HasIteration, PreHeaderBB, ExitBB);
  221. if (Scheduling == OMPGeneralSchedulingType::StaticChunked) {
  222. Builder.SetInsertPoint(PreHeaderBB);
  223. LB = Builder.CreateAlignedLoad(LongType, LBPtr, Alignment,
  224. "polly.indvar.LB.entry");
  225. UB = Builder.CreateAlignedLoad(LongType, UBPtr, Alignment,
  226. "polly.indvar.UB.entry");
  227. }
  228. Builder.SetInsertPoint(CheckNextBB);
  229. if (Scheduling == OMPGeneralSchedulingType::StaticChunked) {
  230. Value *NextLB =
  231. Builder.CreateAdd(LB, ChunkedStride, "polly.indvar.nextLB");
  232. Value *NextUB = Builder.CreateAdd(UB, ChunkedStride);
  233. Value *NextUBOutOfBounds =
  234. Builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_SGT, NextUB,
  235. AdjustedUB, "polly.indvar.nextUB.outOfBounds");
  236. NextUB = Builder.CreateSelect(NextUBOutOfBounds, AdjustedUB, NextUB,
  237. "polly.indvar.nextUB");
  238. Builder.CreateAlignedStore(NextLB, LBPtr, Alignment);
  239. Builder.CreateAlignedStore(NextUB, UBPtr, Alignment);
  240. Value *HasWork =
  241. Builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_SLE, NextLB,
  242. AdjustedUB, "polly.hasWork");
  243. Builder.CreateCondBr(HasWork, PreHeaderBB, ExitBB);
  244. } else {
  245. Builder.CreateBr(ExitBB);
  246. }
  247. Builder.SetInsertPoint(PreHeaderBB);
  248. }
  249. break;
  250. }
  251. Builder.CreateBr(CheckNextBB);
  252. Builder.SetInsertPoint(&*--Builder.GetInsertPoint());
  253. BasicBlock *AfterBB;
  254. Value *IV = createLoop(LB, UB, SequentialLoopStride, Builder, LI, DT, AfterBB,
  255. ICmpInst::ICMP_SLE, nullptr, true,
  256. /* UseGuard */ false);
  257. BasicBlock::iterator LoopBody = Builder.GetInsertPoint();
  258. // Add code to terminate this subfunction.
  259. Builder.SetInsertPoint(ExitBB);
  260. // Static (i.e. non-dynamic) scheduling types, are terminated with a fini-call
  261. if (Scheduling == OMPGeneralSchedulingType::StaticChunked ||
  262. Scheduling == OMPGeneralSchedulingType::StaticNonChunked) {
  263. createCallStaticFini(ID);
  264. }
  265. Builder.CreateRetVoid();
  266. Builder.SetInsertPoint(&*LoopBody);
  267. return std::make_tuple(IV, SubFn);
  268. }
  269. Value *ParallelLoopGeneratorKMP::createCallGlobalThreadNum() {
  270. const std::string Name = "__kmpc_global_thread_num";
  271. Function *F = M->getFunction(Name);
  272. // If F is not available, declare it.
  273. if (!F) {
  274. StructType *IdentTy =
  275. StructType::getTypeByName(M->getContext(), "struct.ident_t");
  276. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  277. Type *Params[] = {IdentTy->getPointerTo()};
  278. FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(), Params, false);
  279. F = Function::Create(Ty, Linkage, Name, M);
  280. }
  281. CallInst *Call = Builder.CreateCall(F, {SourceLocationInfo});
  282. Call->setDebugLoc(DLGenerated);
  283. return Call;
  284. }
  285. void ParallelLoopGeneratorKMP::createCallPushNumThreads(Value *GlobalThreadID,
  286. Value *NumThreads) {
  287. const std::string Name = "__kmpc_push_num_threads";
  288. Function *F = M->getFunction(Name);
  289. // If F is not available, declare it.
  290. if (!F) {
  291. StructType *IdentTy =
  292. StructType::getTypeByName(M->getContext(), "struct.ident_t");
  293. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  294. Type *Params[] = {IdentTy->getPointerTo(), Builder.getInt32Ty(),
  295. Builder.getInt32Ty()};
  296. FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
  297. F = Function::Create(Ty, Linkage, Name, M);
  298. }
  299. Value *Args[] = {SourceLocationInfo, GlobalThreadID, NumThreads};
  300. CallInst *Call = Builder.CreateCall(F, Args);
  301. Call->setDebugLoc(DLGenerated);
  302. }
  303. void ParallelLoopGeneratorKMP::createCallStaticInit(Value *GlobalThreadID,
  304. Value *IsLastPtr,
  305. Value *LBPtr, Value *UBPtr,
  306. Value *StridePtr,
  307. Value *ChunkSize) {
  308. const std::string Name =
  309. is64BitArch() ? "__kmpc_for_static_init_8" : "__kmpc_for_static_init_4";
  310. Function *F = M->getFunction(Name);
  311. StructType *IdentTy =
  312. StructType::getTypeByName(M->getContext(), "struct.ident_t");
  313. // If F is not available, declare it.
  314. if (!F) {
  315. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  316. Type *Params[] = {IdentTy->getPointerTo(),
  317. Builder.getInt32Ty(),
  318. Builder.getInt32Ty(),
  319. Builder.getInt32Ty()->getPointerTo(),
  320. LongType->getPointerTo(),
  321. LongType->getPointerTo(),
  322. LongType->getPointerTo(),
  323. LongType,
  324. LongType};
  325. FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
  326. F = Function::Create(Ty, Linkage, Name, M);
  327. }
  328. // The parameter 'ChunkSize' will hold strictly positive integer values,
  329. // regardless of PollyChunkSize's value
  330. Value *Args[] = {
  331. SourceLocationInfo,
  332. GlobalThreadID,
  333. Builder.getInt32(int(getSchedType(PollyChunkSize, PollyScheduling))),
  334. IsLastPtr,
  335. LBPtr,
  336. UBPtr,
  337. StridePtr,
  338. ConstantInt::get(LongType, 1),
  339. ChunkSize};
  340. CallInst *Call = Builder.CreateCall(F, Args);
  341. Call->setDebugLoc(DLGenerated);
  342. }
  343. void ParallelLoopGeneratorKMP::createCallStaticFini(Value *GlobalThreadID) {
  344. const std::string Name = "__kmpc_for_static_fini";
  345. Function *F = M->getFunction(Name);
  346. StructType *IdentTy =
  347. StructType::getTypeByName(M->getContext(), "struct.ident_t");
  348. // If F is not available, declare it.
  349. if (!F) {
  350. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  351. Type *Params[] = {IdentTy->getPointerTo(), Builder.getInt32Ty()};
  352. FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
  353. F = Function::Create(Ty, Linkage, Name, M);
  354. }
  355. Value *Args[] = {SourceLocationInfo, GlobalThreadID};
  356. CallInst *Call = Builder.CreateCall(F, Args);
  357. Call->setDebugLoc(DLGenerated);
  358. }
  359. void ParallelLoopGeneratorKMP::createCallDispatchInit(Value *GlobalThreadID,
  360. Value *LB, Value *UB,
  361. Value *Inc,
  362. Value *ChunkSize) {
  363. const std::string Name =
  364. is64BitArch() ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_4";
  365. Function *F = M->getFunction(Name);
  366. StructType *IdentTy =
  367. StructType::getTypeByName(M->getContext(), "struct.ident_t");
  368. // If F is not available, declare it.
  369. if (!F) {
  370. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  371. Type *Params[] = {IdentTy->getPointerTo(),
  372. Builder.getInt32Ty(),
  373. Builder.getInt32Ty(),
  374. LongType,
  375. LongType,
  376. LongType,
  377. LongType};
  378. FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
  379. F = Function::Create(Ty, Linkage, Name, M);
  380. }
  381. // The parameter 'ChunkSize' will hold strictly positive integer values,
  382. // regardless of PollyChunkSize's value
  383. Value *Args[] = {
  384. SourceLocationInfo,
  385. GlobalThreadID,
  386. Builder.getInt32(int(getSchedType(PollyChunkSize, PollyScheduling))),
  387. LB,
  388. UB,
  389. Inc,
  390. ChunkSize};
  391. CallInst *Call = Builder.CreateCall(F, Args);
  392. Call->setDebugLoc(DLGenerated);
  393. }
  394. Value *ParallelLoopGeneratorKMP::createCallDispatchNext(Value *GlobalThreadID,
  395. Value *IsLastPtr,
  396. Value *LBPtr,
  397. Value *UBPtr,
  398. Value *StridePtr) {
  399. const std::string Name =
  400. is64BitArch() ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_4";
  401. Function *F = M->getFunction(Name);
  402. StructType *IdentTy =
  403. StructType::getTypeByName(M->getContext(), "struct.ident_t");
  404. // If F is not available, declare it.
  405. if (!F) {
  406. GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
  407. Type *Params[] = {IdentTy->getPointerTo(),
  408. Builder.getInt32Ty(),
  409. Builder.getInt32Ty()->getPointerTo(),
  410. LongType->getPointerTo(),
  411. LongType->getPointerTo(),
  412. LongType->getPointerTo()};
  413. FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(), Params, false);
  414. F = Function::Create(Ty, Linkage, Name, M);
  415. }
  416. Value *Args[] = {SourceLocationInfo, GlobalThreadID, IsLastPtr, LBPtr, UBPtr,
  417. StridePtr};
  418. CallInst *Call = Builder.CreateCall(F, Args);
  419. Call->setDebugLoc(DLGenerated);
  420. return Call;
  421. }
  422. // TODO: This function currently creates a source location dummy. It might be
  423. // necessary to (actually) provide information, in the future.
  424. GlobalVariable *ParallelLoopGeneratorKMP::createSourceLocation() {
  425. const std::string LocName = ".loc.dummy";
  426. GlobalVariable *SourceLocDummy = M->getGlobalVariable(LocName);
  427. if (SourceLocDummy == nullptr) {
  428. const std::string StructName = "struct.ident_t";
  429. StructType *IdentTy =
  430. StructType::getTypeByName(M->getContext(), StructName);
  431. // If the ident_t StructType is not available, declare it.
  432. // in LLVM-IR: ident_t = type { i32, i32, i32, i32, i8* }
  433. if (!IdentTy) {
  434. Type *LocMembers[] = {Builder.getInt32Ty(), Builder.getInt32Ty(),
  435. Builder.getInt32Ty(), Builder.getInt32Ty(),
  436. Builder.getInt8PtrTy()};
  437. IdentTy =
  438. StructType::create(M->getContext(), LocMembers, StructName, false);
  439. }
  440. const auto ArrayType =
  441. llvm::ArrayType::get(Builder.getInt8Ty(), /* Length */ 23);
  442. // Global Variable Definitions
  443. GlobalVariable *StrVar =
  444. new GlobalVariable(*M, ArrayType, true, GlobalValue::PrivateLinkage,
  445. nullptr, ".str.ident");
  446. StrVar->setAlignment(llvm::Align(1));
  447. SourceLocDummy = new GlobalVariable(
  448. *M, IdentTy, true, GlobalValue::PrivateLinkage, nullptr, LocName);
  449. SourceLocDummy->setAlignment(llvm::Align(8));
  450. // Constant Definitions
  451. Constant *InitStr = ConstantDataArray::getString(
  452. M->getContext(), "Source location dummy.", true);
  453. Constant *StrPtr = static_cast<Constant *>(Builder.CreateInBoundsGEP(
  454. ArrayType, StrVar, {Builder.getInt32(0), Builder.getInt32(0)}));
  455. Constant *LocInitStruct = ConstantStruct::get(
  456. IdentTy, {Builder.getInt32(0), Builder.getInt32(0), Builder.getInt32(0),
  457. Builder.getInt32(0), StrPtr});
  458. // Initialize variables
  459. StrVar->setInitializer(InitStr);
  460. SourceLocDummy->setInitializer(LocInitStruct);
  461. }
  462. return SourceLocDummy;
  463. }
  464. bool ParallelLoopGeneratorKMP::is64BitArch() {
  465. return (LongType->getIntegerBitWidth() == 64);
  466. }
  467. OMPGeneralSchedulingType ParallelLoopGeneratorKMP::getSchedType(
  468. int ChunkSize, OMPGeneralSchedulingType Scheduling) const {
  469. if (ChunkSize == 0 && Scheduling == OMPGeneralSchedulingType::StaticChunked)
  470. return OMPGeneralSchedulingType::StaticNonChunked;
  471. return Scheduling;
  472. }