clang API Documentation
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