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 "CGCleanup.h" 15 #include "CGOpenMPRuntime.h" 16 #include "CodeGenFunction.h" 17 #include "CodeGenModule.h" 18 #include "TargetInfo.h" 19 #include "clang/AST/Stmt.h" 20 #include "clang/AST/StmtOpenMP.h" 21 #include "clang/AST/DeclOpenMP.h" 22 #include "llvm/IR/CallSite.h" 23 using namespace clang; 24 using namespace CodeGen; 25 26 namespace { 27 /// Lexical scope for OpenMP executable constructs, that handles correct codegen 28 /// for captured expressions. 29 class OMPLexicalScope : public CodeGenFunction::LexicalScope { 30 void emitPreInitStmt(CodeGenFunction &CGF, const OMPExecutableDirective &S) { 31 for (const auto *C : S.clauses()) { 32 if (auto *CPI = OMPClauseWithPreInit::get(C)) { 33 if (auto *PreInit = cast_or_null<DeclStmt>(CPI->getPreInitStmt())) { 34 for (const auto *I : PreInit->decls()) { 35 if (!I->hasAttr<OMPCaptureNoInitAttr>()) 36 CGF.EmitVarDecl(cast<VarDecl>(*I)); 37 else { 38 CodeGenFunction::AutoVarEmission Emission = 39 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 40 CGF.EmitAutoVarCleanups(Emission); 41 } 42 } 43 } 44 } 45 } 46 } 47 CodeGenFunction::OMPPrivateScope InlinedShareds; 48 49 static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) { 50 return CGF.LambdaCaptureFields.lookup(VD) || 51 (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) || 52 (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl)); 53 } 54 55 public: 56 OMPLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S, 57 bool AsInlined = false, bool EmitPreInitStmt = true) 58 : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()), 59 InlinedShareds(CGF) { 60 if (EmitPreInitStmt) 61 emitPreInitStmt(CGF, S); 62 if (AsInlined) { 63 if (S.hasAssociatedStmt()) { 64 auto *CS = cast<CapturedStmt>(S.getAssociatedStmt()); 65 for (auto &C : CS->captures()) { 66 if (C.capturesVariable() || C.capturesVariableByCopy()) { 67 auto *VD = C.getCapturedVar(); 68 DeclRefExpr DRE(const_cast<VarDecl *>(VD), 69 isCapturedVar(CGF, VD) || 70 (CGF.CapturedStmtInfo && 71 InlinedShareds.isGlobalVarCaptured(VD)), 72 VD->getType().getNonReferenceType(), VK_LValue, 73 SourceLocation()); 74 InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address { 75 return CGF.EmitLValue(&DRE).getAddress(); 76 }); 77 } 78 } 79 (void)InlinedShareds.Privatize(); 80 } 81 } 82 } 83 }; 84 85 /// Lexical scope for OpenMP parallel construct, that handles correct codegen 86 /// for captured expressions. 87 class OMPParallelScope final : public OMPLexicalScope { 88 bool EmitPreInitStmt(const OMPExecutableDirective &S) { 89 OpenMPDirectiveKind Kind = S.getDirectiveKind(); 90 return !(isOpenMPTargetExecutionDirective(Kind) || 91 isOpenMPLoopBoundSharingDirective(Kind)) && 92 isOpenMPParallelDirective(Kind); 93 } 94 95 public: 96 OMPParallelScope(CodeGenFunction &CGF, const OMPExecutableDirective &S) 97 : OMPLexicalScope(CGF, S, 98 /*AsInlined=*/false, 99 /*EmitPreInitStmt=*/EmitPreInitStmt(S)) {} 100 }; 101 102 /// Lexical scope for OpenMP teams construct, that handles correct codegen 103 /// for captured expressions. 104 class OMPTeamsScope final : public OMPLexicalScope { 105 bool EmitPreInitStmt(const OMPExecutableDirective &S) { 106 OpenMPDirectiveKind Kind = S.getDirectiveKind(); 107 return !isOpenMPTargetExecutionDirective(Kind) && 108 isOpenMPTeamsDirective(Kind); 109 } 110 111 public: 112 OMPTeamsScope(CodeGenFunction &CGF, const OMPExecutableDirective &S) 113 : OMPLexicalScope(CGF, S, 114 /*AsInlined=*/false, 115 /*EmitPreInitStmt=*/EmitPreInitStmt(S)) {} 116 }; 117 118 /// Private scope for OpenMP loop-based directives, that supports capturing 119 /// of used expression from loop statement. 120 class OMPLoopScope : public CodeGenFunction::RunCleanupsScope { 121 void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopDirective &S) { 122 if (auto *LD = dyn_cast<OMPLoopDirective>(&S)) { 123 if (auto *PreInits = cast_or_null<DeclStmt>(LD->getPreInits())) { 124 for (const auto *I : PreInits->decls()) 125 CGF.EmitVarDecl(cast<VarDecl>(*I)); 126 } 127 } 128 } 129 130 public: 131 OMPLoopScope(CodeGenFunction &CGF, const OMPLoopDirective &S) 132 : CodeGenFunction::RunCleanupsScope(CGF) { 133 emitPreInitStmt(CGF, S); 134 } 135 }; 136 137 } // namespace 138 139 llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) { 140 auto &C = getContext(); 141 llvm::Value *Size = nullptr; 142 auto SizeInChars = C.getTypeSizeInChars(Ty); 143 if (SizeInChars.isZero()) { 144 // getTypeSizeInChars() returns 0 for a VLA. 145 while (auto *VAT = C.getAsVariableArrayType(Ty)) { 146 llvm::Value *ArraySize; 147 std::tie(ArraySize, Ty) = getVLASize(VAT); 148 Size = Size ? Builder.CreateNUWMul(Size, ArraySize) : ArraySize; 149 } 150 SizeInChars = C.getTypeSizeInChars(Ty); 151 if (SizeInChars.isZero()) 152 return llvm::ConstantInt::get(SizeTy, /*V=*/0); 153 Size = Builder.CreateNUWMul(Size, CGM.getSize(SizeInChars)); 154 } else 155 Size = CGM.getSize(SizeInChars); 156 return Size; 157 } 158 159 void CodeGenFunction::GenerateOpenMPCapturedVars( 160 const CapturedStmt &S, SmallVectorImpl<llvm::Value *> &CapturedVars) { 161 const RecordDecl *RD = S.getCapturedRecordDecl(); 162 auto CurField = RD->field_begin(); 163 auto CurCap = S.captures().begin(); 164 for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(), 165 E = S.capture_init_end(); 166 I != E; ++I, ++CurField, ++CurCap) { 167 if (CurField->hasCapturedVLAType()) { 168 auto VAT = CurField->getCapturedVLAType(); 169 auto *Val = VLASizeMap[VAT->getSizeExpr()]; 170 CapturedVars.push_back(Val); 171 } else if (CurCap->capturesThis()) 172 CapturedVars.push_back(CXXThisValue); 173 else if (CurCap->capturesVariableByCopy()) { 174 llvm::Value *CV = 175 EmitLoadOfLValue(EmitLValue(*I), SourceLocation()).getScalarVal(); 176 177 // If the field is not a pointer, we need to save the actual value 178 // and load it as a void pointer. 179 if (!CurField->getType()->isAnyPointerType()) { 180 auto &Ctx = getContext(); 181 auto DstAddr = CreateMemTemp( 182 Ctx.getUIntPtrType(), 183 Twine(CurCap->getCapturedVar()->getName()) + ".casted"); 184 LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType()); 185 186 auto *SrcAddrVal = EmitScalarConversion( 187 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()), 188 Ctx.getPointerType(CurField->getType()), SourceLocation()); 189 LValue SrcLV = 190 MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType()); 191 192 // Store the value using the source type pointer. 193 EmitStoreThroughLValue(RValue::get(CV), SrcLV); 194 195 // Load the value using the destination type pointer. 196 CV = EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal(); 197 } 198 CapturedVars.push_back(CV); 199 } else { 200 assert(CurCap->capturesVariable() && "Expected capture by reference."); 201 CapturedVars.push_back(EmitLValue(*I).getAddress().getPointer()); 202 } 203 } 204 } 205 206 static Address castValueFromUintptr(CodeGenFunction &CGF, QualType DstType, 207 StringRef Name, LValue AddrLV, 208 bool isReferenceType = false) { 209 ASTContext &Ctx = CGF.getContext(); 210 211 auto *CastedPtr = CGF.EmitScalarConversion( 212 AddrLV.getAddress().getPointer(), Ctx.getUIntPtrType(), 213 Ctx.getPointerType(DstType), SourceLocation()); 214 auto TmpAddr = 215 CGF.MakeNaturalAlignAddrLValue(CastedPtr, Ctx.getPointerType(DstType)) 216 .getAddress(); 217 218 // If we are dealing with references we need to return the address of the 219 // reference instead of the reference of the value. 220 if (isReferenceType) { 221 QualType RefType = Ctx.getLValueReferenceType(DstType); 222 auto *RefVal = TmpAddr.getPointer(); 223 TmpAddr = CGF.CreateMemTemp(RefType, Twine(Name) + ".ref"); 224 auto TmpLVal = CGF.MakeAddrLValue(TmpAddr, RefType); 225 CGF.EmitStoreThroughLValue(RValue::get(RefVal), TmpLVal, /*isInit*/ true); 226 } 227 228 return TmpAddr; 229 } 230 231 static QualType getCanonicalParamType(ASTContext &C, QualType T) { 232 if (T->isLValueReferenceType()) { 233 return C.getLValueReferenceType( 234 getCanonicalParamType(C, T.getNonReferenceType()), 235 /*SpelledAsLValue=*/false); 236 } 237 if (T->isPointerType()) 238 return C.getPointerType(getCanonicalParamType(C, T->getPointeeType())); 239 return C.getCanonicalParamType(T); 240 } 241 242 namespace { 243 /// Contains required data for proper outlined function codegen. 244 struct FunctionOptions { 245 /// Captured statement for which the function is generated. 246 const CapturedStmt *S = nullptr; 247 /// true if cast to/from UIntPtr is required for variables captured by 248 /// value. 249 const bool UIntPtrCastRequired = true; 250 /// true if only casted argumefnts must be registered as local args or VLA 251 /// sizes. 252 const bool RegisterCastedArgsOnly = false; 253 /// Name of the generated function. 254 const StringRef FunctionName; 255 explicit FunctionOptions(const CapturedStmt *S, bool UIntPtrCastRequired, 256 bool RegisterCastedArgsOnly, 257 StringRef FunctionName) 258 : S(S), UIntPtrCastRequired(UIntPtrCastRequired), 259 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly), 260 FunctionName(FunctionName) {} 261 }; 262 } 263 264 static std::pair<llvm::Function *, bool> emitOutlinedFunctionPrologue( 265 CodeGenFunction &CGF, FunctionArgList &Args, 266 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> 267 &LocalAddrs, 268 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> 269 &VLASizes, 270 llvm::Value *&CXXThisValue, const FunctionOptions &FO) { 271 const CapturedDecl *CD = FO.S->getCapturedDecl(); 272 const RecordDecl *RD = FO.S->getCapturedRecordDecl(); 273 assert(CD->hasBody() && "missing CapturedDecl body"); 274 275 CXXThisValue = nullptr; 276 // Build the argument list. 277 CodeGenModule &CGM = CGF.CGM; 278 ASTContext &Ctx = CGM.getContext(); 279 FunctionArgList TargetArgs; 280 bool HasUIntPtrArgs = false; 281 Args.append(CD->param_begin(), 282 std::next(CD->param_begin(), CD->getContextParamPosition())); 283 TargetArgs.append( 284 CD->param_begin(), 285 std::next(CD->param_begin(), CD->getContextParamPosition())); 286 auto I = FO.S->captures().begin(); 287 for (auto *FD : RD->fields()) { 288 QualType ArgType = FD->getType(); 289 IdentifierInfo *II = nullptr; 290 VarDecl *CapVar = nullptr; 291 292 // If this is a capture by copy and the type is not a pointer, the outlined 293 // function argument type should be uintptr and the value properly casted to 294 // uintptr. This is necessary given that the runtime library is only able to 295 // deal with pointers. We can pass in the same way the VLA type sizes to the 296 // outlined function. 297 if ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) || 298 I->capturesVariableArrayType()) { 299 HasUIntPtrArgs = true; 300 if (FO.UIntPtrCastRequired) 301 ArgType = Ctx.getUIntPtrType(); 302 } 303 304 if (I->capturesVariable() || I->capturesVariableByCopy()) { 305 CapVar = I->getCapturedVar(); 306 II = CapVar->getIdentifier(); 307 } else if (I->capturesThis()) 308 II = &Ctx.Idents.get("this"); 309 else { 310 assert(I->capturesVariableArrayType()); 311 II = &Ctx.Idents.get("vla"); 312 } 313 if (ArgType->isVariablyModifiedType()) 314 ArgType = getCanonicalParamType(Ctx, ArgType.getNonReferenceType()); 315 auto *Arg = 316 ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(), II, 317 ArgType, ImplicitParamDecl::Other); 318 Args.emplace_back(Arg); 319 // Do not cast arguments if we emit function with non-original types. 320 TargetArgs.emplace_back( 321 FO.UIntPtrCastRequired 322 ? Arg 323 : CGM.getOpenMPRuntime().translateParameter(FD, Arg)); 324 ++I; 325 } 326 Args.append( 327 std::next(CD->param_begin(), CD->getContextParamPosition() + 1), 328 CD->param_end()); 329 TargetArgs.append( 330 std::next(CD->param_begin(), CD->getContextParamPosition() + 1), 331 CD->param_end()); 332 333 // Create the function declaration. 334 FunctionType::ExtInfo ExtInfo; 335 const CGFunctionInfo &FuncInfo = 336 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, TargetArgs); 337 llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo); 338 339 llvm::Function *F = 340 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage, 341 FO.FunctionName, &CGM.getModule()); 342 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo); 343 if (CD->isNothrow()) 344 F->setDoesNotThrow(); 345 346 // Generate the function. 347 CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, TargetArgs, CD->getLocation(), 348 CD->getBody()->getLocStart()); 349 unsigned Cnt = CD->getContextParamPosition(); 350 I = FO.S->captures().begin(); 351 for (auto *FD : RD->fields()) { 352 // Do not map arguments if we emit function with non-original types. 353 Address LocalAddr(Address::invalid()); 354 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) { 355 LocalAddr = CGM.getOpenMPRuntime().getParameterAddress(CGF, Args[Cnt], 356 TargetArgs[Cnt]); 357 } else { 358 LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]); 359 } 360 // If we are capturing a pointer by copy we don't need to do anything, just 361 // use the value that we get from the arguments. 362 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) { 363 const VarDecl *CurVD = I->getCapturedVar(); 364 // If the variable is a reference we need to materialize it here. 365 if (CurVD->getType()->isReferenceType()) { 366 Address RefAddr = CGF.CreateMemTemp( 367 CurVD->getType(), CGM.getPointerAlign(), ".materialized_ref"); 368 CGF.EmitStoreOfScalar(LocalAddr.getPointer(), RefAddr, 369 /*Volatile=*/false, CurVD->getType()); 370 LocalAddr = RefAddr; 371 } 372 if (!FO.RegisterCastedArgsOnly) 373 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}}); 374 ++Cnt; 375 ++I; 376 continue; 377 } 378 379 LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); 380 LValue ArgLVal = 381 CGF.MakeAddrLValue(LocalAddr, Args[Cnt]->getType(), BaseInfo); 382 if (FD->hasCapturedVLAType()) { 383 if (FO.UIntPtrCastRequired) { 384 ArgLVal = CGF.MakeAddrLValue(castValueFromUintptr(CGF, FD->getType(), 385 Args[Cnt]->getName(), 386 ArgLVal), 387 FD->getType(), BaseInfo); 388 } 389 auto *ExprArg = 390 CGF.EmitLoadOfLValue(ArgLVal, SourceLocation()).getScalarVal(); 391 auto VAT = FD->getCapturedVLAType(); 392 VLASizes.insert({Args[Cnt], {VAT->getSizeExpr(), ExprArg}}); 393 } else if (I->capturesVariable()) { 394 auto *Var = I->getCapturedVar(); 395 QualType VarTy = Var->getType(); 396 Address ArgAddr = ArgLVal.getAddress(); 397 if (!VarTy->isReferenceType()) { 398 if (ArgLVal.getType()->isLValueReferenceType()) { 399 ArgAddr = CGF.EmitLoadOfReference( 400 ArgAddr, ArgLVal.getType()->castAs<ReferenceType>()); 401 } else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) { 402 assert(ArgLVal.getType()->isPointerType()); 403 ArgAddr = CGF.EmitLoadOfPointer( 404 ArgAddr, ArgLVal.getType()->castAs<PointerType>()); 405 } 406 } 407 if (!FO.RegisterCastedArgsOnly) { 408 LocalAddrs.insert( 409 {Args[Cnt], 410 {Var, Address(ArgAddr.getPointer(), Ctx.getDeclAlign(Var))}}); 411 } 412 } else if (I->capturesVariableByCopy()) { 413 assert(!FD->getType()->isAnyPointerType() && 414 "Not expecting a captured pointer."); 415 auto *Var = I->getCapturedVar(); 416 QualType VarTy = Var->getType(); 417 LocalAddrs.insert( 418 {Args[Cnt], 419 {Var, 420 FO.UIntPtrCastRequired 421 ? castValueFromUintptr(CGF, FD->getType(), Args[Cnt]->getName(), 422 ArgLVal, VarTy->isReferenceType()) 423 : ArgLVal.getAddress()}}); 424 } else { 425 // If 'this' is captured, load it into CXXThisValue. 426 assert(I->capturesThis()); 427 CXXThisValue = CGF.EmitLoadOfLValue(ArgLVal, Args[Cnt]->getLocation()) 428 .getScalarVal(); 429 LocalAddrs.insert({Args[Cnt], {nullptr, ArgLVal.getAddress()}}); 430 } 431 ++Cnt; 432 ++I; 433 } 434 435 return {F, HasUIntPtrArgs}; 436 } 437 438 llvm::Function * 439 CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { 440 assert( 441 CapturedStmtInfo && 442 "CapturedStmtInfo should be set when generating the captured function"); 443 const CapturedDecl *CD = S.getCapturedDecl(); 444 // Build the argument list. 445 bool NeedWrapperFunction = 446 getDebugInfo() && 447 CGM.getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo; 448 FunctionArgList Args; 449 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs; 450 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes; 451 FunctionOptions FO(&S, !NeedWrapperFunction, /*RegisterCastedArgsOnly=*/false, 452 CapturedStmtInfo->getHelperName()); 453 llvm::Function *F; 454 bool HasUIntPtrArgs; 455 std::tie(F, HasUIntPtrArgs) = emitOutlinedFunctionPrologue( 456 *this, Args, LocalAddrs, VLASizes, CXXThisValue, FO); 457 for (const auto &LocalAddrPair : LocalAddrs) { 458 if (LocalAddrPair.second.first) { 459 setAddrOfLocalVar(LocalAddrPair.second.first, 460 LocalAddrPair.second.second); 461 } 462 } 463 for (const auto &VLASizePair : VLASizes) 464 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second; 465 PGO.assignRegionCounters(GlobalDecl(CD), F); 466 CapturedStmtInfo->EmitBody(*this, CD->getBody()); 467 FinishFunction(CD->getBodyRBrace()); 468 if (!NeedWrapperFunction || !HasUIntPtrArgs) 469 return F; 470 471 SmallString<256> Buffer; 472 llvm::raw_svector_ostream Out(Buffer); 473 Out << "__nondebug_wrapper_" << CapturedStmtInfo->getHelperName(); 474 FunctionOptions WrapperFO(&S, /*UIntPtrCastRequired=*/true, 475 /*RegisterCastedArgsOnly=*/true, Out.str()); 476 CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true); 477 WrapperCGF.disableDebugInfo(); 478 Args.clear(); 479 LocalAddrs.clear(); 480 VLASizes.clear(); 481 llvm::Function *WrapperF = 482 emitOutlinedFunctionPrologue(WrapperCGF, Args, LocalAddrs, VLASizes, 483 WrapperCGF.CXXThisValue, WrapperFO).first; 484 LValueBaseInfo BaseInfo(AlignmentSource::Decl, false); 485 llvm::SmallVector<llvm::Value *, 4> CallArgs; 486 for (const auto *Arg : Args) { 487 llvm::Value *CallArg; 488 auto I = LocalAddrs.find(Arg); 489 if (I != LocalAddrs.end()) { 490 LValue LV = 491 WrapperCGF.MakeAddrLValue(I->second.second, Arg->getType(), BaseInfo); 492 CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation()); 493 } else { 494 auto EI = VLASizes.find(Arg); 495 if (EI != VLASizes.end()) 496 CallArg = EI->second.second; 497 else { 498 LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg), 499 Arg->getType(), BaseInfo); 500 CallArg = WrapperCGF.EmitLoadOfScalar(LV, SourceLocation()); 501 } 502 } 503 CallArgs.emplace_back(CallArg); 504 } 505 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, F, CallArgs); 506 WrapperCGF.FinishFunction(); 507 return WrapperF; 508 } 509 510 //===----------------------------------------------------------------------===// 511 // OpenMP Directive Emission 512 //===----------------------------------------------------------------------===// 513 void CodeGenFunction::EmitOMPAggregateAssign( 514 Address DestAddr, Address SrcAddr, QualType OriginalType, 515 const llvm::function_ref<void(Address, Address)> &CopyGen) { 516 // Perform element-by-element initialization. 517 QualType ElementTy; 518 519 // Drill down to the base element type on both arrays. 520 auto ArrayTy = OriginalType->getAsArrayTypeUnsafe(); 521 auto NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr); 522 SrcAddr = Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 523 524 auto SrcBegin = SrcAddr.getPointer(); 525 auto DestBegin = DestAddr.getPointer(); 526 // Cast from pointer to array type to pointer to single element. 527 auto DestEnd = Builder.CreateGEP(DestBegin, NumElements); 528 // The basic structure here is a while-do loop. 529 auto BodyBB = createBasicBlock("omp.arraycpy.body"); 530 auto DoneBB = createBasicBlock("omp.arraycpy.done"); 531 auto IsEmpty = 532 Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty"); 533 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 534 535 // Enter the loop body, making that address the current address. 536 auto EntryBB = Builder.GetInsertBlock(); 537 EmitBlock(BodyBB); 538 539 CharUnits ElementSize = getContext().getTypeSizeInChars(ElementTy); 540 541 llvm::PHINode *SrcElementPHI = 542 Builder.CreatePHI(SrcBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 543 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 544 Address SrcElementCurrent = 545 Address(SrcElementPHI, 546 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 547 548 llvm::PHINode *DestElementPHI = 549 Builder.CreatePHI(DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 550 DestElementPHI->addIncoming(DestBegin, EntryBB); 551 Address DestElementCurrent = 552 Address(DestElementPHI, 553 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 554 555 // Emit copy. 556 CopyGen(DestElementCurrent, SrcElementCurrent); 557 558 // Shift the address forward by one element. 559 auto DestElementNext = Builder.CreateConstGEP1_32( 560 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 561 auto SrcElementNext = Builder.CreateConstGEP1_32( 562 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 563 // Check whether we've reached the end. 564 auto Done = 565 Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 566 Builder.CreateCondBr(Done, DoneBB, BodyBB); 567 DestElementPHI->addIncoming(DestElementNext, Builder.GetInsertBlock()); 568 SrcElementPHI->addIncoming(SrcElementNext, Builder.GetInsertBlock()); 569 570 // Done. 571 EmitBlock(DoneBB, /*IsFinished=*/true); 572 } 573 574 void CodeGenFunction::EmitOMPCopy(QualType OriginalType, Address DestAddr, 575 Address SrcAddr, const VarDecl *DestVD, 576 const VarDecl *SrcVD, const Expr *Copy) { 577 if (OriginalType->isArrayType()) { 578 auto *BO = dyn_cast<BinaryOperator>(Copy); 579 if (BO && BO->getOpcode() == BO_Assign) { 580 // Perform simple memcpy for simple copying. 581 EmitAggregateAssign(DestAddr, SrcAddr, OriginalType); 582 } else { 583 // For arrays with complex element types perform element by element 584 // copying. 585 EmitOMPAggregateAssign( 586 DestAddr, SrcAddr, OriginalType, 587 [this, Copy, SrcVD, DestVD](Address DestElement, Address SrcElement) { 588 // Working with the single array element, so have to remap 589 // destination and source variables to corresponding array 590 // elements. 591 CodeGenFunction::OMPPrivateScope Remap(*this); 592 Remap.addPrivate(DestVD, [DestElement]() -> Address { 593 return DestElement; 594 }); 595 Remap.addPrivate( 596 SrcVD, [SrcElement]() -> Address { return SrcElement; }); 597 (void)Remap.Privatize(); 598 EmitIgnoredExpr(Copy); 599 }); 600 } 601 } else { 602 // Remap pseudo source variable to private copy. 603 CodeGenFunction::OMPPrivateScope Remap(*this); 604 Remap.addPrivate(SrcVD, [SrcAddr]() -> Address { return SrcAddr; }); 605 Remap.addPrivate(DestVD, [DestAddr]() -> Address { return DestAddr; }); 606 (void)Remap.Privatize(); 607 // Emit copying of the whole variable. 608 EmitIgnoredExpr(Copy); 609 } 610 } 611 612 bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D, 613 OMPPrivateScope &PrivateScope) { 614 if (!HaveInsertPoint()) 615 return false; 616 bool FirstprivateIsLastprivate = false; 617 llvm::DenseSet<const VarDecl *> Lastprivates; 618 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) { 619 for (const auto *D : C->varlists()) 620 Lastprivates.insert( 621 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl()); 622 } 623 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate; 624 CGCapturedStmtInfo CapturesInfo(cast<CapturedStmt>(*D.getAssociatedStmt())); 625 for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) { 626 auto IRef = C->varlist_begin(); 627 auto InitsRef = C->inits().begin(); 628 for (auto IInit : C->private_copies()) { 629 auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 630 bool ThisFirstprivateIsLastprivate = 631 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0; 632 auto *CapFD = CapturesInfo.lookup(OrigVD); 633 auto *FD = CapturedStmtInfo->lookup(OrigVD); 634 if (!ThisFirstprivateIsLastprivate && FD && (FD == CapFD) && 635 !FD->getType()->isReferenceType()) { 636 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()); 637 ++IRef; 638 ++InitsRef; 639 continue; 640 } 641 FirstprivateIsLastprivate = 642 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate; 643 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) { 644 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); 645 auto *VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl()); 646 bool IsRegistered; 647 DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD), 648 /*RefersToEnclosingVariableOrCapture=*/FD != nullptr, 649 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); 650 Address OriginalAddr = EmitLValue(&DRE).getAddress(); 651 QualType Type = VD->getType(); 652 if (Type->isArrayType()) { 653 // Emit VarDecl with copy init for arrays. 654 // Get the address of the original variable captured in current 655 // captured region. 656 IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address { 657 auto Emission = EmitAutoVarAlloca(*VD); 658 auto *Init = VD->getInit(); 659 if (!isa<CXXConstructExpr>(Init) || isTrivialInitializer(Init)) { 660 // Perform simple memcpy. 661 EmitAggregateAssign(Emission.getAllocatedAddress(), OriginalAddr, 662 Type); 663 } else { 664 EmitOMPAggregateAssign( 665 Emission.getAllocatedAddress(), OriginalAddr, Type, 666 [this, VDInit, Init](Address DestElement, 667 Address SrcElement) { 668 // Clean up any temporaries needed by the initialization. 669 RunCleanupsScope InitScope(*this); 670 // Emit initialization for single element. 671 setAddrOfLocalVar(VDInit, SrcElement); 672 EmitAnyExprToMem(Init, DestElement, 673 Init->getType().getQualifiers(), 674 /*IsInitializer*/ false); 675 LocalDeclMap.erase(VDInit); 676 }); 677 } 678 EmitAutoVarCleanups(Emission); 679 return Emission.getAllocatedAddress(); 680 }); 681 } else { 682 IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address { 683 // Emit private VarDecl with copy init. 684 // Remap temp VDInit variable to the address of the original 685 // variable 686 // (for proper handling of captured global variables). 687 setAddrOfLocalVar(VDInit, OriginalAddr); 688 EmitDecl(*VD); 689 LocalDeclMap.erase(VDInit); 690 return GetAddrOfLocalVar(VD); 691 }); 692 } 693 assert(IsRegistered && 694 "firstprivate var already registered as private"); 695 // Silence the warning about unused variable. 696 (void)IsRegistered; 697 } 698 ++IRef; 699 ++InitsRef; 700 } 701 } 702 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty(); 703 } 704 705 void CodeGenFunction::EmitOMPPrivateClause( 706 const OMPExecutableDirective &D, 707 CodeGenFunction::OMPPrivateScope &PrivateScope) { 708 if (!HaveInsertPoint()) 709 return; 710 llvm::DenseSet<const VarDecl *> EmittedAsPrivate; 711 for (const auto *C : D.getClausesOfKind<OMPPrivateClause>()) { 712 auto IRef = C->varlist_begin(); 713 for (auto IInit : C->private_copies()) { 714 auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 715 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { 716 auto VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); 717 bool IsRegistered = 718 PrivateScope.addPrivate(OrigVD, [&]() -> Address { 719 // Emit private VarDecl with copy init. 720 EmitDecl(*VD); 721 return GetAddrOfLocalVar(VD); 722 }); 723 assert(IsRegistered && "private var already registered as private"); 724 // Silence the warning about unused variable. 725 (void)IsRegistered; 726 } 727 ++IRef; 728 } 729 } 730 } 731 732 bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { 733 if (!HaveInsertPoint()) 734 return false; 735 // threadprivate_var1 = master_threadprivate_var1; 736 // operator=(threadprivate_var2, master_threadprivate_var2); 737 // ... 738 // __kmpc_barrier(&loc, global_tid); 739 llvm::DenseSet<const VarDecl *> CopiedVars; 740 llvm::BasicBlock *CopyBegin = nullptr, *CopyEnd = nullptr; 741 for (const auto *C : D.getClausesOfKind<OMPCopyinClause>()) { 742 auto IRef = C->varlist_begin(); 743 auto ISrcRef = C->source_exprs().begin(); 744 auto IDestRef = C->destination_exprs().begin(); 745 for (auto *AssignOp : C->assignment_ops()) { 746 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 747 QualType Type = VD->getType(); 748 if (CopiedVars.insert(VD->getCanonicalDecl()).second) { 749 // Get the address of the master variable. If we are emitting code with 750 // TLS support, the address is passed from the master as field in the 751 // captured declaration. 752 Address MasterAddr = Address::invalid(); 753 if (getLangOpts().OpenMPUseTLS && 754 getContext().getTargetInfo().isTLSSupported()) { 755 assert(CapturedStmtInfo->lookup(VD) && 756 "Copyin threadprivates should have been captured!"); 757 DeclRefExpr DRE(const_cast<VarDecl *>(VD), true, (*IRef)->getType(), 758 VK_LValue, (*IRef)->getExprLoc()); 759 MasterAddr = EmitLValue(&DRE).getAddress(); 760 LocalDeclMap.erase(VD); 761 } else { 762 MasterAddr = 763 Address(VD->isStaticLocal() ? CGM.getStaticLocalDeclAddress(VD) 764 : CGM.GetAddrOfGlobal(VD), 765 getContext().getDeclAlign(VD)); 766 } 767 // Get the address of the threadprivate variable. 768 Address PrivateAddr = EmitLValue(*IRef).getAddress(); 769 if (CopiedVars.size() == 1) { 770 // At first check if current thread is a master thread. If it is, no 771 // need to copy data. 772 CopyBegin = createBasicBlock("copyin.not.master"); 773 CopyEnd = createBasicBlock("copyin.not.master.end"); 774 Builder.CreateCondBr( 775 Builder.CreateICmpNE( 776 Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy), 777 Builder.CreatePtrToInt(PrivateAddr.getPointer(), CGM.IntPtrTy)), 778 CopyBegin, CopyEnd); 779 EmitBlock(CopyBegin); 780 } 781 auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl()); 782 auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl()); 783 EmitOMPCopy(Type, PrivateAddr, MasterAddr, DestVD, SrcVD, AssignOp); 784 } 785 ++IRef; 786 ++ISrcRef; 787 ++IDestRef; 788 } 789 } 790 if (CopyEnd) { 791 // Exit out of copying procedure for non-master thread. 792 EmitBlock(CopyEnd, /*IsFinished=*/true); 793 return true; 794 } 795 return false; 796 } 797 798 bool CodeGenFunction::EmitOMPLastprivateClauseInit( 799 const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope) { 800 if (!HaveInsertPoint()) 801 return false; 802 bool HasAtLeastOneLastprivate = false; 803 llvm::DenseSet<const VarDecl *> SIMDLCVs; 804 if (isOpenMPSimdDirective(D.getDirectiveKind())) { 805 auto *LoopDirective = cast<OMPLoopDirective>(&D); 806 for (auto *C : LoopDirective->counters()) { 807 SIMDLCVs.insert( 808 cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl()); 809 } 810 } 811 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars; 812 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) { 813 HasAtLeastOneLastprivate = true; 814 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) 815 break; 816 auto IRef = C->varlist_begin(); 817 auto IDestRef = C->destination_exprs().begin(); 818 for (auto *IInit : C->private_copies()) { 819 // Keep the address of the original variable for future update at the end 820 // of the loop. 821 auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 822 // Taskloops do not require additional initialization, it is done in 823 // runtime support library. 824 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) { 825 auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl()); 826 PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() -> Address { 827 DeclRefExpr DRE( 828 const_cast<VarDecl *>(OrigVD), 829 /*RefersToEnclosingVariableOrCapture=*/CapturedStmtInfo->lookup( 830 OrigVD) != nullptr, 831 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); 832 return EmitLValue(&DRE).getAddress(); 833 }); 834 // Check if the variable is also a firstprivate: in this case IInit is 835 // not generated. Initialization of this variable will happen in codegen 836 // for 'firstprivate' clause. 837 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) { 838 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); 839 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address { 840 // Emit private VarDecl with copy init. 841 EmitDecl(*VD); 842 return GetAddrOfLocalVar(VD); 843 }); 844 assert(IsRegistered && 845 "lastprivate var already registered as private"); 846 (void)IsRegistered; 847 } 848 } 849 ++IRef; 850 ++IDestRef; 851 } 852 } 853 return HasAtLeastOneLastprivate; 854 } 855 856 void CodeGenFunction::EmitOMPLastprivateClauseFinal( 857 const OMPExecutableDirective &D, bool NoFinals, 858 llvm::Value *IsLastIterCond) { 859 if (!HaveInsertPoint()) 860 return; 861 // Emit following code: 862 // if (<IsLastIterCond>) { 863 // orig_var1 = private_orig_var1; 864 // ... 865 // orig_varn = private_orig_varn; 866 // } 867 llvm::BasicBlock *ThenBB = nullptr; 868 llvm::BasicBlock *DoneBB = nullptr; 869 if (IsLastIterCond) { 870 ThenBB = createBasicBlock(".omp.lastprivate.then"); 871 DoneBB = createBasicBlock(".omp.lastprivate.done"); 872 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB); 873 EmitBlock(ThenBB); 874 } 875 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars; 876 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates; 877 if (auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) { 878 auto IC = LoopDirective->counters().begin(); 879 for (auto F : LoopDirective->finals()) { 880 auto *D = 881 cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl())->getCanonicalDecl(); 882 if (NoFinals) 883 AlreadyEmittedVars.insert(D); 884 else 885 LoopCountersAndUpdates[D] = F; 886 ++IC; 887 } 888 } 889 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) { 890 auto IRef = C->varlist_begin(); 891 auto ISrcRef = C->source_exprs().begin(); 892 auto IDestRef = C->destination_exprs().begin(); 893 for (auto *AssignOp : C->assignment_ops()) { 894 auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 895 QualType Type = PrivateVD->getType(); 896 auto *CanonicalVD = PrivateVD->getCanonicalDecl(); 897 if (AlreadyEmittedVars.insert(CanonicalVD).second) { 898 // If lastprivate variable is a loop control variable for loop-based 899 // directive, update its value before copyin back to original 900 // variable. 901 if (auto *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD)) 902 EmitIgnoredExpr(FinalExpr); 903 auto *SrcVD = cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl()); 904 auto *DestVD = cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl()); 905 // Get the address of the original variable. 906 Address OriginalAddr = GetAddrOfLocalVar(DestVD); 907 // Get the address of the private variable. 908 Address PrivateAddr = GetAddrOfLocalVar(PrivateVD); 909 if (auto RefTy = PrivateVD->getType()->getAs<ReferenceType>()) 910 PrivateAddr = 911 Address(Builder.CreateLoad(PrivateAddr), 912 getNaturalTypeAlignment(RefTy->getPointeeType())); 913 EmitOMPCopy(Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp); 914 } 915 ++IRef; 916 ++ISrcRef; 917 ++IDestRef; 918 } 919 if (auto *PostUpdate = C->getPostUpdateExpr()) 920 EmitIgnoredExpr(PostUpdate); 921 } 922 if (IsLastIterCond) 923 EmitBlock(DoneBB, /*IsFinished=*/true); 924 } 925 926 void CodeGenFunction::EmitOMPReductionClauseInit( 927 const OMPExecutableDirective &D, 928 CodeGenFunction::OMPPrivateScope &PrivateScope) { 929 if (!HaveInsertPoint()) 930 return; 931 SmallVector<const Expr *, 4> Shareds; 932 SmallVector<const Expr *, 4> Privates; 933 SmallVector<const Expr *, 4> ReductionOps; 934 SmallVector<const Expr *, 4> LHSs; 935 SmallVector<const Expr *, 4> RHSs; 936 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) { 937 auto IPriv = C->privates().begin(); 938 auto IRed = C->reduction_ops().begin(); 939 auto ILHS = C->lhs_exprs().begin(); 940 auto IRHS = C->rhs_exprs().begin(); 941 for (const auto *Ref : C->varlists()) { 942 Shareds.emplace_back(Ref); 943 Privates.emplace_back(*IPriv); 944 ReductionOps.emplace_back(*IRed); 945 LHSs.emplace_back(*ILHS); 946 RHSs.emplace_back(*IRHS); 947 std::advance(IPriv, 1); 948 std::advance(IRed, 1); 949 std::advance(ILHS, 1); 950 std::advance(IRHS, 1); 951 } 952 } 953 ReductionCodeGen RedCG(Shareds, Privates, ReductionOps); 954 unsigned Count = 0; 955 auto ILHS = LHSs.begin(); 956 auto IRHS = RHSs.begin(); 957 auto IPriv = Privates.begin(); 958 for (const auto *IRef : Shareds) { 959 auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl()); 960 // Emit private VarDecl with reduction init. 961 RedCG.emitSharedLValue(*this, Count); 962 RedCG.emitAggregateType(*this, Count); 963 auto Emission = EmitAutoVarAlloca(*PrivateVD); 964 RedCG.emitInitialization(*this, Count, Emission.getAllocatedAddress(), 965 RedCG.getSharedLValue(Count), 966 [&Emission](CodeGenFunction &CGF) { 967 CGF.EmitAutoVarInit(Emission); 968 return true; 969 }); 970 EmitAutoVarCleanups(Emission); 971 Address BaseAddr = RedCG.adjustPrivateAddress( 972 *this, Count, Emission.getAllocatedAddress()); 973 bool IsRegistered = PrivateScope.addPrivate( 974 RedCG.getBaseDecl(Count), [BaseAddr]() -> Address { return BaseAddr; }); 975 assert(IsRegistered && "private var already registered as private"); 976 // Silence the warning about unused variable. 977 (void)IsRegistered; 978 979 auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 980 auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 981 if (isa<OMPArraySectionExpr>(IRef)) { 982 // Store the address of the original variable associated with the LHS 983 // implicit variable. 984 PrivateScope.addPrivate(LHSVD, [&RedCG, Count]() -> Address { 985 return RedCG.getSharedLValue(Count).getAddress(); 986 }); 987 PrivateScope.addPrivate(RHSVD, [this, PrivateVD]() -> Address { 988 return GetAddrOfLocalVar(PrivateVD); 989 }); 990 } else if (isa<ArraySubscriptExpr>(IRef)) { 991 // Store the address of the original variable associated with the LHS 992 // implicit variable. 993 PrivateScope.addPrivate(LHSVD, [&RedCG, Count]() -> Address { 994 return RedCG.getSharedLValue(Count).getAddress(); 995 }); 996 PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() -> Address { 997 return Builder.CreateElementBitCast(GetAddrOfLocalVar(PrivateVD), 998 ConvertTypeForMem(RHSVD->getType()), 999 "rhs.begin"); 1000 }); 1001 } else { 1002 QualType Type = PrivateVD->getType(); 1003 bool IsArray = getContext().getAsArrayType(Type) != nullptr; 1004 Address OriginalAddr = RedCG.getSharedLValue(Count).getAddress(); 1005 // Store the address of the original variable associated with the LHS 1006 // implicit variable. 1007 if (IsArray) { 1008 OriginalAddr = Builder.CreateElementBitCast( 1009 OriginalAddr, ConvertTypeForMem(LHSVD->getType()), "lhs.begin"); 1010 } 1011 PrivateScope.addPrivate( 1012 LHSVD, [OriginalAddr]() -> Address { return OriginalAddr; }); 1013 PrivateScope.addPrivate( 1014 RHSVD, [this, PrivateVD, RHSVD, IsArray]() -> Address { 1015 return IsArray 1016 ? Builder.CreateElementBitCast( 1017 GetAddrOfLocalVar(PrivateVD), 1018 ConvertTypeForMem(RHSVD->getType()), "rhs.begin") 1019 : GetAddrOfLocalVar(PrivateVD); 1020 }); 1021 } 1022 ++ILHS; 1023 ++IRHS; 1024 ++IPriv; 1025 ++Count; 1026 } 1027 } 1028 1029 void CodeGenFunction::EmitOMPReductionClauseFinal( 1030 const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind) { 1031 if (!HaveInsertPoint()) 1032 return; 1033 llvm::SmallVector<const Expr *, 8> Privates; 1034 llvm::SmallVector<const Expr *, 8> LHSExprs; 1035 llvm::SmallVector<const Expr *, 8> RHSExprs; 1036 llvm::SmallVector<const Expr *, 8> ReductionOps; 1037 bool HasAtLeastOneReduction = false; 1038 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) { 1039 HasAtLeastOneReduction = true; 1040 Privates.append(C->privates().begin(), C->privates().end()); 1041 LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end()); 1042 RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end()); 1043 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end()); 1044 } 1045 if (HasAtLeastOneReduction) { 1046 bool WithNowait = D.getSingleClause<OMPNowaitClause>() || 1047 isOpenMPParallelDirective(D.getDirectiveKind()) || 1048 D.getDirectiveKind() == OMPD_simd; 1049 bool SimpleReduction = D.getDirectiveKind() == OMPD_simd; 1050 // Emit nowait reduction if nowait clause is present or directive is a 1051 // parallel directive (it always has implicit barrier). 1052 CGM.getOpenMPRuntime().emitReduction( 1053 *this, D.getLocEnd(), Privates, LHSExprs, RHSExprs, ReductionOps, 1054 {WithNowait, SimpleReduction, ReductionKind}); 1055 } 1056 } 1057 1058 static void emitPostUpdateForReductionClause( 1059 CodeGenFunction &CGF, const OMPExecutableDirective &D, 1060 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen) { 1061 if (!CGF.HaveInsertPoint()) 1062 return; 1063 llvm::BasicBlock *DoneBB = nullptr; 1064 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) { 1065 if (auto *PostUpdate = C->getPostUpdateExpr()) { 1066 if (!DoneBB) { 1067 if (auto *Cond = CondGen(CGF)) { 1068 // If the first post-update expression is found, emit conditional 1069 // block if it was requested. 1070 auto *ThenBB = CGF.createBasicBlock(".omp.reduction.pu"); 1071 DoneBB = CGF.createBasicBlock(".omp.reduction.pu.done"); 1072 CGF.Builder.CreateCondBr(Cond, ThenBB, DoneBB); 1073 CGF.EmitBlock(ThenBB); 1074 } 1075 } 1076 CGF.EmitIgnoredExpr(PostUpdate); 1077 } 1078 } 1079 if (DoneBB) 1080 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 1081 } 1082 1083 namespace { 1084 /// Codegen lambda for appending distribute lower and upper bounds to outlined 1085 /// parallel function. This is necessary for combined constructs such as 1086 /// 'distribute parallel for' 1087 typedef llvm::function_ref<void(CodeGenFunction &, 1088 const OMPExecutableDirective &, 1089 llvm::SmallVectorImpl<llvm::Value *> &)> 1090 CodeGenBoundParametersTy; 1091 } // anonymous namespace 1092 1093 static void emitCommonOMPParallelDirective( 1094 CodeGenFunction &CGF, const OMPExecutableDirective &S, 1095 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1096 const CodeGenBoundParametersTy &CodeGenBoundParameters) { 1097 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel); 1098 auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction( 1099 S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen); 1100 if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) { 1101 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 1102 auto NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(), 1103 /*IgnoreResultAssign*/ true); 1104 CGF.CGM.getOpenMPRuntime().emitNumThreadsClause( 1105 CGF, NumThreads, NumThreadsClause->getLocStart()); 1106 } 1107 if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) { 1108 CodeGenFunction::RunCleanupsScope ProcBindScope(CGF); 1109 CGF.CGM.getOpenMPRuntime().emitProcBindClause( 1110 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getLocStart()); 1111 } 1112 const Expr *IfCond = nullptr; 1113 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { 1114 if (C->getNameModifier() == OMPD_unknown || 1115 C->getNameModifier() == OMPD_parallel) { 1116 IfCond = C->getCondition(); 1117 break; 1118 } 1119 } 1120 1121 OMPParallelScope Scope(CGF, S); 1122 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 1123 // Combining 'distribute' with 'for' requires sharing each 'distribute' chunk 1124 // lower and upper bounds with the pragma 'for' chunking mechanism. 1125 // The following lambda takes care of appending the lower and upper bound 1126 // parameters when necessary 1127 CodeGenBoundParameters(CGF, S, CapturedVars); 1128 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars); 1129 CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getLocStart(), OutlinedFn, 1130 CapturedVars, IfCond); 1131 } 1132 1133 static void emitEmptyBoundParameters(CodeGenFunction &, 1134 const OMPExecutableDirective &, 1135 llvm::SmallVectorImpl<llvm::Value *> &) {} 1136 1137 void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) { 1138 // Emit parallel region as a standalone region. 1139 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 1140 OMPPrivateScope PrivateScope(CGF); 1141 bool Copyins = CGF.EmitOMPCopyinClause(S); 1142 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); 1143 if (Copyins) { 1144 // Emit implicit barrier to synchronize threads and avoid data races on 1145 // propagation master's thread values of threadprivate variables to local 1146 // instances of that variables of all other implicit threads. 1147 CGF.CGM.getOpenMPRuntime().emitBarrierCall( 1148 CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false, 1149 /*ForceSimpleCall=*/true); 1150 } 1151 CGF.EmitOMPPrivateClause(S, PrivateScope); 1152 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 1153 (void)PrivateScope.Privatize(); 1154 CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 1155 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel); 1156 }; 1157 emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen, 1158 emitEmptyBoundParameters); 1159 emitPostUpdateForReductionClause( 1160 *this, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; }); 1161 } 1162 1163 void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D, 1164 JumpDest LoopExit) { 1165 RunCleanupsScope BodyScope(*this); 1166 // Update counters values on current iteration. 1167 for (auto I : D.updates()) { 1168 EmitIgnoredExpr(I); 1169 } 1170 // Update the linear variables. 1171 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { 1172 for (auto *U : C->updates()) 1173 EmitIgnoredExpr(U); 1174 } 1175 1176 // On a continue in the body, jump to the end. 1177 auto Continue = getJumpDestInCurrentScope("omp.body.continue"); 1178 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); 1179 // Emit loop body. 1180 EmitStmt(D.getBody()); 1181 // The end (updates/cleanups). 1182 EmitBlock(Continue.getBlock()); 1183 BreakContinueStack.pop_back(); 1184 } 1185 1186 void CodeGenFunction::EmitOMPInnerLoop( 1187 const Stmt &S, bool RequiresCleanup, const Expr *LoopCond, 1188 const Expr *IncExpr, 1189 const llvm::function_ref<void(CodeGenFunction &)> &BodyGen, 1190 const llvm::function_ref<void(CodeGenFunction &)> &PostIncGen) { 1191 auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end"); 1192 1193 // Start the loop with a block that tests the condition. 1194 auto CondBlock = createBasicBlock("omp.inner.for.cond"); 1195 EmitBlock(CondBlock); 1196 const SourceRange &R = S.getSourceRange(); 1197 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()), 1198 SourceLocToDebugLoc(R.getEnd())); 1199 1200 // If there are any cleanups between here and the loop-exit scope, 1201 // create a block to stage a loop exit along. 1202 auto ExitBlock = LoopExit.getBlock(); 1203 if (RequiresCleanup) 1204 ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup"); 1205 1206 auto LoopBody = createBasicBlock("omp.inner.for.body"); 1207 1208 // Emit condition. 1209 EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S)); 1210 if (ExitBlock != LoopExit.getBlock()) { 1211 EmitBlock(ExitBlock); 1212 EmitBranchThroughCleanup(LoopExit); 1213 } 1214 1215 EmitBlock(LoopBody); 1216 incrementProfileCounter(&S); 1217 1218 // Create a block for the increment. 1219 auto Continue = getJumpDestInCurrentScope("omp.inner.for.inc"); 1220 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); 1221 1222 BodyGen(*this); 1223 1224 // Emit "IV = IV + 1" and a back-edge to the condition block. 1225 EmitBlock(Continue.getBlock()); 1226 EmitIgnoredExpr(IncExpr); 1227 PostIncGen(*this); 1228 BreakContinueStack.pop_back(); 1229 EmitBranch(CondBlock); 1230 LoopStack.pop(); 1231 // Emit the fall-through block. 1232 EmitBlock(LoopExit.getBlock()); 1233 } 1234 1235 void CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) { 1236 if (!HaveInsertPoint()) 1237 return; 1238 // Emit inits for the linear variables. 1239 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { 1240 for (auto *Init : C->inits()) { 1241 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl()); 1242 if (auto *Ref = dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) { 1243 AutoVarEmission Emission = EmitAutoVarAlloca(*VD); 1244 auto *OrigVD = cast<VarDecl>(Ref->getDecl()); 1245 DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD), 1246 CapturedStmtInfo->lookup(OrigVD) != nullptr, 1247 VD->getInit()->getType(), VK_LValue, 1248 VD->getInit()->getExprLoc()); 1249 EmitExprAsInit(&DRE, VD, MakeAddrLValue(Emission.getAllocatedAddress(), 1250 VD->getType()), 1251 /*capturedByInit=*/false); 1252 EmitAutoVarCleanups(Emission); 1253 } else 1254 EmitVarDecl(*VD); 1255 } 1256 // Emit the linear steps for the linear clauses. 1257 // If a step is not constant, it is pre-calculated before the loop. 1258 if (auto CS = cast_or_null<BinaryOperator>(C->getCalcStep())) 1259 if (auto SaveRef = cast<DeclRefExpr>(CS->getLHS())) { 1260 EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl())); 1261 // Emit calculation of the linear step. 1262 EmitIgnoredExpr(CS); 1263 } 1264 } 1265 } 1266 1267 void CodeGenFunction::EmitOMPLinearClauseFinal( 1268 const OMPLoopDirective &D, 1269 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen) { 1270 if (!HaveInsertPoint()) 1271 return; 1272 llvm::BasicBlock *DoneBB = nullptr; 1273 // Emit the final values of the linear variables. 1274 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { 1275 auto IC = C->varlist_begin(); 1276 for (auto *F : C->finals()) { 1277 if (!DoneBB) { 1278 if (auto *Cond = CondGen(*this)) { 1279 // If the first post-update expression is found, emit conditional 1280 // block if it was requested. 1281 auto *ThenBB = createBasicBlock(".omp.linear.pu"); 1282 DoneBB = createBasicBlock(".omp.linear.pu.done"); 1283 Builder.CreateCondBr(Cond, ThenBB, DoneBB); 1284 EmitBlock(ThenBB); 1285 } 1286 } 1287 auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl()); 1288 DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD), 1289 CapturedStmtInfo->lookup(OrigVD) != nullptr, 1290 (*IC)->getType(), VK_LValue, (*IC)->getExprLoc()); 1291 Address OrigAddr = EmitLValue(&DRE).getAddress(); 1292 CodeGenFunction::OMPPrivateScope VarScope(*this); 1293 VarScope.addPrivate(OrigVD, [OrigAddr]() -> Address { return OrigAddr; }); 1294 (void)VarScope.Privatize(); 1295 EmitIgnoredExpr(F); 1296 ++IC; 1297 } 1298 if (auto *PostUpdate = C->getPostUpdateExpr()) 1299 EmitIgnoredExpr(PostUpdate); 1300 } 1301 if (DoneBB) 1302 EmitBlock(DoneBB, /*IsFinished=*/true); 1303 } 1304 1305 static void emitAlignedClause(CodeGenFunction &CGF, 1306 const OMPExecutableDirective &D) { 1307 if (!CGF.HaveInsertPoint()) 1308 return; 1309 for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) { 1310 unsigned ClauseAlignment = 0; 1311 if (auto AlignmentExpr = Clause->getAlignment()) { 1312 auto AlignmentCI = 1313 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr)); 1314 ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue()); 1315 } 1316 for (auto E : Clause->varlists()) { 1317 unsigned Alignment = ClauseAlignment; 1318 if (Alignment == 0) { 1319 // OpenMP [2.8.1, Description] 1320 // If no optional parameter is specified, implementation-defined default 1321 // alignments for SIMD instructions on the target platforms are assumed. 1322 Alignment = 1323 CGF.getContext() 1324 .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign( 1325 E->getType()->getPointeeType())) 1326 .getQuantity(); 1327 } 1328 assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) && 1329 "alignment is not power of 2"); 1330 if (Alignment != 0) { 1331 llvm::Value *PtrValue = CGF.EmitScalarExpr(E); 1332 CGF.EmitAlignmentAssumption(PtrValue, Alignment); 1333 } 1334 } 1335 } 1336 } 1337 1338 void CodeGenFunction::EmitOMPPrivateLoopCounters( 1339 const OMPLoopDirective &S, CodeGenFunction::OMPPrivateScope &LoopScope) { 1340 if (!HaveInsertPoint()) 1341 return; 1342 auto I = S.private_counters().begin(); 1343 for (auto *E : S.counters()) { 1344 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 1345 auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()); 1346 (void)LoopScope.addPrivate(VD, [&]() -> Address { 1347 // Emit var without initialization. 1348 if (!LocalDeclMap.count(PrivateVD)) { 1349 auto VarEmission = EmitAutoVarAlloca(*PrivateVD); 1350 EmitAutoVarCleanups(VarEmission); 1351 } 1352 DeclRefExpr DRE(const_cast<VarDecl *>(PrivateVD), 1353 /*RefersToEnclosingVariableOrCapture=*/false, 1354 (*I)->getType(), VK_LValue, (*I)->getExprLoc()); 1355 return EmitLValue(&DRE).getAddress(); 1356 }); 1357 if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) || 1358 VD->hasGlobalStorage()) { 1359 (void)LoopScope.addPrivate(PrivateVD, [&]() -> Address { 1360 DeclRefExpr DRE(const_cast<VarDecl *>(VD), 1361 LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD), 1362 E->getType(), VK_LValue, E->getExprLoc()); 1363 return EmitLValue(&DRE).getAddress(); 1364 }); 1365 } 1366 ++I; 1367 } 1368 } 1369 1370 static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, 1371 const Expr *Cond, llvm::BasicBlock *TrueBlock, 1372 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) { 1373 if (!CGF.HaveInsertPoint()) 1374 return; 1375 { 1376 CodeGenFunction::OMPPrivateScope PreCondScope(CGF); 1377 CGF.EmitOMPPrivateLoopCounters(S, PreCondScope); 1378 (void)PreCondScope.Privatize(); 1379 // Get initial values of real counters. 1380 for (auto I : S.inits()) { 1381 CGF.EmitIgnoredExpr(I); 1382 } 1383 } 1384 // Check that loop is executed at least one time. 1385 CGF.EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount); 1386 } 1387 1388 void CodeGenFunction::EmitOMPLinearClause( 1389 const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope) { 1390 if (!HaveInsertPoint()) 1391 return; 1392 llvm::DenseSet<const VarDecl *> SIMDLCVs; 1393 if (isOpenMPSimdDirective(D.getDirectiveKind())) { 1394 auto *LoopDirective = cast<OMPLoopDirective>(&D); 1395 for (auto *C : LoopDirective->counters()) { 1396 SIMDLCVs.insert( 1397 cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl()); 1398 } 1399 } 1400 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { 1401 auto CurPrivate = C->privates().begin(); 1402 for (auto *E : C->varlists()) { 1403 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 1404 auto *PrivateVD = 1405 cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl()); 1406 if (!SIMDLCVs.count(VD->getCanonicalDecl())) { 1407 bool IsRegistered = PrivateScope.addPrivate(VD, [&]() -> Address { 1408 // Emit private VarDecl with copy init. 1409 EmitVarDecl(*PrivateVD); 1410 return GetAddrOfLocalVar(PrivateVD); 1411 }); 1412 assert(IsRegistered && "linear var already registered as private"); 1413 // Silence the warning about unused variable. 1414 (void)IsRegistered; 1415 } else 1416 EmitVarDecl(*PrivateVD); 1417 ++CurPrivate; 1418 } 1419 } 1420 } 1421 1422 static void emitSimdlenSafelenClause(CodeGenFunction &CGF, 1423 const OMPExecutableDirective &D, 1424 bool IsMonotonic) { 1425 if (!CGF.HaveInsertPoint()) 1426 return; 1427 if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) { 1428 RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(), 1429 /*ignoreResult=*/true); 1430 llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal()); 1431 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue()); 1432 // In presence of finite 'safelen', it may be unsafe to mark all 1433 // the memory instructions parallel, because loop-carried 1434 // dependences of 'safelen' iterations are possible. 1435 if (!IsMonotonic) 1436 CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>()); 1437 } else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) { 1438 RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(), 1439 /*ignoreResult=*/true); 1440 llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal()); 1441 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue()); 1442 // In presence of finite 'safelen', it may be unsafe to mark all 1443 // the memory instructions parallel, because loop-carried 1444 // dependences of 'safelen' iterations are possible. 1445 CGF.LoopStack.setParallel(false); 1446 } 1447 } 1448 1449 void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D, 1450 bool IsMonotonic) { 1451 // Walk clauses and process safelen/lastprivate. 1452 LoopStack.setParallel(!IsMonotonic); 1453 LoopStack.setVectorizeEnable(true); 1454 emitSimdlenSafelenClause(*this, D, IsMonotonic); 1455 } 1456 1457 void CodeGenFunction::EmitOMPSimdFinal( 1458 const OMPLoopDirective &D, 1459 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> &CondGen) { 1460 if (!HaveInsertPoint()) 1461 return; 1462 llvm::BasicBlock *DoneBB = nullptr; 1463 auto IC = D.counters().begin(); 1464 auto IPC = D.private_counters().begin(); 1465 for (auto F : D.finals()) { 1466 auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl()); 1467 auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl()); 1468 auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD); 1469 if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD) || 1470 OrigVD->hasGlobalStorage() || CED) { 1471 if (!DoneBB) { 1472 if (auto *Cond = CondGen(*this)) { 1473 // If the first post-update expression is found, emit conditional 1474 // block if it was requested. 1475 auto *ThenBB = createBasicBlock(".omp.final.then"); 1476 DoneBB = createBasicBlock(".omp.final.done"); 1477 Builder.CreateCondBr(Cond, ThenBB, DoneBB); 1478 EmitBlock(ThenBB); 1479 } 1480 } 1481 Address OrigAddr = Address::invalid(); 1482 if (CED) 1483 OrigAddr = EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress(); 1484 else { 1485 DeclRefExpr DRE(const_cast<VarDecl *>(PrivateVD), 1486 /*RefersToEnclosingVariableOrCapture=*/false, 1487 (*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc()); 1488 OrigAddr = EmitLValue(&DRE).getAddress(); 1489 } 1490 OMPPrivateScope VarScope(*this); 1491 VarScope.addPrivate(OrigVD, 1492 [OrigAddr]() -> Address { return OrigAddr; }); 1493 (void)VarScope.Privatize(); 1494 EmitIgnoredExpr(F); 1495 } 1496 ++IC; 1497 ++IPC; 1498 } 1499 if (DoneBB) 1500 EmitBlock(DoneBB, /*IsFinished=*/true); 1501 } 1502 1503 static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, 1504 const OMPLoopDirective &S, 1505 CodeGenFunction::JumpDest LoopExit) { 1506 CGF.EmitOMPLoopBody(S, LoopExit); 1507 CGF.EmitStopPoint(&S); 1508 } 1509 1510 void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { 1511 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 1512 OMPLoopScope PreInitScope(CGF, S); 1513 // if (PreCond) { 1514 // for (IV in 0..LastIteration) BODY; 1515 // <Final counter/linear vars updates>; 1516 // } 1517 // 1518 1519 // Emit: if (PreCond) - begin. 1520 // If the condition constant folds and can be elided, avoid emitting the 1521 // whole loop. 1522 bool CondConstant; 1523 llvm::BasicBlock *ContBlock = nullptr; 1524 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { 1525 if (!CondConstant) 1526 return; 1527 } else { 1528 auto *ThenBlock = CGF.createBasicBlock("simd.if.then"); 1529 ContBlock = CGF.createBasicBlock("simd.if.end"); 1530 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock, 1531 CGF.getProfileCount(&S)); 1532 CGF.EmitBlock(ThenBlock); 1533 CGF.incrementProfileCounter(&S); 1534 } 1535 1536 // Emit the loop iteration variable. 1537 const Expr *IVExpr = S.getIterationVariable(); 1538 const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl()); 1539 CGF.EmitVarDecl(*IVDecl); 1540 CGF.EmitIgnoredExpr(S.getInit()); 1541 1542 // Emit the iterations count variable. 1543 // If it is not a variable, Sema decided to calculate iterations count on 1544 // each iteration (e.g., it is foldable into a constant). 1545 if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { 1546 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); 1547 // Emit calculation of the iterations count. 1548 CGF.EmitIgnoredExpr(S.getCalcLastIteration()); 1549 } 1550 1551 CGF.EmitOMPSimdInit(S); 1552 1553 emitAlignedClause(CGF, S); 1554 CGF.EmitOMPLinearClauseInit(S); 1555 { 1556 OMPPrivateScope LoopScope(CGF); 1557 CGF.EmitOMPPrivateLoopCounters(S, LoopScope); 1558 CGF.EmitOMPLinearClause(S, LoopScope); 1559 CGF.EmitOMPPrivateClause(S, LoopScope); 1560 CGF.EmitOMPReductionClauseInit(S, LoopScope); 1561 bool HasLastprivateClause = 1562 CGF.EmitOMPLastprivateClauseInit(S, LoopScope); 1563 (void)LoopScope.Privatize(); 1564 CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), 1565 S.getInc(), 1566 [&S](CodeGenFunction &CGF) { 1567 CGF.EmitOMPLoopBody(S, JumpDest()); 1568 CGF.EmitStopPoint(&S); 1569 }, 1570 [](CodeGenFunction &) {}); 1571 CGF.EmitOMPSimdFinal( 1572 S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; }); 1573 // Emit final copy of the lastprivate variables at the end of loops. 1574 if (HasLastprivateClause) 1575 CGF.EmitOMPLastprivateClauseFinal(S, /*NoFinals=*/true); 1576 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_simd); 1577 emitPostUpdateForReductionClause( 1578 CGF, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; }); 1579 } 1580 CGF.EmitOMPLinearClauseFinal( 1581 S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; }); 1582 // Emit: if (PreCond) - end. 1583 if (ContBlock) { 1584 CGF.EmitBranch(ContBlock); 1585 CGF.EmitBlock(ContBlock, true); 1586 } 1587 }; 1588 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 1589 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen); 1590 } 1591 1592 void CodeGenFunction::EmitOMPOuterLoop( 1593 bool DynamicOrOrdered, bool IsMonotonic, const OMPLoopDirective &S, 1594 CodeGenFunction::OMPPrivateScope &LoopScope, 1595 const CodeGenFunction::OMPLoopArguments &LoopArgs, 1596 const CodeGenFunction::CodeGenLoopTy &CodeGenLoop, 1597 const CodeGenFunction::CodeGenOrderedTy &CodeGenOrdered) { 1598 auto &RT = CGM.getOpenMPRuntime(); 1599 1600 const Expr *IVExpr = S.getIterationVariable(); 1601 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); 1602 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); 1603 1604 auto LoopExit = getJumpDestInCurrentScope("omp.dispatch.end"); 1605 1606 // Start the loop with a block that tests the condition. 1607 auto CondBlock = createBasicBlock("omp.dispatch.cond"); 1608 EmitBlock(CondBlock); 1609 const SourceRange &R = S.getSourceRange(); 1610 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()), 1611 SourceLocToDebugLoc(R.getEnd())); 1612 1613 llvm::Value *BoolCondVal = nullptr; 1614 if (!DynamicOrOrdered) { 1615 // UB = min(UB, GlobalUB) or 1616 // UB = min(UB, PrevUB) for combined loop sharing constructs (e.g. 1617 // 'distribute parallel for') 1618 EmitIgnoredExpr(LoopArgs.EUB); 1619 // IV = LB 1620 EmitIgnoredExpr(LoopArgs.Init); 1621 // IV < UB 1622 BoolCondVal = EvaluateExprAsBool(LoopArgs.Cond); 1623 } else { 1624 BoolCondVal = 1625 RT.emitForNext(*this, S.getLocStart(), IVSize, IVSigned, LoopArgs.IL, 1626 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST); 1627 } 1628 1629 // If there are any cleanups between here and the loop-exit scope, 1630 // create a block to stage a loop exit along. 1631 auto ExitBlock = LoopExit.getBlock(); 1632 if (LoopScope.requiresCleanups()) 1633 ExitBlock = createBasicBlock("omp.dispatch.cleanup"); 1634 1635 auto LoopBody = createBasicBlock("omp.dispatch.body"); 1636 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock); 1637 if (ExitBlock != LoopExit.getBlock()) { 1638 EmitBlock(ExitBlock); 1639 EmitBranchThroughCleanup(LoopExit); 1640 } 1641 EmitBlock(LoopBody); 1642 1643 // Emit "IV = LB" (in case of static schedule, we have already calculated new 1644 // LB for loop condition and emitted it above). 1645 if (DynamicOrOrdered) 1646 EmitIgnoredExpr(LoopArgs.Init); 1647 1648 // Create a block for the increment. 1649 auto Continue = getJumpDestInCurrentScope("omp.dispatch.inc"); 1650 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); 1651 1652 // Generate !llvm.loop.parallel metadata for loads and stores for loops 1653 // with dynamic/guided scheduling and without ordered clause. 1654 if (!isOpenMPSimdDirective(S.getDirectiveKind())) 1655 LoopStack.setParallel(!IsMonotonic); 1656 else 1657 EmitOMPSimdInit(S, IsMonotonic); 1658 1659 SourceLocation Loc = S.getLocStart(); 1660 1661 // when 'distribute' is not combined with a 'for': 1662 // while (idx <= UB) { BODY; ++idx; } 1663 // when 'distribute' is combined with a 'for' 1664 // (e.g. 'distribute parallel for') 1665 // while (idx <= UB) { <CodeGen rest of pragma>; idx += ST; } 1666 EmitOMPInnerLoop( 1667 S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr, 1668 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) { 1669 CodeGenLoop(CGF, S, LoopExit); 1670 }, 1671 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) { 1672 CodeGenOrdered(CGF, Loc, IVSize, IVSigned); 1673 }); 1674 1675 EmitBlock(Continue.getBlock()); 1676 BreakContinueStack.pop_back(); 1677 if (!DynamicOrOrdered) { 1678 // Emit "LB = LB + Stride", "UB = UB + Stride". 1679 EmitIgnoredExpr(LoopArgs.NextLB); 1680 EmitIgnoredExpr(LoopArgs.NextUB); 1681 } 1682 1683 EmitBranch(CondBlock); 1684 LoopStack.pop(); 1685 // Emit the fall-through block. 1686 EmitBlock(LoopExit.getBlock()); 1687 1688 // Tell the runtime we are done. 1689 auto &&CodeGen = [DynamicOrOrdered, &S](CodeGenFunction &CGF) { 1690 if (!DynamicOrOrdered) 1691 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd()); 1692 }; 1693 OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen); 1694 } 1695 1696 void CodeGenFunction::EmitOMPForOuterLoop( 1697 const OpenMPScheduleTy &ScheduleKind, bool IsMonotonic, 1698 const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered, 1699 const OMPLoopArguments &LoopArgs, 1700 const CodeGenDispatchBoundsTy &CGDispatchBounds) { 1701 auto &RT = CGM.getOpenMPRuntime(); 1702 1703 // Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime). 1704 const bool DynamicOrOrdered = 1705 Ordered || RT.isDynamic(ScheduleKind.Schedule); 1706 1707 assert((Ordered || 1708 !RT.isStaticNonchunked(ScheduleKind.Schedule, 1709 LoopArgs.Chunk != nullptr)) && 1710 "static non-chunked schedule does not need outer loop"); 1711 1712 // Emit outer loop. 1713 // 1714 // OpenMP [2.7.1, Loop Construct, Description, table 2-1] 1715 // When schedule(dynamic,chunk_size) is specified, the iterations are 1716 // distributed to threads in the team in chunks as the threads request them. 1717 // Each thread executes a chunk of iterations, then requests another chunk, 1718 // until no chunks remain to be distributed. Each chunk contains chunk_size 1719 // iterations, except for the last chunk to be distributed, which may have 1720 // fewer iterations. When no chunk_size is specified, it defaults to 1. 1721 // 1722 // When schedule(guided,chunk_size) is specified, the iterations are assigned 1723 // to threads in the team in chunks as the executing threads request them. 1724 // Each thread executes a chunk of iterations, then requests another chunk, 1725 // until no chunks remain to be assigned. For a chunk_size of 1, the size of 1726 // each chunk is proportional to the number of unassigned iterations divided 1727 // by the number of threads in the team, decreasing to 1. For a chunk_size 1728 // with value k (greater than 1), the size of each chunk is determined in the 1729 // same way, with the restriction that the chunks do not contain fewer than k 1730 // iterations (except for the last chunk to be assigned, which may have fewer 1731 // than k iterations). 1732 // 1733 // When schedule(auto) is specified, the decision regarding scheduling is 1734 // delegated to the compiler and/or runtime system. The programmer gives the 1735 // implementation the freedom to choose any possible mapping of iterations to 1736 // threads in the team. 1737 // 1738 // When schedule(runtime) is specified, the decision regarding scheduling is 1739 // deferred until run time, and the schedule and chunk size are taken from the 1740 // run-sched-var ICV. If the ICV is set to auto, the schedule is 1741 // implementation defined 1742 // 1743 // while(__kmpc_dispatch_next(&LB, &UB)) { 1744 // idx = LB; 1745 // while (idx <= UB) { BODY; ++idx; 1746 // __kmpc_dispatch_fini_(4|8)[u](); // For ordered loops only. 1747 // } // inner loop 1748 // } 1749 // 1750 // OpenMP [2.7.1, Loop Construct, Description, table 2-1] 1751 // When schedule(static, chunk_size) is specified, iterations are divided into 1752 // chunks of size chunk_size, and the chunks are assigned to the threads in 1753 // the team in a round-robin fashion in the order of the thread number. 1754 // 1755 // while(UB = min(UB, GlobalUB), idx = LB, idx < UB) { 1756 // while (idx <= UB) { BODY; ++idx; } // inner loop 1757 // LB = LB + ST; 1758 // UB = UB + ST; 1759 // } 1760 // 1761 1762 const Expr *IVExpr = S.getIterationVariable(); 1763 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); 1764 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); 1765 1766 if (DynamicOrOrdered) { 1767 auto DispatchBounds = CGDispatchBounds(*this, S, LoopArgs.LB, LoopArgs.UB); 1768 llvm::Value *LBVal = DispatchBounds.first; 1769 llvm::Value *UBVal = DispatchBounds.second; 1770 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal, 1771 LoopArgs.Chunk}; 1772 RT.emitForDispatchInit(*this, S.getLocStart(), ScheduleKind, IVSize, 1773 IVSigned, Ordered, DipatchRTInputValues); 1774 } else { 1775 RT.emitForStaticInit(*this, S.getLocStart(), ScheduleKind, IVSize, IVSigned, 1776 Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB, 1777 LoopArgs.ST, LoopArgs.Chunk); 1778 } 1779 1780 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc, 1781 const unsigned IVSize, 1782 const bool IVSigned) { 1783 if (Ordered) { 1784 CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd(CGF, Loc, IVSize, 1785 IVSigned); 1786 } 1787 }; 1788 1789 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST, 1790 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB); 1791 OuterLoopArgs.IncExpr = S.getInc(); 1792 OuterLoopArgs.Init = S.getInit(); 1793 OuterLoopArgs.Cond = S.getCond(); 1794 OuterLoopArgs.NextLB = S.getNextLowerBound(); 1795 OuterLoopArgs.NextUB = S.getNextUpperBound(); 1796 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs, 1797 emitOMPLoopBodyWithStopPoint, CodeGenOrdered); 1798 } 1799 1800 static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, 1801 const unsigned IVSize, const bool IVSigned) {} 1802 1803 void CodeGenFunction::EmitOMPDistributeOuterLoop( 1804 OpenMPDistScheduleClauseKind ScheduleKind, const OMPLoopDirective &S, 1805 OMPPrivateScope &LoopScope, const OMPLoopArguments &LoopArgs, 1806 const CodeGenLoopTy &CodeGenLoopContent) { 1807 1808 auto &RT = CGM.getOpenMPRuntime(); 1809 1810 // Emit outer loop. 1811 // Same behavior as a OMPForOuterLoop, except that schedule cannot be 1812 // dynamic 1813 // 1814 1815 const Expr *IVExpr = S.getIterationVariable(); 1816 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); 1817 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); 1818 1819 RT.emitDistributeStaticInit(*this, S.getLocStart(), ScheduleKind, IVSize, 1820 IVSigned, /* Ordered = */ false, LoopArgs.IL, 1821 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST, 1822 LoopArgs.Chunk); 1823 1824 // for combined 'distribute' and 'for' the increment expression of distribute 1825 // is store in DistInc. For 'distribute' alone, it is in Inc. 1826 Expr *IncExpr; 1827 if (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())) 1828 IncExpr = S.getDistInc(); 1829 else 1830 IncExpr = S.getInc(); 1831 1832 // this routine is shared by 'omp distribute parallel for' and 1833 // 'omp distribute': select the right EUB expression depending on the 1834 // directive 1835 OMPLoopArguments OuterLoopArgs; 1836 OuterLoopArgs.LB = LoopArgs.LB; 1837 OuterLoopArgs.UB = LoopArgs.UB; 1838 OuterLoopArgs.ST = LoopArgs.ST; 1839 OuterLoopArgs.IL = LoopArgs.IL; 1840 OuterLoopArgs.Chunk = LoopArgs.Chunk; 1841 OuterLoopArgs.EUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 1842 ? S.getCombinedEnsureUpperBound() 1843 : S.getEnsureUpperBound(); 1844 OuterLoopArgs.IncExpr = IncExpr; 1845 OuterLoopArgs.Init = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 1846 ? S.getCombinedInit() 1847 : S.getInit(); 1848 OuterLoopArgs.Cond = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 1849 ? S.getCombinedCond() 1850 : S.getCond(); 1851 OuterLoopArgs.NextLB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 1852 ? S.getCombinedNextLowerBound() 1853 : S.getNextLowerBound(); 1854 OuterLoopArgs.NextUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 1855 ? S.getCombinedNextUpperBound() 1856 : S.getNextUpperBound(); 1857 1858 EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false, S, 1859 LoopScope, OuterLoopArgs, CodeGenLoopContent, 1860 emitEmptyOrdered); 1861 } 1862 1863 /// Emit a helper variable and return corresponding lvalue. 1864 static LValue EmitOMPHelperVar(CodeGenFunction &CGF, 1865 const DeclRefExpr *Helper) { 1866 auto VDecl = cast<VarDecl>(Helper->getDecl()); 1867 CGF.EmitVarDecl(*VDecl); 1868 return CGF.EmitLValue(Helper); 1869 } 1870 1871 static std::pair<LValue, LValue> 1872 emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, 1873 const OMPExecutableDirective &S) { 1874 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S); 1875 LValue LB = 1876 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable())); 1877 LValue UB = 1878 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable())); 1879 1880 // When composing 'distribute' with 'for' (e.g. as in 'distribute 1881 // parallel for') we need to use the 'distribute' 1882 // chunk lower and upper bounds rather than the whole loop iteration 1883 // space. These are parameters to the outlined function for 'parallel' 1884 // and we copy the bounds of the previous schedule into the 1885 // the current ones. 1886 LValue PrevLB = CGF.EmitLValue(LS.getPrevLowerBoundVariable()); 1887 LValue PrevUB = CGF.EmitLValue(LS.getPrevUpperBoundVariable()); 1888 llvm::Value *PrevLBVal = CGF.EmitLoadOfScalar(PrevLB, SourceLocation()); 1889 PrevLBVal = CGF.EmitScalarConversion( 1890 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(), 1891 LS.getIterationVariable()->getType(), SourceLocation()); 1892 llvm::Value *PrevUBVal = CGF.EmitLoadOfScalar(PrevUB, SourceLocation()); 1893 PrevUBVal = CGF.EmitScalarConversion( 1894 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(), 1895 LS.getIterationVariable()->getType(), SourceLocation()); 1896 1897 CGF.EmitStoreOfScalar(PrevLBVal, LB); 1898 CGF.EmitStoreOfScalar(PrevUBVal, UB); 1899 1900 return {LB, UB}; 1901 } 1902 1903 /// if the 'for' loop has a dispatch schedule (e.g. dynamic, guided) then 1904 /// we need to use the LB and UB expressions generated by the worksharing 1905 /// code generation support, whereas in non combined situations we would 1906 /// just emit 0 and the LastIteration expression 1907 /// This function is necessary due to the difference of the LB and UB 1908 /// types for the RT emission routines for 'for_static_init' and 1909 /// 'for_dispatch_init' 1910 static std::pair<llvm::Value *, llvm::Value *> 1911 emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF, 1912 const OMPExecutableDirective &S, 1913 Address LB, Address UB) { 1914 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S); 1915 const Expr *IVExpr = LS.getIterationVariable(); 1916 // when implementing a dynamic schedule for a 'for' combined with a 1917 // 'distribute' (e.g. 'distribute parallel for'), the 'for' loop 1918 // is not normalized as each team only executes its own assigned 1919 // distribute chunk 1920 QualType IteratorTy = IVExpr->getType(); 1921 llvm::Value *LBVal = CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy, 1922 SourceLocation()); 1923 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy, 1924 SourceLocation()); 1925 return {LBVal, UBVal}; 1926 } 1927 1928 static void emitDistributeParallelForDistributeInnerBoundParams( 1929 CodeGenFunction &CGF, const OMPExecutableDirective &S, 1930 llvm::SmallVectorImpl<llvm::Value *> &CapturedVars) { 1931 const auto &Dir = cast<OMPLoopDirective>(S); 1932 LValue LB = 1933 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable())); 1934 auto LBCast = CGF.Builder.CreateIntCast( 1935 CGF.Builder.CreateLoad(LB.getAddress()), CGF.SizeTy, /*isSigned=*/false); 1936 CapturedVars.push_back(LBCast); 1937 LValue UB = 1938 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable())); 1939 1940 auto UBCast = CGF.Builder.CreateIntCast( 1941 CGF.Builder.CreateLoad(UB.getAddress()), CGF.SizeTy, /*isSigned=*/false); 1942 CapturedVars.push_back(UBCast); 1943 } 1944 1945 static void 1946 emitInnerParallelForWhenCombined(CodeGenFunction &CGF, 1947 const OMPLoopDirective &S, 1948 CodeGenFunction::JumpDest LoopExit) { 1949 auto &&CGInlinedWorksharingLoop = [&S](CodeGenFunction &CGF, 1950 PrePostActionTy &) { 1951 CGF.EmitOMPWorksharingLoop(S, S.getPrevEnsureUpperBound(), 1952 emitDistributeParallelForInnerBounds, 1953 emitDistributeParallelForDispatchBounds); 1954 }; 1955 1956 emitCommonOMPParallelDirective( 1957 CGF, S, OMPD_for, CGInlinedWorksharingLoop, 1958 emitDistributeParallelForDistributeInnerBoundParams); 1959 } 1960 1961 void CodeGenFunction::EmitOMPDistributeParallelForDirective( 1962 const OMPDistributeParallelForDirective &S) { 1963 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 1964 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, 1965 S.getDistInc()); 1966 }; 1967 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 1968 OMPCancelStackRAII CancelRegion(*this, OMPD_distribute_parallel_for, 1969 /*HasCancel=*/false); 1970 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen, 1971 /*HasCancel=*/false); 1972 } 1973 1974 void CodeGenFunction::EmitOMPDistributeParallelForSimdDirective( 1975 const OMPDistributeParallelForSimdDirective &S) { 1976 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 1977 CGM.getOpenMPRuntime().emitInlinedDirective( 1978 *this, OMPD_distribute_parallel_for_simd, 1979 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 1980 OMPLoopScope PreInitScope(CGF, S); 1981 CGF.EmitStmt( 1982 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 1983 }); 1984 } 1985 1986 void CodeGenFunction::EmitOMPDistributeSimdDirective( 1987 const OMPDistributeSimdDirective &S) { 1988 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 1989 CGM.getOpenMPRuntime().emitInlinedDirective( 1990 *this, OMPD_distribute_simd, 1991 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 1992 OMPLoopScope PreInitScope(CGF, S); 1993 CGF.EmitStmt( 1994 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 1995 }); 1996 } 1997 1998 void CodeGenFunction::EmitOMPTargetParallelForSimdDirective( 1999 const OMPTargetParallelForSimdDirective &S) { 2000 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2001 CGM.getOpenMPRuntime().emitInlinedDirective( 2002 *this, OMPD_target_parallel_for_simd, 2003 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2004 OMPLoopScope PreInitScope(CGF, S); 2005 CGF.EmitStmt( 2006 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2007 }); 2008 } 2009 2010 void CodeGenFunction::EmitOMPTargetSimdDirective( 2011 const OMPTargetSimdDirective &S) { 2012 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2013 CGM.getOpenMPRuntime().emitInlinedDirective( 2014 *this, OMPD_target_simd, [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2015 OMPLoopScope PreInitScope(CGF, S); 2016 CGF.EmitStmt( 2017 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2018 }); 2019 } 2020 2021 void CodeGenFunction::EmitOMPTeamsDistributeDirective( 2022 const OMPTeamsDistributeDirective &S) { 2023 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2024 CGM.getOpenMPRuntime().emitInlinedDirective( 2025 *this, OMPD_teams_distribute, 2026 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2027 OMPLoopScope PreInitScope(CGF, S); 2028 CGF.EmitStmt( 2029 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2030 }); 2031 } 2032 2033 void CodeGenFunction::EmitOMPTeamsDistributeSimdDirective( 2034 const OMPTeamsDistributeSimdDirective &S) { 2035 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2036 CGM.getOpenMPRuntime().emitInlinedDirective( 2037 *this, OMPD_teams_distribute_simd, 2038 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2039 OMPLoopScope PreInitScope(CGF, S); 2040 CGF.EmitStmt( 2041 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2042 }); 2043 } 2044 2045 void CodeGenFunction::EmitOMPTeamsDistributeParallelForSimdDirective( 2046 const OMPTeamsDistributeParallelForSimdDirective &S) { 2047 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2048 CGM.getOpenMPRuntime().emitInlinedDirective( 2049 *this, OMPD_teams_distribute_parallel_for_simd, 2050 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2051 OMPLoopScope PreInitScope(CGF, S); 2052 CGF.EmitStmt( 2053 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2054 }); 2055 } 2056 2057 void CodeGenFunction::EmitOMPTeamsDistributeParallelForDirective( 2058 const OMPTeamsDistributeParallelForDirective &S) { 2059 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2060 CGM.getOpenMPRuntime().emitInlinedDirective( 2061 *this, OMPD_teams_distribute_parallel_for, 2062 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2063 OMPLoopScope PreInitScope(CGF, S); 2064 CGF.EmitStmt( 2065 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2066 }); 2067 } 2068 2069 void CodeGenFunction::EmitOMPTargetTeamsDistributeDirective( 2070 const OMPTargetTeamsDistributeDirective &S) { 2071 CGM.getOpenMPRuntime().emitInlinedDirective( 2072 *this, OMPD_target_teams_distribute, 2073 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2074 CGF.EmitStmt( 2075 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2076 }); 2077 } 2078 2079 void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDirective( 2080 const OMPTargetTeamsDistributeParallelForDirective &S) { 2081 CGM.getOpenMPRuntime().emitInlinedDirective( 2082 *this, OMPD_target_teams_distribute_parallel_for, 2083 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2084 CGF.EmitStmt( 2085 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2086 }); 2087 } 2088 2089 void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDirective( 2090 const OMPTargetTeamsDistributeParallelForSimdDirective &S) { 2091 CGM.getOpenMPRuntime().emitInlinedDirective( 2092 *this, OMPD_target_teams_distribute_parallel_for_simd, 2093 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2094 CGF.EmitStmt( 2095 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2096 }); 2097 } 2098 2099 void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDirective( 2100 const OMPTargetTeamsDistributeSimdDirective &S) { 2101 CGM.getOpenMPRuntime().emitInlinedDirective( 2102 *this, OMPD_target_teams_distribute_simd, 2103 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2104 CGF.EmitStmt( 2105 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2106 }); 2107 } 2108 2109 namespace { 2110 struct ScheduleKindModifiersTy { 2111 OpenMPScheduleClauseKind Kind; 2112 OpenMPScheduleClauseModifier M1; 2113 OpenMPScheduleClauseModifier M2; 2114 ScheduleKindModifiersTy(OpenMPScheduleClauseKind Kind, 2115 OpenMPScheduleClauseModifier M1, 2116 OpenMPScheduleClauseModifier M2) 2117 : Kind(Kind), M1(M1), M2(M2) {} 2118 }; 2119 } // namespace 2120 2121 bool CodeGenFunction::EmitOMPWorksharingLoop( 2122 const OMPLoopDirective &S, Expr *EUB, 2123 const CodeGenLoopBoundsTy &CodeGenLoopBounds, 2124 const CodeGenDispatchBoundsTy &CGDispatchBounds) { 2125 // Emit the loop iteration variable. 2126 auto IVExpr = cast<DeclRefExpr>(S.getIterationVariable()); 2127 auto IVDecl = cast<VarDecl>(IVExpr->getDecl()); 2128 EmitVarDecl(*IVDecl); 2129 2130 // Emit the iterations count variable. 2131 // If it is not a variable, Sema decided to calculate iterations count on each 2132 // iteration (e.g., it is foldable into a constant). 2133 if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { 2134 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); 2135 // Emit calculation of the iterations count. 2136 EmitIgnoredExpr(S.getCalcLastIteration()); 2137 } 2138 2139 auto &RT = CGM.getOpenMPRuntime(); 2140 2141 bool HasLastprivateClause; 2142 // Check pre-condition. 2143 { 2144 OMPLoopScope PreInitScope(*this, S); 2145 // Skip the entire loop if we don't meet the precondition. 2146 // If the condition constant folds and can be elided, avoid emitting the 2147 // whole loop. 2148 bool CondConstant; 2149 llvm::BasicBlock *ContBlock = nullptr; 2150 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { 2151 if (!CondConstant) 2152 return false; 2153 } else { 2154 auto *ThenBlock = createBasicBlock("omp.precond.then"); 2155 ContBlock = createBasicBlock("omp.precond.end"); 2156 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock, 2157 getProfileCount(&S)); 2158 EmitBlock(ThenBlock); 2159 incrementProfileCounter(&S); 2160 } 2161 2162 bool Ordered = false; 2163 if (auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) { 2164 if (OrderedClause->getNumForLoops()) 2165 RT.emitDoacrossInit(*this, S); 2166 else 2167 Ordered = true; 2168 } 2169 2170 llvm::DenseSet<const Expr *> EmittedFinals; 2171 emitAlignedClause(*this, S); 2172 EmitOMPLinearClauseInit(S); 2173 // Emit helper vars inits. 2174 2175 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*this, S); 2176 LValue LB = Bounds.first; 2177 LValue UB = Bounds.second; 2178 LValue ST = 2179 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable())); 2180 LValue IL = 2181 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable())); 2182 2183 // Emit 'then' code. 2184 { 2185 OMPPrivateScope LoopScope(*this); 2186 if (EmitOMPFirstprivateClause(S, LoopScope)) { 2187 // Emit implicit barrier to synchronize threads and avoid data races on 2188 // initialization of firstprivate variables and post-update of 2189 // lastprivate variables. 2190 CGM.getOpenMPRuntime().emitBarrierCall( 2191 *this, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false, 2192 /*ForceSimpleCall=*/true); 2193 } 2194 EmitOMPPrivateClause(S, LoopScope); 2195 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope); 2196 EmitOMPReductionClauseInit(S, LoopScope); 2197 EmitOMPPrivateLoopCounters(S, LoopScope); 2198 EmitOMPLinearClause(S, LoopScope); 2199 (void)LoopScope.Privatize(); 2200 2201 // Detect the loop schedule kind and chunk. 2202 llvm::Value *Chunk = nullptr; 2203 OpenMPScheduleTy ScheduleKind; 2204 if (auto *C = S.getSingleClause<OMPScheduleClause>()) { 2205 ScheduleKind.Schedule = C->getScheduleKind(); 2206 ScheduleKind.M1 = C->getFirstScheduleModifier(); 2207 ScheduleKind.M2 = C->getSecondScheduleModifier(); 2208 if (const auto *Ch = C->getChunkSize()) { 2209 Chunk = EmitScalarExpr(Ch); 2210 Chunk = EmitScalarConversion(Chunk, Ch->getType(), 2211 S.getIterationVariable()->getType(), 2212 S.getLocStart()); 2213 } 2214 } 2215 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); 2216 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); 2217 // OpenMP 4.5, 2.7.1 Loop Construct, Description. 2218 // If the static schedule kind is specified or if the ordered clause is 2219 // specified, and if no monotonic modifier is specified, the effect will 2220 // be as if the monotonic modifier was specified. 2221 if (RT.isStaticNonchunked(ScheduleKind.Schedule, 2222 /* Chunked */ Chunk != nullptr) && 2223 !Ordered) { 2224 if (isOpenMPSimdDirective(S.getDirectiveKind())) 2225 EmitOMPSimdInit(S, /*IsMonotonic=*/true); 2226 // OpenMP [2.7.1, Loop Construct, Description, table 2-1] 2227 // When no chunk_size is specified, the iteration space is divided into 2228 // chunks that are approximately equal in size, and at most one chunk is 2229 // distributed to each thread. Note that the size of the chunks is 2230 // unspecified in this case. 2231 RT.emitForStaticInit(*this, S.getLocStart(), ScheduleKind, 2232 IVSize, IVSigned, Ordered, 2233 IL.getAddress(), LB.getAddress(), 2234 UB.getAddress(), ST.getAddress()); 2235 auto LoopExit = 2236 getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit")); 2237 // UB = min(UB, GlobalUB); 2238 EmitIgnoredExpr(S.getEnsureUpperBound()); 2239 // IV = LB; 2240 EmitIgnoredExpr(S.getInit()); 2241 // while (idx <= UB) { BODY; ++idx; } 2242 EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), 2243 S.getInc(), 2244 [&S, LoopExit](CodeGenFunction &CGF) { 2245 CGF.EmitOMPLoopBody(S, LoopExit); 2246 CGF.EmitStopPoint(&S); 2247 }, 2248 [](CodeGenFunction &) {}); 2249 EmitBlock(LoopExit.getBlock()); 2250 // Tell the runtime we are done. 2251 auto &&CodeGen = [&S](CodeGenFunction &CGF) { 2252 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd()); 2253 }; 2254 OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen); 2255 } else { 2256 const bool IsMonotonic = 2257 Ordered || ScheduleKind.Schedule == OMPC_SCHEDULE_static || 2258 ScheduleKind.Schedule == OMPC_SCHEDULE_unknown || 2259 ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic || 2260 ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_monotonic; 2261 // Emit the outer loop, which requests its work chunk [LB..UB] from 2262 // runtime and runs the inner loop to process it. 2263 const OMPLoopArguments LoopArguments(LB.getAddress(), UB.getAddress(), 2264 ST.getAddress(), IL.getAddress(), 2265 Chunk, EUB); 2266 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered, 2267 LoopArguments, CGDispatchBounds); 2268 } 2269 if (isOpenMPSimdDirective(S.getDirectiveKind())) { 2270 EmitOMPSimdFinal(S, 2271 [&](CodeGenFunction &CGF) -> llvm::Value * { 2272 return CGF.Builder.CreateIsNotNull( 2273 CGF.EmitLoadOfScalar(IL, S.getLocStart())); 2274 }); 2275 } 2276 EmitOMPReductionClauseFinal( 2277 S, /*ReductionKind=*/isOpenMPSimdDirective(S.getDirectiveKind()) 2278 ? /*Parallel and Simd*/ OMPD_parallel_for_simd 2279 : /*Parallel only*/ OMPD_parallel); 2280 // Emit post-update of the reduction variables if IsLastIter != 0. 2281 emitPostUpdateForReductionClause( 2282 *this, S, [&](CodeGenFunction &CGF) -> llvm::Value * { 2283 return CGF.Builder.CreateIsNotNull( 2284 CGF.EmitLoadOfScalar(IL, S.getLocStart())); 2285 }); 2286 // Emit final copy of the lastprivate variables if IsLastIter != 0. 2287 if (HasLastprivateClause) 2288 EmitOMPLastprivateClauseFinal( 2289 S, isOpenMPSimdDirective(S.getDirectiveKind()), 2290 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getLocStart()))); 2291 } 2292 EmitOMPLinearClauseFinal(S, [&](CodeGenFunction &CGF) -> llvm::Value * { 2293 return CGF.Builder.CreateIsNotNull( 2294 CGF.EmitLoadOfScalar(IL, S.getLocStart())); 2295 }); 2296 // We're now done with the loop, so jump to the continuation block. 2297 if (ContBlock) { 2298 EmitBranch(ContBlock); 2299 EmitBlock(ContBlock, true); 2300 } 2301 } 2302 return HasLastprivateClause; 2303 } 2304 2305 /// The following two functions generate expressions for the loop lower 2306 /// and upper bounds in case of static and dynamic (dispatch) schedule 2307 /// of the associated 'for' or 'distribute' loop. 2308 static std::pair<LValue, LValue> 2309 emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S) { 2310 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S); 2311 LValue LB = 2312 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable())); 2313 LValue UB = 2314 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable())); 2315 return {LB, UB}; 2316 } 2317 2318 /// When dealing with dispatch schedules (e.g. dynamic, guided) we do not 2319 /// consider the lower and upper bound expressions generated by the 2320 /// worksharing loop support, but we use 0 and the iteration space size as 2321 /// constants 2322 static std::pair<llvm::Value *, llvm::Value *> 2323 emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, 2324 Address LB, Address UB) { 2325 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S); 2326 const Expr *IVExpr = LS.getIterationVariable(); 2327 const unsigned IVSize = CGF.getContext().getTypeSize(IVExpr->getType()); 2328 llvm::Value *LBVal = CGF.Builder.getIntN(IVSize, 0); 2329 llvm::Value *UBVal = CGF.EmitScalarExpr(LS.getLastIteration()); 2330 return {LBVal, UBVal}; 2331 } 2332 2333 void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) { 2334 bool HasLastprivates = false; 2335 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF, 2336 PrePostActionTy &) { 2337 OMPCancelStackRAII CancelRegion(CGF, OMPD_for, S.hasCancel()); 2338 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), 2339 emitForLoopBounds, 2340 emitDispatchForLoopBounds); 2341 }; 2342 { 2343 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2344 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen, 2345 S.hasCancel()); 2346 } 2347 2348 // Emit an implicit barrier at the end. 2349 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) { 2350 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for); 2351 } 2352 } 2353 2354 void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) { 2355 bool HasLastprivates = false; 2356 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF, 2357 PrePostActionTy &) { 2358 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), 2359 emitForLoopBounds, 2360 emitDispatchForLoopBounds); 2361 }; 2362 { 2363 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2364 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen); 2365 } 2366 2367 // Emit an implicit barrier at the end. 2368 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) { 2369 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_for); 2370 } 2371 } 2372 2373 static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, 2374 const Twine &Name, 2375 llvm::Value *Init = nullptr) { 2376 auto LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty); 2377 if (Init) 2378 CGF.EmitStoreThroughLValue(RValue::get(Init), LVal, /*isInit*/ true); 2379 return LVal; 2380 } 2381 2382 void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { 2383 auto *Stmt = cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt(); 2384 auto *CS = dyn_cast<CompoundStmt>(Stmt); 2385 bool HasLastprivates = false; 2386 auto &&CodeGen = [&S, Stmt, CS, &HasLastprivates](CodeGenFunction &CGF, 2387 PrePostActionTy &) { 2388 auto &C = CGF.CGM.getContext(); 2389 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2390 // Emit helper vars inits. 2391 LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.", 2392 CGF.Builder.getInt32(0)); 2393 auto *GlobalUBVal = CS != nullptr ? CGF.Builder.getInt32(CS->size() - 1) 2394 : CGF.Builder.getInt32(0); 2395 LValue UB = 2396 createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal); 2397 LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.", 2398 CGF.Builder.getInt32(1)); 2399 LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.", 2400 CGF.Builder.getInt32(0)); 2401 // Loop counter. 2402 LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv."); 2403 OpaqueValueExpr IVRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue); 2404 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV); 2405 OpaqueValueExpr UBRefExpr(S.getLocStart(), KmpInt32Ty, VK_LValue); 2406 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB); 2407 // Generate condition for loop. 2408 BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, 2409 OK_Ordinary, S.getLocStart(), FPOptions()); 2410 // Increment for loop counter. 2411 UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary, 2412 S.getLocStart()); 2413 auto BodyGen = [Stmt, CS, &S, &IV](CodeGenFunction &CGF) { 2414 // Iterate through all sections and emit a switch construct: 2415 // switch (IV) { 2416 // case 0: 2417 // <SectionStmt[0]>; 2418 // break; 2419 // ... 2420 // case <NumSection> - 1: 2421 // <SectionStmt[<NumSection> - 1]>; 2422 // break; 2423 // } 2424 // .omp.sections.exit: 2425 auto *ExitBB = CGF.createBasicBlock(".omp.sections.exit"); 2426 auto *SwitchStmt = CGF.Builder.CreateSwitch( 2427 CGF.EmitLoadOfLValue(IV, S.getLocStart()).getScalarVal(), ExitBB, 2428 CS == nullptr ? 1 : CS->size()); 2429 if (CS) { 2430 unsigned CaseNumber = 0; 2431 for (auto *SubStmt : CS->children()) { 2432 auto CaseBB = CGF.createBasicBlock(".omp.sections.case"); 2433 CGF.EmitBlock(CaseBB); 2434 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB); 2435 CGF.EmitStmt(SubStmt); 2436 CGF.EmitBranch(ExitBB); 2437 ++CaseNumber; 2438 } 2439 } else { 2440 auto CaseBB = CGF.createBasicBlock(".omp.sections.case"); 2441 CGF.EmitBlock(CaseBB); 2442 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB); 2443 CGF.EmitStmt(Stmt); 2444 CGF.EmitBranch(ExitBB); 2445 } 2446 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 2447 }; 2448 2449 CodeGenFunction::OMPPrivateScope LoopScope(CGF); 2450 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) { 2451 // Emit implicit barrier to synchronize threads and avoid data races on 2452 // initialization of firstprivate variables and post-update of lastprivate 2453 // variables. 2454 CGF.CGM.getOpenMPRuntime().emitBarrierCall( 2455 CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false, 2456 /*ForceSimpleCall=*/true); 2457 } 2458 CGF.EmitOMPPrivateClause(S, LoopScope); 2459 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); 2460 CGF.EmitOMPReductionClauseInit(S, LoopScope); 2461 (void)LoopScope.Privatize(); 2462 2463 // Emit static non-chunked loop. 2464 OpenMPScheduleTy ScheduleKind; 2465 ScheduleKind.Schedule = OMPC_SCHEDULE_static; 2466 CGF.CGM.getOpenMPRuntime().emitForStaticInit( 2467 CGF, S.getLocStart(), ScheduleKind, /*IVSize=*/32, 2468 /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(), LB.getAddress(), 2469 UB.getAddress(), ST.getAddress()); 2470 // UB = min(UB, GlobalUB); 2471 auto *UBVal = CGF.EmitLoadOfScalar(UB, S.getLocStart()); 2472 auto *MinUBGlobalUB = CGF.Builder.CreateSelect( 2473 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal); 2474 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB); 2475 // IV = LB; 2476 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getLocStart()), IV); 2477 // while (idx <= UB) { BODY; ++idx; } 2478 CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen, 2479 [](CodeGenFunction &) {}); 2480 // Tell the runtime we are done. 2481 auto &&CodeGen = [&S](CodeGenFunction &CGF) { 2482 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getLocEnd()); 2483 }; 2484 CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen); 2485 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel); 2486 // Emit post-update of the reduction variables if IsLastIter != 0. 2487 emitPostUpdateForReductionClause( 2488 CGF, S, [&](CodeGenFunction &CGF) -> llvm::Value * { 2489 return CGF.Builder.CreateIsNotNull( 2490 CGF.EmitLoadOfScalar(IL, S.getLocStart())); 2491 }); 2492 2493 // Emit final copy of the lastprivate variables if IsLastIter != 0. 2494 if (HasLastprivates) 2495 CGF.EmitOMPLastprivateClauseFinal( 2496 S, /*NoFinals=*/false, 2497 CGF.Builder.CreateIsNotNull( 2498 CGF.EmitLoadOfScalar(IL, S.getLocStart()))); 2499 }; 2500 2501 bool HasCancel = false; 2502 if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S)) 2503 HasCancel = OSD->hasCancel(); 2504 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S)) 2505 HasCancel = OPSD->hasCancel(); 2506 OMPCancelStackRAII CancelRegion(*this, S.getDirectiveKind(), HasCancel); 2507 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen, 2508 HasCancel); 2509 // Emit barrier for lastprivates only if 'sections' directive has 'nowait' 2510 // clause. Otherwise the barrier will be generated by the codegen for the 2511 // directive. 2512 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) { 2513 // Emit implicit barrier to synchronize threads and avoid data races on 2514 // initialization of firstprivate variables. 2515 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), 2516 OMPD_unknown); 2517 } 2518 } 2519 2520 void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) { 2521 { 2522 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2523 EmitSections(S); 2524 } 2525 // Emit an implicit barrier at the end. 2526 if (!S.getSingleClause<OMPNowaitClause>()) { 2527 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), 2528 OMPD_sections); 2529 } 2530 } 2531 2532 void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) { 2533 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2534 CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2535 }; 2536 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2537 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen, 2538 S.hasCancel()); 2539 } 2540 2541 void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) { 2542 llvm::SmallVector<const Expr *, 8> CopyprivateVars; 2543 llvm::SmallVector<const Expr *, 8> DestExprs; 2544 llvm::SmallVector<const Expr *, 8> SrcExprs; 2545 llvm::SmallVector<const Expr *, 8> AssignmentOps; 2546 // Check if there are any 'copyprivate' clauses associated with this 2547 // 'single' construct. 2548 // Build a list of copyprivate variables along with helper expressions 2549 // (<source>, <destination>, <destination>=<source> expressions) 2550 for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) { 2551 CopyprivateVars.append(C->varlists().begin(), C->varlists().end()); 2552 DestExprs.append(C->destination_exprs().begin(), 2553 C->destination_exprs().end()); 2554 SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end()); 2555 AssignmentOps.append(C->assignment_ops().begin(), 2556 C->assignment_ops().end()); 2557 } 2558 // Emit code for 'single' region along with 'copyprivate' clauses 2559 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 2560 Action.Enter(CGF); 2561 OMPPrivateScope SingleScope(CGF); 2562 (void)CGF.EmitOMPFirstprivateClause(S, SingleScope); 2563 CGF.EmitOMPPrivateClause(S, SingleScope); 2564 (void)SingleScope.Privatize(); 2565 CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2566 }; 2567 { 2568 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2569 CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(), 2570 CopyprivateVars, DestExprs, 2571 SrcExprs, AssignmentOps); 2572 } 2573 // Emit an implicit barrier at the end (to avoid data race on firstprivate 2574 // init or if no 'nowait' clause was specified and no 'copyprivate' clause). 2575 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) { 2576 CGM.getOpenMPRuntime().emitBarrierCall( 2577 *this, S.getLocStart(), 2578 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single); 2579 } 2580 } 2581 2582 void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) { 2583 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 2584 Action.Enter(CGF); 2585 CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2586 }; 2587 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2588 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getLocStart()); 2589 } 2590 2591 void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) { 2592 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 2593 Action.Enter(CGF); 2594 CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2595 }; 2596 Expr *Hint = nullptr; 2597 if (auto *HintClause = S.getSingleClause<OMPHintClause>()) 2598 Hint = HintClause->getHint(); 2599 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2600 CGM.getOpenMPRuntime().emitCriticalRegion(*this, 2601 S.getDirectiveName().getAsString(), 2602 CodeGen, S.getLocStart(), Hint); 2603 } 2604 2605 void CodeGenFunction::EmitOMPParallelForDirective( 2606 const OMPParallelForDirective &S) { 2607 // Emit directive as a combined directive that consists of two implicit 2608 // directives: 'parallel' with 'for' directive. 2609 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2610 OMPCancelStackRAII CancelRegion(CGF, OMPD_parallel_for, S.hasCancel()); 2611 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds, 2612 emitDispatchForLoopBounds); 2613 }; 2614 emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen, 2615 emitEmptyBoundParameters); 2616 } 2617 2618 void CodeGenFunction::EmitOMPParallelForSimdDirective( 2619 const OMPParallelForSimdDirective &S) { 2620 // Emit directive as a combined directive that consists of two implicit 2621 // directives: 'parallel' with 'for' directive. 2622 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2623 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds, 2624 emitDispatchForLoopBounds); 2625 }; 2626 emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen, 2627 emitEmptyBoundParameters); 2628 } 2629 2630 void CodeGenFunction::EmitOMPParallelSectionsDirective( 2631 const OMPParallelSectionsDirective &S) { 2632 // Emit directive as a combined directive that consists of two implicit 2633 // directives: 'parallel' with 'sections' directive. 2634 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2635 CGF.EmitSections(S); 2636 }; 2637 emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen, 2638 emitEmptyBoundParameters); 2639 } 2640 2641 void CodeGenFunction::EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, 2642 const RegionCodeGenTy &BodyGen, 2643 const TaskGenTy &TaskGen, 2644 OMPTaskDataTy &Data) { 2645 // Emit outlined function for task construct. 2646 auto CS = cast<CapturedStmt>(S.getAssociatedStmt()); 2647 auto *I = CS->getCapturedDecl()->param_begin(); 2648 auto *PartId = std::next(I); 2649 auto *TaskT = std::next(I, 4); 2650 // Check if the task is final 2651 if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) { 2652 // If the condition constant folds and can be elided, try to avoid emitting 2653 // the condition and the dead arm of the if/else. 2654 auto *Cond = Clause->getCondition(); 2655 bool CondConstant; 2656 if (ConstantFoldsToSimpleInteger(Cond, CondConstant)) 2657 Data.Final.setInt(CondConstant); 2658 else 2659 Data.Final.setPointer(EvaluateExprAsBool(Cond)); 2660 } else { 2661 // By default the task is not final. 2662 Data.Final.setInt(/*IntVal=*/false); 2663 } 2664 // Check if the task has 'priority' clause. 2665 if (const auto *Clause = S.getSingleClause<OMPPriorityClause>()) { 2666 auto *Prio = Clause->getPriority(); 2667 Data.Priority.setInt(/*IntVal=*/true); 2668 Data.Priority.setPointer(EmitScalarConversion( 2669 EmitScalarExpr(Prio), Prio->getType(), 2670 getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1), 2671 Prio->getExprLoc())); 2672 } 2673 // The first function argument for tasks is a thread id, the second one is a 2674 // part id (0 for tied tasks, >=0 for untied task). 2675 llvm::DenseSet<const VarDecl *> EmittedAsPrivate; 2676 // Get list of private variables. 2677 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 2678 auto IRef = C->varlist_begin(); 2679 for (auto *IInit : C->private_copies()) { 2680 auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 2681 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { 2682 Data.PrivateVars.push_back(*IRef); 2683 Data.PrivateCopies.push_back(IInit); 2684 } 2685 ++IRef; 2686 } 2687 } 2688 EmittedAsPrivate.clear(); 2689 // Get list of firstprivate variables. 2690 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 2691 auto IRef = C->varlist_begin(); 2692 auto IElemInitRef = C->inits().begin(); 2693 for (auto *IInit : C->private_copies()) { 2694 auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 2695 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { 2696 Data.FirstprivateVars.push_back(*IRef); 2697 Data.FirstprivateCopies.push_back(IInit); 2698 Data.FirstprivateInits.push_back(*IElemInitRef); 2699 } 2700 ++IRef; 2701 ++IElemInitRef; 2702 } 2703 } 2704 // Get list of lastprivate variables (for taskloops). 2705 llvm::DenseMap<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs; 2706 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 2707 auto IRef = C->varlist_begin(); 2708 auto ID = C->destination_exprs().begin(); 2709 for (auto *IInit : C->private_copies()) { 2710 auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 2711 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { 2712 Data.LastprivateVars.push_back(*IRef); 2713 Data.LastprivateCopies.push_back(IInit); 2714 } 2715 LastprivateDstsOrigs.insert( 2716 {cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()), 2717 cast<DeclRefExpr>(*IRef)}); 2718 ++IRef; 2719 ++ID; 2720 } 2721 } 2722 SmallVector<const Expr *, 4> LHSs; 2723 SmallVector<const Expr *, 4> RHSs; 2724 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 2725 auto IPriv = C->privates().begin(); 2726 auto IRed = C->reduction_ops().begin(); 2727 auto ILHS = C->lhs_exprs().begin(); 2728 auto IRHS = C->rhs_exprs().begin(); 2729 for (const auto *Ref : C->varlists()) { 2730 Data.ReductionVars.emplace_back(Ref); 2731 Data.ReductionCopies.emplace_back(*IPriv); 2732 Data.ReductionOps.emplace_back(*IRed); 2733 LHSs.emplace_back(*ILHS); 2734 RHSs.emplace_back(*IRHS); 2735 std::advance(IPriv, 1); 2736 std::advance(IRed, 1); 2737 std::advance(ILHS, 1); 2738 std::advance(IRHS, 1); 2739 } 2740 } 2741 Data.Reductions = CGM.getOpenMPRuntime().emitTaskReductionInit( 2742 *this, S.getLocStart(), LHSs, RHSs, Data); 2743 // Build list of dependences. 2744 for (const auto *C : S.getClausesOfKind<OMPDependClause>()) 2745 for (auto *IRef : C->varlists()) 2746 Data.Dependences.push_back(std::make_pair(C->getDependencyKind(), IRef)); 2747 auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs]( 2748 CodeGenFunction &CGF, PrePostActionTy &Action) { 2749 // Set proper addresses for generated private copies. 2750 OMPPrivateScope Scope(CGF); 2751 if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() || 2752 !Data.LastprivateVars.empty()) { 2753 auto *CopyFn = CGF.Builder.CreateLoad( 2754 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(3))); 2755 auto *PrivatesPtr = CGF.Builder.CreateLoad( 2756 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(2))); 2757 // Map privates. 2758 llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs; 2759 llvm::SmallVector<llvm::Value *, 16> CallArgs; 2760 CallArgs.push_back(PrivatesPtr); 2761 for (auto *E : Data.PrivateVars) { 2762 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2763 Address PrivatePtr = CGF.CreateMemTemp( 2764 CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr"); 2765 PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr)); 2766 CallArgs.push_back(PrivatePtr.getPointer()); 2767 } 2768 for (auto *E : Data.FirstprivateVars) { 2769 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2770 Address PrivatePtr = 2771 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), 2772 ".firstpriv.ptr.addr"); 2773 PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr)); 2774 CallArgs.push_back(PrivatePtr.getPointer()); 2775 } 2776 for (auto *E : Data.LastprivateVars) { 2777 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2778 Address PrivatePtr = 2779 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), 2780 ".lastpriv.ptr.addr"); 2781 PrivatePtrs.push_back(std::make_pair(VD, PrivatePtr)); 2782 CallArgs.push_back(PrivatePtr.getPointer()); 2783 } 2784 CGF.EmitRuntimeCall(CopyFn, CallArgs); 2785 for (auto &&Pair : LastprivateDstsOrigs) { 2786 auto *OrigVD = cast<VarDecl>(Pair.second->getDecl()); 2787 DeclRefExpr DRE( 2788 const_cast<VarDecl *>(OrigVD), 2789 /*RefersToEnclosingVariableOrCapture=*/CGF.CapturedStmtInfo->lookup( 2790 OrigVD) != nullptr, 2791 Pair.second->getType(), VK_LValue, Pair.second->getExprLoc()); 2792 Scope.addPrivate(Pair.first, [&CGF, &DRE]() { 2793 return CGF.EmitLValue(&DRE).getAddress(); 2794 }); 2795 } 2796 for (auto &&Pair : PrivatePtrs) { 2797 Address Replacement(CGF.Builder.CreateLoad(Pair.second), 2798 CGF.getContext().getDeclAlign(Pair.first)); 2799 Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; }); 2800 } 2801 } 2802 if (Data.Reductions) { 2803 OMPLexicalScope LexScope(CGF, S, /*AsInlined=*/true); 2804 ReductionCodeGen RedCG(Data.ReductionVars, Data.ReductionCopies, 2805 Data.ReductionOps); 2806 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad( 2807 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(9))); 2808 for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) { 2809 RedCG.emitSharedLValue(CGF, Cnt); 2810 RedCG.emitAggregateType(CGF, Cnt); 2811 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( 2812 CGF, S.getLocStart(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); 2813 Replacement = 2814 Address(CGF.EmitScalarConversion( 2815 Replacement.getPointer(), CGF.getContext().VoidPtrTy, 2816 CGF.getContext().getPointerType( 2817 Data.ReductionCopies[Cnt]->getType()), 2818 SourceLocation()), 2819 Replacement.getAlignment()); 2820 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); 2821 Scope.addPrivate(RedCG.getBaseDecl(Cnt), 2822 [Replacement]() { return Replacement; }); 2823 // FIXME: This must removed once the runtime library is fixed. 2824 // Emit required threadprivate variables for 2825 // initilizer/combiner/finalizer. 2826 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getLocStart(), 2827 RedCG, Cnt); 2828 } 2829 } 2830 // Privatize all private variables except for in_reduction items. 2831 (void)Scope.Privatize(); 2832 SmallVector<const Expr *, 4> InRedVars; 2833 SmallVector<const Expr *, 4> InRedPrivs; 2834 SmallVector<const Expr *, 4> InRedOps; 2835 SmallVector<const Expr *, 4> TaskgroupDescriptors; 2836 for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) { 2837 auto IPriv = C->privates().begin(); 2838 auto IRed = C->reduction_ops().begin(); 2839 auto ITD = C->taskgroup_descriptors().begin(); 2840 for (const auto *Ref : C->varlists()) { 2841 InRedVars.emplace_back(Ref); 2842 InRedPrivs.emplace_back(*IPriv); 2843 InRedOps.emplace_back(*IRed); 2844 TaskgroupDescriptors.emplace_back(*ITD); 2845 std::advance(IPriv, 1); 2846 std::advance(IRed, 1); 2847 std::advance(ITD, 1); 2848 } 2849 } 2850 // Privatize in_reduction items here, because taskgroup descriptors must be 2851 // privatized earlier. 2852 OMPPrivateScope InRedScope(CGF); 2853 if (!InRedVars.empty()) { 2854 ReductionCodeGen RedCG(InRedVars, InRedPrivs, InRedOps); 2855 for (unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) { 2856 RedCG.emitSharedLValue(CGF, Cnt); 2857 RedCG.emitAggregateType(CGF, Cnt); 2858 // The taskgroup descriptor variable is always implicit firstprivate and 2859 // privatized already during procoessing of the firstprivates. 2860 llvm::Value *ReductionsPtr = CGF.EmitLoadOfScalar( 2861 CGF.EmitLValue(TaskgroupDescriptors[Cnt]), SourceLocation()); 2862 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( 2863 CGF, S.getLocStart(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); 2864 Replacement = Address( 2865 CGF.EmitScalarConversion( 2866 Replacement.getPointer(), CGF.getContext().VoidPtrTy, 2867 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), 2868 SourceLocation()), 2869 Replacement.getAlignment()); 2870 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); 2871 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt), 2872 [Replacement]() { return Replacement; }); 2873 // FIXME: This must removed once the runtime library is fixed. 2874 // Emit required threadprivate variables for 2875 // initilizer/combiner/finalizer. 2876 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getLocStart(), 2877 RedCG, Cnt); 2878 } 2879 } 2880 (void)InRedScope.Privatize(); 2881 2882 Action.Enter(CGF); 2883 BodyGen(CGF); 2884 }; 2885 auto *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction( 2886 S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, Data.Tied, 2887 Data.NumberOfParts); 2888 OMPLexicalScope Scope(*this, S); 2889 TaskGen(*this, OutlinedFn, Data); 2890 } 2891 2892 void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) { 2893 // Emit outlined function for task construct. 2894 auto CS = cast<CapturedStmt>(S.getAssociatedStmt()); 2895 auto CapturedStruct = GenerateCapturedStmtArgument(*CS); 2896 auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); 2897 const Expr *IfCond = nullptr; 2898 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { 2899 if (C->getNameModifier() == OMPD_unknown || 2900 C->getNameModifier() == OMPD_task) { 2901 IfCond = C->getCondition(); 2902 break; 2903 } 2904 } 2905 2906 OMPTaskDataTy Data; 2907 // Check if we should emit tied or untied task. 2908 Data.Tied = !S.getSingleClause<OMPUntiedClause>(); 2909 auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) { 2910 CGF.EmitStmt(CS->getCapturedStmt()); 2911 }; 2912 auto &&TaskGen = [&S, SharedsTy, CapturedStruct, 2913 IfCond](CodeGenFunction &CGF, llvm::Value *OutlinedFn, 2914 const OMPTaskDataTy &Data) { 2915 CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getLocStart(), S, OutlinedFn, 2916 SharedsTy, CapturedStruct, IfCond, 2917 Data); 2918 }; 2919 EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Data); 2920 } 2921 2922 void CodeGenFunction::EmitOMPTaskyieldDirective( 2923 const OMPTaskyieldDirective &S) { 2924 CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getLocStart()); 2925 } 2926 2927 void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) { 2928 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getLocStart(), OMPD_barrier); 2929 } 2930 2931 void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) { 2932 CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getLocStart()); 2933 } 2934 2935 void CodeGenFunction::EmitOMPTaskgroupDirective( 2936 const OMPTaskgroupDirective &S) { 2937 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 2938 Action.Enter(CGF); 2939 if (const Expr *E = S.getReductionRef()) { 2940 SmallVector<const Expr *, 4> LHSs; 2941 SmallVector<const Expr *, 4> RHSs; 2942 OMPTaskDataTy Data; 2943 for (const auto *C : S.getClausesOfKind<OMPTaskReductionClause>()) { 2944 auto IPriv = C->privates().begin(); 2945 auto IRed = C->reduction_ops().begin(); 2946 auto ILHS = C->lhs_exprs().begin(); 2947 auto IRHS = C->rhs_exprs().begin(); 2948 for (const auto *Ref : C->varlists()) { 2949 Data.ReductionVars.emplace_back(Ref); 2950 Data.ReductionCopies.emplace_back(*IPriv); 2951 Data.ReductionOps.emplace_back(*IRed); 2952 LHSs.emplace_back(*ILHS); 2953 RHSs.emplace_back(*IRHS); 2954 std::advance(IPriv, 1); 2955 std::advance(IRed, 1); 2956 std::advance(ILHS, 1); 2957 std::advance(IRHS, 1); 2958 } 2959 } 2960 llvm::Value *ReductionDesc = 2961 CGF.CGM.getOpenMPRuntime().emitTaskReductionInit(CGF, S.getLocStart(), 2962 LHSs, RHSs, Data); 2963 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2964 CGF.EmitVarDecl(*VD); 2965 CGF.EmitStoreOfScalar(ReductionDesc, CGF.GetAddrOfLocalVar(VD), 2966 /*Volatile=*/false, E->getType()); 2967 } 2968 CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 2969 }; 2970 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 2971 CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getLocStart()); 2972 } 2973 2974 void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) { 2975 CGM.getOpenMPRuntime().emitFlush(*this, [&]() -> ArrayRef<const Expr *> { 2976 if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>()) { 2977 return llvm::makeArrayRef(FlushClause->varlist_begin(), 2978 FlushClause->varlist_end()); 2979 } 2980 return llvm::None; 2981 }(), S.getLocStart()); 2982 } 2983 2984 void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S, 2985 const CodeGenLoopTy &CodeGenLoop, 2986 Expr *IncExpr) { 2987 // Emit the loop iteration variable. 2988 auto IVExpr = cast<DeclRefExpr>(S.getIterationVariable()); 2989 auto IVDecl = cast<VarDecl>(IVExpr->getDecl()); 2990 EmitVarDecl(*IVDecl); 2991 2992 // Emit the iterations count variable. 2993 // If it is not a variable, Sema decided to calculate iterations count on each 2994 // iteration (e.g., it is foldable into a constant). 2995 if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { 2996 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); 2997 // Emit calculation of the iterations count. 2998 EmitIgnoredExpr(S.getCalcLastIteration()); 2999 } 3000 3001 auto &RT = CGM.getOpenMPRuntime(); 3002 3003 bool HasLastprivateClause = false; 3004 // Check pre-condition. 3005 { 3006 OMPLoopScope PreInitScope(*this, S); 3007 // Skip the entire loop if we don't meet the precondition. 3008 // If the condition constant folds and can be elided, avoid emitting the 3009 // whole loop. 3010 bool CondConstant; 3011 llvm::BasicBlock *ContBlock = nullptr; 3012 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { 3013 if (!CondConstant) 3014 return; 3015 } else { 3016 auto *ThenBlock = createBasicBlock("omp.precond.then"); 3017 ContBlock = createBasicBlock("omp.precond.end"); 3018 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock, 3019 getProfileCount(&S)); 3020 EmitBlock(ThenBlock); 3021 incrementProfileCounter(&S); 3022 } 3023 3024 // Emit 'then' code. 3025 { 3026 // Emit helper vars inits. 3027 3028 LValue LB = EmitOMPHelperVar( 3029 *this, cast<DeclRefExpr>( 3030 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 3031 ? S.getCombinedLowerBoundVariable() 3032 : S.getLowerBoundVariable()))); 3033 LValue UB = EmitOMPHelperVar( 3034 *this, cast<DeclRefExpr>( 3035 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 3036 ? S.getCombinedUpperBoundVariable() 3037 : S.getUpperBoundVariable()))); 3038 LValue ST = 3039 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable())); 3040 LValue IL = 3041 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable())); 3042 3043 OMPPrivateScope LoopScope(*this); 3044 if (EmitOMPFirstprivateClause(S, LoopScope)) { 3045 // Emit implicit barrier to synchronize threads and avoid data races on 3046 // initialization of firstprivate variables and post-update of 3047 // lastprivate variables. 3048 CGM.getOpenMPRuntime().emitBarrierCall( 3049 *this, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false, 3050 /*ForceSimpleCall=*/true); 3051 } 3052 EmitOMPPrivateClause(S, LoopScope); 3053 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope); 3054 EmitOMPPrivateLoopCounters(S, LoopScope); 3055 (void)LoopScope.Privatize(); 3056 3057 // Detect the distribute schedule kind and chunk. 3058 llvm::Value *Chunk = nullptr; 3059 OpenMPDistScheduleClauseKind ScheduleKind = OMPC_DIST_SCHEDULE_unknown; 3060 if (auto *C = S.getSingleClause<OMPDistScheduleClause>()) { 3061 ScheduleKind = C->getDistScheduleKind(); 3062 if (const auto *Ch = C->getChunkSize()) { 3063 Chunk = EmitScalarExpr(Ch); 3064 Chunk = EmitScalarConversion(Chunk, Ch->getType(), 3065 S.getIterationVariable()->getType(), 3066 S.getLocStart()); 3067 } 3068 } 3069 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); 3070 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); 3071 3072 // OpenMP [2.10.8, distribute Construct, Description] 3073 // If dist_schedule is specified, kind must be static. If specified, 3074 // iterations are divided into chunks of size chunk_size, chunks are 3075 // assigned to the teams of the league in a round-robin fashion in the 3076 // order of the team number. When no chunk_size is specified, the 3077 // iteration space is divided into chunks that are approximately equal 3078 // in size, and at most one chunk is distributed to each team of the 3079 // league. The size of the chunks is unspecified in this case. 3080 if (RT.isStaticNonchunked(ScheduleKind, 3081 /* Chunked */ Chunk != nullptr)) { 3082 RT.emitDistributeStaticInit(*this, S.getLocStart(), ScheduleKind, 3083 IVSize, IVSigned, /* Ordered = */ false, 3084 IL.getAddress(), LB.getAddress(), 3085 UB.getAddress(), ST.getAddress()); 3086 auto LoopExit = 3087 getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit")); 3088 // UB = min(UB, GlobalUB); 3089 EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 3090 ? S.getCombinedEnsureUpperBound() 3091 : S.getEnsureUpperBound()); 3092 // IV = LB; 3093 EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 3094 ? S.getCombinedInit() 3095 : S.getInit()); 3096 3097 Expr *Cond = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 3098 ? S.getCombinedCond() 3099 : S.getCond(); 3100 3101 // for distribute alone, codegen 3102 // while (idx <= UB) { BODY; ++idx; } 3103 // when combined with 'for' (e.g. as in 'distribute parallel for') 3104 // while (idx <= UB) { <CodeGen rest of pragma>; idx += ST; } 3105 EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), Cond, IncExpr, 3106 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) { 3107 CodeGenLoop(CGF, S, LoopExit); 3108 }, 3109 [](CodeGenFunction &) {}); 3110 EmitBlock(LoopExit.getBlock()); 3111 // Tell the runtime we are done. 3112 RT.emitForStaticFinish(*this, S.getLocStart()); 3113 } else { 3114 // Emit the outer loop, which requests its work chunk [LB..UB] from 3115 // runtime and runs the inner loop to process it. 3116 const OMPLoopArguments LoopArguments = { 3117 LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(), 3118 Chunk}; 3119 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments, 3120 CodeGenLoop); 3121 } 3122 3123 // Emit final copy of the lastprivate variables if IsLastIter != 0. 3124 if (HasLastprivateClause) 3125 EmitOMPLastprivateClauseFinal( 3126 S, /*NoFinals=*/false, 3127 Builder.CreateIsNotNull( 3128 EmitLoadOfScalar(IL, S.getLocStart()))); 3129 } 3130 3131 // We're now done with the loop, so jump to the continuation block. 3132 if (ContBlock) { 3133 EmitBranch(ContBlock); 3134 EmitBlock(ContBlock, true); 3135 } 3136 } 3137 } 3138 3139 void CodeGenFunction::EmitOMPDistributeDirective( 3140 const OMPDistributeDirective &S) { 3141 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 3142 3143 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); 3144 }; 3145 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 3146 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen, 3147 false); 3148 } 3149 3150 static llvm::Function *emitOutlinedOrderedFunction(CodeGenModule &CGM, 3151 const CapturedStmt *S) { 3152 CodeGenFunction CGF(CGM, /*suppressNewContext=*/true); 3153 CodeGenFunction::CGCapturedStmtInfo CapStmtInfo; 3154 CGF.CapturedStmtInfo = &CapStmtInfo; 3155 auto *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S); 3156 Fn->addFnAttr(llvm::Attribute::NoInline); 3157 return Fn; 3158 } 3159 3160 void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) { 3161 if (!S.getAssociatedStmt()) { 3162 for (const auto *DC : S.getClausesOfKind<OMPDependClause>()) 3163 CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC); 3164 return; 3165 } 3166 auto *C = S.getSingleClause<OMPSIMDClause>(); 3167 auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF, 3168 PrePostActionTy &Action) { 3169 if (C) { 3170 auto CS = cast<CapturedStmt>(S.getAssociatedStmt()); 3171 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 3172 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars); 3173 auto *OutlinedFn = emitOutlinedOrderedFunction(CGM, CS); 3174 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, OutlinedFn, 3175 CapturedVars); 3176 } else { 3177 Action.Enter(CGF); 3178 CGF.EmitStmt( 3179 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 3180 } 3181 }; 3182 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 3183 CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getLocStart(), !C); 3184 } 3185 3186 static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val, 3187 QualType SrcType, QualType DestType, 3188 SourceLocation Loc) { 3189 assert(CGF.hasScalarEvaluationKind(DestType) && 3190 "DestType must have scalar evaluation kind."); 3191 assert(!Val.isAggregate() && "Must be a scalar or complex."); 3192 return Val.isScalar() 3193 ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType, DestType, 3194 Loc) 3195 : CGF.EmitComplexToScalarConversion(Val.getComplexVal(), SrcType, 3196 DestType, Loc); 3197 } 3198 3199 static CodeGenFunction::ComplexPairTy 3200 convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, 3201 QualType DestType, SourceLocation Loc) { 3202 assert(CGF.getEvaluationKind(DestType) == TEK_Complex && 3203 "DestType must have complex evaluation kind."); 3204 CodeGenFunction::ComplexPairTy ComplexVal; 3205 if (Val.isScalar()) { 3206 // Convert the input element to the element type of the complex. 3207 auto DestElementType = DestType->castAs<ComplexType>()->getElementType(); 3208 auto ScalarVal = CGF.EmitScalarConversion(Val.getScalarVal(), SrcType, 3209 DestElementType, Loc); 3210 ComplexVal = CodeGenFunction::ComplexPairTy( 3211 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType())); 3212 } else { 3213 assert(Val.isComplex() && "Must be a scalar or complex."); 3214 auto SrcElementType = SrcType->castAs<ComplexType>()->getElementType(); 3215 auto DestElementType = DestType->castAs<ComplexType>()->getElementType(); 3216 ComplexVal.first = CGF.EmitScalarConversion( 3217 Val.getComplexVal().first, SrcElementType, DestElementType, Loc); 3218 ComplexVal.second = CGF.EmitScalarConversion( 3219 Val.getComplexVal().second, SrcElementType, DestElementType, Loc); 3220 } 3221 return ComplexVal; 3222 } 3223 3224 static void emitSimpleAtomicStore(CodeGenFunction &CGF, bool IsSeqCst, 3225 LValue LVal, RValue RVal) { 3226 if (LVal.isGlobalReg()) { 3227 CGF.EmitStoreThroughGlobalRegLValue(RVal, LVal); 3228 } else { 3229 CGF.EmitAtomicStore(RVal, LVal, 3230 IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent 3231 : llvm::AtomicOrdering::Monotonic, 3232 LVal.isVolatile(), /*IsInit=*/false); 3233 } 3234 } 3235 3236 void CodeGenFunction::emitOMPSimpleStore(LValue LVal, RValue RVal, 3237 QualType RValTy, SourceLocation Loc) { 3238 switch (getEvaluationKind(LVal.getType())) { 3239 case TEK_Scalar: 3240 EmitStoreThroughLValue(RValue::get(convertToScalarValue( 3241 *this, RVal, RValTy, LVal.getType(), Loc)), 3242 LVal); 3243 break; 3244 case TEK_Complex: 3245 EmitStoreOfComplex( 3246 convertToComplexValue(*this, RVal, RValTy, LVal.getType(), Loc), LVal, 3247 /*isInit=*/false); 3248 break; 3249 case TEK_Aggregate: 3250 llvm_unreachable("Must be a scalar or complex."); 3251 } 3252 } 3253 3254 static void EmitOMPAtomicReadExpr(CodeGenFunction &CGF, bool IsSeqCst, 3255 const Expr *X, const Expr *V, 3256 SourceLocation Loc) { 3257 // v = x; 3258 assert(V->isLValue() && "V of 'omp atomic read' is not lvalue"); 3259 assert(X->isLValue() && "X of 'omp atomic read' is not lvalue"); 3260 LValue XLValue = CGF.EmitLValue(X); 3261 LValue VLValue = CGF.EmitLValue(V); 3262 RValue Res = XLValue.isGlobalReg() 3263 ? CGF.EmitLoadOfLValue(XLValue, Loc) 3264 : CGF.EmitAtomicLoad( 3265 XLValue, Loc, 3266 IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent 3267 : llvm::AtomicOrdering::Monotonic, 3268 XLValue.isVolatile()); 3269 // OpenMP, 2.12.6, atomic Construct 3270 // Any atomic construct with a seq_cst clause forces the atomically 3271 // performed operation to include an implicit flush operation without a 3272 // list. 3273 if (IsSeqCst) 3274 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc); 3275 CGF.emitOMPSimpleStore(VLValue, Res, X->getType().getNonReferenceType(), Loc); 3276 } 3277 3278 static void EmitOMPAtomicWriteExpr(CodeGenFunction &CGF, bool IsSeqCst, 3279 const Expr *X, const Expr *E, 3280 SourceLocation Loc) { 3281 // x = expr; 3282 assert(X->isLValue() && "X of 'omp atomic write' is not lvalue"); 3283 emitSimpleAtomicStore(CGF, IsSeqCst, CGF.EmitLValue(X), CGF.EmitAnyExpr(E)); 3284 // OpenMP, 2.12.6, atomic Construct 3285 // Any atomic construct with a seq_cst clause forces the atomically 3286 // performed operation to include an implicit flush operation without a 3287 // list. 3288 if (IsSeqCst) 3289 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc); 3290 } 3291 3292 static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, 3293 RValue Update, 3294 BinaryOperatorKind BO, 3295 llvm::AtomicOrdering AO, 3296 bool IsXLHSInRHSPart) { 3297 auto &Context = CGF.CGM.getContext(); 3298 // Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x' 3299 // expression is simple and atomic is allowed for the given type for the 3300 // target platform. 3301 if (BO == BO_Comma || !Update.isScalar() || 3302 !Update.getScalarVal()->getType()->isIntegerTy() || 3303 !X.isSimple() || (!isa<llvm::ConstantInt>(Update.getScalarVal()) && 3304 (Update.getScalarVal()->getType() != 3305 X.getAddress().getElementType())) || 3306 !X.getAddress().getElementType()->isIntegerTy() || 3307 !Context.getTargetInfo().hasBuiltinAtomic( 3308 Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment()))) 3309 return std::make_pair(false, RValue::get(nullptr)); 3310 3311 llvm::AtomicRMWInst::BinOp RMWOp; 3312 switch (BO) { 3313 case BO_Add: 3314 RMWOp = llvm::AtomicRMWInst::Add; 3315 break; 3316 case BO_Sub: 3317 if (!IsXLHSInRHSPart) 3318 return std::make_pair(false, RValue::get(nullptr)); 3319 RMWOp = llvm::AtomicRMWInst::Sub; 3320 break; 3321 case BO_And: 3322 RMWOp = llvm::AtomicRMWInst::And; 3323 break; 3324 case BO_Or: 3325 RMWOp = llvm::AtomicRMWInst::Or; 3326 break; 3327 case BO_Xor: 3328 RMWOp = llvm::AtomicRMWInst::Xor; 3329 break; 3330 case BO_LT: 3331 RMWOp = X.getType()->hasSignedIntegerRepresentation() 3332 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min 3333 : llvm::AtomicRMWInst::Max) 3334 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin 3335 : llvm::AtomicRMWInst::UMax); 3336 break; 3337 case BO_GT: 3338 RMWOp = X.getType()->hasSignedIntegerRepresentation() 3339 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max 3340 : llvm::AtomicRMWInst::Min) 3341 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax 3342 : llvm::AtomicRMWInst::UMin); 3343 break; 3344 case BO_Assign: 3345 RMWOp = llvm::AtomicRMWInst::Xchg; 3346 break; 3347 case BO_Mul: 3348 case BO_Div: 3349 case BO_Rem: 3350 case BO_Shl: 3351 case BO_Shr: 3352 case BO_LAnd: 3353 case BO_LOr: 3354 return std::make_pair(false, RValue::get(nullptr)); 3355 case BO_PtrMemD: 3356 case BO_PtrMemI: 3357 case BO_LE: 3358 case BO_GE: 3359 case BO_EQ: 3360 case BO_NE: 3361 case BO_AddAssign: 3362 case BO_SubAssign: 3363 case BO_AndAssign: 3364 case BO_OrAssign: 3365 case BO_XorAssign: 3366 case BO_MulAssign: 3367 case BO_DivAssign: 3368 case BO_RemAssign: 3369 case BO_ShlAssign: 3370 case BO_ShrAssign: 3371 case BO_Comma: 3372 llvm_unreachable("Unsupported atomic update operation"); 3373 } 3374 auto *UpdateVal = Update.getScalarVal(); 3375 if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) { 3376 UpdateVal = CGF.Builder.CreateIntCast( 3377 IC, X.getAddress().getElementType(), 3378 X.getType()->hasSignedIntegerRepresentation()); 3379 } 3380 auto *Res = CGF.Builder.CreateAtomicRMW(RMWOp, X.getPointer(), UpdateVal, AO); 3381 return std::make_pair(true, RValue::get(Res)); 3382 } 3383 3384 std::pair<bool, RValue> CodeGenFunction::EmitOMPAtomicSimpleUpdateExpr( 3385 LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, 3386 llvm::AtomicOrdering AO, SourceLocation Loc, 3387 const llvm::function_ref<RValue(RValue)> &CommonGen) { 3388 // Update expressions are allowed to have the following forms: 3389 // x binop= expr; -> xrval + expr; 3390 // x++, ++x -> xrval + 1; 3391 // x--, --x -> xrval - 1; 3392 // x = x binop expr; -> xrval binop expr 3393 // x = expr Op x; - > expr binop xrval; 3394 auto Res = emitOMPAtomicRMW(*this, X, E, BO, AO, IsXLHSInRHSPart); 3395 if (!Res.first) { 3396 if (X.isGlobalReg()) { 3397 // Emit an update expression: 'xrval' binop 'expr' or 'expr' binop 3398 // 'xrval'. 3399 EmitStoreThroughLValue(CommonGen(EmitLoadOfLValue(X, Loc)), X); 3400 } else { 3401 // Perform compare-and-swap procedure. 3402 EmitAtomicUpdate(X, AO, CommonGen, X.getType().isVolatileQualified()); 3403 } 3404 } 3405 return Res; 3406 } 3407 3408 static void EmitOMPAtomicUpdateExpr(CodeGenFunction &CGF, bool IsSeqCst, 3409 const Expr *X, const Expr *E, 3410 const Expr *UE, bool IsXLHSInRHSPart, 3411 SourceLocation Loc) { 3412 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) && 3413 "Update expr in 'atomic update' must be a binary operator."); 3414 auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts()); 3415 // Update expressions are allowed to have the following forms: 3416 // x binop= expr; -> xrval + expr; 3417 // x++, ++x -> xrval + 1; 3418 // x--, --x -> xrval - 1; 3419 // x = x binop expr; -> xrval binop expr 3420 // x = expr Op x; - > expr binop xrval; 3421 assert(X->isLValue() && "X of 'omp atomic update' is not lvalue"); 3422 LValue XLValue = CGF.EmitLValue(X); 3423 RValue ExprRValue = CGF.EmitAnyExpr(E); 3424 auto AO = IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent 3425 : llvm::AtomicOrdering::Monotonic; 3426 auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts()); 3427 auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts()); 3428 auto *XRValExpr = IsXLHSInRHSPart ? LHS : RHS; 3429 auto *ERValExpr = IsXLHSInRHSPart ? RHS : LHS; 3430 auto Gen = 3431 [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) -> RValue { 3432 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue); 3433 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue); 3434 return CGF.EmitAnyExpr(UE); 3435 }; 3436 (void)CGF.EmitOMPAtomicSimpleUpdateExpr( 3437 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen); 3438 // OpenMP, 2.12.6, atomic Construct 3439 // Any atomic construct with a seq_cst clause forces the atomically 3440 // performed operation to include an implicit flush operation without a 3441 // list. 3442 if (IsSeqCst) 3443 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc); 3444 } 3445 3446 static RValue convertToType(CodeGenFunction &CGF, RValue Value, 3447 QualType SourceType, QualType ResType, 3448 SourceLocation Loc) { 3449 switch (CGF.getEvaluationKind(ResType)) { 3450 case TEK_Scalar: 3451 return RValue::get( 3452 convertToScalarValue(CGF, Value, SourceType, ResType, Loc)); 3453 case TEK_Complex: { 3454 auto Res = convertToComplexValue(CGF, Value, SourceType, ResType, Loc); 3455 return RValue::getComplex(Res.first, Res.second); 3456 } 3457 case TEK_Aggregate: 3458 break; 3459 } 3460 llvm_unreachable("Must be a scalar or complex."); 3461 } 3462 3463 static void EmitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst, 3464 bool IsPostfixUpdate, const Expr *V, 3465 const Expr *X, const Expr *E, 3466 const Expr *UE, bool IsXLHSInRHSPart, 3467 SourceLocation Loc) { 3468 assert(X->isLValue() && "X of 'omp atomic capture' is not lvalue"); 3469 assert(V->isLValue() && "V of 'omp atomic capture' is not lvalue"); 3470 RValue NewVVal; 3471 LValue VLValue = CGF.EmitLValue(V); 3472 LValue XLValue = CGF.EmitLValue(X); 3473 RValue ExprRValue = CGF.EmitAnyExpr(E); 3474 auto AO = IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent 3475 : llvm::AtomicOrdering::Monotonic; 3476 QualType NewVValType; 3477 if (UE) { 3478 // 'x' is updated with some additional value. 3479 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) && 3480 "Update expr in 'atomic capture' must be a binary operator."); 3481 auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts()); 3482 // Update expressions are allowed to have the following forms: 3483 // x binop= expr; -> xrval + expr; 3484 // x++, ++x -> xrval + 1; 3485 // x--, --x -> xrval - 1; 3486 // x = x binop expr; -> xrval binop expr 3487 // x = expr Op x; - > expr binop xrval; 3488 auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts()); 3489 auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts()); 3490 auto *XRValExpr = IsXLHSInRHSPart ? LHS : RHS; 3491 NewVValType = XRValExpr->getType(); 3492 auto *ERValExpr = IsXLHSInRHSPart ? RHS : LHS; 3493 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr, 3494 IsPostfixUpdate](RValue XRValue) -> RValue { 3495 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue); 3496 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue); 3497 RValue Res = CGF.EmitAnyExpr(UE); 3498 NewVVal = IsPostfixUpdate ? XRValue : Res; 3499 return Res; 3500 }; 3501 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr( 3502 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen); 3503 if (Res.first) { 3504 // 'atomicrmw' instruction was generated. 3505 if (IsPostfixUpdate) { 3506 // Use old value from 'atomicrmw'. 3507 NewVVal = Res.second; 3508 } else { 3509 // 'atomicrmw' does not provide new value, so evaluate it using old 3510 // value of 'x'. 3511 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue); 3512 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second); 3513 NewVVal = CGF.EmitAnyExpr(UE); 3514 } 3515 } 3516 } else { 3517 // 'x' is simply rewritten with some 'expr'. 3518 NewVValType = X->getType().getNonReferenceType(); 3519 ExprRValue = convertToType(CGF, ExprRValue, E->getType(), 3520 X->getType().getNonReferenceType(), Loc); 3521 auto &&Gen = [&NewVVal, ExprRValue](RValue XRValue) -> RValue { 3522 NewVVal = XRValue; 3523 return ExprRValue; 3524 }; 3525 // Try to perform atomicrmw xchg, otherwise simple exchange. 3526 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr( 3527 XLValue, ExprRValue, /*BO=*/BO_Assign, /*IsXLHSInRHSPart=*/false, AO, 3528 Loc, Gen); 3529 if (Res.first) { 3530 // 'atomicrmw' instruction was generated. 3531 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue; 3532 } 3533 } 3534 // Emit post-update store to 'v' of old/new 'x' value. 3535 CGF.emitOMPSimpleStore(VLValue, NewVVal, NewVValType, Loc); 3536 // OpenMP, 2.12.6, atomic Construct 3537 // Any atomic construct with a seq_cst clause forces the atomically 3538 // performed operation to include an implicit flush operation without a 3539 // list. 3540 if (IsSeqCst) 3541 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc); 3542 } 3543 3544 static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, 3545 bool IsSeqCst, bool IsPostfixUpdate, 3546 const Expr *X, const Expr *V, const Expr *E, 3547 const Expr *UE, bool IsXLHSInRHSPart, 3548 SourceLocation Loc) { 3549 switch (Kind) { 3550 case OMPC_read: 3551 EmitOMPAtomicReadExpr(CGF, IsSeqCst, X, V, Loc); 3552 break; 3553 case OMPC_write: 3554 EmitOMPAtomicWriteExpr(CGF, IsSeqCst, X, E, Loc); 3555 break; 3556 case OMPC_unknown: 3557 case OMPC_update: 3558 EmitOMPAtomicUpdateExpr(CGF, IsSeqCst, X, E, UE, IsXLHSInRHSPart, Loc); 3559 break; 3560 case OMPC_capture: 3561 EmitOMPAtomicCaptureExpr(CGF, IsSeqCst, IsPostfixUpdate, V, X, E, UE, 3562 IsXLHSInRHSPart, Loc); 3563 break; 3564 case OMPC_if: 3565 case OMPC_final: 3566 case OMPC_num_threads: 3567 case OMPC_private: 3568 case OMPC_firstprivate: 3569 case OMPC_lastprivate: 3570 case OMPC_reduction: 3571 case OMPC_task_reduction: 3572 case OMPC_in_reduction: 3573 case OMPC_safelen: 3574 case OMPC_simdlen: 3575 case OMPC_collapse: 3576 case OMPC_default: 3577 case OMPC_seq_cst: 3578 case OMPC_shared: 3579 case OMPC_linear: 3580 case OMPC_aligned: 3581 case OMPC_copyin: 3582 case OMPC_copyprivate: 3583 case OMPC_flush: 3584 case OMPC_proc_bind: 3585 case OMPC_schedule: 3586 case OMPC_ordered: 3587 case OMPC_nowait: 3588 case OMPC_untied: 3589 case OMPC_threadprivate: 3590 case OMPC_depend: 3591 case OMPC_mergeable: 3592 case OMPC_device: 3593 case OMPC_threads: 3594 case OMPC_simd: 3595 case OMPC_map: 3596 case OMPC_num_teams: 3597 case OMPC_thread_limit: 3598 case OMPC_priority: 3599 case OMPC_grainsize: 3600 case OMPC_nogroup: 3601 case OMPC_num_tasks: 3602 case OMPC_hint: 3603 case OMPC_dist_schedule: 3604 case OMPC_defaultmap: 3605 case OMPC_uniform: 3606 case OMPC_to: 3607 case OMPC_from: 3608 case OMPC_use_device_ptr: 3609 case OMPC_is_device_ptr: 3610 llvm_unreachable("Clause is not allowed in 'omp atomic'."); 3611 } 3612 } 3613 3614 void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) { 3615 bool IsSeqCst = S.getSingleClause<OMPSeqCstClause>(); 3616 OpenMPClauseKind Kind = OMPC_unknown; 3617 for (auto *C : S.clauses()) { 3618 // Find first clause (skip seq_cst clause, if it is first). 3619 if (C->getClauseKind() != OMPC_seq_cst) { 3620 Kind = C->getClauseKind(); 3621 break; 3622 } 3623 } 3624 3625 const auto *CS = 3626 S.getAssociatedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 3627 if (const auto *EWC = dyn_cast<ExprWithCleanups>(CS)) { 3628 enterFullExpression(EWC); 3629 } 3630 // Processing for statements under 'atomic capture'. 3631 if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) { 3632 for (const auto *C : Compound->body()) { 3633 if (const auto *EWC = dyn_cast<ExprWithCleanups>(C)) { 3634 enterFullExpression(EWC); 3635 } 3636 } 3637 } 3638 3639 auto &&CodeGen = [&S, Kind, IsSeqCst, CS](CodeGenFunction &CGF, 3640 PrePostActionTy &) { 3641 CGF.EmitStopPoint(CS); 3642 EmitOMPAtomicExpr(CGF, Kind, IsSeqCst, S.isPostfixUpdate(), S.getX(), 3643 S.getV(), S.getExpr(), S.getUpdateExpr(), 3644 S.isXLHSInRHSPart(), S.getLocStart()); 3645 }; 3646 OMPLexicalScope Scope(*this, S, /*AsInlined=*/true); 3647 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen); 3648 } 3649 3650 static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, 3651 const OMPExecutableDirective &S, 3652 const RegionCodeGenTy &CodeGen) { 3653 assert(isOpenMPTargetExecutionDirective(S.getDirectiveKind())); 3654 CodeGenModule &CGM = CGF.CGM; 3655 const CapturedStmt &CS = *cast<CapturedStmt>(S.getAssociatedStmt()); 3656 3657 llvm::Function *Fn = nullptr; 3658 llvm::Constant *FnID = nullptr; 3659 3660 const Expr *IfCond = nullptr; 3661 // Check for the at most one if clause associated with the target region. 3662 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { 3663 if (C->getNameModifier() == OMPD_unknown || 3664 C->getNameModifier() == OMPD_target) { 3665 IfCond = C->getCondition(); 3666 break; 3667 } 3668 } 3669 3670 // Check if we have any device clause associated with the directive. 3671 const Expr *Device = nullptr; 3672 if (auto *C = S.getSingleClause<OMPDeviceClause>()) { 3673 Device = C->getDevice(); 3674 } 3675 3676 // Check if we have an if clause whose conditional always evaluates to false 3677 // or if we do not have any targets specified. If so the target region is not 3678 // an offload entry point. 3679 bool IsOffloadEntry = true; 3680 if (IfCond) { 3681 bool Val; 3682 if (CGF.ConstantFoldsToSimpleInteger(IfCond, Val) && !Val) 3683 IsOffloadEntry = false; 3684 } 3685 if (CGM.getLangOpts().OMPTargetTriples.empty()) 3686 IsOffloadEntry = false; 3687 3688 assert(CGF.CurFuncDecl && "No parent declaration for target region!"); 3689 StringRef ParentName; 3690 // In case we have Ctors/Dtors we use the complete type variant to produce 3691 // the mangling of the device outlined kernel. 3692 if (auto *D = dyn_cast<CXXConstructorDecl>(CGF.CurFuncDecl)) 3693 ParentName = CGM.getMangledName(GlobalDecl(D, Ctor_Complete)); 3694 else if (auto *D = dyn_cast<CXXDestructorDecl>(CGF.CurFuncDecl)) 3695 ParentName = CGM.getMangledName(GlobalDecl(D, Dtor_Complete)); 3696 else 3697 ParentName = 3698 CGM.getMangledName(GlobalDecl(cast<FunctionDecl>(CGF.CurFuncDecl))); 3699 3700 // Emit target region as a standalone region. 3701 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID, 3702 IsOffloadEntry, CodeGen); 3703 OMPLexicalScope Scope(CGF, S); 3704 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 3705 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 3706 CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device, 3707 CapturedVars); 3708 } 3709 3710 static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, 3711 PrePostActionTy &Action) { 3712 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 3713 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); 3714 CGF.EmitOMPPrivateClause(S, PrivateScope); 3715 (void)PrivateScope.Privatize(); 3716 3717 Action.Enter(CGF); 3718 CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 3719 } 3720 3721 void CodeGenFunction::EmitOMPTargetDeviceFunction(CodeGenModule &CGM, 3722 StringRef ParentName, 3723 const OMPTargetDirective &S) { 3724 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 3725 emitTargetRegion(CGF, S, Action); 3726 }; 3727 llvm::Function *Fn; 3728 llvm::Constant *Addr; 3729 // Emit target region as a standalone region. 3730 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 3731 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 3732 assert(Fn && Addr && "Target device function emission failed."); 3733 } 3734 3735 void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &S) { 3736 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 3737 emitTargetRegion(CGF, S, Action); 3738 }; 3739 emitCommonOMPTargetDirective(*this, S, CodeGen); 3740 } 3741 3742 static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF, 3743 const OMPExecutableDirective &S, 3744 OpenMPDirectiveKind InnermostKind, 3745 const RegionCodeGenTy &CodeGen) { 3746 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams); 3747 auto OutlinedFn = CGF.CGM.getOpenMPRuntime().emitTeamsOutlinedFunction( 3748 S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen); 3749 3750 const OMPNumTeamsClause *NT = S.getSingleClause<OMPNumTeamsClause>(); 3751 const OMPThreadLimitClause *TL = S.getSingleClause<OMPThreadLimitClause>(); 3752 if (NT || TL) { 3753 Expr *NumTeams = (NT) ? NT->getNumTeams() : nullptr; 3754 Expr *ThreadLimit = (TL) ? TL->getThreadLimit() : nullptr; 3755 3756 CGF.CGM.getOpenMPRuntime().emitNumTeamsClause(CGF, NumTeams, ThreadLimit, 3757 S.getLocStart()); 3758 } 3759 3760 OMPTeamsScope Scope(CGF, S); 3761 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 3762 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars); 3763 CGF.CGM.getOpenMPRuntime().emitTeamsCall(CGF, S, S.getLocStart(), OutlinedFn, 3764 CapturedVars); 3765 } 3766 3767 void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &S) { 3768 // Emit teams region as a standalone region. 3769 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 3770 OMPPrivateScope PrivateScope(CGF); 3771 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); 3772 CGF.EmitOMPPrivateClause(S, PrivateScope); 3773 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 3774 (void)PrivateScope.Privatize(); 3775 CGF.EmitStmt(cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 3776 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); 3777 }; 3778 emitCommonOMPTeamsDirective(*this, S, OMPD_teams, CodeGen); 3779 emitPostUpdateForReductionClause( 3780 *this, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; }); 3781 } 3782 3783 static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action, 3784 const OMPTargetTeamsDirective &S) { 3785 auto *CS = S.getCapturedStmt(OMPD_teams); 3786 Action.Enter(CGF); 3787 auto &&CodeGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) { 3788 // TODO: Add support for clauses. 3789 CGF.EmitStmt(CS->getCapturedStmt()); 3790 }; 3791 emitCommonOMPTeamsDirective(CGF, S, OMPD_teams, CodeGen); 3792 } 3793 3794 void CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 3795 CodeGenModule &CGM, StringRef ParentName, 3796 const OMPTargetTeamsDirective &S) { 3797 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 3798 emitTargetTeamsRegion(CGF, Action, S); 3799 }; 3800 llvm::Function *Fn; 3801 llvm::Constant *Addr; 3802 // Emit target region as a standalone region. 3803 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 3804 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 3805 assert(Fn && Addr && "Target device function emission failed."); 3806 } 3807 3808 void CodeGenFunction::EmitOMPTargetTeamsDirective( 3809 const OMPTargetTeamsDirective &S) { 3810 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 3811 emitTargetTeamsRegion(CGF, Action, S); 3812 }; 3813 emitCommonOMPTargetDirective(*this, S, CodeGen); 3814 } 3815 3816 void CodeGenFunction::EmitOMPCancellationPointDirective( 3817 const OMPCancellationPointDirective &S) { 3818 CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getLocStart(), 3819 S.getCancelRegion()); 3820 } 3821 3822 void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) { 3823 const Expr *IfCond = nullptr; 3824 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { 3825 if (C->getNameModifier() == OMPD_unknown || 3826 C->getNameModifier() == OMPD_cancel) { 3827 IfCond = C->getCondition(); 3828 break; 3829 } 3830 } 3831 CGM.getOpenMPRuntime().emitCancelCall(*this, S.getLocStart(), IfCond, 3832 S.getCancelRegion()); 3833 } 3834 3835 CodeGenFunction::JumpDest 3836 CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) { 3837 if (Kind == OMPD_parallel || Kind == OMPD_task || 3838 Kind == OMPD_target_parallel) 3839 return ReturnBlock; 3840 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections || 3841 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for || 3842 Kind == OMPD_distribute_parallel_for || 3843 Kind == OMPD_target_parallel_for); 3844 return OMPCancelStack.getExitBlock(); 3845 } 3846 3847 void CodeGenFunction::EmitOMPUseDevicePtrClause( 3848 const OMPClause &NC, OMPPrivateScope &PrivateScope, 3849 const llvm::DenseMap<const ValueDecl *, Address> &CaptureDeviceAddrMap) { 3850 const auto &C = cast<OMPUseDevicePtrClause>(NC); 3851 auto OrigVarIt = C.varlist_begin(); 3852 auto InitIt = C.inits().begin(); 3853 for (auto PvtVarIt : C.private_copies()) { 3854 auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*OrigVarIt)->getDecl()); 3855 auto *InitVD = cast<VarDecl>(cast<DeclRefExpr>(*InitIt)->getDecl()); 3856 auto *PvtVD = cast<VarDecl>(cast<DeclRefExpr>(PvtVarIt)->getDecl()); 3857 3858 // In order to identify the right initializer we need to match the 3859 // declaration used by the mapping logic. In some cases we may get 3860 // OMPCapturedExprDecl that refers to the original declaration. 3861 const ValueDecl *MatchingVD = OrigVD; 3862 if (auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) { 3863 // OMPCapturedExprDecl are used to privative fields of the current 3864 // structure. 3865 auto *ME = cast<MemberExpr>(OED->getInit()); 3866 assert(isa<CXXThisExpr>(ME->getBase()) && 3867 "Base should be the current struct!"); 3868 MatchingVD = ME->getMemberDecl(); 3869 } 3870 3871 // If we don't have information about the current list item, move on to 3872 // the next one. 3873 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD); 3874 if (InitAddrIt == CaptureDeviceAddrMap.end()) 3875 continue; 3876 3877 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [&]() -> Address { 3878 // Initialize the temporary initialization variable with the address we 3879 // get from the runtime library. We have to cast the source address 3880 // because it is always a void *. References are materialized in the 3881 // privatization scope, so the initialization here disregards the fact 3882 // the original variable is a reference. 3883 QualType AddrQTy = 3884 getContext().getPointerType(OrigVD->getType().getNonReferenceType()); 3885 llvm::Type *AddrTy = ConvertTypeForMem(AddrQTy); 3886 Address InitAddr = Builder.CreateBitCast(InitAddrIt->second, AddrTy); 3887 setAddrOfLocalVar(InitVD, InitAddr); 3888 3889 // Emit private declaration, it will be initialized by the value we 3890 // declaration we just added to the local declarations map. 3891 EmitDecl(*PvtVD); 3892 3893 // The initialization variables reached its purpose in the emission 3894 // ofthe previous declaration, so we don't need it anymore. 3895 LocalDeclMap.erase(InitVD); 3896 3897 // Return the address of the private variable. 3898 return GetAddrOfLocalVar(PvtVD); 3899 }); 3900 assert(IsRegistered && "firstprivate var already registered as private"); 3901 // Silence the warning about unused variable. 3902 (void)IsRegistered; 3903 3904 ++OrigVarIt; 3905 ++InitIt; 3906 } 3907 } 3908 3909 // Generate the instructions for '#pragma omp target data' directive. 3910 void CodeGenFunction::EmitOMPTargetDataDirective( 3911 const OMPTargetDataDirective &S) { 3912 CGOpenMPRuntime::TargetDataInfo Info(/*RequiresDevicePointerInfo=*/true); 3913 3914 // Create a pre/post action to signal the privatization of the device pointer. 3915 // This action can be replaced by the OpenMP runtime code generation to 3916 // deactivate privatization. 3917 bool PrivatizeDevicePointers = false; 3918 class DevicePointerPrivActionTy : public PrePostActionTy { 3919 bool &PrivatizeDevicePointers; 3920 3921 public: 3922 explicit DevicePointerPrivActionTy(bool &PrivatizeDevicePointers) 3923 : PrePostActionTy(), PrivatizeDevicePointers(PrivatizeDevicePointers) {} 3924 void Enter(CodeGenFunction &CGF) override { 3925 PrivatizeDevicePointers = true; 3926 } 3927 }; 3928 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers); 3929 3930 auto &&CodeGen = [&S, &Info, &PrivatizeDevicePointers]( 3931 CodeGenFunction &CGF, PrePostActionTy &Action) { 3932 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 3933 CGF.EmitStmt( 3934 cast<CapturedStmt>(S.getAssociatedStmt())->getCapturedStmt()); 3935 }; 3936 3937 // Codegen that selects wheather to generate the privatization code or not. 3938 auto &&PrivCodeGen = [&S, &Info, &PrivatizeDevicePointers, 3939 &InnermostCodeGen](CodeGenFunction &CGF, 3940 PrePostActionTy &Action) { 3941 RegionCodeGenTy RCG(InnermostCodeGen); 3942 PrivatizeDevicePointers = false; 3943 3944 // Call the pre-action to change the status of PrivatizeDevicePointers if 3945 // needed. 3946 Action.Enter(CGF); 3947 3948 if (PrivatizeDevicePointers) { 3949 OMPPrivateScope PrivateScope(CGF); 3950 // Emit all instances of the use_device_ptr clause. 3951 for (const auto *C : S.getClausesOfKind<OMPUseDevicePtrClause>()) 3952 CGF.EmitOMPUseDevicePtrClause(*C, PrivateScope, 3953 Info.CaptureDeviceAddrMap); 3954 (void)PrivateScope.Privatize(); 3955 RCG(CGF); 3956 } else 3957 RCG(CGF); 3958 }; 3959 3960 // Forward the provided action to the privatization codegen. 3961 RegionCodeGenTy PrivRCG(PrivCodeGen); 3962 PrivRCG.setAction(Action); 3963 3964 // Notwithstanding the body of the region is emitted as inlined directive, 3965 // we don't use an inline scope as changes in the references inside the 3966 // region are expected to be visible outside, so we do not privative them. 3967 OMPLexicalScope Scope(CGF, S); 3968 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data, 3969 PrivRCG); 3970 }; 3971 3972 RegionCodeGenTy RCG(CodeGen); 3973 3974 // If we don't have target devices, don't bother emitting the data mapping 3975 // code. 3976 if (CGM.getLangOpts().OMPTargetTriples.empty()) { 3977 RCG(*this); 3978 return; 3979 } 3980 3981 // Check if we have any if clause associated with the directive. 3982 const Expr *IfCond = nullptr; 3983 if (auto *C = S.getSingleClause<OMPIfClause>()) 3984 IfCond = C->getCondition(); 3985 3986 // Check if we have any device clause associated with the directive. 3987 const Expr *Device = nullptr; 3988 if (auto *C = S.getSingleClause<OMPDeviceClause>()) 3989 Device = C->getDevice(); 3990 3991 // Set the action to signal privatization of device pointers. 3992 RCG.setAction(PrivAction); 3993 3994 // Emit region code. 3995 CGM.getOpenMPRuntime().emitTargetDataCalls(*this, S, IfCond, Device, RCG, 3996 Info); 3997 } 3998 3999 void CodeGenFunction::EmitOMPTargetEnterDataDirective( 4000 const OMPTargetEnterDataDirective &S) { 4001 // If we don't have target devices, don't bother emitting the data mapping 4002 // code. 4003 if (CGM.getLangOpts().OMPTargetTriples.empty()) 4004 return; 4005 4006 // Check if we have any if clause associated with the directive. 4007 const Expr *IfCond = nullptr; 4008 if (auto *C = S.getSingleClause<OMPIfClause>()) 4009 IfCond = C->getCondition(); 4010 4011 // Check if we have any device clause associated with the directive. 4012 const Expr *Device = nullptr; 4013 if (auto *C = S.getSingleClause<OMPDeviceClause>()) 4014 Device = C->getDevice(); 4015 4016 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device); 4017 } 4018 4019 void CodeGenFunction::EmitOMPTargetExitDataDirective( 4020 const OMPTargetExitDataDirective &S) { 4021 // If we don't have target devices, don't bother emitting the data mapping 4022 // code. 4023 if (CGM.getLangOpts().OMPTargetTriples.empty()) 4024 return; 4025 4026 // Check if we have any if clause associated with the directive. 4027 const Expr *IfCond = nullptr; 4028 if (auto *C = S.getSingleClause<OMPIfClause>()) 4029 IfCond = C->getCondition(); 4030 4031 // Check if we have any device clause associated with the directive. 4032 const Expr *Device = nullptr; 4033 if (auto *C = S.getSingleClause<OMPDeviceClause>()) 4034 Device = C->getDevice(); 4035 4036 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device); 4037 } 4038 4039 static void emitTargetParallelRegion(CodeGenFunction &CGF, 4040 const OMPTargetParallelDirective &S, 4041 PrePostActionTy &Action) { 4042 // Get the captured statement associated with the 'parallel' region. 4043 auto *CS = S.getCapturedStmt(OMPD_parallel); 4044 Action.Enter(CGF); 4045 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &) { 4046 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 4047 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); 4048 CGF.EmitOMPPrivateClause(S, PrivateScope); 4049 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 4050 (void)PrivateScope.Privatize(); 4051 // TODO: Add support for clauses. 4052 CGF.EmitStmt(CS->getCapturedStmt()); 4053 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel); 4054 }; 4055 emitCommonOMPParallelDirective(CGF, S, OMPD_parallel, CodeGen, 4056 emitEmptyBoundParameters); 4057 emitPostUpdateForReductionClause( 4058 CGF, S, [](CodeGenFunction &) -> llvm::Value * { return nullptr; }); 4059 } 4060 4061 void CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 4062 CodeGenModule &CGM, StringRef ParentName, 4063 const OMPTargetParallelDirective &S) { 4064 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 4065 emitTargetParallelRegion(CGF, S, Action); 4066 }; 4067 llvm::Function *Fn; 4068 llvm::Constant *Addr; 4069 // Emit target region as a standalone region. 4070 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 4071 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 4072 assert(Fn && Addr && "Target device function emission failed."); 4073 } 4074 4075 void CodeGenFunction::EmitOMPTargetParallelDirective( 4076 const OMPTargetParallelDirective &S) { 4077 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 4078 emitTargetParallelRegion(CGF, S, Action); 4079 }; 4080 emitCommonOMPTargetDirective(*this, S, CodeGen); 4081 } 4082 4083 void CodeGenFunction::EmitOMPTargetParallelForDirective( 4084 const OMPTargetParallelForDirective &S) { 4085 // TODO: codegen for target parallel for. 4086 } 4087 4088 /// Emit a helper variable and return corresponding lvalue. 4089 static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper, 4090 const ImplicitParamDecl *PVD, 4091 CodeGenFunction::OMPPrivateScope &Privates) { 4092 auto *VDecl = cast<VarDecl>(Helper->getDecl()); 4093 Privates.addPrivate( 4094 VDecl, [&CGF, PVD]() -> Address { return CGF.GetAddrOfLocalVar(PVD); }); 4095 } 4096 4097 void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) { 4098 assert(isOpenMPTaskLoopDirective(S.getDirectiveKind())); 4099 // Emit outlined function for task construct. 4100 auto CS = cast<CapturedStmt>(S.getAssociatedStmt()); 4101 auto CapturedStruct = GenerateCapturedStmtArgument(*CS); 4102 auto SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); 4103 const Expr *IfCond = nullptr; 4104 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { 4105 if (C->getNameModifier() == OMPD_unknown || 4106 C->getNameModifier() == OMPD_taskloop) { 4107 IfCond = C->getCondition(); 4108 break; 4109 } 4110 } 4111 4112 OMPTaskDataTy Data; 4113 // Check if taskloop must be emitted without taskgroup. 4114 Data.Nogroup = S.getSingleClause<OMPNogroupClause>(); 4115 // TODO: Check if we should emit tied or untied task. 4116 Data.Tied = true; 4117 // Set scheduling for taskloop 4118 if (const auto* Clause = S.getSingleClause<OMPGrainsizeClause>()) { 4119 // grainsize clause 4120 Data.Schedule.setInt(/*IntVal=*/false); 4121 Data.Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize())); 4122 } else if (const auto* Clause = S.getSingleClause<OMPNumTasksClause>()) { 4123 // num_tasks clause 4124 Data.Schedule.setInt(/*IntVal=*/true); 4125 Data.Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks())); 4126 } 4127 4128 auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) { 4129 // if (PreCond) { 4130 // for (IV in 0..LastIteration) BODY; 4131 // <Final counter/linear vars updates>; 4132 // } 4133 // 4134 4135 // Emit: if (PreCond) - begin. 4136 // If the condition constant folds and can be elided, avoid emitting the 4137 // whole loop. 4138 bool CondConstant; 4139 llvm::BasicBlock *ContBlock = nullptr; 4140 OMPLoopScope PreInitScope(CGF, S); 4141 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { 4142 if (!CondConstant) 4143 return; 4144 } else { 4145 auto *ThenBlock = CGF.createBasicBlock("taskloop.if.then"); 4146 ContBlock = CGF.createBasicBlock("taskloop.if.end"); 4147 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock, 4148 CGF.getProfileCount(&S)); 4149 CGF.EmitBlock(ThenBlock); 4150 CGF.incrementProfileCounter(&S); 4151 } 4152 4153 if (isOpenMPSimdDirective(S.getDirectiveKind())) 4154 CGF.EmitOMPSimdInit(S); 4155 4156 OMPPrivateScope LoopScope(CGF); 4157 // Emit helper vars inits. 4158 enum { LowerBound = 5, UpperBound, Stride, LastIter }; 4159 auto *I = CS->getCapturedDecl()->param_begin(); 4160 auto *LBP = std::next(I, LowerBound); 4161 auto *UBP = std::next(I, UpperBound); 4162 auto *STP = std::next(I, Stride); 4163 auto *LIP = std::next(I, LastIter); 4164 mapParam(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()), *LBP, 4165 LoopScope); 4166 mapParam(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()), *UBP, 4167 LoopScope); 4168 mapParam(CGF, cast<DeclRefExpr>(S.getStrideVariable()), *STP, LoopScope); 4169 mapParam(CGF, cast<DeclRefExpr>(S.getIsLastIterVariable()), *LIP, 4170 LoopScope); 4171 CGF.EmitOMPPrivateLoopCounters(S, LoopScope); 4172 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); 4173 (void)LoopScope.Privatize(); 4174 // Emit the loop iteration variable. 4175 const Expr *IVExpr = S.getIterationVariable(); 4176 const VarDecl *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl()); 4177 CGF.EmitVarDecl(*IVDecl); 4178 CGF.EmitIgnoredExpr(S.getInit()); 4179 4180 // Emit the iterations count variable. 4181 // If it is not a variable, Sema decided to calculate iterations count on 4182 // each iteration (e.g., it is foldable into a constant). 4183 if (auto LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { 4184 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); 4185 // Emit calculation of the iterations count. 4186 CGF.EmitIgnoredExpr(S.getCalcLastIteration()); 4187 } 4188 4189 CGF.EmitOMPInnerLoop(S, LoopScope.requiresCleanups(), S.getCond(), 4190 S.getInc(), 4191 [&S](CodeGenFunction &CGF) { 4192 CGF.EmitOMPLoopBody(S, JumpDest()); 4193 CGF.EmitStopPoint(&S); 4194 }, 4195 [](CodeGenFunction &) {}); 4196 // Emit: if (PreCond) - end. 4197 if (ContBlock) { 4198 CGF.EmitBranch(ContBlock); 4199 CGF.EmitBlock(ContBlock, true); 4200 } 4201 // Emit final copy of the lastprivate variables if IsLastIter != 0. 4202 if (HasLastprivateClause) { 4203 CGF.EmitOMPLastprivateClauseFinal( 4204 S, isOpenMPSimdDirective(S.getDirectiveKind()), 4205 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar( 4206 CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false, 4207 (*LIP)->getType(), S.getLocStart()))); 4208 } 4209 }; 4210 auto &&TaskGen = [&S, SharedsTy, CapturedStruct, 4211 IfCond](CodeGenFunction &CGF, llvm::Value *OutlinedFn, 4212 const OMPTaskDataTy &Data) { 4213 auto &&CodeGen = [&](CodeGenFunction &CGF, PrePostActionTy &) { 4214 OMPLoopScope PreInitScope(CGF, S); 4215 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getLocStart(), S, 4216 OutlinedFn, SharedsTy, 4217 CapturedStruct, IfCond, Data); 4218 }; 4219 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop, 4220 CodeGen); 4221 }; 4222 if (Data.Nogroup) 4223 EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Data); 4224 else { 4225 CGM.getOpenMPRuntime().emitTaskgroupRegion( 4226 *this, 4227 [&S, &BodyGen, &TaskGen, &Data](CodeGenFunction &CGF, 4228 PrePostActionTy &Action) { 4229 Action.Enter(CGF); 4230 CGF.EmitOMPTaskBasedDirective(S, BodyGen, TaskGen, Data); 4231 }, 4232 S.getLocStart()); 4233 } 4234 } 4235 4236 void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) { 4237 EmitOMPTaskLoopBasedDirective(S); 4238 } 4239 4240 void CodeGenFunction::EmitOMPTaskLoopSimdDirective( 4241 const OMPTaskLoopSimdDirective &S) { 4242 EmitOMPTaskLoopBasedDirective(S); 4243 } 4244 4245 // Generate the instructions for '#pragma omp target update' directive. 4246 void CodeGenFunction::EmitOMPTargetUpdateDirective( 4247 const OMPTargetUpdateDirective &S) { 4248 // If we don't have target devices, don't bother emitting the data mapping 4249 // code. 4250 if (CGM.getLangOpts().OMPTargetTriples.empty()) 4251 return; 4252 4253 // Check if we have any if clause associated with the directive. 4254 const Expr *IfCond = nullptr; 4255 if (auto *C = S.getSingleClause<OMPIfClause>()) 4256 IfCond = C->getCondition(); 4257 4258 // Check if we have any device clause associated with the directive. 4259 const Expr *Device = nullptr; 4260 if (auto *C = S.getSingleClause<OMPDeviceClause>()) 4261 Device = C->getDevice(); 4262 4263 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device); 4264 } 4265