Coverage Report

Created: 2019-07-24 05:18

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