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