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 /// \brief Emits code for OpenMP parallel directive in the parallel region.
187 static void EmitOMPParallelCall(CodeGenFunction &CGF,
188                                 const OMPParallelDirective &S,
189                                 llvm::Value *OutlinedFn,
190                                 llvm::Value *CapturedStruct) {
191   if (auto C = S.getSingleClause(/*K*/ OMPC_num_threads)) {
192     CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
193     auto NumThreadsClause = cast<OMPNumThreadsClause>(C);
194     auto NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
195                                          /*IgnoreResultAssign*/ true);
196     CGF.CGM.getOpenMPRuntime().EmitOMPNumThreadsClause(
197         CGF, NumThreads, NumThreadsClause->getLocStart());
198   }
199   CGF.CGM.getOpenMPRuntime().EmitOMPParallelCall(CGF, S.getLocStart(),
200                                                  OutlinedFn, CapturedStruct);
201 }
202 
203 void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
204   auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
205   auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
206   auto OutlinedFn = CGM.getOpenMPRuntime().EmitOpenMPOutlinedFunction(
207       S, *CS->getCapturedDecl()->param_begin());
208   if (auto C = S.getSingleClause(/*K*/ OMPC_if)) {
209     auto Cond = cast<OMPIfClause>(C)->getCondition();
210     EmitOMPIfClause(*this, Cond, [&](bool ThenBlock) {
211       if (ThenBlock)
212         EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
213       else
214         CGM.getOpenMPRuntime().EmitOMPSerialCall(*this, S.getLocStart(),
215                                                  OutlinedFn, CapturedStruct);
216     });
217   } else
218     EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
219 }
220 
221 void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &S,
222                                       bool SeparateIter) {
223   RunCleanupsScope BodyScope(*this);
224   // Update counters values on current iteration.
225   for (auto I : S.updates()) {
226     EmitIgnoredExpr(I);
227   }
228   // On a continue in the body, jump to the end.
229   auto Continue = getJumpDestInCurrentScope("omp.body.continue");
230   BreakContinueStack.push_back(BreakContinue(JumpDest(), Continue));
231   // Emit loop body.
232   EmitStmt(S.getBody());
233   // The end (updates/cleanups).
234   EmitBlock(Continue.getBlock());
235   BreakContinueStack.pop_back();
236   if (SeparateIter) {
237     // TODO: Update lastprivates if the SeparateIter flag is true.
238     // This will be implemented in a follow-up OMPLastprivateClause patch, but
239     // result should be still correct without it, as we do not make these
240     // variables private yet.
241   }
242 }
243 
244 void CodeGenFunction::EmitOMPInnerLoop(const OMPLoopDirective &S,
245                                        OMPPrivateScope &LoopScope,
246                                        bool SeparateIter) {
247   auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
248   auto Cnt = getPGORegionCounter(&S);
249 
250   // Start the loop with a block that tests the condition.
251   auto CondBlock = createBasicBlock("omp.inner.for.cond");
252   EmitBlock(CondBlock);
253   LoopStack.push(CondBlock);
254 
255   // If there are any cleanups between here and the loop-exit scope,
256   // create a block to stage a loop exit along.
257   auto ExitBlock = LoopExit.getBlock();
258   if (LoopScope.requiresCleanups())
259     ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
260 
261   auto LoopBody = createBasicBlock("omp.inner.for.body");
262 
263   // Emit condition: "IV < LastIteration + 1 [ - 1]"
264   // ("- 1" when lastprivate clause is present - separate one iteration).
265   llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond(SeparateIter));
266   Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,
267                        PGO.createLoopWeights(S.getCond(SeparateIter), Cnt));
268 
269   if (ExitBlock != LoopExit.getBlock()) {
270     EmitBlock(ExitBlock);
271     EmitBranchThroughCleanup(LoopExit);
272   }
273 
274   EmitBlock(LoopBody);
275   Cnt.beginRegion(Builder);
276 
277   // Create a block for the increment.
278   auto Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
279   BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
280 
281   EmitOMPLoopBody(S);
282   EmitStopPoint(&S);
283 
284   // Emit "IV = IV + 1" and a back-edge to the condition block.
285   EmitBlock(Continue.getBlock());
286   EmitIgnoredExpr(S.getInc());
287   BreakContinueStack.pop_back();
288   EmitBranch(CondBlock);
289   LoopStack.pop();
290   // Emit the fall-through block.
291   EmitBlock(LoopExit.getBlock());
292 }
293 
294 void CodeGenFunction::EmitOMPSimdFinal(const OMPLoopDirective &S) {
295   auto IC = S.counters().begin();
296   for (auto F : S.finals()) {
297     if (LocalDeclMap.lookup(cast<DeclRefExpr>((*IC))->getDecl())) {
298       EmitIgnoredExpr(F);
299     }
300     ++IC;
301   }
302 }
303 
304 static void EmitOMPAlignedClause(CodeGenFunction &CGF, CodeGenModule &CGM,
305                                  const OMPAlignedClause &Clause) {
306   unsigned ClauseAlignment = 0;
307   if (auto AlignmentExpr = Clause.getAlignment()) {
308     auto AlignmentCI =
309         cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
310     ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue());
311   }
312   for (auto E : Clause.varlists()) {
313     unsigned Alignment = ClauseAlignment;
314     if (Alignment == 0) {
315       // OpenMP [2.8.1, Description]
316       // If no optional parameter is specified, implementation-defined default
317       // alignments for SIMD instructions on the target platforms are assumed.
318       Alignment = CGM.getTargetCodeGenInfo().getOpenMPSimdDefaultAlignment(
319           E->getType());
320     }
321     assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
322            "alignment is not power of 2");
323     if (Alignment != 0) {
324       llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
325       CGF.EmitAlignmentAssumption(PtrValue, Alignment);
326     }
327   }
328 }
329 
330 static void EmitPrivateLoopCounters(CodeGenFunction &CGF,
331                                     CodeGenFunction::OMPPrivateScope &LoopScope,
332                                     ArrayRef<Expr *> Counters) {
333   for (auto *E : Counters) {
334     auto VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
335     bool IsRegistered = LoopScope.addPrivate(VD, [&]() -> llvm::Value * {
336       // Emit var without initialization.
337       auto VarEmission = CGF.EmitAutoVarAlloca(*VD);
338       CGF.EmitAutoVarCleanups(VarEmission);
339       return VarEmission.getAllocatedAddress();
340     });
341     assert(IsRegistered && "counter already registered as private");
342     // Silence the warning about unused variable.
343     (void)IsRegistered;
344   }
345   (void)LoopScope.Privatize();
346 }
347 
348 void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
349   // Pragma 'simd' code depends on presence of 'lastprivate'.
350   // If present, we have to separate last iteration of the loop:
351   //
352   // if (LastIteration != 0) {
353   //   for (IV in 0..LastIteration-1) BODY;
354   //   BODY with updates of lastprivate vars;
355   //   <Final counter/linear vars updates>;
356   // }
357   //
358   // otherwise (when there's no lastprivate):
359   //
360   //   for (IV in 0..LastIteration) BODY;
361   //   <Final counter/linear vars updates>;
362   //
363 
364   // Walk clauses and process safelen/lastprivate.
365   bool SeparateIter = false;
366   LoopStack.setParallel();
367   LoopStack.setVectorizerEnable(true);
368   for (auto C : S.clauses()) {
369     switch (C->getClauseKind()) {
370     case OMPC_safelen: {
371       RValue Len = EmitAnyExpr(cast<OMPSafelenClause>(C)->getSafelen(),
372                                AggValueSlot::ignored(), true);
373       llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
374       LoopStack.setVectorizerWidth(Val->getZExtValue());
375       // In presence of finite 'safelen', it may be unsafe to mark all
376       // the memory instructions parallel, because loop-carried
377       // dependences of 'safelen' iterations are possible.
378       LoopStack.setParallel(false);
379       break;
380     }
381     case OMPC_aligned:
382       EmitOMPAlignedClause(*this, CGM, cast<OMPAlignedClause>(*C));
383       break;
384     case OMPC_lastprivate:
385       SeparateIter = true;
386       break;
387     default:
388       // Not handled yet
389       ;
390     }
391   }
392 
393   RunCleanupsScope DirectiveScope(*this);
394 
395   CGDebugInfo *DI = getDebugInfo();
396   if (DI)
397     DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
398 
399   // Emit the loop iteration variable.
400   const Expr *IVExpr = S.getIterationVariable();
401   const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
402   EmitVarDecl(*IVDecl);
403   EmitIgnoredExpr(S.getInit());
404 
405   // Emit the iterations count variable.
406   // If it is not a variable, Sema decided to calculate iterations count on each
407   // iteration (e.g., it is foldable into a constant).
408   if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
409     EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
410     // Emit calculation of the iterations count.
411     EmitIgnoredExpr(S.getCalcLastIteration());
412   }
413 
414   if (SeparateIter) {
415     // Emit: if (LastIteration > 0) - begin.
416     RegionCounter Cnt = getPGORegionCounter(&S);
417     auto ThenBlock = createBasicBlock("simd.if.then");
418     auto ContBlock = createBasicBlock("simd.if.end");
419     EmitBranchOnBoolExpr(S.getPreCond(), ThenBlock, ContBlock, Cnt.getCount());
420     EmitBlock(ThenBlock);
421     Cnt.beginRegion(Builder);
422     // Emit 'then' code.
423     {
424       OMPPrivateScope LoopScope(*this);
425       EmitPrivateLoopCounters(*this, LoopScope, S.counters());
426       EmitOMPInnerLoop(S, LoopScope, /* SeparateIter */ true);
427       EmitOMPLoopBody(S, /* SeparateIter */ true);
428     }
429     EmitOMPSimdFinal(S);
430     // Emit: if (LastIteration != 0) - end.
431     EmitBranch(ContBlock);
432     EmitBlock(ContBlock, true);
433   } else {
434     {
435       OMPPrivateScope LoopScope(*this);
436       EmitPrivateLoopCounters(*this, LoopScope, S.counters());
437       EmitOMPInnerLoop(S, LoopScope);
438     }
439     EmitOMPSimdFinal(S);
440   }
441 
442   if (DI)
443     DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
444 }
445 
446 void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &) {
447   llvm_unreachable("CodeGen for 'omp for' is not supported yet.");
448 }
449 
450 void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &) {
451   llvm_unreachable("CodeGen for 'omp for simd' is not supported yet.");
452 }
453 
454 void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &) {
455   llvm_unreachable("CodeGen for 'omp sections' is not supported yet.");
456 }
457 
458 void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &) {
459   llvm_unreachable("CodeGen for 'omp section' is not supported yet.");
460 }
461 
462 void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) {
463   llvm_unreachable("CodeGen for 'omp single' is not supported yet.");
464 }
465 
466 void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &) {
467   llvm_unreachable("CodeGen for 'omp master' is not supported yet.");
468 }
469 
470 void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
471   // __kmpc_critical();
472   // <captured_body>
473   // __kmpc_end_critical();
474   //
475 
476   auto Lock = CGM.getOpenMPRuntime().GetCriticalRegionLock(
477       S.getDirectiveName().getAsString());
478   CGM.getOpenMPRuntime().EmitOMPCriticalRegionStart(*this, Lock,
479                                                     S.getLocStart());
480   {
481     RunCleanupsScope Scope(*this);
482     EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
483     EnsureInsertPoint();
484   }
485   CGM.getOpenMPRuntime().EmitOMPCriticalRegionEnd(*this, Lock, S.getLocEnd());
486 }
487 
488 void
489 CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) {
490   llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet.");
491 }
492 
493 void CodeGenFunction::EmitOMPParallelForSimdDirective(
494     const OMPParallelForSimdDirective &) {
495   llvm_unreachable("CodeGen for 'omp parallel for simd' is not supported yet.");
496 }
497 
498 void CodeGenFunction::EmitOMPParallelSectionsDirective(
499     const OMPParallelSectionsDirective &) {
500   llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
501 }
502 
503 void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) {
504   llvm_unreachable("CodeGen for 'omp task' is not supported yet.");
505 }
506 
507 void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) {
508   llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet.");
509 }
510 
511 void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &) {
512   llvm_unreachable("CodeGen for 'omp barrier' is not supported yet.");
513 }
514 
515 void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &) {
516   llvm_unreachable("CodeGen for 'omp taskwait' is not supported yet.");
517 }
518 
519 void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &) {
520   llvm_unreachable("CodeGen for 'omp flush' is not supported yet.");
521 }
522 
523 void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &) {
524   llvm_unreachable("CodeGen for 'omp ordered' is not supported yet.");
525 }
526 
527 void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &) {
528   llvm_unreachable("CodeGen for 'omp atomic' is not supported yet.");
529 }
530 
531 void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) {
532   llvm_unreachable("CodeGen for 'omp target' is not supported yet.");
533 }
534 
535 void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &) {
536   llvm_unreachable("CodeGen for 'omp teams' is not supported yet.");
537 }
538 
539