1 //===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This contains code to emit OpenMP nodes as LLVM code.
12 //===----------------------------------------------------------------------===//
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;
24 /// \brief RAII for emitting code of CapturedStmt without function outlining.
25 class InlinedOpenMPRegion {
27 CodeGenFunction::CGCapturedStmtInfo *PrevCapturedStmtInfo;
28 const Decl *StoredCurCodeDecl;
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 {
34 CGInlinedOpenMPRegionInfo() : CGCapturedStmtInfo() {}
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();
44 ~InlinedOpenMPRegion() {
45 delete CGF.CapturedStmtInfo;
46 CGF.CapturedStmtInfo = PrevCapturedStmtInfo;
47 CGF.CurCodeDecl = StoredCurCodeDecl;
52 //===----------------------------------------------------------------------===//
53 // OpenMP Directive Emission
54 //===----------------------------------------------------------------------===//
56 /// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
57 /// function. Here is the logic:
63 static void EmitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
64 const std::function<void(bool)> &CodeGen) {
65 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
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.
70 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
71 CodeGen(CondConstant);
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);
82 // Emit the 'then' code.
83 CGF.EmitBlock(ThenBlock);
84 CodeGen(/*ThenBlock*/ true);
85 CGF.EmitBranch(ContBlock);
86 // Emit the 'else' code if present.
88 // There is no need to emit line number for unconditional branch.
89 ApplyDebugLocation DL(CGF);
90 CGF.EmitBlock(ElseBlock);
92 CodeGen(/*ThenBlock*/ false);
94 // There is no need to emit line number for unconditional branch.
95 ApplyDebugLocation DL(CGF);
96 CGF.EmitBranch(ContBlock);
98 // Emit the continuation block for code after the if.
99 CGF.EmitBlock(ContBlock, /*IsFinished*/ true);
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());
113 // Perform element-by-element initialization.
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");
127 Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
128 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
130 // Enter the loop body, making that address the current address.
131 auto EntryBB = Builder.GetInsertBlock();
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);
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");
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);
157 // Check whether we've reached the end.
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());
165 EmitBlock(DoneBB, true);
167 EmitBlock(createBasicBlock(".omp.assign.end."));
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;
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());
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();
202 IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
203 // Emit private VarDecl with copy init.
205 return GetAddrOfLocalVar(VD);
207 assert(IsRegistered && "counter already registered as private");
208 // Silence the warning about unused variable.
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;
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());
229 PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
230 // Emit private VarDecl with copy init.
232 return GetAddrOfLocalVar(VD);
234 assert(IsRegistered && "counter already registered as private");
235 // Silence the warning about unused variable.
242 /// \brief Emits code for OpenMP parallel directive in the parallel region.
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());
255 CGF.CGM.getOpenMPRuntime().EmitOMPParallelCall(CGF, S.getLocStart(),
256 OutlinedFn, CapturedStruct);
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) {
268 EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
270 CGM.getOpenMPRuntime().EmitOMPSerialCall(*this, S.getLocStart(),
271 OutlinedFn, CapturedStruct);
274 EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
277 void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &S,
279 RunCleanupsScope BodyScope(*this);
280 // Update counters values on current iteration.
281 for (auto I : S.updates()) {
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));
288 EmitStmt(S.getBody());
289 // The end (updates/cleanups).
290 EmitBlock(Continue.getBlock());
291 BreakContinueStack.pop_back();
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.
300 void CodeGenFunction::EmitOMPInnerLoop(const OMPLoopDirective &S,
301 OMPPrivateScope &LoopScope,
303 auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
304 auto Cnt = getPGORegionCounter(&S);
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);
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");
317 auto LoopBody = createBasicBlock("omp.inner.for.body");
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));
325 if (ExitBlock != LoopExit.getBlock()) {
326 EmitBlock(ExitBlock);
327 EmitBranchThroughCleanup(LoopExit);
331 Cnt.beginRegion(Builder);
333 // Create a block for the increment.
334 auto Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
335 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
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);
346 // Emit the fall-through block.
347 EmitBlock(LoopExit.getBlock());
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())) {
360 static void EmitOMPAlignedClause(CodeGenFunction &CGF, CodeGenModule &CGM,
361 const OMPAlignedClause &Clause) {
362 unsigned ClauseAlignment = 0;
363 if (auto AlignmentExpr = Clause.getAlignment()) {
365 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
366 ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue());
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(
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);
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();
397 assert(IsRegistered && "counter already registered as private");
398 // Silence the warning about unused variable.
401 (void)LoopScope.Privatize();
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:
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>;
414 // otherwise (when there's no lastprivate):
416 // for (IV in 0..LastIteration) BODY;
417 // <Final counter/linear vars updates>;
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()) {
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);
438 EmitOMPAlignedClause(*this, CGM, cast<OMPAlignedClause>(*C));
440 case OMPC_lastprivate:
449 InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
450 RunCleanupsScope DirectiveScope(*this);
452 CGDebugInfo *DI = getDebugInfo();
454 DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
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());
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());
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);
481 OMPPrivateScope LoopScope(*this);
482 EmitPrivateLoopCounters(*this, LoopScope, S.counters());
483 EmitOMPInnerLoop(S, LoopScope, /* SeparateIter */ true);
484 EmitOMPLoopBody(S, /* SeparateIter */ true);
487 // Emit: if (LastIteration != 0) - end.
488 EmitBranch(ContBlock);
489 EmitBlock(ContBlock, true);
492 OMPPrivateScope LoopScope(*this);
493 EmitPrivateLoopCounters(*this, LoopScope, S.counters());
494 EmitOMPInnerLoop(S, LoopScope);
500 DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
503 /// \brief Emit a helper variable and return corresponding lvalue.
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);
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);
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());
526 auto &RT = CGM.getOpenMPRuntime();
528 // Check pre-condition.
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);
539 // Emit helper vars inits.
541 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getLowerBoundVariable()));
543 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getUpperBoundVariable()));
545 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
547 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
549 OMPPrivateScope LoopScope(*this);
550 EmitPrivateLoopCounters(*this, LoopScope, S.counters());
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());
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(),
576 // UB = min(UB, GlobalUB);
577 EmitIgnoredExpr(S.getEnsureUpperBound());
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);
585 ErrorUnsupported(&S, "OpenMP loop with requested schedule");
587 // We're now done with the loop, so jump to the continuation block.
588 EmitBranch(ContBlock);
589 EmitBlock(ContBlock, true);
593 void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
594 InlinedOpenMPRegion Region(*this, S.getAssociatedStmt());
595 RunCleanupsScope DirectiveScope(*this);
597 CGDebugInfo *DI = getDebugInfo();
599 DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
601 EmitOMPWorksharingLoop(S);
603 // Emit an implicit barrier at the end.
604 CGM.getOpenMPRuntime().EmitOMPBarrierCall(*this, S.getLocStart(),
605 /*IsExplicit*/ false);
607 DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
610 void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &) {
611 llvm_unreachable("CodeGen for 'omp for simd' is not supported yet.");
614 void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &) {
615 llvm_unreachable("CodeGen for 'omp sections' is not supported yet.");
618 void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &) {
619 llvm_unreachable("CodeGen for 'omp section' is not supported yet.");
622 void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) {
623 llvm_unreachable("CodeGen for 'omp single' is not supported yet.");
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());
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);
641 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
647 CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) {
648 llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet.");
651 void CodeGenFunction::EmitOMPParallelForSimdDirective(
652 const OMPParallelForSimdDirective &) {
653 llvm_unreachable("CodeGen for 'omp parallel for simd' is not supported yet.");
656 void CodeGenFunction::EmitOMPParallelSectionsDirective(
657 const OMPParallelSectionsDirective &) {
658 llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
661 void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) {
662 llvm_unreachable("CodeGen for 'omp task' is not supported yet.");
665 void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) {
666 llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet.");
669 void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
670 CGM.getOpenMPRuntime().EmitOMPBarrierCall(*this, S.getLocStart());
673 void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &) {
674 llvm_unreachable("CodeGen for 'omp taskwait' is not supported yet.");
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());
690 void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &) {
691 llvm_unreachable("CodeGen for 'omp ordered' is not supported yet.");
694 void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &) {
695 llvm_unreachable("CodeGen for 'omp atomic' is not supported yet.");
698 void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) {
699 llvm_unreachable("CodeGen for 'omp target' is not supported yet.");
702 void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &) {
703 llvm_unreachable("CodeGen for 'omp teams' is not supported yet.");