blob: b2e91b5472779220c9ec39c09f85bcf652641c65 [file] [log] [blame]
Tobias Grosserf74a4cd2012-03-23 10:35:18 +00001//===------ LoopGenerators.cpp - IR helper to create loops ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains functions to create scalar and OpenMP parallel loops
11// as LLVM-IR.
12//
13//===----------------------------------------------------------------------===//
14
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000015#include "polly/ScopDetection.h"
Hongbin Zheng8a846612012-04-25 13:18:28 +000016#include "polly/CodeGen/LoopGenerators.h"
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000017#include "llvm/Analysis/Dominators.h"
Chandler Carruth535d52c2013-01-02 11:47:44 +000018#include "llvm/IR/DataLayout.h"
Tobias Grosser83628182013-05-07 08:11:54 +000019#include "llvm/IR/Module.h"
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000020#include "llvm/Transforms/Utils/BasicBlockUtils.h"
21
22using namespace llvm;
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000023using namespace polly;
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000024
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000025Value *polly::createLoop(Value *LB, Value *UB, Value *Stride,
Tobias Grosser1bb59b02012-12-29 23:47:38 +000026 IRBuilder<> &Builder, Pass *P, BasicBlock *&AfterBlock,
Tobias Grosserc967d8e2012-10-16 07:29:13 +000027 ICmpInst::Predicate Predicate) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000028 DominatorTree &DT = P->getAnalysis<DominatorTree>();
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000029 Function *F = Builder.GetInsertBlock()->getParent();
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000030 LLVMContext &Context = F->getContext();
31
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000032 BasicBlock *PreheaderBB = Builder.GetInsertBlock();
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000033 BasicBlock *HeaderBB = BasicBlock::Create(Context, "polly.loop_header", F);
34 BasicBlock *BodyBB = BasicBlock::Create(Context, "polly.loop_body", F);
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000035 BasicBlock *AfterBB = SplitBlock(PreheaderBB, Builder.GetInsertPoint()++, P);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000036 AfterBB->setName("polly.loop_after");
37
38 PreheaderBB->getTerminator()->setSuccessor(0, HeaderBB);
39 DT.addNewBlock(HeaderBB, PreheaderBB);
40
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000041 Builder.SetInsertPoint(HeaderBB);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000042
43 // Use the type of upper and lower bound.
Tobias Grosserae2d83e2012-12-29 23:57:18 +000044 assert(LB->getType() == UB->getType() &&
45 "Different types for upper and lower bound.");
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000046
47 IntegerType *LoopIVType = dyn_cast<IntegerType>(UB->getType());
48 assert(LoopIVType && "UB is not integer?");
49
50 // IV
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000051 PHINode *IV = Builder.CreatePHI(LoopIVType, 2, "polly.loopiv");
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000052 IV->addIncoming(LB, PreheaderBB);
53
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000054 Stride = Builder.CreateZExtOrBitCast(Stride, LoopIVType);
Tobias Grosser400a4ac2012-05-29 09:11:59 +000055 Value *IncrementedIV = Builder.CreateNSWAdd(IV, Stride, "polly.next_loopiv");
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000056
57 // Exit condition.
58 Value *CMP;
Tobias Grosserc967d8e2012-10-16 07:29:13 +000059 CMP = Builder.CreateICmp(Predicate, IV, UB);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000060
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000061 Builder.CreateCondBr(CMP, BodyBB, AfterBB);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000062 DT.addNewBlock(BodyBB, HeaderBB);
63
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000064 Builder.SetInsertPoint(BodyBB);
65 Builder.CreateBr(HeaderBB);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000066 IV->addIncoming(IncrementedIV, BodyBB);
67 DT.changeImmediateDominator(AfterBB, HeaderBB);
68
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000069 Builder.SetInsertPoint(BodyBB->begin());
70 AfterBlock = AfterBB;
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000071
72 return IV;
73}
74
Tobias Grosserc14582f2013-02-05 18:01:29 +000075void OMPGenerator::createCallParallelLoopStart(
76 Value *SubFunction, Value *SubfunctionParam, Value *NumberOfThreads,
77 Value *LowerBound, Value *UpperBound, Value *Stride) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000078 Module *M = getModule();
79 const char *Name = "GOMP_parallel_loop_runtime_start";
80 Function *F = M->getFunction(Name);
81
82 // If F is not available, declare it.
83 if (!F) {
84 Type *LongTy = getIntPtrTy();
85 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
86
Tobias Grosserc14582f2013-02-05 18:01:29 +000087 Type *Params[] = { PointerType::getUnqual(FunctionType::get(
88 Builder.getVoidTy(), Builder.getInt8PtrTy(), false)),
89 Builder.getInt8PtrTy(), Builder.getInt32Ty(), LongTy,
90 LongTy, LongTy, };
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000091
92 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
93 F = Function::Create(Ty, Linkage, Name, M);
94 }
95
Tobias Grosserc14582f2013-02-05 18:01:29 +000096 Value *Args[] = { SubFunction, SubfunctionParam, NumberOfThreads, LowerBound,
97 UpperBound, Stride, };
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000098
99 Builder.CreateCall(F, Args);
100}
101
Tobias Grossere602a072013-05-07 07:30:56 +0000102Value *OMPGenerator::createCallLoopNext(Value *LowerBoundPtr,
103 Value *UpperBoundPtr) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000104 Module *M = getModule();
105 const char *Name = "GOMP_loop_runtime_next";
106 Function *F = M->getFunction(Name);
107
108 // If F is not available, declare it.
109 if (!F) {
110 Type *LongPtrTy = PointerType::getUnqual(getIntPtrTy());
111 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
112
Tobias Grosserc14582f2013-02-05 18:01:29 +0000113 Type *Params[] = { LongPtrTy, LongPtrTy, };
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000114
115 FunctionType *Ty = FunctionType::get(Builder.getInt8Ty(), Params, false);
116 F = Function::Create(Ty, Linkage, Name, M);
117 }
118
Tobias Grosserc14582f2013-02-05 18:01:29 +0000119 Value *Args[] = { LowerBoundPtr, UpperBoundPtr, };
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000120
121 Value *Return = Builder.CreateCall(F, Args);
Tobias Grosserc14582f2013-02-05 18:01:29 +0000122 Return = Builder.CreateICmpNE(
123 Return, Builder.CreateZExt(Builder.getFalse(), Return->getType()));
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000124 return Return;
125}
126
127void OMPGenerator::createCallParallelEnd() {
128 const char *Name = "GOMP_parallel_end";
129 Module *M = getModule();
130 Function *F = M->getFunction(Name);
131
132 // If F is not available, declare it.
133 if (!F) {
134 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
135
136 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
137 F = Function::Create(Ty, Linkage, Name, M);
138 }
139
140 Builder.CreateCall(F);
141}
142
143void OMPGenerator::createCallLoopEndNowait() {
144 const char *Name = "GOMP_loop_end_nowait";
145 Module *M = getModule();
146 Function *F = M->getFunction(Name);
147
148 // If F is not available, declare it.
149 if (!F) {
150 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
151
152 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
153 F = Function::Create(Ty, Linkage, Name, M);
154 }
155
156 Builder.CreateCall(F);
157}
158
159IntegerType *OMPGenerator::getIntPtrTy() {
Tobias Grosser5d01691d2012-11-01 16:45:18 +0000160 return P->getAnalysis<DataLayout>().getIntPtrType(Builder.getContext());
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000161}
162
163Module *OMPGenerator::getModule() {
164 return Builder.GetInsertBlock()->getParent()->getParent();
165}
166
167Function *OMPGenerator::createSubfunctionDefinition() {
168 Module *M = getModule();
169 Function *F = Builder.GetInsertBlock()->getParent();
Tobias Grosserc14582f2013-02-05 18:01:29 +0000170 std::vector<Type *> Arguments(1, Builder.getInt8PtrTy());
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000171 FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false);
172 Function *FN = Function::Create(FT, Function::InternalLinkage,
173 F->getName() + ".omp_subfn", M);
174 // Do not run any polly pass on the new function.
175 P->getAnalysis<polly::ScopDetection>().markFunctionAsInvalid(FN);
176
177 Function::arg_iterator AI = FN->arg_begin();
178 AI->setName("omp.userContext");
179
180 return FN;
181}
182
Tobias Grosserc14582f2013-02-05 18:01:29 +0000183Value *OMPGenerator::loadValuesIntoStruct(SetVector<Value *> &Values) {
184 std::vector<Type *> Members;
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000185
186 for (unsigned i = 0; i < Values.size(); i++)
187 Members.push_back(Values[i]->getType());
188
189 StructType *Ty = StructType::get(Builder.getContext(), Members);
190 Value *Struct = Builder.CreateAlloca(Ty, 0, "omp.userContext");
191
192 for (unsigned i = 0; i < Values.size(); i++) {
193 Value *Address = Builder.CreateStructGEP(Struct, i);
194 Builder.CreateStore(Values[i], Address);
195 }
196
197 return Struct;
198}
199
Tobias Grossere602a072013-05-07 07:30:56 +0000200void OMPGenerator::extractValuesFromStruct(SetVector<Value *> OldValues,
201 Value *Struct,
202 ValueToValueMapTy &Map) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000203 for (unsigned i = 0; i < OldValues.size(); i++) {
204 Value *Address = Builder.CreateStructGEP(Struct, i);
205 Value *NewValue = Builder.CreateLoad(Address);
Andy Gibbs36e6ca02013-03-20 15:42:59 +0000206 Map.insert(std::make_pair(OldValues[i], NewValue));
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000207 }
208}
209
Tobias Grossere602a072013-05-07 07:30:56 +0000210Value *OMPGenerator::createSubfunction(Value *Stride, Value *StructData,
211 SetVector<Value *> Data,
212 ValueToValueMapTy &Map,
213 Function **SubFunction) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000214 Function *FN = createSubfunctionDefinition();
215
216 BasicBlock *PrevBB, *HeaderBB, *ExitBB, *CheckNextBB, *LoadIVBoundsBB,
Tobias Grosserc14582f2013-02-05 18:01:29 +0000217 *AfterBB;
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000218 Value *LowerBoundPtr, *UpperBoundPtr, *UserContext, *Ret1, *HasNextSchedule,
Tobias Grosserc14582f2013-02-05 18:01:29 +0000219 *LowerBound, *UpperBound, *IV;
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000220 Type *IntPtrTy = getIntPtrTy();
221 LLVMContext &Context = FN->getContext();
222
223 // Store the previous basic block.
224 PrevBB = Builder.GetInsertBlock();
225
226 // Create basic blocks.
227 HeaderBB = BasicBlock::Create(Context, "omp.setup", FN);
228 ExitBB = BasicBlock::Create(Context, "omp.exit", FN);
229 CheckNextBB = BasicBlock::Create(Context, "omp.checkNext", FN);
230 LoadIVBoundsBB = BasicBlock::Create(Context, "omp.loadIVBounds", FN);
231
232 DominatorTree &DT = P->getAnalysis<DominatorTree>();
233 DT.addNewBlock(HeaderBB, PrevBB);
234 DT.addNewBlock(ExitBB, HeaderBB);
235 DT.addNewBlock(CheckNextBB, HeaderBB);
236 DT.addNewBlock(LoadIVBoundsBB, HeaderBB);
237
238 // Fill up basic block HeaderBB.
239 Builder.SetInsertPoint(HeaderBB);
240 LowerBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.lowerBoundPtr");
241 UpperBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.upperBoundPtr");
242 UserContext = Builder.CreateBitCast(FN->arg_begin(), StructData->getType(),
243 "omp.userContext");
244
245 extractValuesFromStruct(Data, UserContext, Map);
246 Builder.CreateBr(CheckNextBB);
247
248 // Add code to check if another set of iterations will be executed.
249 Builder.SetInsertPoint(CheckNextBB);
250 Ret1 = createCallLoopNext(LowerBoundPtr, UpperBoundPtr);
251 HasNextSchedule = Builder.CreateTrunc(Ret1, Builder.getInt1Ty(),
252 "omp.hasNextScheduleBlock");
253 Builder.CreateCondBr(HasNextSchedule, LoadIVBoundsBB, ExitBB);
254
255 // Add code to to load the iv bounds for this set of iterations.
256 Builder.SetInsertPoint(LoadIVBoundsBB);
257 LowerBound = Builder.CreateLoad(LowerBoundPtr, "omp.lowerBound");
258 UpperBound = Builder.CreateLoad(UpperBoundPtr, "omp.upperBound");
259
260 // Subtract one as the upper bound provided by openmp is a < comparison
261 // whereas the codegenForSequential function creates a <= comparison.
262 UpperBound = Builder.CreateSub(UpperBound, ConstantInt::get(IntPtrTy, 1),
263 "omp.upperBoundAdjusted");
264
265 Builder.CreateBr(CheckNextBB);
266 Builder.SetInsertPoint(--Builder.GetInsertPoint());
Tobias Grosserc967d8e2012-10-16 07:29:13 +0000267 IV = createLoop(LowerBound, UpperBound, Stride, Builder, P, AfterBB,
268 ICmpInst::ICMP_SLE);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000269
270 BasicBlock::iterator LoopBody = Builder.GetInsertPoint();
271 Builder.SetInsertPoint(AfterBB->begin());
272
273 // Add code to terminate this openmp subfunction.
274 Builder.SetInsertPoint(ExitBB);
275 createCallLoopEndNowait();
276 Builder.CreateRetVoid();
277
278 Builder.SetInsertPoint(LoopBody);
279 *SubFunction = FN;
280
281 return IV;
282}
283
Tobias Grossere602a072013-05-07 07:30:56 +0000284Value *OMPGenerator::createParallelLoop(Value *LowerBound, Value *UpperBound,
285 Value *Stride,
286 SetVector<Value *> &Values,
287 ValueToValueMapTy &Map,
288 BasicBlock::iterator *LoopBody) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000289 Value *Struct, *IV, *SubfunctionParam, *NumberOfThreads;
290 Function *SubFunction;
291
292 Struct = loadValuesIntoStruct(Values);
293
294 BasicBlock::iterator PrevInsertPoint = Builder.GetInsertPoint();
295 IV = createSubfunction(Stride, Struct, Values, Map, &SubFunction);
296 *LoopBody = Builder.GetInsertPoint();
297 Builder.SetInsertPoint(PrevInsertPoint);
298
299 // Create call for GOMP_parallel_loop_runtime_start.
Tobias Grosserc14582f2013-02-05 18:01:29 +0000300 SubfunctionParam =
301 Builder.CreateBitCast(Struct, Builder.getInt8PtrTy(), "omp_data");
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000302
303 NumberOfThreads = Builder.getInt32(0);
304
305 // Add one as the upper bound provided by openmp is a < comparison
306 // whereas the codegenForSequential function creates a <= comparison.
Tobias Grosserc14582f2013-02-05 18:01:29 +0000307 UpperBound =
308 Builder.CreateAdd(UpperBound, ConstantInt::get(getIntPtrTy(), 1));
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000309
310 createCallParallelLoopStart(SubFunction, SubfunctionParam, NumberOfThreads,
311 LowerBound, UpperBound, Stride);
312 Builder.CreateCall(SubFunction, SubfunctionParam);
313 createCallParallelEnd();
314
315 return IV;
316}