Polly 23.0.0git
LoopGeneratorsKMP.cpp
Go to the documentation of this file.
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
14#include "llvm/Analysis/LoopInfo.h"
15#include "llvm/IR/Dominators.h"
16#include "llvm/IR/Module.h"
17
18using namespace llvm;
19using namespace polly;
20
22 Value *SubFnParam,
23 Value *LB, Value *UB,
24 Value *Stride) {
25 const std::string Name = "__kmpc_fork_call";
26 Function *F = M->getFunction(Name);
27 Type *KMPCMicroTy = StructType::getTypeByName(M->getContext(), "kmpc_micro");
28
29 if (!KMPCMicroTy) {
30 // void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid, ...)
31 Type *MicroParams[] = {Builder.getPtrTy(0), Builder.getPtrTy(0)};
32
33 KMPCMicroTy = FunctionType::get(Builder.getVoidTy(), MicroParams, true);
34 }
35
36 // If F is not available, declare it.
37 if (!F) {
38 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
39 Type *Params[] = {Builder.getPtrTy(0), Builder.getInt32Ty(),
40 Builder.getPtrTy(0)};
41
42 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, true);
43 F = Function::Create(Ty, Linkage, Name, M);
44 }
45
46 Value *Task =
47 Builder.CreatePointerBitCastOrAddrSpaceCast(SubFn, Builder.getPtrTy(0));
48
49 Value *Args[] = {SourceLocationInfo,
50 Builder.getInt32(4) /* Number of arguments (w/o Task) */,
51 Task,
52 LB,
53 UB,
54 Stride,
55 SubFnParam};
56
57 CallInst *Call = Builder.CreateCall(F, Args);
58 Call->setDebugLoc(DLGenerated);
59}
60
62 Value *SubFnParam,
63 Value *LB, Value *UB,
64 Value *Stride) {
65 // Inform OpenMP runtime about the number of threads if greater than zero
66 if (PollyNumThreads > 0) {
67 Value *GlobalThreadID = createCallGlobalThreadNum();
68 createCallPushNumThreads(GlobalThreadID, Builder.getInt32(PollyNumThreads));
69 }
70
71 // Tell the runtime we start a parallel loop
72 createCallSpawnThreads(SubFn, SubFnParam, LB, UB, Stride);
73}
74
76 std::vector<Type *> Arguments = {
77 Builder.getPtrTy(0), Builder.getPtrTy(0), LongType, LongType, LongType,
78 Builder.getPtrTy()};
79
80 FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false);
81 Function *SubFn = Function::Create(FT, Function::InternalLinkage,
82 F->getName() + "_polly_subfn", M);
83 // Name the function's arguments
84 Function::arg_iterator AI = SubFn->arg_begin();
85 AI->setName("polly.kmpc.global_tid");
86 std::advance(AI, 1);
87 AI->setName("polly.kmpc.bound_tid");
88 std::advance(AI, 1);
89 AI->setName("polly.kmpc.lb");
90 std::advance(AI, 1);
91 AI->setName("polly.kmpc.ub");
92 std::advance(AI, 1);
93 AI->setName("polly.kmpc.inc");
94 std::advance(AI, 1);
95 AI->setName("polly.kmpc.shared");
96
97 return SubFn;
98}
99
100// Create a subfunction of the following (preliminary) structure:
101//
102// PrevBB
103// |
104// v
105// HeaderBB
106// / | _____
107// / v v |
108// / PreHeaderBB |
109// | | |
110// | v |
111// | CheckNextBB |
112// \ | \_____/
113// \ |
114// v v
115// ExitBB
116//
117// HeaderBB will hold allocations, loading of variables and kmp-init calls.
118// CheckNextBB will check for more work (dynamic / static chunked) or will be
119// empty (static non chunked).
120// If there is more work to do: go to PreHeaderBB, otherwise go to ExitBB.
121// PreHeaderBB loads the new boundaries (& will lead to the loop body later on).
122// Just like CheckNextBB: PreHeaderBB is (preliminary) empty in the static non
123// chunked scheduling case. ExitBB marks the end of the parallel execution.
124// The possibly empty BasicBlocks will automatically be removed.
125std::tuple<Value *, Function *>
127 AllocaInst *StructData,
128 SetVector<Value *> Data, ValueMapT &Map) {
129 Function *SubFn = createSubFnDefinition();
130 LLVMContext &Context = SubFn->getContext();
131
132 // Create basic blocks.
133 BasicBlock *HeaderBB = BasicBlock::Create(Context, "polly.par.setup", SubFn);
134 // Add terminator so that DT computation doesn't fail.
135 auto *UI = new UnreachableInst(Context, HeaderBB);
136 SubFnDT = std::make_unique<DominatorTree>(*SubFn);
137 SubFnLI = std::make_unique<LoopInfo>(*SubFnDT);
138 UI->eraseFromParent();
139
140 BasicBlock *ExitBB = BasicBlock::Create(Context, "polly.par.exit", SubFn);
141 BasicBlock *CheckNextBB =
142 BasicBlock::Create(Context, "polly.par.checkNext", SubFn);
143 BasicBlock *PreHeaderBB =
144 BasicBlock::Create(Context, "polly.par.loadIVBounds", SubFn);
145
146 SubFnDT->addNewBlock(ExitBB, HeaderBB);
147 SubFnDT->addNewBlock(CheckNextBB, HeaderBB);
148 SubFnDT->addNewBlock(PreHeaderBB, HeaderBB);
149
150 // Fill up basic block HeaderBB.
151 Builder.SetInsertPoint(HeaderBB);
152 Value *LBPtr = Builder.CreateAlloca(LongType, nullptr, "polly.par.LBPtr");
153 Value *UBPtr = Builder.CreateAlloca(LongType, nullptr, "polly.par.UBPtr");
154 Value *IsLastPtr = Builder.CreateAlloca(Builder.getInt32Ty(), nullptr,
155 "polly.par.lastIterPtr");
156 Value *StridePtr =
157 Builder.CreateAlloca(LongType, nullptr, "polly.par.StridePtr");
158
159 // Get iterator for retrieving the previously defined parameters.
160 Function::arg_iterator AI = SubFn->arg_begin();
161 // First argument holds "global thread ID".
162 Value *IDPtr = &*AI;
163 // Skip "bound thread ID" since it is not used (but had to be defined).
164 std::advance(AI, 2);
165 // Move iterator to: LB, UB, Stride, Shared variable struct.
166 Value *LB = &*AI;
167 std::advance(AI, 1);
168 Value *UB = &*AI;
169 std::advance(AI, 1);
170 Value *Stride = &*AI;
171 std::advance(AI, 1);
172 Value *Shared = &*AI;
173
174 extractValuesFromStruct(Data, StructData->getAllocatedType(), Shared, Map);
175
176 const auto Alignment = llvm::Align(is64BitArch() ? 8 : 4);
177 Value *ID = Builder.CreateAlignedLoad(Builder.getInt32Ty(), IDPtr, Alignment,
178 "polly.par.global_tid");
179
180 Builder.CreateAlignedStore(LB, LBPtr, Alignment);
181 Builder.CreateAlignedStore(UB, UBPtr, Alignment);
182 Builder.CreateAlignedStore(Builder.getInt32(0), IsLastPtr, Alignment);
183 Builder.CreateAlignedStore(Stride, StridePtr, Alignment);
184
185 // Subtract one as the upper bound provided by openmp is a < comparison
186 // whereas the codegenForSequential function creates a <= comparison.
187 Value *AdjustedUB = Builder.CreateAdd(UB, ConstantInt::get(LongType, -1),
188 "polly.indvar.UBAdjusted");
189
190 Value *ChunkSize =
191 ConstantInt::get(LongType, std::max<int>(PollyChunkSize, 1));
192
193 OMPGeneralSchedulingType Scheduling =
195
196 switch (Scheduling) {
200 // "DYNAMIC" scheduling types are handled below (including 'runtime')
201 {
202 UB = AdjustedUB;
203 createCallDispatchInit(ID, LB, UB, Stride, ChunkSize);
204 Value *HasWork =
205 createCallDispatchNext(ID, IsLastPtr, LBPtr, UBPtr, StridePtr);
206 Value *HasIteration =
207 Builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_EQ, HasWork,
208 Builder.getInt32(1), "polly.hasIteration");
209 Builder.CreateCondBr(HasIteration, PreHeaderBB, ExitBB);
210
211 Builder.SetInsertPoint(CheckNextBB);
212 HasWork = createCallDispatchNext(ID, IsLastPtr, LBPtr, UBPtr, StridePtr);
213 HasIteration =
214 Builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_EQ, HasWork,
215 Builder.getInt32(1), "polly.hasWork");
216 Builder.CreateCondBr(HasIteration, PreHeaderBB, ExitBB);
217
218 Builder.SetInsertPoint(PreHeaderBB);
219 LB = Builder.CreateAlignedLoad(LongType, LBPtr, Alignment,
220 "polly.indvar.LB");
221 UB = Builder.CreateAlignedLoad(LongType, UBPtr, Alignment,
222 "polly.indvar.UB");
223 }
224 break;
227 // "STATIC" scheduling types are handled below
228 {
229 Builder.CreateAlignedStore(AdjustedUB, UBPtr, Alignment);
230 createCallStaticInit(ID, IsLastPtr, LBPtr, UBPtr, StridePtr, ChunkSize);
231
232 Value *ChunkedStride = Builder.CreateAlignedLoad(
233 LongType, StridePtr, Alignment, "polly.kmpc.stride");
234
235 LB = Builder.CreateAlignedLoad(LongType, LBPtr, Alignment,
236 "polly.indvar.LB");
237 UB = Builder.CreateAlignedLoad(LongType, UBPtr, Alignment,
238 "polly.indvar.UB.temp");
239
240 Value *UBInRange =
241 Builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_SLE, UB, AdjustedUB,
242 "polly.indvar.UB.inRange");
243 UB = Builder.CreateSelect(UBInRange, UB, AdjustedUB, "polly.indvar.UB");
244 Builder.CreateAlignedStore(UB, UBPtr, Alignment);
245
246 Value *HasIteration = Builder.CreateICmp(
247 llvm::CmpInst::Predicate::ICMP_SLE, LB, UB, "polly.hasIteration");
248 Builder.CreateCondBr(HasIteration, PreHeaderBB, ExitBB);
249
250 if (Scheduling == OMPGeneralSchedulingType::StaticChunked) {
251 Builder.SetInsertPoint(PreHeaderBB);
252 LB = Builder.CreateAlignedLoad(LongType, LBPtr, Alignment,
253 "polly.indvar.LB.entry");
254 UB = Builder.CreateAlignedLoad(LongType, UBPtr, Alignment,
255 "polly.indvar.UB.entry");
256 }
257
258 Builder.SetInsertPoint(CheckNextBB);
259
260 if (Scheduling == OMPGeneralSchedulingType::StaticChunked) {
261 Value *NextLB =
262 Builder.CreateAdd(LB, ChunkedStride, "polly.indvar.nextLB");
263 Value *NextUB = Builder.CreateAdd(UB, ChunkedStride);
264
265 Value *NextUBOutOfBounds =
266 Builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_SGT, NextUB,
267 AdjustedUB, "polly.indvar.nextUB.outOfBounds");
268 NextUB = Builder.CreateSelect(NextUBOutOfBounds, AdjustedUB, NextUB,
269 "polly.indvar.nextUB");
270
271 Builder.CreateAlignedStore(NextLB, LBPtr, Alignment);
272 Builder.CreateAlignedStore(NextUB, UBPtr, Alignment);
273
274 Value *HasWork =
275 Builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_SLE, NextLB,
276 AdjustedUB, "polly.hasWork");
277 Builder.CreateCondBr(HasWork, PreHeaderBB, ExitBB);
278 } else {
279 Builder.CreateBr(ExitBB);
280 }
281
282 Builder.SetInsertPoint(PreHeaderBB);
283 }
284 break;
285 }
286
287 Builder.CreateBr(CheckNextBB);
288 Builder.SetInsertPoint(std::prev(Builder.GetInsertPoint()));
289 BasicBlock *AfterBB;
290 Value *IV = createLoop(LB, UB, SequentialLoopStride, Builder, *SubFnLI,
291 *SubFnDT, AfterBB, ICmpInst::ICMP_SLE, nullptr, true,
292 /* UseGuard */ false);
293
294 BasicBlock::iterator LoopBody = Builder.GetInsertPoint();
295
296 // Add code to terminate this subfunction.
297 Builder.SetInsertPoint(ExitBB);
298 // Static (i.e. non-dynamic) scheduling types, are terminated with a fini-call
299 if (Scheduling == OMPGeneralSchedulingType::StaticChunked ||
302 }
303 Builder.CreateRetVoid();
304 Builder.SetInsertPoint(LoopBody);
305
306 // FIXME: Call SubFnDT->verify() and SubFnLI->verify() to check that the
307 // DominatorTree/LoopInfo has been created correctly. Alternatively, recreate
308 // from scratch since it is not needed here directly.
309
310 return std::make_tuple(IV, SubFn);
311}
312
314 const std::string Name = "__kmpc_global_thread_num";
315 Function *F = M->getFunction(Name);
316
317 // If F is not available, declare it.
318 if (!F) {
319 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
320 Type *Params[] = {Builder.getPtrTy(0)};
321
322 FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(), Params, false);
323 F = Function::Create(Ty, Linkage, Name, M);
324 }
325
326 CallInst *Call = Builder.CreateCall(F, {SourceLocationInfo});
327 Call->setDebugLoc(DLGenerated);
328 return Call;
329}
330
332 Value *NumThreads) {
333 const std::string Name = "__kmpc_push_num_threads";
334 Function *F = M->getFunction(Name);
335
336 // If F is not available, declare it.
337 if (!F) {
338 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
339 Type *Params[] = {Builder.getPtrTy(0), Builder.getInt32Ty(),
340 Builder.getInt32Ty()};
341
342 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
343 F = Function::Create(Ty, Linkage, Name, M);
344 }
345
346 Value *Args[] = {SourceLocationInfo, GlobalThreadID, NumThreads};
347
348 CallInst *Call = Builder.CreateCall(F, Args);
349 Call->setDebugLoc(DLGenerated);
350}
351
353 Value *IsLastPtr,
354 Value *LBPtr, Value *UBPtr,
355 Value *StridePtr,
356 Value *ChunkSize) {
357 const std::string Name =
358 is64BitArch() ? "__kmpc_for_static_init_8" : "__kmpc_for_static_init_4";
359 Function *F = M->getFunction(Name);
360
361 // If F is not available, declare it.
362 if (!F) {
363 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
364
365 Type *Params[] = {Builder.getPtrTy(0),
366 Builder.getInt32Ty(),
367 Builder.getInt32Ty(),
368 Builder.getPtrTy(0),
369 Builder.getPtrTy(0),
370 Builder.getPtrTy(0),
371 Builder.getPtrTy(0),
372 LongType,
373 LongType};
374
375 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
376 F = Function::Create(Ty, Linkage, Name, M);
377 }
378
379 // The parameter 'ChunkSize' will hold strictly positive integer values,
380 // regardless of PollyChunkSize's value
381 Value *Args[] = {
383 GlobalThreadID,
385 IsLastPtr,
386 LBPtr,
387 UBPtr,
388 StridePtr,
389 ConstantInt::get(LongType, 1),
390 ChunkSize};
391
392 CallInst *Call = Builder.CreateCall(F, Args);
393 Call->setDebugLoc(DLGenerated);
394}
395
397 const std::string Name = "__kmpc_for_static_fini";
398 Function *F = M->getFunction(Name);
399
400 // If F is not available, declare it.
401 if (!F) {
402 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
403 Type *Params[] = {Builder.getPtrTy(0), Builder.getInt32Ty()};
404 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
405 F = Function::Create(Ty, Linkage, Name, M);
406 }
407
408 Value *Args[] = {SourceLocationInfo, GlobalThreadID};
409
410 CallInst *Call = Builder.CreateCall(F, Args);
411 Call->setDebugLoc(DLGenerated);
412}
413
415 Value *LB, Value *UB,
416 Value *Inc,
417 Value *ChunkSize) {
418 const std::string Name =
419 is64BitArch() ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_4";
420 Function *F = M->getFunction(Name);
421
422 // If F is not available, declare it.
423 if (!F) {
424 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
425
426 Type *Params[] = {Builder.getPtrTy(0),
427 Builder.getInt32Ty(),
428 Builder.getInt32Ty(),
429 LongType,
430 LongType,
431 LongType,
432 LongType};
433
434 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
435 F = Function::Create(Ty, Linkage, Name, M);
436 }
437
438 // The parameter 'ChunkSize' will hold strictly positive integer values,
439 // regardless of PollyChunkSize's value
440 Value *Args[] = {
442 GlobalThreadID,
444 LB,
445 UB,
446 Inc,
447 ChunkSize};
448
449 CallInst *Call = Builder.CreateCall(F, Args);
450 Call->setDebugLoc(DLGenerated);
451}
452
454 Value *IsLastPtr,
455 Value *LBPtr,
456 Value *UBPtr,
457 Value *StridePtr) {
458 const std::string Name =
459 is64BitArch() ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_4";
460 Function *F = M->getFunction(Name);
461
462 // If F is not available, declare it.
463 if (!F) {
464 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
465
466 Type *Params[] = {Builder.getPtrTy(0), Builder.getInt32Ty(),
467 Builder.getPtrTy(0), Builder.getPtrTy(0),
468 Builder.getPtrTy(0), Builder.getPtrTy(0)};
469
470 FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(), Params, false);
471 F = Function::Create(Ty, Linkage, Name, M);
472 }
473
474 Value *Args[] = {SourceLocationInfo, GlobalThreadID, IsLastPtr, LBPtr, UBPtr,
475 StridePtr};
476
477 CallInst *Call = Builder.CreateCall(F, Args);
478 Call->setDebugLoc(DLGenerated);
479 return Call;
480}
481
482// TODO: This function currently creates a source location dummy. It might be
483// necessary to (actually) provide information, in the future.
485 const std::string LocName = ".loc.dummy";
486 GlobalVariable *SourceLocDummy = M->getGlobalVariable(LocName);
487
488 if (SourceLocDummy == nullptr) {
489 const std::string StructName = "struct.ident_t";
490 StructType *IdentTy =
491 StructType::getTypeByName(M->getContext(), StructName);
492
493 // If the ident_t StructType is not available, declare it.
494 // in LLVM-IR: ident_t = type { i32, i32, i32, i32, i8* }
495 if (!IdentTy) {
496 Type *LocMembers[] = {Builder.getInt32Ty(), Builder.getInt32Ty(),
497 Builder.getInt32Ty(), Builder.getInt32Ty(),
498 Builder.getPtrTy()};
499
500 IdentTy =
501 StructType::create(M->getContext(), LocMembers, StructName, false);
502 }
503
504 const auto ArrayType =
505 llvm::ArrayType::get(Builder.getInt8Ty(), /* Length */ 23);
506
507 // Global Variable Definitions
508 GlobalVariable *StrVar =
509 new GlobalVariable(*M, ArrayType, true, GlobalValue::PrivateLinkage,
510 nullptr, ".str.ident");
511 StrVar->setAlignment(llvm::Align(1));
512
513 SourceLocDummy = new GlobalVariable(
514 *M, IdentTy, true, GlobalValue::PrivateLinkage, nullptr, LocName);
515 SourceLocDummy->setAlignment(llvm::Align(8));
516
517 // Constant Definitions
518 Constant *InitStr = ConstantDataArray::getString(
519 M->getContext(), "Source location dummy.", true);
520
521 Constant *StrPtr = static_cast<Constant *>(Builder.CreateInBoundsGEP(
522 ArrayType, StrVar, {Builder.getInt32(0), Builder.getInt32(0)}));
523
524 Constant *LocInitStruct = ConstantStruct::get(
525 IdentTy, {Builder.getInt32(0), Builder.getInt32(0), Builder.getInt32(0),
526 Builder.getInt32(0), StrPtr});
527
528 // Initialize variables
529 StrVar->setInitializer(InitStr);
530 SourceLocDummy->setInitializer(LocInitStruct);
531 }
532
533 return SourceLocDummy;
534}
535
537 return (LongType->getIntegerBitWidth() == 64);
538}
539
541 int ChunkSize, OMPGeneralSchedulingType Scheduling) const {
542 if (ChunkSize == 0 && Scheduling == OMPGeneralSchedulingType::StaticChunked)
544
545 return Scheduling;
546}
void createCallStaticFini(Value *GlobalThreadID)
Create a runtime library call to mark the end of a statically scheduled loop.
Function * prepareSubFnDefinition(Function *F) const override
Prepare the definition of the parallel subfunction.
void createCallSpawnThreads(Value *SubFn, Value *SubFnParam, Value *LB, Value *UB, Value *Stride)
Create a runtime library call to spawn the worker threads.
void createCallDispatchInit(Value *GlobalThreadID, Value *LB, Value *UB, Value *Inc, Value *ChunkSize)
Create a runtime library call to prepare the OpenMP runtime.
std::tuple< Value *, Function * > createSubFn(Value *Stride, AllocaInst *Struct, SetVector< Value * > UsedValues, ValueMapT &VMap) override
Create the parallel subfunction.
void createCallStaticInit(Value *GlobalThreadID, Value *IsLastPtr, Value *LBPtr, Value *UBPtr, Value *StridePtr, Value *ChunkSize)
Create a runtime library call to prepare the OpenMP runtime.
GlobalVariable * createSourceLocation()
Create the current source location.
void deployParallelExecution(Function *SubFn, Value *SubFnParam, Value *LB, Value *UB, Value *Stride) override
Create the runtime library calls for spawn and join of the worker threads.
void createCallPushNumThreads(Value *GlobalThreadID, Value *NumThreads)
Create a runtime library call to request a number of threads.
OMPGeneralSchedulingType getSchedType(int ChunkSize, OMPGeneralSchedulingType Scheduling) const
Convert the combination of given chunk size and scheduling type (which might have been set via the co...
Value * createCallDispatchNext(Value *GlobalThreadID, Value *IsLastPtr, Value *LBPtr, Value *UBPtr, Value *StridePtr)
Create a runtime library call to retrieve the next (dynamically) allocated chunk of work for this thr...
bool is64BitArch()
Returns True if 'LongType' is 64bit wide, otherwise: False.
GlobalValue * SourceLocationInfo
The source location struct of this loop.
Value * createCallGlobalThreadNum()
Create a runtime library call to get the current global thread number.
PollyIRBuilder & Builder
The IR builder we use to create instructions.
Function * createSubFnDefinition()
Create the definition of the parallel subfunction.
std::unique_ptr< DominatorTree > SubFnDT
The dominance tree for the generated subfunction.
Module * M
The current module.
llvm::DebugLoc DLGenerated
Debug location for generated code without direct link to any specific line.
Type * LongType
The type of a "long" on this hardware used for backend calls.
void extractValuesFromStruct(SetVector< Value * > Values, Type *Ty, Value *Struct, ValueMapT &VMap)
Extract all values from the Struct and construct the mapping.
std::unique_ptr< LoopInfo > SubFnLI
The loop info for the generated subfunction.
OMPGeneralSchedulingType PollyScheduling
int PollyNumThreads
@ Value
MemoryKind::Value: Models an llvm::Value.
Definition ScopInfo.h:149
int PollyChunkSize
Value * createLoop(Value *LowerBound, Value *UpperBound, Value *Stride, PollyIRBuilder &Builder, LoopInfo &LI, DominatorTree &DT, BasicBlock *&ExitBlock, ICmpInst::Predicate Predicate, ScopAnnotator *Annotator=nullptr, bool Parallel=false, bool UseGuard=true, bool LoopVectDisabled=false)
Create a scalar do/for-style loop.
OMPGeneralSchedulingType
General scheduling types of parallel OpenMP for loops.
llvm::DenseMap< llvm::AssertingVH< llvm::Value >, llvm::AssertingVH< llvm::Value > > ValueMapT
Type to remap values.
Definition ScopHelper.h:106