LoopGeneratorsKMP.cpp 21 KB

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