clang API Documentation

CGStmtOpenMP.cpp
Go to the documentation of this file.
00001 //===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This contains code to emit OpenMP nodes as LLVM code.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "CGOpenMPRuntime.h"
00015 #include "CodeGenFunction.h"
00016 #include "CodeGenModule.h"
00017 #include "clang/AST/Stmt.h"
00018 #include "clang/AST/StmtOpenMP.h"
00019 #include "TargetInfo.h"
00020 using namespace clang;
00021 using namespace CodeGen;
00022 
00023 //===----------------------------------------------------------------------===//
00024 //                              OpenMP Directive Emission
00025 //===----------------------------------------------------------------------===//
00026 
00027 /// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen
00028 /// function. Here is the logic:
00029 /// if (Cond) {
00030 ///   CodeGen(true);
00031 /// } else {
00032 ///   CodeGen(false);
00033 /// }
00034 static void EmitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
00035                             const std::function<void(bool)> &CodeGen) {
00036   CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
00037 
00038   // If the condition constant folds and can be elided, try to avoid emitting
00039   // the condition and the dead arm of the if/else.
00040   bool CondConstant;
00041   if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
00042     CodeGen(CondConstant);
00043     return;
00044   }
00045 
00046   // Otherwise, the condition did not fold, or we couldn't elide it.  Just
00047   // emit the conditional branch.
00048   auto ThenBlock = CGF.createBasicBlock(/*name*/ "omp_if.then");
00049   auto ElseBlock = CGF.createBasicBlock(/*name*/ "omp_if.else");
00050   auto ContBlock = CGF.createBasicBlock(/*name*/ "omp_if.end");
00051   CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount*/ 0);
00052 
00053   // Emit the 'then' code.
00054   CGF.EmitBlock(ThenBlock);
00055   CodeGen(/*ThenBlock*/ true);
00056   CGF.EmitBranch(ContBlock);
00057   // Emit the 'else' code if present.
00058   {
00059     // There is no need to emit line number for unconditional branch.
00060     SuppressDebugLocation SDL(CGF.Builder);
00061     CGF.EmitBlock(ElseBlock);
00062   }
00063   CodeGen(/*ThenBlock*/ false);
00064   {
00065     // There is no need to emit line number for unconditional branch.
00066     SuppressDebugLocation SDL(CGF.Builder);
00067     CGF.EmitBranch(ContBlock);
00068   }
00069   // Emit the continuation block for code after the if.
00070   CGF.EmitBlock(ContBlock, /*IsFinished*/ true);
00071 }
00072 
00073 void CodeGenFunction::EmitOMPAggregateAssign(LValue OriginalAddr,
00074                                              llvm::Value *PrivateAddr,
00075                                              const Expr *AssignExpr,
00076                                              QualType OriginalType,
00077                                              const VarDecl *VDInit) {
00078   EmitBlock(createBasicBlock(".omp.assign.begin."));
00079   if (!isa<CXXConstructExpr>(AssignExpr) || isTrivialInitializer(AssignExpr)) {
00080     // Perform simple memcpy.
00081     EmitAggregateAssign(PrivateAddr, OriginalAddr.getAddress(),
00082                         AssignExpr->getType());
00083   } else {
00084     // Perform element-by-element initialization.
00085     QualType ElementTy;
00086     auto SrcBegin = OriginalAddr.getAddress();
00087     auto DestBegin = PrivateAddr;
00088     auto ArrayTy = OriginalType->getAsArrayTypeUnsafe();
00089     auto SrcNumElements = emitArrayLength(ArrayTy, ElementTy, SrcBegin);
00090     auto DestNumElements = emitArrayLength(ArrayTy, ElementTy, DestBegin);
00091     auto SrcEnd = Builder.CreateGEP(SrcBegin, SrcNumElements);
00092     auto DestEnd = Builder.CreateGEP(DestBegin, DestNumElements);
00093     // The basic structure here is a do-while loop, because we don't
00094     // need to check for the zero-element case.
00095     auto BodyBB = createBasicBlock("omp.arraycpy.body");
00096     auto DoneBB = createBasicBlock("omp.arraycpy.done");
00097     auto IsEmpty =
00098         Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
00099     Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
00100 
00101     // Enter the loop body, making that address the current address.
00102     auto EntryBB = Builder.GetInsertBlock();
00103     EmitBlock(BodyBB);
00104     auto SrcElementPast = Builder.CreatePHI(SrcBegin->getType(), 2,
00105                                             "omp.arraycpy.srcElementPast");
00106     SrcElementPast->addIncoming(SrcEnd, EntryBB);
00107     auto DestElementPast = Builder.CreatePHI(DestBegin->getType(), 2,
00108                                              "omp.arraycpy.destElementPast");
00109     DestElementPast->addIncoming(DestEnd, EntryBB);
00110 
00111     // Shift the address back by one element.
00112     auto NegativeOne = llvm::ConstantInt::get(SizeTy, -1, true);
00113     auto DestElement = Builder.CreateGEP(DestElementPast, NegativeOne,
00114                                          "omp.arraycpy.dest.element");
00115     auto SrcElement = Builder.CreateGEP(SrcElementPast, NegativeOne,
00116                                         "omp.arraycpy.src.element");
00117     {
00118       // Create RunCleanScope to cleanup possible temps.
00119       CodeGenFunction::RunCleanupsScope Init(*this);
00120       // Emit initialization for single element.
00121       LocalDeclMap[VDInit] = SrcElement;
00122       EmitAnyExprToMem(AssignExpr, DestElement,
00123                        AssignExpr->getType().getQualifiers(),
00124                        /*IsInitializer*/ false);
00125       LocalDeclMap.erase(VDInit);
00126     }
00127 
00128     // Check whether we've reached the end.
00129     auto Done =
00130         Builder.CreateICmpEQ(DestElement, DestBegin, "omp.arraycpy.done");
00131     Builder.CreateCondBr(Done, DoneBB, BodyBB);
00132     DestElementPast->addIncoming(DestElement, Builder.GetInsertBlock());
00133     SrcElementPast->addIncoming(SrcElement, Builder.GetInsertBlock());
00134 
00135     // Done.
00136     EmitBlock(DoneBB, true);
00137   }
00138   EmitBlock(createBasicBlock(".omp.assign.end."));
00139 }
00140 
00141 void CodeGenFunction::EmitOMPFirstprivateClause(
00142     const OMPExecutableDirective &D,
00143     CodeGenFunction::OMPPrivateScope &PrivateScope) {
00144   auto PrivateFilter = [](const OMPClause *C) -> bool {
00145     return C->getClauseKind() == OMPC_firstprivate;
00146   };
00147   for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)>
00148            I(D.clauses(), PrivateFilter); I; ++I) {
00149     auto *C = cast<OMPFirstprivateClause>(*I);
00150     auto IRef = C->varlist_begin();
00151     auto InitsRef = C->inits().begin();
00152     for (auto IInit : C->private_copies()) {
00153       auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
00154       auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
00155       bool IsRegistered;
00156       if (*InitsRef != nullptr) {
00157         // Emit VarDecl with copy init for arrays.
00158         auto *FD = CapturedStmtInfo->lookup(OrigVD);
00159         LValue Base = MakeNaturalAlignAddrLValue(
00160             CapturedStmtInfo->getContextValue(),
00161             getContext().getTagDeclType(FD->getParent()));
00162         auto OriginalAddr = EmitLValueForField(Base, FD);
00163         auto VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
00164         IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
00165           auto Emission = EmitAutoVarAlloca(*VD);
00166           // Emit initialization of aggregate firstprivate vars.
00167           EmitOMPAggregateAssign(OriginalAddr, Emission.getAllocatedAddress(),
00168                                  VD->getInit(), (*IRef)->getType(), VDInit);
00169           EmitAutoVarCleanups(Emission);
00170           return Emission.getAllocatedAddress();
00171         });
00172       } else
00173         IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
00174           // Emit private VarDecl with copy init.
00175           EmitDecl(*VD);
00176           return GetAddrOfLocalVar(VD);
00177         });
00178       assert(IsRegistered && "counter already registered as private");
00179       // Silence the warning about unused variable.
00180       (void)IsRegistered;
00181       ++IRef, ++InitsRef;
00182     }
00183   }
00184 }
00185 
00186 void CodeGenFunction::EmitOMPPrivateClause(
00187     const OMPExecutableDirective &D,
00188     CodeGenFunction::OMPPrivateScope &PrivateScope) {
00189   auto PrivateFilter = [](const OMPClause *C) -> bool {
00190     return C->getClauseKind() == OMPC_private;
00191   };
00192   for (OMPExecutableDirective::filtered_clause_iterator<decltype(PrivateFilter)>
00193            I(D.clauses(), PrivateFilter); I; ++I) {
00194     auto *C = cast<OMPPrivateClause>(*I);
00195     auto IRef = C->varlist_begin();
00196     for (auto IInit : C->private_copies()) {
00197       auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
00198       auto VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
00199       bool IsRegistered =
00200           PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * {
00201             // Emit private VarDecl with copy init.
00202             EmitDecl(*VD);
00203             return GetAddrOfLocalVar(VD);
00204           });
00205       assert(IsRegistered && "counter already registered as private");
00206       // Silence the warning about unused variable.
00207       (void)IsRegistered;
00208       ++IRef;
00209     }
00210   }
00211 }
00212 
00213 /// \brief Emits code for OpenMP parallel directive in the parallel region.
00214 static void EmitOMPParallelCall(CodeGenFunction &CGF,
00215                                 const OMPParallelDirective &S,
00216                                 llvm::Value *OutlinedFn,
00217                                 llvm::Value *CapturedStruct) {
00218   if (auto C = S.getSingleClause(/*K*/ OMPC_num_threads)) {
00219     CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
00220     auto NumThreadsClause = cast<OMPNumThreadsClause>(C);
00221     auto NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
00222                                          /*IgnoreResultAssign*/ true);
00223     CGF.CGM.getOpenMPRuntime().EmitOMPNumThreadsClause(
00224         CGF, NumThreads, NumThreadsClause->getLocStart());
00225   }
00226   CGF.CGM.getOpenMPRuntime().EmitOMPParallelCall(CGF, S.getLocStart(),
00227                                                  OutlinedFn, CapturedStruct);
00228 }
00229 
00230 void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
00231   auto CS = cast<CapturedStmt>(S.getAssociatedStmt());
00232   auto CapturedStruct = GenerateCapturedStmtArgument(*CS);
00233   auto OutlinedFn = CGM.getOpenMPRuntime().EmitOpenMPOutlinedFunction(
00234       S, *CS->getCapturedDecl()->param_begin());
00235   if (auto C = S.getSingleClause(/*K*/ OMPC_if)) {
00236     auto Cond = cast<OMPIfClause>(C)->getCondition();
00237     EmitOMPIfClause(*this, Cond, [&](bool ThenBlock) {
00238       if (ThenBlock)
00239         EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
00240       else
00241         CGM.getOpenMPRuntime().EmitOMPSerialCall(*this, S.getLocStart(),
00242                                                  OutlinedFn, CapturedStruct);
00243     });
00244   } else
00245     EmitOMPParallelCall(*this, S, OutlinedFn, CapturedStruct);
00246 }
00247 
00248 void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &S,
00249                                       bool SeparateIter) {
00250   RunCleanupsScope BodyScope(*this);
00251   // Update counters values on current iteration.
00252   for (auto I : S.updates()) {
00253     EmitIgnoredExpr(I);
00254   }
00255   // On a continue in the body, jump to the end.
00256   auto Continue = getJumpDestInCurrentScope("omp.body.continue");
00257   BreakContinueStack.push_back(BreakContinue(JumpDest(), Continue));
00258   // Emit loop body.
00259   EmitStmt(S.getBody());
00260   // The end (updates/cleanups).
00261   EmitBlock(Continue.getBlock());
00262   BreakContinueStack.pop_back();
00263   if (SeparateIter) {
00264     // TODO: Update lastprivates if the SeparateIter flag is true.
00265     // This will be implemented in a follow-up OMPLastprivateClause patch, but
00266     // result should be still correct without it, as we do not make these
00267     // variables private yet.
00268   }
00269 }
00270 
00271 void CodeGenFunction::EmitOMPInnerLoop(const OMPLoopDirective &S,
00272                                        OMPPrivateScope &LoopScope,
00273                                        bool SeparateIter) {
00274   auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
00275   auto Cnt = getPGORegionCounter(&S);
00276 
00277   // Start the loop with a block that tests the condition.
00278   auto CondBlock = createBasicBlock("omp.inner.for.cond");
00279   EmitBlock(CondBlock);
00280   LoopStack.push(CondBlock);
00281 
00282   // If there are any cleanups between here and the loop-exit scope,
00283   // create a block to stage a loop exit along.
00284   auto ExitBlock = LoopExit.getBlock();
00285   if (LoopScope.requiresCleanups())
00286     ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
00287 
00288   auto LoopBody = createBasicBlock("omp.inner.for.body");
00289 
00290   // Emit condition: "IV < LastIteration + 1 [ - 1]"
00291   // ("- 1" when lastprivate clause is present - separate one iteration).
00292   llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond(SeparateIter));
00293   Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,
00294                        PGO.createLoopWeights(S.getCond(SeparateIter), Cnt));
00295 
00296   if (ExitBlock != LoopExit.getBlock()) {
00297     EmitBlock(ExitBlock);
00298     EmitBranchThroughCleanup(LoopExit);
00299   }
00300 
00301   EmitBlock(LoopBody);
00302   Cnt.beginRegion(Builder);
00303 
00304   // Create a block for the increment.
00305   auto Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
00306   BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
00307 
00308   EmitOMPLoopBody(S);
00309   EmitStopPoint(&S);
00310 
00311   // Emit "IV = IV + 1" and a back-edge to the condition block.
00312   EmitBlock(Continue.getBlock());
00313   EmitIgnoredExpr(S.getInc());
00314   BreakContinueStack.pop_back();
00315   EmitBranch(CondBlock);
00316   LoopStack.pop();
00317   // Emit the fall-through block.
00318   EmitBlock(LoopExit.getBlock());
00319 }
00320 
00321 void CodeGenFunction::EmitOMPSimdFinal(const OMPLoopDirective &S) {
00322   auto IC = S.counters().begin();
00323   for (auto F : S.finals()) {
00324     if (LocalDeclMap.lookup(cast<DeclRefExpr>((*IC))->getDecl())) {
00325       EmitIgnoredExpr(F);
00326     }
00327     ++IC;
00328   }
00329 }
00330 
00331 static void EmitOMPAlignedClause(CodeGenFunction &CGF, CodeGenModule &CGM,
00332                                  const OMPAlignedClause &Clause) {
00333   unsigned ClauseAlignment = 0;
00334   if (auto AlignmentExpr = Clause.getAlignment()) {
00335     auto AlignmentCI =
00336         cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
00337     ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue());
00338   }
00339   for (auto E : Clause.varlists()) {
00340     unsigned Alignment = ClauseAlignment;
00341     if (Alignment == 0) {
00342       // OpenMP [2.8.1, Description]
00343       // If no optional parameter is specified, implementation-defined default
00344       // alignments for SIMD instructions on the target platforms are assumed.
00345       Alignment = CGM.getTargetCodeGenInfo().getOpenMPSimdDefaultAlignment(
00346           E->getType());
00347     }
00348     assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
00349            "alignment is not power of 2");
00350     if (Alignment != 0) {
00351       llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
00352       CGF.EmitAlignmentAssumption(PtrValue, Alignment);
00353     }
00354   }
00355 }
00356 
00357 static void EmitPrivateLoopCounters(CodeGenFunction &CGF,
00358                                     CodeGenFunction::OMPPrivateScope &LoopScope,
00359                                     ArrayRef<Expr *> Counters) {
00360   for (auto *E : Counters) {
00361     auto VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
00362     bool IsRegistered = LoopScope.addPrivate(VD, [&]() -> llvm::Value * {
00363       // Emit var without initialization.
00364       auto VarEmission = CGF.EmitAutoVarAlloca(*VD);
00365       CGF.EmitAutoVarCleanups(VarEmission);
00366       return VarEmission.getAllocatedAddress();
00367     });
00368     assert(IsRegistered && "counter already registered as private");
00369     // Silence the warning about unused variable.
00370     (void)IsRegistered;
00371   }
00372   (void)LoopScope.Privatize();
00373 }
00374 
00375 void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
00376   // Pragma 'simd' code depends on presence of 'lastprivate'.
00377   // If present, we have to separate last iteration of the loop:
00378   //
00379   // if (LastIteration != 0) {
00380   //   for (IV in 0..LastIteration-1) BODY;
00381   //   BODY with updates of lastprivate vars;
00382   //   <Final counter/linear vars updates>;
00383   // }
00384   //
00385   // otherwise (when there's no lastprivate):
00386   //
00387   //   for (IV in 0..LastIteration) BODY;
00388   //   <Final counter/linear vars updates>;
00389   //
00390 
00391   // Walk clauses and process safelen/lastprivate.
00392   bool SeparateIter = false;
00393   LoopStack.setParallel();
00394   LoopStack.setVectorizerEnable(true);
00395   for (auto C : S.clauses()) {
00396     switch (C->getClauseKind()) {
00397     case OMPC_safelen: {
00398       RValue Len = EmitAnyExpr(cast<OMPSafelenClause>(C)->getSafelen(),
00399                                AggValueSlot::ignored(), true);
00400       llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
00401       LoopStack.setVectorizerWidth(Val->getZExtValue());
00402       // In presence of finite 'safelen', it may be unsafe to mark all
00403       // the memory instructions parallel, because loop-carried
00404       // dependences of 'safelen' iterations are possible.
00405       LoopStack.setParallel(false);
00406       break;
00407     }
00408     case OMPC_aligned:
00409       EmitOMPAlignedClause(*this, CGM, cast<OMPAlignedClause>(*C));
00410       break;
00411     case OMPC_lastprivate:
00412       SeparateIter = true;
00413       break;
00414     default:
00415       // Not handled yet
00416       ;
00417     }
00418   }
00419 
00420   RunCleanupsScope DirectiveScope(*this);
00421 
00422   CGDebugInfo *DI = getDebugInfo();
00423   if (DI)
00424     DI->EmitLexicalBlockStart(Builder, S.getSourceRange().getBegin());
00425 
00426   // Emit the loop iteration variable.
00427   const Expr *IVExpr = S.getIterationVariable();
00428   const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
00429   EmitVarDecl(*IVDecl);
00430   EmitIgnoredExpr(S.getInit());
00431 
00432   // Emit the iterations count variable.
00433   // If it is not a variable, Sema decided to calculate iterations count on each
00434   // iteration (e.g., it is foldable into a constant).
00435   if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
00436     EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
00437     // Emit calculation of the iterations count.
00438     EmitIgnoredExpr(S.getCalcLastIteration());
00439   }
00440 
00441   if (SeparateIter) {
00442     // Emit: if (LastIteration > 0) - begin.
00443     RegionCounter Cnt = getPGORegionCounter(&S);
00444     auto ThenBlock = createBasicBlock("simd.if.then");
00445     auto ContBlock = createBasicBlock("simd.if.end");
00446     EmitBranchOnBoolExpr(S.getPreCond(), ThenBlock, ContBlock, Cnt.getCount());
00447     EmitBlock(ThenBlock);
00448     Cnt.beginRegion(Builder);
00449     // Emit 'then' code.
00450     {
00451       OMPPrivateScope LoopScope(*this);
00452       EmitPrivateLoopCounters(*this, LoopScope, S.counters());
00453       EmitOMPInnerLoop(S, LoopScope, /* SeparateIter */ true);
00454       EmitOMPLoopBody(S, /* SeparateIter */ true);
00455     }
00456     EmitOMPSimdFinal(S);
00457     // Emit: if (LastIteration != 0) - end.
00458     EmitBranch(ContBlock);
00459     EmitBlock(ContBlock, true);
00460   } else {
00461     {
00462       OMPPrivateScope LoopScope(*this);
00463       EmitPrivateLoopCounters(*this, LoopScope, S.counters());
00464       EmitOMPInnerLoop(S, LoopScope);
00465     }
00466     EmitOMPSimdFinal(S);
00467   }
00468 
00469   if (DI)
00470     DI->EmitLexicalBlockEnd(Builder, S.getSourceRange().getEnd());
00471 }
00472 
00473 void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &) {
00474   llvm_unreachable("CodeGen for 'omp for' is not supported yet.");
00475 }
00476 
00477 void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &) {
00478   llvm_unreachable("CodeGen for 'omp for simd' is not supported yet.");
00479 }
00480 
00481 void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &) {
00482   llvm_unreachable("CodeGen for 'omp sections' is not supported yet.");
00483 }
00484 
00485 void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &) {
00486   llvm_unreachable("CodeGen for 'omp section' is not supported yet.");
00487 }
00488 
00489 void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) {
00490   llvm_unreachable("CodeGen for 'omp single' is not supported yet.");
00491 }
00492 
00493 void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &) {
00494   llvm_unreachable("CodeGen for 'omp master' is not supported yet.");
00495 }
00496 
00497 void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
00498   // __kmpc_critical();
00499   // <captured_body>
00500   // __kmpc_end_critical();
00501   //
00502 
00503   auto Lock = CGM.getOpenMPRuntime().GetCriticalRegionLock(
00504       S.getDirectiveName().getAsString());
00505   CGM.getOpenMPRuntime().EmitOMPCriticalRegionStart(*this, Lock,
00506                                                     S.getLocStart());
00507   {
00508     RunCleanupsScope Scope(*this);
00509     EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt());
00510     EnsureInsertPoint();
00511   }
00512   CGM.getOpenMPRuntime().EmitOMPCriticalRegionEnd(*this, Lock, S.getLocEnd());
00513 }
00514 
00515 void
00516 CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) {
00517   llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet.");
00518 }
00519 
00520 void CodeGenFunction::EmitOMPParallelForSimdDirective(
00521     const OMPParallelForSimdDirective &) {
00522   llvm_unreachable("CodeGen for 'omp parallel for simd' is not supported yet.");
00523 }
00524 
00525 void CodeGenFunction::EmitOMPParallelSectionsDirective(
00526     const OMPParallelSectionsDirective &) {
00527   llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
00528 }
00529 
00530 void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) {
00531   llvm_unreachable("CodeGen for 'omp task' is not supported yet.");
00532 }
00533 
00534 void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) {
00535   llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet.");
00536 }
00537 
00538 void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &) {
00539   llvm_unreachable("CodeGen for 'omp barrier' is not supported yet.");
00540 }
00541 
00542 void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &) {
00543   llvm_unreachable("CodeGen for 'omp taskwait' is not supported yet.");
00544 }
00545 
00546 void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &) {
00547   llvm_unreachable("CodeGen for 'omp flush' is not supported yet.");
00548 }
00549 
00550 void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &) {
00551   llvm_unreachable("CodeGen for 'omp ordered' is not supported yet.");
00552 }
00553 
00554 void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &) {
00555   llvm_unreachable("CodeGen for 'omp atomic' is not supported yet.");
00556 }
00557 
00558 void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &) {
00559   llvm_unreachable("CodeGen for 'omp target' is not supported yet.");
00560 }
00561 
00562 void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &) {
00563   llvm_unreachable("CodeGen for 'omp teams' is not supported yet.");
00564 }
00565