Coverage Report

Created: 2019-07-24 05:18

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