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