blob: 21fe8bf37b91178c20cdf704fc28bea904370ccc [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
Chandler Carruth535d52c2013-01-02 11:47:44 +000018#include "llvm/IR/Module.h"
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000019#include "llvm/Analysis/Dominators.h"
Chandler Carruth535d52c2013-01-02 11:47:44 +000020#include "llvm/IR/DataLayout.h"
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000021#include "llvm/Transforms/Utils/BasicBlockUtils.h"
22
23using namespace llvm;
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000024using namespace polly;
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000025
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000026Value *polly::createLoop(Value *LB, Value *UB, Value *Stride,
Tobias Grosser1bb59b02012-12-29 23:47:38 +000027 IRBuilder<> &Builder, Pass *P, BasicBlock *&AfterBlock,
Tobias Grosserc967d8e2012-10-16 07:29:13 +000028 ICmpInst::Predicate Predicate) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000029 DominatorTree &DT = P->getAnalysis<DominatorTree>();
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000030 Function *F = Builder.GetInsertBlock()->getParent();
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000031 LLVMContext &Context = F->getContext();
32
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000033 BasicBlock *PreheaderBB = Builder.GetInsertBlock();
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000034 BasicBlock *HeaderBB = BasicBlock::Create(Context, "polly.loop_header", F);
35 BasicBlock *BodyBB = BasicBlock::Create(Context, "polly.loop_body", F);
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000036 BasicBlock *AfterBB = SplitBlock(PreheaderBB, Builder.GetInsertPoint()++, P);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000037 AfterBB->setName("polly.loop_after");
38
39 PreheaderBB->getTerminator()->setSuccessor(0, HeaderBB);
40 DT.addNewBlock(HeaderBB, PreheaderBB);
41
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000042 Builder.SetInsertPoint(HeaderBB);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000043
44 // Use the type of upper and lower bound.
Tobias Grosserae2d83e2012-12-29 23:57:18 +000045 assert(LB->getType() == UB->getType() &&
46 "Different types for upper and lower bound.");
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000047
48 IntegerType *LoopIVType = dyn_cast<IntegerType>(UB->getType());
49 assert(LoopIVType && "UB is not integer?");
50
51 // IV
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000052 PHINode *IV = Builder.CreatePHI(LoopIVType, 2, "polly.loopiv");
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000053 IV->addIncoming(LB, PreheaderBB);
54
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000055 Stride = Builder.CreateZExtOrBitCast(Stride, LoopIVType);
Tobias Grosser400a4ac2012-05-29 09:11:59 +000056 Value *IncrementedIV = Builder.CreateNSWAdd(IV, Stride, "polly.next_loopiv");
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000057
58 // Exit condition.
59 Value *CMP;
Tobias Grosserc967d8e2012-10-16 07:29:13 +000060 CMP = Builder.CreateICmp(Predicate, IV, UB);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000061
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000062 Builder.CreateCondBr(CMP, BodyBB, AfterBB);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000063 DT.addNewBlock(BodyBB, HeaderBB);
64
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000065 Builder.SetInsertPoint(BodyBB);
66 Builder.CreateBr(HeaderBB);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000067 IV->addIncoming(IncrementedIV, BodyBB);
68 DT.changeImmediateDominator(AfterBB, HeaderBB);
69
Hongbin Zheng4ac4e152012-04-23 13:03:56 +000070 Builder.SetInsertPoint(BodyBB->begin());
71 AfterBlock = AfterBB;
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000072
73 return IV;
74}
75
Tobias Grosserc14582f2013-02-05 18:01:29 +000076void OMPGenerator::createCallParallelLoopStart(
77 Value *SubFunction, Value *SubfunctionParam, Value *NumberOfThreads,
78 Value *LowerBound, Value *UpperBound, Value *Stride) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000079 Module *M = getModule();
80 const char *Name = "GOMP_parallel_loop_runtime_start";
81 Function *F = M->getFunction(Name);
82
83 // If F is not available, declare it.
84 if (!F) {
85 Type *LongTy = getIntPtrTy();
86 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
87
Tobias Grosserc14582f2013-02-05 18:01:29 +000088 Type *Params[] = { PointerType::getUnqual(FunctionType::get(
89 Builder.getVoidTy(), Builder.getInt8PtrTy(), false)),
90 Builder.getInt8PtrTy(), Builder.getInt32Ty(), LongTy,
91 LongTy, LongTy, };
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000092
93 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Params, false);
94 F = Function::Create(Ty, Linkage, Name, M);
95 }
96
Tobias Grosserc14582f2013-02-05 18:01:29 +000097 Value *Args[] = { SubFunction, SubfunctionParam, NumberOfThreads, LowerBound,
98 UpperBound, Stride, };
Tobias Grosserf74a4cd2012-03-23 10:35:18 +000099
100 Builder.CreateCall(F, Args);
101}
102
Tobias Grossere602a072013-05-07 07:30:56 +0000103Value *OMPGenerator::createCallLoopNext(Value *LowerBoundPtr,
104 Value *UpperBoundPtr) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000105 Module *M = getModule();
106 const char *Name = "GOMP_loop_runtime_next";
107 Function *F = M->getFunction(Name);
108
109 // If F is not available, declare it.
110 if (!F) {
111 Type *LongPtrTy = PointerType::getUnqual(getIntPtrTy());
112 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
113
Tobias Grosserc14582f2013-02-05 18:01:29 +0000114 Type *Params[] = { LongPtrTy, LongPtrTy, };
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000115
116 FunctionType *Ty = FunctionType::get(Builder.getInt8Ty(), Params, false);
117 F = Function::Create(Ty, Linkage, Name, M);
118 }
119
Tobias Grosserc14582f2013-02-05 18:01:29 +0000120 Value *Args[] = { LowerBoundPtr, UpperBoundPtr, };
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000121
122 Value *Return = Builder.CreateCall(F, Args);
Tobias Grosserc14582f2013-02-05 18:01:29 +0000123 Return = Builder.CreateICmpNE(
124 Return, Builder.CreateZExt(Builder.getFalse(), Return->getType()));
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000125 return Return;
126}
127
128void OMPGenerator::createCallParallelEnd() {
129 const char *Name = "GOMP_parallel_end";
130 Module *M = getModule();
131 Function *F = M->getFunction(Name);
132
133 // If F is not available, declare it.
134 if (!F) {
135 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
136
137 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
138 F = Function::Create(Ty, Linkage, Name, M);
139 }
140
141 Builder.CreateCall(F);
142}
143
144void OMPGenerator::createCallLoopEndNowait() {
145 const char *Name = "GOMP_loop_end_nowait";
146 Module *M = getModule();
147 Function *F = M->getFunction(Name);
148
149 // If F is not available, declare it.
150 if (!F) {
151 GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
152
153 FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
154 F = Function::Create(Ty, Linkage, Name, M);
155 }
156
157 Builder.CreateCall(F);
158}
159
160IntegerType *OMPGenerator::getIntPtrTy() {
Tobias Grosser5d01691d2012-11-01 16:45:18 +0000161 return P->getAnalysis<DataLayout>().getIntPtrType(Builder.getContext());
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000162}
163
164Module *OMPGenerator::getModule() {
165 return Builder.GetInsertBlock()->getParent()->getParent();
166}
167
168Function *OMPGenerator::createSubfunctionDefinition() {
169 Module *M = getModule();
170 Function *F = Builder.GetInsertBlock()->getParent();
Tobias Grosserc14582f2013-02-05 18:01:29 +0000171 std::vector<Type *> Arguments(1, Builder.getInt8PtrTy());
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000172 FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false);
173 Function *FN = Function::Create(FT, Function::InternalLinkage,
174 F->getName() + ".omp_subfn", M);
175 // Do not run any polly pass on the new function.
176 P->getAnalysis<polly::ScopDetection>().markFunctionAsInvalid(FN);
177
178 Function::arg_iterator AI = FN->arg_begin();
179 AI->setName("omp.userContext");
180
181 return FN;
182}
183
Tobias Grosserc14582f2013-02-05 18:01:29 +0000184Value *OMPGenerator::loadValuesIntoStruct(SetVector<Value *> &Values) {
185 std::vector<Type *> Members;
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000186
187 for (unsigned i = 0; i < Values.size(); i++)
188 Members.push_back(Values[i]->getType());
189
190 StructType *Ty = StructType::get(Builder.getContext(), Members);
191 Value *Struct = Builder.CreateAlloca(Ty, 0, "omp.userContext");
192
193 for (unsigned i = 0; i < Values.size(); i++) {
194 Value *Address = Builder.CreateStructGEP(Struct, i);
195 Builder.CreateStore(Values[i], Address);
196 }
197
198 return Struct;
199}
200
Tobias Grossere602a072013-05-07 07:30:56 +0000201void OMPGenerator::extractValuesFromStruct(SetVector<Value *> OldValues,
202 Value *Struct,
203 ValueToValueMapTy &Map) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000204 for (unsigned i = 0; i < OldValues.size(); i++) {
205 Value *Address = Builder.CreateStructGEP(Struct, i);
206 Value *NewValue = Builder.CreateLoad(Address);
Andy Gibbs36e6ca02013-03-20 15:42:59 +0000207 Map.insert(std::make_pair(OldValues[i], NewValue));
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000208 }
209}
210
Tobias Grossere602a072013-05-07 07:30:56 +0000211Value *OMPGenerator::createSubfunction(Value *Stride, Value *StructData,
212 SetVector<Value *> Data,
213 ValueToValueMapTy &Map,
214 Function **SubFunction) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000215 Function *FN = createSubfunctionDefinition();
216
217 BasicBlock *PrevBB, *HeaderBB, *ExitBB, *CheckNextBB, *LoadIVBoundsBB,
Tobias Grosserc14582f2013-02-05 18:01:29 +0000218 *AfterBB;
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000219 Value *LowerBoundPtr, *UpperBoundPtr, *UserContext, *Ret1, *HasNextSchedule,
Tobias Grosserc14582f2013-02-05 18:01:29 +0000220 *LowerBound, *UpperBound, *IV;
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000221 Type *IntPtrTy = getIntPtrTy();
222 LLVMContext &Context = FN->getContext();
223
224 // Store the previous basic block.
225 PrevBB = Builder.GetInsertBlock();
226
227 // Create basic blocks.
228 HeaderBB = BasicBlock::Create(Context, "omp.setup", FN);
229 ExitBB = BasicBlock::Create(Context, "omp.exit", FN);
230 CheckNextBB = BasicBlock::Create(Context, "omp.checkNext", FN);
231 LoadIVBoundsBB = BasicBlock::Create(Context, "omp.loadIVBounds", FN);
232
233 DominatorTree &DT = P->getAnalysis<DominatorTree>();
234 DT.addNewBlock(HeaderBB, PrevBB);
235 DT.addNewBlock(ExitBB, HeaderBB);
236 DT.addNewBlock(CheckNextBB, HeaderBB);
237 DT.addNewBlock(LoadIVBoundsBB, HeaderBB);
238
239 // Fill up basic block HeaderBB.
240 Builder.SetInsertPoint(HeaderBB);
241 LowerBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.lowerBoundPtr");
242 UpperBoundPtr = Builder.CreateAlloca(IntPtrTy, 0, "omp.upperBoundPtr");
243 UserContext = Builder.CreateBitCast(FN->arg_begin(), StructData->getType(),
244 "omp.userContext");
245
246 extractValuesFromStruct(Data, UserContext, Map);
247 Builder.CreateBr(CheckNextBB);
248
249 // Add code to check if another set of iterations will be executed.
250 Builder.SetInsertPoint(CheckNextBB);
251 Ret1 = createCallLoopNext(LowerBoundPtr, UpperBoundPtr);
252 HasNextSchedule = Builder.CreateTrunc(Ret1, Builder.getInt1Ty(),
253 "omp.hasNextScheduleBlock");
254 Builder.CreateCondBr(HasNextSchedule, LoadIVBoundsBB, ExitBB);
255
256 // Add code to to load the iv bounds for this set of iterations.
257 Builder.SetInsertPoint(LoadIVBoundsBB);
258 LowerBound = Builder.CreateLoad(LowerBoundPtr, "omp.lowerBound");
259 UpperBound = Builder.CreateLoad(UpperBoundPtr, "omp.upperBound");
260
261 // Subtract one as the upper bound provided by openmp is a < comparison
262 // whereas the codegenForSequential function creates a <= comparison.
263 UpperBound = Builder.CreateSub(UpperBound, ConstantInt::get(IntPtrTy, 1),
264 "omp.upperBoundAdjusted");
265
266 Builder.CreateBr(CheckNextBB);
267 Builder.SetInsertPoint(--Builder.GetInsertPoint());
Tobias Grosserc967d8e2012-10-16 07:29:13 +0000268 IV = createLoop(LowerBound, UpperBound, Stride, Builder, P, AfterBB,
269 ICmpInst::ICMP_SLE);
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000270
271 BasicBlock::iterator LoopBody = Builder.GetInsertPoint();
272 Builder.SetInsertPoint(AfterBB->begin());
273
274 // Add code to terminate this openmp subfunction.
275 Builder.SetInsertPoint(ExitBB);
276 createCallLoopEndNowait();
277 Builder.CreateRetVoid();
278
279 Builder.SetInsertPoint(LoopBody);
280 *SubFunction = FN;
281
282 return IV;
283}
284
Tobias Grossere602a072013-05-07 07:30:56 +0000285Value *OMPGenerator::createParallelLoop(Value *LowerBound, Value *UpperBound,
286 Value *Stride,
287 SetVector<Value *> &Values,
288 ValueToValueMapTy &Map,
289 BasicBlock::iterator *LoopBody) {
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000290 Value *Struct, *IV, *SubfunctionParam, *NumberOfThreads;
291 Function *SubFunction;
292
293 Struct = loadValuesIntoStruct(Values);
294
295 BasicBlock::iterator PrevInsertPoint = Builder.GetInsertPoint();
296 IV = createSubfunction(Stride, Struct, Values, Map, &SubFunction);
297 *LoopBody = Builder.GetInsertPoint();
298 Builder.SetInsertPoint(PrevInsertPoint);
299
300 // Create call for GOMP_parallel_loop_runtime_start.
Tobias Grosserc14582f2013-02-05 18:01:29 +0000301 SubfunctionParam =
302 Builder.CreateBitCast(Struct, Builder.getInt8PtrTy(), "omp_data");
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000303
304 NumberOfThreads = Builder.getInt32(0);
305
306 // Add one as the upper bound provided by openmp is a < comparison
307 // whereas the codegenForSequential function creates a <= comparison.
Tobias Grosserc14582f2013-02-05 18:01:29 +0000308 UpperBound =
309 Builder.CreateAdd(UpperBound, ConstantInt::get(getIntPtrTy(), 1));
Tobias Grosserf74a4cd2012-03-23 10:35:18 +0000310
311 createCallParallelLoopStart(SubFunction, SubfunctionParam, NumberOfThreads,
312 LowerBound, UpperBound, Stride);
313 Builder.CreateCall(SubFunction, SubfunctionParam);
314 createCallParallelEnd();
315
316 return IV;
317}