1 //===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===//
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 contains code to emit OpenMP nodes as LLVM code.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "CGOpenMPRuntime.h"
15 #include "CodeGenFunction.h"
16 #include "CodeGenModule.h"
17 #include "TargetInfo.h"
18 #include "clang/AST/Stmt.h"
19 #include "clang/AST/StmtOpenMP.h"
20 using namespace clang;
21 using namespace CodeGen;
22
23 namespace {
24 /// \brief RAII for emitting code of CapturedStmt without function outlining.
25 class InlinedOpenMPRegion {
26 CodeGenFunction &CGF;
27 CodeGenFunction::CGCapturedStmtInfo *PrevCapturedStmtInfo;
28 const Decl *StoredCurCodeDecl;
29
30 /// \brief A class to emit CapturedStmt construct as inlined statement without
31 /// generating a function for outlined code.
32 class CGInlinedOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
33 public:
CGInlinedOpenMPRegionInfo()34 CGInlinedOpenMPRegionInfo() : CGCapturedStmtInfo() {}
35 };
36
37 public:
InlinedOpenMPRegion(CodeGenFunction & CGF,const Stmt * S)38 InlinedOpenMPRegion(CodeGenFunction &CGF, const Stmt *S)
39 : CGF(CGF), PrevCapturedStmtInfo(CGF.CapturedStmtInfo),
40 StoredCurCodeDecl(CGF.CurCodeDecl) {
41 CGF.CurCodeDecl = cast<CapturedStmt>(S)->getCapturedDecl();
42 CGF.CapturedStmtInfo = new CGInlinedOpenMPRegionInfo();
43 }
~InlinedOpenMPRegion()44 ~InlinedOpenMPRegion() {
45 delete CGF.CapturedStmtInfo;
46 CGF.CapturedStmtInfo = PrevCapturedStmtInfo;
47 CGF.CurCodeDecl = StoredCurCodeDecl;
48 }
49 };
50 } // namespace
51
52 //===----------------------------------------------------------------------===//
53 // OpenMP Directive Emission
54 //===----------------------------------------------------------------------===//
55
56 /// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
57 /// function. Here is the logic:
58 /// if (Cond) {
59 /// CodeGen(true);
60 /// } else {
61 /// CodeGen(false);
62 /// }
EmitOMPIfClause(CodeGenFunction & CGF,const Expr * Cond,const std::function<void (bool)> & CodeGen)63 static void EmitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
64 const std::function<void(bool)> &CodeGen) {
65 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
66
67 // If the condition constant folds and can be elided, try to avoid emitting
68 // the condition and the dead arm of the if/else.
69 bool CondConstant;
70 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
71 CodeGen(CondConstant);
72 return;
73 }
74
75 // Otherwise, the condition did not fold, or we couldn't elide it. Just
76 // emit the conditional branch.
77 auto ThenBlock = CGF.createBasicBlock(/*name*/ "omp_if.then");
78 auto ElseBlock = CGF.createBasicBlock(/*name*/ "omp_if.else");
79 auto ContBlock = CGF.createBasicBlock(/*name*/ "omp_if.end");
80 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount*/ 0);
81
82 // Emit the 'then' code.
83 CGF.EmitBlock(ThenBlock);
84 CodeGen(/*ThenBlock*/ true);
85 CGF.EmitBranch(ContBlock);
86 // Emit the 'else' code if present.
87 {
88 // There is no need to emit line number for unconditional branch.
89 ApplyDebugLocation DL(CGF);
90 CGF.EmitBlock(ElseBlock);
91 }
92 CodeGen(/*ThenBlock*/ false);
93 {
94 // There is no need to emit line number for unconditional branch.
95 ApplyDebugLocation DL(CGF);
96 CGF.EmitBranch(ContBlock);
97 }
98 // Emit the continuation block for code after the if.
99 CGF.EmitBlock(ContBlock, /*IsFinished*/ true);
100 }
101
EmitOMPAggregateAssign(LValue OriginalAddr,llvm::Value * PrivateAddr,const Expr * AssignExpr,QualType OriginalType,const VarDecl * VDInit)102 void CodeGenFunction::EmitOMPAggregateAssign(LValue OriginalAddr,
103 llvm::Value *PrivateAddr,
104 const Expr *AssignExpr,
105 QualType OriginalType,
106 const VarDecl *VDInit) {
107 EmitBlock(createBasicBlock(".omp.assign.begin."));
108 if (!isa<CXXConstructExpr>(AssignExpr) || isTrivialInitializer(AssignExpr)) {
109 // Perform simple memcpy.
110 EmitAggregateAssign(PrivateAddr, OriginalAddr.getAddress(),
111 AssignExpr->getType());
112 } else {
113 // Perform element-by-element initialization.
114 QualType ElementTy;
115 auto SrcBegin = OriginalAddr.getAddress();
116 auto DestBegin = PrivateAddr;
117 auto ArrayTy = OriginalType->getAsArrayTypeUnsafe();
118 auto SrcNumElements = emitArrayLength(ArrayTy, ElementTy, SrcBegin);
119 auto DestNumElements = emitArrayLength(ArrayTy, ElementTy, DestBegin);
120 auto SrcEnd = Builder.CreateGEP(SrcBegin, SrcNumElements);
121 auto DestEnd = Builder.CreateGEP(DestBegin, DestNumElements);
122 // The basic structure here is a do-while loop, because we don't
123 // need to check for the zero-element case.
124 auto BodyBB = createBasicBlock("omp.arraycpy.body");
125 auto DoneBB = createBasicBlock("omp.arraycpy.done");
126 auto IsEmpty =
127 Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
128 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
129
130 // Enter the loop body, making that address the current address.
131 auto EntryBB = Builder.GetInsertBlock();
132 EmitBlock(BodyBB);
133 auto SrcElementPast = Builder.CreatePHI(SrcBegin->getType(), 2,
134 "omp.arraycpy.srcElementPast");
135 SrcElementPast->addIncoming(SrcEnd, EntryBB);
136 auto DestElementPast = Builder.CreatePHI(DestBegin->getType(), 2,
137 "omp.arraycpy.destElementPast");
138 DestElementPast->addIncoming(DestEnd, EntryBB);
139
140 // Shift the address back by one element.
141 auto NegativeOne = llvm::ConstantInt::get(SizeTy, -1, true);
142 auto DestElement = Builder.CreateGEP(DestElementPast, NegativeOne,
143 "omp.arraycpy.dest.element");
144 auto SrcElement = Builder.CreateGEP(SrcElementPast, NegativeOne,
145 "omp.arraycpy.src.element");
146 {
147 // Create RunCleanScope to cleanup possible temps.
148 CodeGenFunction::RunCleanupsScope Init(*this);
149 // Emit initialization for single element.
150 LocalDeclMap[VDInit] = SrcElement;
151 EmitAnyExprToMem(AssignExpr, DestElement,
152 AssignExpr->getType().getQualifiers(),
153 /*IsInitializer*/ false);
154 LocalDeclMap.erase(VDInit);
155 }
156
157 // Check whether we've reached the end.
158 auto Done =
159 Builder.CreateICmpEQ(DestElement, DestBegin, "omp.arraycpy.done");
160 Builder.CreateCondBr(Done, DoneBB, BodyBB);
161 DestElementPast->addIncoming(DestElement, Builder.GetInsertBlock());
162 SrcElementPast->addIncoming(SrcElement, Builder.GetInsertBlock());
163
164 // Done.
165 EmitBlock(DoneBB, true);
166 }
167 EmitBlock(createBasicBlock(".omp.assign.end."));
168 }
169
EmitOMPFirstprivateClause(const OMPExecutableDirective & D,CodeGenFunction::OMPPrivateScope & PrivateScope)170 void CodeGenFunction::EmitOMPFirstprivateClause(
171 const OMPExecutableDirective &D,
172 CodeGenFunction::OMPPrivateScope &PrivateScope) {
173 auto PrivateFilter = [](const OMPClause *C) -> bool {
174 return C->getClauseKind() == OMPC_firstprivate;
175 };
176 for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)>
177 I(D.clauses(), PrivateFilter); I; ++I) {
178 auto *C = cast<OMPFirstprivateClause>(*I);
179 auto IRef = C->varlist_begin();
180 auto InitsRef = C->inits().begin();
181 for (auto IInit : C->private_copies()) {
182 auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
183 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
184 bool IsRegistered;
185 if (*InitsRef != nullptr) {
186 // Emit VarDecl with copy init for arrays.
187 auto *FD = CapturedStmtInfo->lookup(OrigVD);
188 LValue Base = MakeNaturalAlignAddrLValue(
189 CapturedStmtInfo->getContextValue(),
190 getContext().getTagDeclType(FD->getParent()));
191 auto OriginalAddr = EmitLValueForField(Base, FD);
192 auto VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
193 IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
194 auto Emission = EmitAutoVarAlloca(*VD);
195 // Emit initialization of aggregate firstprivate vars.
196 EmitOMPAggregateAssign(OriginalAddr, Emission.getAllocatedAddress(),
197 VD->getInit(), (*IRef)->getType(), VDInit);
198 EmitAutoVarCleanups(Emission);
199 return Emission.getAllocatedAddress();
200 });
201 } else
202 IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
203 // Emit private VarDecl with copy init.
204 EmitDecl(*VD);
205 return GetAddrOfLocalVar(VD);
206 });
207 assert(IsRegistered && "counter already registered as private");
208 // Silence the warning about unused variable.
209 (void)IsRegistered;
210 ++IRef, ++InitsRef;
211 }
212 }
213 }
214
EmitOMPPrivateClause(const OMPExecutableDirective & D,CodeGenFunction::OMPPrivateScope & PrivateScope)215 void CodeGenFunction::EmitOMPPrivateClause(
216 const OMPExecutableDirective &D,
217 CodeGenFunction::OMPPrivateScope &PrivateScope) {
218 auto PrivateFilter = [](const OMPClause *C) -> bool {
219 return C->getClauseKind() == OMPC_private;
220 };
221 for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)>
222 I(D.clauses(), PrivateFilter); I; ++I) {
223 auto *C = cast<OMPPrivateClause>(*I);
224 auto IRef = C->varlist_begin();
225 for (auto IInit : C->private_copies()) {
226 auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
227 auto VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
228 bool IsRegistered =
229 PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
230 // Emit private VarDecl with copy init.
231 EmitDecl(*VD);
232 return GetAddrOfLocalVar(VD);
233 });
234 assert(IsRegistered && "counter already registered as private");
235 // Silence the warning about unused variable.
236 (void)IsRegistered;
237 ++IRef;
238 }
239 }
240 }
241
242 /// \brief Emits code for OpenMP parallel directive in the parallel region.
EmitOMPParallelCall(CodeGenFunction & CGF,const OMPParallelDirective & S,llvm::Value * OutlinedFn,llvm::Value * CapturedStruct)243 static void EmitOMPParallelCall(CodeGenFunction &CGF,
244 const OMPParallelDirective &S,
245 llvm::Value *OutlinedFn,
246 llvm::Value *CapturedStruct) {
247 if (auto C = S.getSingleClause(/*K*/ OMPC_num_threads)) {
248 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
249 auto NumThreadsClause = cast<OMPNumThreadsClause>(C);
250 auto NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
251 /*IgnoreResultAssign*/ true);
252 CGF.CGM.getOpenMPRuntime().EmitOMPNumThreadsClause(
253 CGF, NumThreads, NumThreadsClause->getLocStart());
254 }
255 CGF.CGM.getOpenMPRuntime().EmitOMPParallelCall(CGF, S.getLocStart(),
256 OutlinedFn, CapturedStruct);
257 }
258
EmitOMPParallelDirective(const OMPParallelDirective & S)259 void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
260 auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
261 auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
262 auto OutlinedFn = CGM.getOpenMPRuntime().EmitOpenMPOutlinedFunction(
263 S, *CS->getCapturedDecl()->param_begin());
264 if (auto C = S.getSingleClause(/*K*/ OMPC_if)) {
265 auto Cond = cast<OMPIfClause>(C)->getCondition();
266 EmitOMPIfClause(*this, Cond, [&](bool ThenBlock) {
267 if (ThenBlock)
268 EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
269 else
270 CGM.getOpenMPRuntime().EmitOMPSerialCall(*this, S.getLocStart(),
271 OutlinedFn, CapturedStruct);
272 });
273 } else
274 EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
275 }
276
EmitOMPLoopBody(const OMPLoopDirective & S,bool SeparateIter)277 void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &S,
278 bool SeparateIter) {
279 RunCleanupsScope BodyScope(*this);
280 // Update counters values on current iteration.
281 for (auto I : S.updates()) {
282 EmitIgnoredExpr(I);
283 }
284 // On a continue in the body, jump to the end.
285 auto Continue = getJumpDestInCurrentScope("omp.body.continue");
286 BreakContinueStack.push_back(BreakContinue(JumpDest(), Continue));
287 // Emit loop body.
288 EmitStmt(S.getBody());
289 // The end (updates/cleanups).
290 EmitBlock(Continue.getBlock());
291 BreakContinueStack.pop_back();
292 if (SeparateIter) {
293 // TODO: Update lastprivates if the SeparateIter flag is true.
294 // This will be implemented in a follow-up OMPLastprivateClause patch, but
295 // result should be still correct without it, as we do not make these
296 // variables private yet.
297 }
298 }
299
EmitOMPInnerLoop(const OMPLoopDirective & S,OMPPrivateScope & LoopScope,bool SeparateIter)300 void CodeGenFunction::EmitOMPInnerLoop(const OMPLoopDirective &S,
301 OMPPrivateScope &LoopScope,
302 bool SeparateIter) {
303 auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
304 auto Cnt = getPGORegionCounter(&S);
305
306 // Start the loop with a block that tests the condition.
307 auto CondBlock = createBasicBlock("omp.inner.for.cond");
308 EmitBlock(CondBlock);
309 LoopStack.push(CondBlock);
310
311 // If there are any cleanups between here and the loop-exit scope,
312 // create a block to stage a loop exit along.
313 auto ExitBlock = LoopExit.getBlock();
314 if (LoopScope.requiresCleanups())
315 ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
316
317 auto LoopBody = createBasicBlock("omp.inner.for.body");
318
319 // Emit condition: "IV < LastIteration + 1 [ - 1]"
320 // ("- 1" when lastprivate clause is present - separate one iteration).
321 llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond(SeparateIter));
322 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,
323 PGO.createLoopWeights(S.getCond(SeparateIter), Cnt));
324
325 if (ExitBlock != LoopExit.getBlock()) {
326 EmitBlock(ExitBlock);
327 EmitBranchThroughCleanup(LoopExit);
328 }
329
330 EmitBlock(LoopBody);
331 Cnt.beginRegion(Builder);
332
333 // Create a block for the increment.
334 auto Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
335 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
336
337 EmitOMPLoopBody(S);
338 EmitStopPoint(&S);
339
340 // Emit "IV = IV + 1" and a back-edge to the condition block.
341 EmitBlock(Continue.getBlock());
342 EmitIgnoredExpr(S.getInc());
343 BreakContinueStack.pop_back();
344 EmitBranch(CondBlock);
345 LoopStack.pop();
346 // Emit the fall-through block.
347 EmitBlock(LoopExit.getBlock());
348 }
349
EmitOMPSimdFinal(const OMPLoopDirective & S)350 void CodeGenFunction::EmitOMPSimdFinal(const OMPLoopDirective &S) {
351 auto IC = S.counters().begin();
352 for (auto F : S.finals()) {
353 if (LocalDeclMap.lookup(cast<DeclRefExpr>((*IC))->getDecl())) {
354 EmitIgnoredExpr(F);
355 }
356 ++IC;
357 }
358 }
359
EmitOMPAlignedClause(CodeGenFunction & CGF,CodeGenModule & CGM,const OMPAlignedClause & Clause)360 static void EmitOMPAlignedClause(CodeGenFunction &CGF, CodeGenModule &CGM,
361 const OMPAlignedClause &Clause) {
362 unsigned ClauseAlignment = 0;
363 if (auto AlignmentExpr = Clause.getAlignment()) {
364 auto AlignmentCI =
365 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
366 ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue());
367 }
368 for (auto E : Clause.varlists()) {
369 unsigned Alignment = ClauseAlignment;
370 if (Alignment == 0) {
371 // OpenMP [2.8.1, Description]
372 // If no optional parameter is specified, implementation-defined default
373 // alignments for SIMD instructions on the target platforms are assumed.
374 Alignment = CGM.getTargetCodeGenInfo().getOpenMPSimdDefaultAlignment(
375 E->getType());
376 }
377 assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
378 "alignment is not power of 2");
379 if (Alignment != 0) {
380 llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
381 CGF.EmitAlignmentAssumption(PtrValue, Alignment);
382 }
383 }
384 }
385
EmitPrivateLoopCounters(CodeGenFunction & CGF,CodeGenFunction::OMPPrivateScope & LoopScope,ArrayRef<Expr * > Counters)386 static void EmitPrivateLoopCounters(CodeGenFunction &CGF,
387 CodeGenFunction::OMPPrivateScope &LoopScope,
388 ArrayRef<Expr *> Counters) {
389 for (auto *E : Counters) {
390 auto VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
391 bool IsRegistered = LoopScope.addPrivate(VD, [&]() -> llvm::Value * {
392 // Emit var without initialization.
393 auto VarEmission = CGF.EmitAutoVarAlloca(*VD);
394 CGF.EmitAutoVarCleanups(VarEmission);
395 return VarEmission.getAllocatedAddress();
396 });
397 assert(IsRegistered && "counter already registered as private");
398 // Silence the warning about unused variable.
399 (void)IsRegistered;
400 }
401 (void)LoopScope.Privatize();
402 }
403
EmitOMPSimdDirective(const OMPSimdDirective & S)404 void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
405 // Pragma 'simd' code depends on presence of 'lastprivate'.
406 // If present, we have to separate last iteration of the loop:
407 //
408 // if (LastIteration != 0) {
409 // for (IV in 0..LastIteration-1) BODY;
410 // BODY with updates of lastprivate vars;
411 // <Final counter/linear vars updates>;
412 // }
413 //
414 // otherwise (when there's no lastprivate):
415 //
416 // for (IV in 0..LastIteration) BODY;
417 // <Final counter/linear vars updates>;
418 //
419
420 // Walk clauses and process safelen/lastprivate.
421 bool SeparateIter = false;
422 LoopStack.setParallel();
423 LoopStack.setVectorizerEnable(true);
424 for (auto C : S.clauses()) {
425 switch (C->getClauseKind()) {
426 case OMPC_safelen: {
427 RValue Len = EmitAnyExpr(cast<OMPSafelenClause>(C)->getSafelen(),
428 AggValueSlot::ignored(), true);
429 llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
430 LoopStack.setVectorizerWidth(Val->getZExtValue());
431 // In presence of finite 'safelen', it may be unsafe to mark all
432 // the memory instructions parallel, because loop-carried
433 // dependences of 'safelen' iterations are possible.
434 LoopStack.setParallel(false);
435 break;
436 }
437 case OMPC_aligned:
438 EmitOMPAlignedClause(*this, CGM, cast<OMPAlignedClause>(*C));
439 break;
440 case OMPC_lastprivate:
441 SeparateIter = true;
442 break;
443 default:
444 // Not handled yet
445 ;
446 }
447 }
448
449 InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
450 RunCleanupsScope DirectiveScope(*this);
451
452 CGDebugInfo *DI = getDebugInfo();
453 if (DI)
454 DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
455
456 // Emit the loop iteration variable.
457 const Expr *IVExpr = S.getIterationVariable();
458 const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
459 EmitVarDecl(*IVDecl);
460 EmitIgnoredExpr(S.getInit());
461
462 // Emit the iterations count variable.
463 // If it is not a variable, Sema decided to calculate iterations count on each
464 // iteration (e.g., it is foldable into a constant).
465 if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
466 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
467 // Emit calculation of the iterations count.
468 EmitIgnoredExpr(S.getCalcLastIteration());
469 }
470
471 if (SeparateIter) {
472 // Emit: if (LastIteration > 0) - begin.
473 RegionCounter Cnt = getPGORegionCounter(&S);
474 auto ThenBlock = createBasicBlock("simd.if.then");
475 auto ContBlock = createBasicBlock("simd.if.end");
476 EmitBranchOnBoolExpr(S.getPreCond(), ThenBlock, ContBlock, Cnt.getCount());
477 EmitBlock(ThenBlock);
478 Cnt.beginRegion(Builder);
479 // Emit 'then' code.
480 {
481 OMPPrivateScope LoopScope(*this);
482 EmitPrivateLoopCounters(*this, LoopScope, S.counters());
483 EmitOMPInnerLoop(S, LoopScope, /* SeparateIter */ true);
484 EmitOMPLoopBody(S, /* SeparateIter */ true);
485 }
486 EmitOMPSimdFinal(S);
487 // Emit: if (LastIteration != 0) - end.
488 EmitBranch(ContBlock);
489 EmitBlock(ContBlock, true);
490 } else {
491 {
492 OMPPrivateScope LoopScope(*this);
493 EmitPrivateLoopCounters(*this, LoopScope, S.counters());
494 EmitOMPInnerLoop(S, LoopScope);
495 }
496 EmitOMPSimdFinal(S);
497 }
498
499 if (DI)
500 DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
501 }
502
503 /// \brief Emit a helper variable and return corresponding lvalue.
EmitOMPHelperVar(CodeGenFunction & CGF,const DeclRefExpr * Helper)504 static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
505 const DeclRefExpr *Helper) {
506 auto VDecl = cast<VarDecl>(Helper->getDecl());
507 CGF.EmitVarDecl(*VDecl);
508 return CGF.EmitLValue(Helper);
509 }
510
EmitOMPWorksharingLoop(const OMPLoopDirective & S)511 void CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
512 // Emit the loop iteration variable.
513 auto IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
514 auto IVDecl = cast<VarDecl>(IVExpr->getDecl());
515 EmitVarDecl(*IVDecl);
516
517 // Emit the iterations count variable.
518 // If it is not a variable, Sema decided to calculate iterations count on each
519 // iteration (e.g., it is foldable into a constant).
520 if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
521 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
522 // Emit calculation of the iterations count.
523 EmitIgnoredExpr(S.getCalcLastIteration());
524 }
525
526 auto &RT = CGM.getOpenMPRuntime();
527
528 // Check pre-condition.
529 {
530 // Skip the entire loop if we don't meet the precondition.
531 RegionCounter Cnt = getPGORegionCounter(&S);
532 auto ThenBlock = createBasicBlock("omp.precond.then");
533 auto ContBlock = createBasicBlock("omp.precond.end");
534 EmitBranchOnBoolExpr(S.getPreCond(), ThenBlock, ContBlock, Cnt.getCount());
535 EmitBlock(ThenBlock);
536 Cnt.beginRegion(Builder);
537 // Emit 'then' code.
538 {
539 // Emit helper vars inits.
540 LValue LB =
541 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getLowerBoundVariable()));
542 LValue UB =
543 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getUpperBoundVariable()));
544 LValue ST =
545 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
546 LValue IL =
547 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
548
549 OMPPrivateScope LoopScope(*this);
550 EmitPrivateLoopCounters(*this, LoopScope, S.counters());
551
552 // Detect the loop schedule kind and chunk.
553 auto ScheduleKind = OMPC_SCHEDULE_unknown;
554 llvm::Value *Chunk = nullptr;
555 if (auto C = cast_or_null<OMPScheduleClause>(
556 S.getSingleClause(OMPC_schedule))) {
557 ScheduleKind = C->getScheduleKind();
558 if (auto Ch = C->getChunkSize()) {
559 Chunk = EmitScalarExpr(Ch);
560 Chunk = EmitScalarConversion(Chunk, Ch->getType(),
561 S.getIterationVariable()->getType());
562 }
563 }
564 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
565 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
566 if (RT.isStaticNonchunked(ScheduleKind,
567 /* Chunked */ Chunk != nullptr)) {
568 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
569 // When no chunk_size is specified, the iteration space is divided into
570 // chunks that are approximately equal in size, and at most one chunk is
571 // distributed to each thread. Note that the size of the chunks is
572 // unspecified in this case.
573 RT.EmitOMPForInit(*this, S.getLocStart(), ScheduleKind, IVSize, IVSigned,
574 IL.getAddress(), LB.getAddress(), UB.getAddress(),
575 ST.getAddress());
576 // UB = min(UB, GlobalUB);
577 EmitIgnoredExpr(S.getEnsureUpperBound());
578 // IV = LB;
579 EmitIgnoredExpr(S.getInit());
580 // while (idx <= UB) { BODY; ++idx; }
581 EmitOMPInnerLoop(S, LoopScope);
582 // Tell the runtime we are done.
583 RT.EmitOMPForFinish(*this, S.getLocStart(), ScheduleKind);
584 } else
585 ErrorUnsupported(&S, "OpenMP loop with requested schedule");
586 }
587 // We're now done with the loop, so jump to the continuation block.
588 EmitBranch(ContBlock);
589 EmitBlock(ContBlock, true);
590 }
591 }
592
EmitOMPForDirective(const OMPForDirective & S)593 void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
594 InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
595 RunCleanupsScope DirectiveScope(*this);
596
597 CGDebugInfo *DI = getDebugInfo();
598 if (DI)
599 DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
600
601 EmitOMPWorksharingLoop(S);
602
603 // Emit an implicit barrier at the end.
604 CGM.getOpenMPRuntime().EmitOMPBarrierCall(*this, S.getLocStart(),
605 /*IsExplicit*/ false);
606 if (DI)
607 DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
608 }
609
EmitOMPForSimdDirective(const OMPForSimdDirective &)610 void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &) {
611 llvm_unreachable("CodeGen for 'omp for simd' is not supported yet.");
612 }
613
EmitOMPSectionsDirective(const OMPSectionsDirective &)614 void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &) {
615 llvm_unreachable("CodeGen for 'omp sections' is not supported yet.");
616 }
617
EmitOMPSectionDirective(const OMPSectionDirective &)618 void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &) {
619 llvm_unreachable("CodeGen for 'omp section' is not supported yet.");
620 }
621
EmitOMPSingleDirective(const OMPSingleDirective &)622 void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) {
623 llvm_unreachable("CodeGen for 'omp single' is not supported yet.");
624 }
625
EmitOMPMasterDirective(const OMPMasterDirective & S)626 void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
627 CGM.getOpenMPRuntime().EmitOMPMasterRegion(*this, [&]() -> void {
628 InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
629 RunCleanupsScope Scope(*this);
630 EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
631 EnsureInsertPoint();
632 }, S.getLocStart());
633 }
634
EmitOMPCriticalDirective(const OMPCriticalDirective & S)635 void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
636 CGM.getOpenMPRuntime().EmitOMPCriticalRegion(
637 *this, S.getDirectiveName().getAsString(), [&]() -> void {
638 InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
639 RunCleanupsScope Scope(*this);
640 EmitStmt(
641 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
642 EnsureInsertPoint();
643 }, S.getLocStart());
644 }
645
646 void
EmitOMPParallelForDirective(const OMPParallelForDirective &)647 CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) {
648 llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet.");
649 }
650
EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &)651 void CodeGenFunction::EmitOMPParallelForSimdDirective(
652 const OMPParallelForSimdDirective &) {
653 llvm_unreachable("CodeGen for 'omp parallel for simd' is not supported yet.");
654 }
655
EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &)656 void CodeGenFunction::EmitOMPParallelSectionsDirective(
657 const OMPParallelSectionsDirective &) {
658 llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
659 }
660
EmitOMPTaskDirective(const OMPTaskDirective &)661 void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) {
662 llvm_unreachable("CodeGen for 'omp task' is not supported yet.");
663 }
664
EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &)665 void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) {
666 llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet.");
667 }
668
EmitOMPBarrierDirective(const OMPBarrierDirective & S)669 void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
670 CGM.getOpenMPRuntime().EmitOMPBarrierCall(*this, S.getLocStart());
671 }
672
EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &)673 void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &) {
674 llvm_unreachable("CodeGen for 'omp taskwait' is not supported yet.");
675 }
676
EmitOMPFlushDirective(const OMPFlushDirective & S)677 void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
678 CGM.getOpenMPRuntime().EmitOMPFlush(
679 *this, [&]() -> ArrayRef<const Expr *> {
680 if (auto C = S.getSingleClause(/*K*/ OMPC_flush)) {
681 auto FlushClause = cast<OMPFlushClause>(C);
682 return llvm::makeArrayRef(FlushClause->varlist_begin(),
683 FlushClause->varlist_end());
684 }
685 return llvm::None;
686 }(),
687 S.getLocStart());
688 }
689
EmitOMPOrderedDirective(const OMPOrderedDirective &)690 void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &) {
691 llvm_unreachable("CodeGen for 'omp ordered' is not supported yet.");
692 }
693
EmitOMPAtomicDirective(const OMPAtomicDirective &)694 void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &) {
695 llvm_unreachable("CodeGen for 'omp atomic' is not supported yet.");
696 }
697
EmitOMPTargetDirective(const OMPTargetDirective &)698 void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) {
699 llvm_unreachable("CodeGen for 'omp target' is not supported yet.");
700 }
701
EmitOMPTeamsDirective(const OMPTeamsDirective &)702 void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &) {
703 llvm_unreachable("CodeGen for 'omp teams' is not supported yet.");
704 }
705
706