1 //===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This contains code to emit OpenMP nodes as LLVM code. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CGCleanup.h" 14 #include "CGOpenMPRuntime.h" 15 #include "CodeGenFunction.h" 16 #include "CodeGenModule.h" 17 #include "TargetInfo.h" 18 #include "clang/AST/ASTContext.h" 19 #include "clang/AST/Attr.h" 20 #include "clang/AST/DeclOpenMP.h" 21 #include "clang/AST/OpenMPClause.h" 22 #include "clang/AST/Stmt.h" 23 #include "clang/AST/StmtOpenMP.h" 24 #include "clang/Basic/OpenMPKinds.h" 25 #include "clang/Basic/PrettyStackTrace.h" 26 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" 27 #include "llvm/IR/Constants.h" 28 #include "llvm/IR/Instructions.h" 29 #include "llvm/Support/AtomicOrdering.h" 30 using namespace clang; 31 using namespace CodeGen; 32 using namespace llvm::omp; 33 34 namespace { 35 /// Lexical scope for OpenMP executable constructs, that handles correct codegen 36 /// for captured expressions. 37 class OMPLexicalScope : public CodeGenFunction::LexicalScope { 38 void emitPreInitStmt(CodeGenFunction &CGF, const OMPExecutableDirective &S) { 39 for (const auto *C : S.clauses()) { 40 if (const auto *CPI = OMPClauseWithPreInit::get(C)) { 41 if (const auto *PreInit = 42 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) { 43 for (const auto *I : PreInit->decls()) { 44 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 45 CGF.EmitVarDecl(cast<VarDecl>(*I)); 46 } else { 47 CodeGenFunction::AutoVarEmission Emission = 48 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 49 CGF.EmitAutoVarCleanups(Emission); 50 } 51 } 52 } 53 } 54 } 55 } 56 CodeGenFunction::OMPPrivateScope InlinedShareds; 57 58 static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) { 59 return CGF.LambdaCaptureFields.lookup(VD) || 60 (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) || 61 (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) && 62 cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD)); 63 } 64 65 public: 66 OMPLexicalScope( 67 CodeGenFunction &CGF, const OMPExecutableDirective &S, 68 const llvm::Optional<OpenMPDirectiveKind> CapturedRegion = llvm::None, 69 const bool EmitPreInitStmt = true) 70 : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()), 71 InlinedShareds(CGF) { 72 if (EmitPreInitStmt) 73 emitPreInitStmt(CGF, S); 74 if (!CapturedRegion.hasValue()) 75 return; 76 assert(S.hasAssociatedStmt() && 77 "Expected associated statement for inlined directive."); 78 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion); 79 for (const auto &C : CS->captures()) { 80 if (C.capturesVariable() || C.capturesVariableByCopy()) { 81 auto *VD = C.getCapturedVar(); 82 assert(VD == VD->getCanonicalDecl() && 83 "Canonical decl must be captured."); 84 DeclRefExpr DRE( 85 CGF.getContext(), const_cast<VarDecl *>(VD), 86 isCapturedVar(CGF, VD) || (CGF.CapturedStmtInfo && 87 InlinedShareds.isGlobalVarCaptured(VD)), 88 VD->getType().getNonReferenceType(), VK_LValue, C.getLocation()); 89 InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address { 90 return CGF.EmitLValue(&DRE).getAddress(CGF); 91 }); 92 } 93 } 94 (void)InlinedShareds.Privatize(); 95 } 96 }; 97 98 /// Lexical scope for OpenMP parallel construct, that handles correct codegen 99 /// for captured expressions. 100 class OMPParallelScope final : public OMPLexicalScope { 101 bool EmitPreInitStmt(const OMPExecutableDirective &S) { 102 OpenMPDirectiveKind Kind = S.getDirectiveKind(); 103 return !(isOpenMPTargetExecutionDirective(Kind) || 104 isOpenMPLoopBoundSharingDirective(Kind)) && 105 isOpenMPParallelDirective(Kind); 106 } 107 108 public: 109 OMPParallelScope(CodeGenFunction &CGF, const OMPExecutableDirective &S) 110 : OMPLexicalScope(CGF, S, /*CapturedRegion=*/llvm::None, 111 EmitPreInitStmt(S)) {} 112 }; 113 114 /// Lexical scope for OpenMP teams construct, that handles correct codegen 115 /// for captured expressions. 116 class OMPTeamsScope final : public OMPLexicalScope { 117 bool EmitPreInitStmt(const OMPExecutableDirective &S) { 118 OpenMPDirectiveKind Kind = S.getDirectiveKind(); 119 return !isOpenMPTargetExecutionDirective(Kind) && 120 isOpenMPTeamsDirective(Kind); 121 } 122 123 public: 124 OMPTeamsScope(CodeGenFunction &CGF, const OMPExecutableDirective &S) 125 : OMPLexicalScope(CGF, S, /*CapturedRegion=*/llvm::None, 126 EmitPreInitStmt(S)) {} 127 }; 128 129 /// Private scope for OpenMP loop-based directives, that supports capturing 130 /// of used expression from loop statement. 131 class OMPLoopScope : public CodeGenFunction::RunCleanupsScope { 132 void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopDirective &S) { 133 CodeGenFunction::OMPMapVars PreCondVars; 134 llvm::DenseSet<const VarDecl *> EmittedAsPrivate; 135 for (const auto *E : S.counters()) { 136 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 137 EmittedAsPrivate.insert(VD->getCanonicalDecl()); 138 (void)PreCondVars.setVarAddr( 139 CGF, VD, CGF.CreateMemTemp(VD->getType().getNonReferenceType())); 140 } 141 // Mark private vars as undefs. 142 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 143 for (const Expr *IRef : C->varlists()) { 144 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl()); 145 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { 146 (void)PreCondVars.setVarAddr( 147 CGF, OrigVD, 148 Address(llvm::UndefValue::get( 149 CGF.ConvertTypeForMem(CGF.getContext().getPointerType( 150 OrigVD->getType().getNonReferenceType()))), 151 CGF.getContext().getDeclAlign(OrigVD))); 152 } 153 } 154 } 155 (void)PreCondVars.apply(CGF); 156 // Emit init, __range and __end variables for C++ range loops. 157 const Stmt *Body = 158 S.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers(); 159 for (unsigned Cnt = 0; Cnt < S.getCollapsedNumber(); ++Cnt) { 160 Body = OMPLoopDirective::tryToFindNextInnerLoop( 161 Body, /*TryImperfectlyNestedLoops=*/true); 162 if (auto *For = dyn_cast<ForStmt>(Body)) { 163 Body = For->getBody(); 164 } else { 165 assert(isa<CXXForRangeStmt>(Body) && 166 "Expected canonical for loop or range-based for loop."); 167 auto *CXXFor = cast<CXXForRangeStmt>(Body); 168 if (const Stmt *Init = CXXFor->getInit()) 169 CGF.EmitStmt(Init); 170 CGF.EmitStmt(CXXFor->getRangeStmt()); 171 CGF.EmitStmt(CXXFor->getEndStmt()); 172 Body = CXXFor->getBody(); 173 } 174 } 175 if (const auto *PreInits = cast_or_null<DeclStmt>(S.getPreInits())) { 176 for (const auto *I : PreInits->decls()) 177 CGF.EmitVarDecl(cast<VarDecl>(*I)); 178 } 179 PreCondVars.restore(CGF); 180 } 181 182 public: 183 OMPLoopScope(CodeGenFunction &CGF, const OMPLoopDirective &S) 184 : CodeGenFunction::RunCleanupsScope(CGF) { 185 emitPreInitStmt(CGF, S); 186 } 187 }; 188 189 class OMPSimdLexicalScope : public CodeGenFunction::LexicalScope { 190 CodeGenFunction::OMPPrivateScope InlinedShareds; 191 192 static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) { 193 return CGF.LambdaCaptureFields.lookup(VD) || 194 (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) || 195 (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) && 196 cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD)); 197 } 198 199 public: 200 OMPSimdLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S) 201 : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()), 202 InlinedShareds(CGF) { 203 for (const auto *C : S.clauses()) { 204 if (const auto *CPI = OMPClauseWithPreInit::get(C)) { 205 if (const auto *PreInit = 206 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) { 207 for (const auto *I : PreInit->decls()) { 208 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 209 CGF.EmitVarDecl(cast<VarDecl>(*I)); 210 } else { 211 CodeGenFunction::AutoVarEmission Emission = 212 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 213 CGF.EmitAutoVarCleanups(Emission); 214 } 215 } 216 } 217 } else if (const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(C)) { 218 for (const Expr *E : UDP->varlists()) { 219 const Decl *D = cast<DeclRefExpr>(E)->getDecl(); 220 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D)) 221 CGF.EmitVarDecl(*OED); 222 } 223 } 224 } 225 if (!isOpenMPSimdDirective(S.getDirectiveKind())) 226 CGF.EmitOMPPrivateClause(S, InlinedShareds); 227 if (const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) { 228 if (const Expr *E = TG->getReductionRef()) 229 CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl())); 230 } 231 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt()); 232 while (CS) { 233 for (auto &C : CS->captures()) { 234 if (C.capturesVariable() || C.capturesVariableByCopy()) { 235 auto *VD = C.getCapturedVar(); 236 assert(VD == VD->getCanonicalDecl() && 237 "Canonical decl must be captured."); 238 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 239 isCapturedVar(CGF, VD) || 240 (CGF.CapturedStmtInfo && 241 InlinedShareds.isGlobalVarCaptured(VD)), 242 VD->getType().getNonReferenceType(), VK_LValue, 243 C.getLocation()); 244 InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address { 245 return CGF.EmitLValue(&DRE).getAddress(CGF); 246 }); 247 } 248 } 249 CS = dyn_cast<CapturedStmt>(CS->getCapturedStmt()); 250 } 251 (void)InlinedShareds.Privatize(); 252 } 253 }; 254 255 } // namespace 256 257 static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, 258 const OMPExecutableDirective &S, 259 const RegionCodeGenTy &CodeGen); 260 261 LValue CodeGenFunction::EmitOMPSharedLValue(const Expr *E) { 262 if (const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) { 263 if (const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) { 264 OrigVD = OrigVD->getCanonicalDecl(); 265 bool IsCaptured = 266 LambdaCaptureFields.lookup(OrigVD) || 267 (CapturedStmtInfo && CapturedStmtInfo->lookup(OrigVD)) || 268 (CurCodeDecl && isa<BlockDecl>(CurCodeDecl)); 269 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), IsCaptured, 270 OrigDRE->getType(), VK_LValue, OrigDRE->getExprLoc()); 271 return EmitLValue(&DRE); 272 } 273 } 274 return EmitLValue(E); 275 } 276 277 llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) { 278 ASTContext &C = getContext(); 279 llvm::Value *Size = nullptr; 280 auto SizeInChars = C.getTypeSizeInChars(Ty); 281 if (SizeInChars.isZero()) { 282 // getTypeSizeInChars() returns 0 for a VLA. 283 while (const VariableArrayType *VAT = C.getAsVariableArrayType(Ty)) { 284 VlaSizePair VlaSize = getVLASize(VAT); 285 Ty = VlaSize.Type; 286 Size = Size ? Builder.CreateNUWMul(Size, VlaSize.NumElts) 287 : VlaSize.NumElts; 288 } 289 SizeInChars = C.getTypeSizeInChars(Ty); 290 if (SizeInChars.isZero()) 291 return llvm::ConstantInt::get(SizeTy, /*V=*/0); 292 return Builder.CreateNUWMul(Size, CGM.getSize(SizeInChars)); 293 } 294 return CGM.getSize(SizeInChars); 295 } 296 297 void CodeGenFunction::GenerateOpenMPCapturedVars( 298 const CapturedStmt &S, SmallVectorImpl<llvm::Value *> &CapturedVars) { 299 const RecordDecl *RD = S.getCapturedRecordDecl(); 300 auto CurField = RD->field_begin(); 301 auto CurCap = S.captures().begin(); 302 for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(), 303 E = S.capture_init_end(); 304 I != E; ++I, ++CurField, ++CurCap) { 305 if (CurField->hasCapturedVLAType()) { 306 const VariableArrayType *VAT = CurField->getCapturedVLAType(); 307 llvm::Value *Val = VLASizeMap[VAT->getSizeExpr()]; 308 CapturedVars.push_back(Val); 309 } else if (CurCap->capturesThis()) { 310 CapturedVars.push_back(CXXThisValue); 311 } else if (CurCap->capturesVariableByCopy()) { 312 llvm::Value *CV = EmitLoadOfScalar(EmitLValue(*I), CurCap->getLocation()); 313 314 // If the field is not a pointer, we need to save the actual value 315 // and load it as a void pointer. 316 if (!CurField->getType()->isAnyPointerType()) { 317 ASTContext &Ctx = getContext(); 318 Address DstAddr = CreateMemTemp( 319 Ctx.getUIntPtrType(), 320 Twine(CurCap->getCapturedVar()->getName(), ".casted")); 321 LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType()); 322 323 llvm::Value *SrcAddrVal = EmitScalarConversion( 324 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()), 325 Ctx.getPointerType(CurField->getType()), CurCap->getLocation()); 326 LValue SrcLV = 327 MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType()); 328 329 // Store the value using the source type pointer. 330 EmitStoreThroughLValue(RValue::get(CV), SrcLV); 331 332 // Load the value using the destination type pointer. 333 CV = EmitLoadOfScalar(DstLV, CurCap->getLocation()); 334 } 335 CapturedVars.push_back(CV); 336 } else { 337 assert(CurCap->capturesVariable() && "Expected capture by reference."); 338 CapturedVars.push_back(EmitLValue(*I).getAddress(*this).getPointer()); 339 } 340 } 341 } 342 343 static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, 344 QualType DstType, StringRef Name, 345 LValue AddrLV) { 346 ASTContext &Ctx = CGF.getContext(); 347 348 llvm::Value *CastedPtr = CGF.EmitScalarConversion( 349 AddrLV.getAddress(CGF).getPointer(), Ctx.getUIntPtrType(), 350 Ctx.getPointerType(DstType), Loc); 351 Address TmpAddr = 352 CGF.MakeNaturalAlignAddrLValue(CastedPtr, Ctx.getPointerType(DstType)) 353 .getAddress(CGF); 354 return TmpAddr; 355 } 356 357 static QualType getCanonicalParamType(ASTContext &C, QualType T) { 358 if (T->isLValueReferenceType()) 359 return C.getLValueReferenceType( 360 getCanonicalParamType(C, T.getNonReferenceType()), 361 /*SpelledAsLValue=*/false); 362 if (T->isPointerType()) 363 return C.getPointerType(getCanonicalParamType(C, T->getPointeeType())); 364 if (const ArrayType *A = T->getAsArrayTypeUnsafe()) { 365 if (const auto *VLA = dyn_cast<VariableArrayType>(A)) 366 return getCanonicalParamType(C, VLA->getElementType()); 367 if (!A->isVariablyModifiedType()) 368 return C.getCanonicalType(T); 369 } 370 return C.getCanonicalParamType(T); 371 } 372 373 namespace { 374 /// Contains required data for proper outlined function codegen. 375 struct FunctionOptions { 376 /// Captured statement for which the function is generated. 377 const CapturedStmt *S = nullptr; 378 /// true if cast to/from UIntPtr is required for variables captured by 379 /// value. 380 const bool UIntPtrCastRequired = true; 381 /// true if only casted arguments must be registered as local args or VLA 382 /// sizes. 383 const bool RegisterCastedArgsOnly = false; 384 /// Name of the generated function. 385 const StringRef FunctionName; 386 /// Location of the non-debug version of the outlined function. 387 SourceLocation Loc; 388 explicit FunctionOptions(const CapturedStmt *S, bool UIntPtrCastRequired, 389 bool RegisterCastedArgsOnly, StringRef FunctionName, 390 SourceLocation Loc) 391 : S(S), UIntPtrCastRequired(UIntPtrCastRequired), 392 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly), 393 FunctionName(FunctionName), Loc(Loc) {} 394 }; 395 } // namespace 396 397 static llvm::Function *emitOutlinedFunctionPrologue( 398 CodeGenFunction &CGF, FunctionArgList &Args, 399 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> 400 &LocalAddrs, 401 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> 402 &VLASizes, 403 llvm::Value *&CXXThisValue, const FunctionOptions &FO) { 404 const CapturedDecl *CD = FO.S->getCapturedDecl(); 405 const RecordDecl *RD = FO.S->getCapturedRecordDecl(); 406 assert(CD->hasBody() && "missing CapturedDecl body"); 407 408 CXXThisValue = nullptr; 409 // Build the argument list. 410 CodeGenModule &CGM = CGF.CGM; 411 ASTContext &Ctx = CGM.getContext(); 412 FunctionArgList TargetArgs; 413 Args.append(CD->param_begin(), 414 std::next(CD->param_begin(), CD->getContextParamPosition())); 415 TargetArgs.append( 416 CD->param_begin(), 417 std::next(CD->param_begin(), CD->getContextParamPosition())); 418 auto I = FO.S->captures().begin(); 419 FunctionDecl *DebugFunctionDecl = nullptr; 420 if (!FO.UIntPtrCastRequired) { 421 FunctionProtoType::ExtProtoInfo EPI; 422 QualType FunctionTy = Ctx.getFunctionType(Ctx.VoidTy, llvm::None, EPI); 423 DebugFunctionDecl = FunctionDecl::Create( 424 Ctx, Ctx.getTranslationUnitDecl(), FO.S->getBeginLoc(), 425 SourceLocation(), DeclarationName(), FunctionTy, 426 Ctx.getTrivialTypeSourceInfo(FunctionTy), SC_Static, 427 /*isInlineSpecified=*/false, /*hasWrittenPrototype=*/false); 428 } 429 for (const FieldDecl *FD : RD->fields()) { 430 QualType ArgType = FD->getType(); 431 IdentifierInfo *II = nullptr; 432 VarDecl *CapVar = nullptr; 433 434 // If this is a capture by copy and the type is not a pointer, the outlined 435 // function argument type should be uintptr and the value properly casted to 436 // uintptr. This is necessary given that the runtime library is only able to 437 // deal with pointers. We can pass in the same way the VLA type sizes to the 438 // outlined function. 439 if (FO.UIntPtrCastRequired && 440 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) || 441 I->capturesVariableArrayType())) 442 ArgType = Ctx.getUIntPtrType(); 443 444 if (I->capturesVariable() || I->capturesVariableByCopy()) { 445 CapVar = I->getCapturedVar(); 446 II = CapVar->getIdentifier(); 447 } else if (I->capturesThis()) { 448 II = &Ctx.Idents.get("this"); 449 } else { 450 assert(I->capturesVariableArrayType()); 451 II = &Ctx.Idents.get("vla"); 452 } 453 if (ArgType->isVariablyModifiedType()) 454 ArgType = getCanonicalParamType(Ctx, ArgType); 455 VarDecl *Arg; 456 if (DebugFunctionDecl && (CapVar || I->capturesThis())) { 457 Arg = ParmVarDecl::Create( 458 Ctx, DebugFunctionDecl, 459 CapVar ? CapVar->getBeginLoc() : FD->getBeginLoc(), 460 CapVar ? CapVar->getLocation() : FD->getLocation(), II, ArgType, 461 /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr); 462 } else { 463 Arg = ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(), 464 II, ArgType, ImplicitParamDecl::Other); 465 } 466 Args.emplace_back(Arg); 467 // Do not cast arguments if we emit function with non-original types. 468 TargetArgs.emplace_back( 469 FO.UIntPtrCastRequired 470 ? Arg 471 : CGM.getOpenMPRuntime().translateParameter(FD, Arg)); 472 ++I; 473 } 474 Args.append( 475 std::next(CD->param_begin(), CD->getContextParamPosition() + 1), 476 CD->param_end()); 477 TargetArgs.append( 478 std::next(CD->param_begin(), CD->getContextParamPosition() + 1), 479 CD->param_end()); 480 481 // Create the function declaration. 482 const CGFunctionInfo &FuncInfo = 483 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, TargetArgs); 484 llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo); 485 486 auto *F = 487 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage, 488 FO.FunctionName, &CGM.getModule()); 489 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo); 490 if (CD->isNothrow()) 491 F->setDoesNotThrow(); 492 F->setDoesNotRecurse(); 493 494 // Generate the function. 495 CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, TargetArgs, 496 FO.UIntPtrCastRequired ? FO.Loc : FO.S->getBeginLoc(), 497 FO.UIntPtrCastRequired ? FO.Loc 498 : CD->getBody()->getBeginLoc()); 499 unsigned Cnt = CD->getContextParamPosition(); 500 I = FO.S->captures().begin(); 501 for (const FieldDecl *FD : RD->fields()) { 502 // Do not map arguments if we emit function with non-original types. 503 Address LocalAddr(Address::invalid()); 504 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) { 505 LocalAddr = CGM.getOpenMPRuntime().getParameterAddress(CGF, Args[Cnt], 506 TargetArgs[Cnt]); 507 } else { 508 LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]); 509 } 510 // If we are capturing a pointer by copy we don't need to do anything, just 511 // use the value that we get from the arguments. 512 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) { 513 const VarDecl *CurVD = I->getCapturedVar(); 514 if (!FO.RegisterCastedArgsOnly) 515 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}}); 516 ++Cnt; 517 ++I; 518 continue; 519 } 520 521 LValue ArgLVal = CGF.MakeAddrLValue(LocalAddr, Args[Cnt]->getType(), 522 AlignmentSource::Decl); 523 if (FD->hasCapturedVLAType()) { 524 if (FO.UIntPtrCastRequired) { 525 ArgLVal = CGF.MakeAddrLValue( 526 castValueFromUintptr(CGF, I->getLocation(), FD->getType(), 527 Args[Cnt]->getName(), ArgLVal), 528 FD->getType(), AlignmentSource::Decl); 529 } 530 llvm::Value *ExprArg = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation()); 531 const VariableArrayType *VAT = FD->getCapturedVLAType(); 532 VLASizes.try_emplace(Args[Cnt], VAT->getSizeExpr(), ExprArg); 533 } else if (I->capturesVariable()) { 534 const VarDecl *Var = I->getCapturedVar(); 535 QualType VarTy = Var->getType(); 536 Address ArgAddr = ArgLVal.getAddress(CGF); 537 if (ArgLVal.getType()->isLValueReferenceType()) { 538 ArgAddr = CGF.EmitLoadOfReference(ArgLVal); 539 } else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) { 540 assert(ArgLVal.getType()->isPointerType()); 541 ArgAddr = CGF.EmitLoadOfPointer( 542 ArgAddr, ArgLVal.getType()->castAs<PointerType>()); 543 } 544 if (!FO.RegisterCastedArgsOnly) { 545 LocalAddrs.insert( 546 {Args[Cnt], 547 {Var, Address(ArgAddr.getPointer(), Ctx.getDeclAlign(Var))}}); 548 } 549 } else if (I->capturesVariableByCopy()) { 550 assert(!FD->getType()->isAnyPointerType() && 551 "Not expecting a captured pointer."); 552 const VarDecl *Var = I->getCapturedVar(); 553 LocalAddrs.insert({Args[Cnt], 554 {Var, FO.UIntPtrCastRequired 555 ? castValueFromUintptr( 556 CGF, I->getLocation(), FD->getType(), 557 Args[Cnt]->getName(), ArgLVal) 558 : ArgLVal.getAddress(CGF)}}); 559 } else { 560 // If 'this' is captured, load it into CXXThisValue. 561 assert(I->capturesThis()); 562 CXXThisValue = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation()); 563 LocalAddrs.insert({Args[Cnt], {nullptr, ArgLVal.getAddress(CGF)}}); 564 } 565 ++Cnt; 566 ++I; 567 } 568 569 return F; 570 } 571 572 llvm::Function * 573 CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, 574 SourceLocation Loc) { 575 assert( 576 CapturedStmtInfo && 577 "CapturedStmtInfo should be set when generating the captured function"); 578 const CapturedDecl *CD = S.getCapturedDecl(); 579 // Build the argument list. 580 bool NeedWrapperFunction = 581 getDebugInfo() && CGM.getCodeGenOpts().hasReducedDebugInfo(); 582 FunctionArgList Args; 583 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs; 584 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes; 585 SmallString<256> Buffer; 586 llvm::raw_svector_ostream Out(Buffer); 587 Out << CapturedStmtInfo->getHelperName(); 588 if (NeedWrapperFunction) 589 Out << "_debug__"; 590 FunctionOptions FO(&S, !NeedWrapperFunction, /*RegisterCastedArgsOnly=*/false, 591 Out.str(), Loc); 592 llvm::Function *F = emitOutlinedFunctionPrologue(*this, Args, LocalAddrs, 593 VLASizes, CXXThisValue, FO); 594 CodeGenFunction::OMPPrivateScope LocalScope(*this); 595 for (const auto &LocalAddrPair : LocalAddrs) { 596 if (LocalAddrPair.second.first) { 597 LocalScope.addPrivate(LocalAddrPair.second.first, [&LocalAddrPair]() { 598 return LocalAddrPair.second.second; 599 }); 600 } 601 } 602 (void)LocalScope.Privatize(); 603 for (const auto &VLASizePair : VLASizes) 604 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second; 605 PGO.assignRegionCounters(GlobalDecl(CD), F); 606 CapturedStmtInfo->EmitBody(*this, CD->getBody()); 607 (void)LocalScope.ForceCleanup(); 608 FinishFunction(CD->getBodyRBrace()); 609 if (!NeedWrapperFunction) 610 return F; 611 612 FunctionOptions WrapperFO(&S, /*UIntPtrCastRequired=*/true, 613 /*RegisterCastedArgsOnly=*/true, 614 CapturedStmtInfo->getHelperName(), Loc); 615 CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true); 616 WrapperCGF.CapturedStmtInfo = CapturedStmtInfo; 617 Args.clear(); 618 LocalAddrs.clear(); 619 VLASizes.clear(); 620 llvm::Function *WrapperF = 621 emitOutlinedFunctionPrologue(WrapperCGF, Args, LocalAddrs, VLASizes, 622 WrapperCGF.CXXThisValue, WrapperFO); 623 llvm::SmallVector<llvm::Value *, 4> CallArgs; 624 for (const auto *Arg : Args) { 625 llvm::Value *CallArg; 626 auto I = LocalAddrs.find(Arg); 627 if (I != LocalAddrs.end()) { 628 LValue LV = WrapperCGF.MakeAddrLValue( 629 I->second.second, 630 I->second.first ? I->second.first->getType() : Arg->getType(), 631 AlignmentSource::Decl); 632 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc()); 633 } else { 634 auto EI = VLASizes.find(Arg); 635 if (EI != VLASizes.end()) { 636 CallArg = EI->second.second; 637 } else { 638 LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg), 639 Arg->getType(), 640 AlignmentSource::Decl); 641 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc()); 642 } 643 } 644 CallArgs.emplace_back(WrapperCGF.EmitFromMemory(CallArg, Arg->getType())); 645 } 646 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs); 647 WrapperCGF.FinishFunction(); 648 return WrapperF; 649 } 650 651 //===----------------------------------------------------------------------===// 652 // OpenMP Directive Emission 653 //===----------------------------------------------------------------------===// 654 void CodeGenFunction::EmitOMPAggregateAssign( 655 Address DestAddr, Address SrcAddr, QualType OriginalType, 656 const llvm::function_ref<void(Address, Address)> CopyGen) { 657 // Perform element-by-element initialization. 658 QualType ElementTy; 659 660 // Drill down to the base element type on both arrays. 661 const ArrayType *ArrayTy = OriginalType->getAsArrayTypeUnsafe(); 662 llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr); 663 SrcAddr = Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 664 665 llvm::Value *SrcBegin = SrcAddr.getPointer(); 666 llvm::Value *DestBegin = DestAddr.getPointer(); 667 // Cast from pointer to array type to pointer to single element. 668 llvm::Value *DestEnd = Builder.CreateGEP(DestBegin, NumElements); 669 // The basic structure here is a while-do loop. 670 llvm::BasicBlock *BodyBB = createBasicBlock("omp.arraycpy.body"); 671 llvm::BasicBlock *DoneBB = createBasicBlock("omp.arraycpy.done"); 672 llvm::Value *IsEmpty = 673 Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty"); 674 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 675 676 // Enter the loop body, making that address the current address. 677 llvm::BasicBlock *EntryBB = Builder.GetInsertBlock(); 678 EmitBlock(BodyBB); 679 680 CharUnits ElementSize = getContext().getTypeSizeInChars(ElementTy); 681 682 llvm::PHINode *SrcElementPHI = 683 Builder.CreatePHI(SrcBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 684 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 685 Address SrcElementCurrent = 686 Address(SrcElementPHI, 687 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 688 689 llvm::PHINode *DestElementPHI = 690 Builder.CreatePHI(DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 691 DestElementPHI->addIncoming(DestBegin, EntryBB); 692 Address DestElementCurrent = 693 Address(DestElementPHI, 694 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 695 696 // Emit copy. 697 CopyGen(DestElementCurrent, SrcElementCurrent); 698 699 // Shift the address forward by one element. 700 llvm::Value *DestElementNext = Builder.CreateConstGEP1_32( 701 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 702 llvm::Value *SrcElementNext = Builder.CreateConstGEP1_32( 703 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 704 // Check whether we've reached the end. 705 llvm::Value *Done = 706 Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 707 Builder.CreateCondBr(Done, DoneBB, BodyBB); 708 DestElementPHI->addIncoming(DestElementNext, Builder.GetInsertBlock()); 709 SrcElementPHI->addIncoming(SrcElementNext, Builder.GetInsertBlock()); 710 711 // Done. 712 EmitBlock(DoneBB, /*IsFinished=*/true); 713 } 714 715 void CodeGenFunction::EmitOMPCopy(QualType OriginalType, Address DestAddr, 716 Address SrcAddr, const VarDecl *DestVD, 717 const VarDecl *SrcVD, const Expr *Copy) { 718 if (OriginalType->isArrayType()) { 719 const auto *BO = dyn_cast<BinaryOperator>(Copy); 720 if (BO && BO->getOpcode() == BO_Assign) { 721 // Perform simple memcpy for simple copying. 722 LValue Dest = MakeAddrLValue(DestAddr, OriginalType); 723 LValue Src = MakeAddrLValue(SrcAddr, OriginalType); 724 EmitAggregateAssign(Dest, Src, OriginalType); 725 } else { 726 // For arrays with complex element types perform element by element 727 // copying. 728 EmitOMPAggregateAssign( 729 DestAddr, SrcAddr, OriginalType, 730 [this, Copy, SrcVD, DestVD](Address DestElement, Address SrcElement) { 731 // Working with the single array element, so have to remap 732 // destination and source variables to corresponding array 733 // elements. 734 CodeGenFunction::OMPPrivateScope Remap(*this); 735 Remap.addPrivate(DestVD, [DestElement]() { return DestElement; }); 736 Remap.addPrivate(SrcVD, [SrcElement]() { return SrcElement; }); 737 (void)Remap.Privatize(); 738 EmitIgnoredExpr(Copy); 739 }); 740 } 741 } else { 742 // Remap pseudo source variable to private copy. 743 CodeGenFunction::OMPPrivateScope Remap(*this); 744 Remap.addPrivate(SrcVD, [SrcAddr]() { return SrcAddr; }); 745 Remap.addPrivate(DestVD, [DestAddr]() { return DestAddr; }); 746 (void)Remap.Privatize(); 747 // Emit copying of the whole variable. 748 EmitIgnoredExpr(Copy); 749 } 750 } 751 752 bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D, 753 OMPPrivateScope &PrivateScope) { 754 if (!HaveInsertPoint()) 755 return false; 756 bool DeviceConstTarget = 757 getLangOpts().OpenMPIsDevice && 758 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 759 bool FirstprivateIsLastprivate = false; 760 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates; 761 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) { 762 for (const auto *D : C->varlists()) 763 Lastprivates.try_emplace( 764 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl(), 765 C->getKind()); 766 } 767 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate; 768 llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 769 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 770 // Force emission of the firstprivate copy if the directive does not emit 771 // outlined function, like omp for, omp simd, omp distribute etc. 772 bool MustEmitFirstprivateCopy = 773 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown; 774 for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) { 775 const auto *IRef = C->varlist_begin(); 776 const auto *InitsRef = C->inits().begin(); 777 for (const Expr *IInit : C->private_copies()) { 778 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 779 bool ThisFirstprivateIsLastprivate = 780 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0; 781 const FieldDecl *FD = CapturedStmtInfo->lookup(OrigVD); 782 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); 783 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD && 784 !FD->getType()->isReferenceType() && 785 (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())) { 786 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()); 787 ++IRef; 788 ++InitsRef; 789 continue; 790 } 791 // Do not emit copy for firstprivate constant variables in target regions, 792 // captured by reference. 793 if (DeviceConstTarget && OrigVD->getType().isConstant(getContext()) && 794 FD && FD->getType()->isReferenceType() && 795 (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())) { 796 (void)CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(*this, 797 OrigVD); 798 ++IRef; 799 ++InitsRef; 800 continue; 801 } 802 FirstprivateIsLastprivate = 803 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate; 804 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) { 805 const auto *VDInit = 806 cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl()); 807 bool IsRegistered; 808 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), 809 /*RefersToEnclosingVariableOrCapture=*/FD != nullptr, 810 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); 811 LValue OriginalLVal; 812 if (!FD) { 813 // Check if the firstprivate variable is just a constant value. 814 ConstantEmission CE = tryEmitAsConstant(&DRE); 815 if (CE && !CE.isReference()) { 816 // Constant value, no need to create a copy. 817 ++IRef; 818 ++InitsRef; 819 continue; 820 } 821 if (CE && CE.isReference()) { 822 OriginalLVal = CE.getReferenceLValue(*this, &DRE); 823 } else { 824 assert(!CE && "Expected non-constant firstprivate."); 825 OriginalLVal = EmitLValue(&DRE); 826 } 827 } else { 828 OriginalLVal = EmitLValue(&DRE); 829 } 830 QualType Type = VD->getType(); 831 if (Type->isArrayType()) { 832 // Emit VarDecl with copy init for arrays. 833 // Get the address of the original variable captured in current 834 // captured region. 835 IsRegistered = PrivateScope.addPrivate( 836 OrigVD, [this, VD, Type, OriginalLVal, VDInit]() { 837 AutoVarEmission Emission = EmitAutoVarAlloca(*VD); 838 const Expr *Init = VD->getInit(); 839 if (!isa<CXXConstructExpr>(Init) || 840 isTrivialInitializer(Init)) { 841 // Perform simple memcpy. 842 LValue Dest = 843 MakeAddrLValue(Emission.getAllocatedAddress(), Type); 844 EmitAggregateAssign(Dest, OriginalLVal, Type); 845 } else { 846 EmitOMPAggregateAssign( 847 Emission.getAllocatedAddress(), 848 OriginalLVal.getAddress(*this), Type, 849 [this, VDInit, Init](Address DestElement, 850 Address SrcElement) { 851 // Clean up any temporaries needed by the 852 // initialization. 853 RunCleanupsScope InitScope(*this); 854 // Emit initialization for single element. 855 setAddrOfLocalVar(VDInit, SrcElement); 856 EmitAnyExprToMem(Init, DestElement, 857 Init->getType().getQualifiers(), 858 /*IsInitializer*/ false); 859 LocalDeclMap.erase(VDInit); 860 }); 861 } 862 EmitAutoVarCleanups(Emission); 863 return Emission.getAllocatedAddress(); 864 }); 865 } else { 866 Address OriginalAddr = OriginalLVal.getAddress(*this); 867 IsRegistered = 868 PrivateScope.addPrivate(OrigVD, [this, VDInit, OriginalAddr, VD, 869 ThisFirstprivateIsLastprivate, 870 OrigVD, &Lastprivates, IRef]() { 871 // Emit private VarDecl with copy init. 872 // Remap temp VDInit variable to the address of the original 873 // variable (for proper handling of captured global variables). 874 setAddrOfLocalVar(VDInit, OriginalAddr); 875 EmitDecl(*VD); 876 LocalDeclMap.erase(VDInit); 877 if (ThisFirstprivateIsLastprivate && 878 Lastprivates[OrigVD->getCanonicalDecl()] == 879 OMPC_LASTPRIVATE_conditional) { 880 // Create/init special variable for lastprivate conditionals. 881 Address VDAddr = 882 CGM.getOpenMPRuntime().emitLastprivateConditionalInit( 883 *this, OrigVD); 884 llvm::Value *V = EmitLoadOfScalar( 885 MakeAddrLValue(GetAddrOfLocalVar(VD), (*IRef)->getType(), 886 AlignmentSource::Decl), 887 (*IRef)->getExprLoc()); 888 EmitStoreOfScalar(V, 889 MakeAddrLValue(VDAddr, (*IRef)->getType(), 890 AlignmentSource::Decl)); 891 LocalDeclMap.erase(VD); 892 setAddrOfLocalVar(VD, VDAddr); 893 return VDAddr; 894 } 895 return GetAddrOfLocalVar(VD); 896 }); 897 } 898 assert(IsRegistered && 899 "firstprivate var already registered as private"); 900 // Silence the warning about unused variable. 901 (void)IsRegistered; 902 } 903 ++IRef; 904 ++InitsRef; 905 } 906 } 907 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty(); 908 } 909 910 void CodeGenFunction::EmitOMPPrivateClause( 911 const OMPExecutableDirective &D, 912 CodeGenFunction::OMPPrivateScope &PrivateScope) { 913 if (!HaveInsertPoint()) 914 return; 915 llvm::DenseSet<const VarDecl *> EmittedAsPrivate; 916 for (const auto *C : D.getClausesOfKind<OMPPrivateClause>()) { 917 auto IRef = C->varlist_begin(); 918 for (const Expr *IInit : C->private_copies()) { 919 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 920 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { 921 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); 922 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD]() { 923 // Emit private VarDecl with copy init. 924 EmitDecl(*VD); 925 return GetAddrOfLocalVar(VD); 926 }); 927 assert(IsRegistered && "private var already registered as private"); 928 // Silence the warning about unused variable. 929 (void)IsRegistered; 930 } 931 ++IRef; 932 } 933 } 934 } 935 936 bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { 937 if (!HaveInsertPoint()) 938 return false; 939 // threadprivate_var1 = master_threadprivate_var1; 940 // operator=(threadprivate_var2, master_threadprivate_var2); 941 // ... 942 // __kmpc_barrier(&loc, global_tid); 943 llvm::DenseSet<const VarDecl *> CopiedVars; 944 llvm::BasicBlock *CopyBegin = nullptr, *CopyEnd = nullptr; 945 for (const auto *C : D.getClausesOfKind<OMPCopyinClause>()) { 946 auto IRef = C->varlist_begin(); 947 auto ISrcRef = C->source_exprs().begin(); 948 auto IDestRef = C->destination_exprs().begin(); 949 for (const Expr *AssignOp : C->assignment_ops()) { 950 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 951 QualType Type = VD->getType(); 952 if (CopiedVars.insert(VD->getCanonicalDecl()).second) { 953 // Get the address of the master variable. If we are emitting code with 954 // TLS support, the address is passed from the master as field in the 955 // captured declaration. 956 Address MasterAddr = Address::invalid(); 957 if (getLangOpts().OpenMPUseTLS && 958 getContext().getTargetInfo().isTLSSupported()) { 959 assert(CapturedStmtInfo->lookup(VD) && 960 "Copyin threadprivates should have been captured!"); 961 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD), true, 962 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); 963 MasterAddr = EmitLValue(&DRE).getAddress(*this); 964 LocalDeclMap.erase(VD); 965 } else { 966 MasterAddr = 967 Address(VD->isStaticLocal() ? CGM.getStaticLocalDeclAddress(VD) 968 : CGM.GetAddrOfGlobal(VD), 969 getContext().getDeclAlign(VD)); 970 } 971 // Get the address of the threadprivate variable. 972 Address PrivateAddr = EmitLValue(*IRef).getAddress(*this); 973 if (CopiedVars.size() == 1) { 974 // At first check if current thread is a master thread. If it is, no 975 // need to copy data. 976 CopyBegin = createBasicBlock("copyin.not.master"); 977 CopyEnd = createBasicBlock("copyin.not.master.end"); 978 Builder.CreateCondBr( 979 Builder.CreateICmpNE( 980 Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy), 981 Builder.CreatePtrToInt(PrivateAddr.getPointer(), 982 CGM.IntPtrTy)), 983 CopyBegin, CopyEnd); 984 EmitBlock(CopyBegin); 985 } 986 const auto *SrcVD = 987 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl()); 988 const auto *DestVD = 989 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl()); 990 EmitOMPCopy(Type, PrivateAddr, MasterAddr, DestVD, SrcVD, AssignOp); 991 } 992 ++IRef; 993 ++ISrcRef; 994 ++IDestRef; 995 } 996 } 997 if (CopyEnd) { 998 // Exit out of copying procedure for non-master thread. 999 EmitBlock(CopyEnd, /*IsFinished=*/true); 1000 return true; 1001 } 1002 return false; 1003 } 1004 1005 bool CodeGenFunction::EmitOMPLastprivateClauseInit( 1006 const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope) { 1007 if (!HaveInsertPoint()) 1008 return false; 1009 bool HasAtLeastOneLastprivate = false; 1010 llvm::DenseSet<const VarDecl *> SIMDLCVs; 1011 if (isOpenMPSimdDirective(D.getDirectiveKind())) { 1012 const auto *LoopDirective = cast<OMPLoopDirective>(&D); 1013 for (const Expr *C : LoopDirective->counters()) { 1014 SIMDLCVs.insert( 1015 cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl()); 1016 } 1017 } 1018 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars; 1019 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) { 1020 HasAtLeastOneLastprivate = true; 1021 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 1022 !getLangOpts().OpenMPSimd) 1023 break; 1024 const auto *IRef = C->varlist_begin(); 1025 const auto *IDestRef = C->destination_exprs().begin(); 1026 for (const Expr *IInit : C->private_copies()) { 1027 // Keep the address of the original variable for future update at the end 1028 // of the loop. 1029 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 1030 // Taskloops do not require additional initialization, it is done in 1031 // runtime support library. 1032 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) { 1033 const auto *DestVD = 1034 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl()); 1035 PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() { 1036 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), 1037 /*RefersToEnclosingVariableOrCapture=*/ 1038 CapturedStmtInfo->lookup(OrigVD) != nullptr, 1039 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); 1040 return EmitLValue(&DRE).getAddress(*this); 1041 }); 1042 // Check if the variable is also a firstprivate: in this case IInit is 1043 // not generated. Initialization of this variable will happen in codegen 1044 // for 'firstprivate' clause. 1045 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) { 1046 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl()); 1047 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD, C, 1048 OrigVD]() { 1049 if (C->getKind() == OMPC_LASTPRIVATE_conditional) { 1050 Address VDAddr = 1051 CGM.getOpenMPRuntime().emitLastprivateConditionalInit(*this, 1052 OrigVD); 1053 setAddrOfLocalVar(VD, VDAddr); 1054 return VDAddr; 1055 } 1056 // Emit private VarDecl with copy init. 1057 EmitDecl(*VD); 1058 return GetAddrOfLocalVar(VD); 1059 }); 1060 assert(IsRegistered && 1061 "lastprivate var already registered as private"); 1062 (void)IsRegistered; 1063 } 1064 } 1065 ++IRef; 1066 ++IDestRef; 1067 } 1068 } 1069 return HasAtLeastOneLastprivate; 1070 } 1071 1072 void CodeGenFunction::EmitOMPLastprivateClauseFinal( 1073 const OMPExecutableDirective &D, bool NoFinals, 1074 llvm::Value *IsLastIterCond) { 1075 if (!HaveInsertPoint()) 1076 return; 1077 // Emit following code: 1078 // if (<IsLastIterCond>) { 1079 // orig_var1 = private_orig_var1; 1080 // ... 1081 // orig_varn = private_orig_varn; 1082 // } 1083 llvm::BasicBlock *ThenBB = nullptr; 1084 llvm::BasicBlock *DoneBB = nullptr; 1085 if (IsLastIterCond) { 1086 // Emit implicit barrier if at least one lastprivate conditional is found 1087 // and this is not a simd mode. 1088 if (!getLangOpts().OpenMPSimd && 1089 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(), 1090 [](const OMPLastprivateClause *C) { 1091 return C->getKind() == OMPC_LASTPRIVATE_conditional; 1092 })) { 1093 CGM.getOpenMPRuntime().emitBarrierCall(*this, D.getBeginLoc(), 1094 OMPD_unknown, 1095 /*EmitChecks=*/false, 1096 /*ForceSimpleCall=*/true); 1097 } 1098 ThenBB = createBasicBlock(".omp.lastprivate.then"); 1099 DoneBB = createBasicBlock(".omp.lastprivate.done"); 1100 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB); 1101 EmitBlock(ThenBB); 1102 } 1103 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars; 1104 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates; 1105 if (const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) { 1106 auto IC = LoopDirective->counters().begin(); 1107 for (const Expr *F : LoopDirective->finals()) { 1108 const auto *D = 1109 cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl())->getCanonicalDecl(); 1110 if (NoFinals) 1111 AlreadyEmittedVars.insert(D); 1112 else 1113 LoopCountersAndUpdates[D] = F; 1114 ++IC; 1115 } 1116 } 1117 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) { 1118 auto IRef = C->varlist_begin(); 1119 auto ISrcRef = C->source_exprs().begin(); 1120 auto IDestRef = C->destination_exprs().begin(); 1121 for (const Expr *AssignOp : C->assignment_ops()) { 1122 const auto *PrivateVD = 1123 cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 1124 QualType Type = PrivateVD->getType(); 1125 const auto *CanonicalVD = PrivateVD->getCanonicalDecl(); 1126 if (AlreadyEmittedVars.insert(CanonicalVD).second) { 1127 // If lastprivate variable is a loop control variable for loop-based 1128 // directive, update its value before copyin back to original 1129 // variable. 1130 if (const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD)) 1131 EmitIgnoredExpr(FinalExpr); 1132 const auto *SrcVD = 1133 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl()); 1134 const auto *DestVD = 1135 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl()); 1136 // Get the address of the private variable. 1137 Address PrivateAddr = GetAddrOfLocalVar(PrivateVD); 1138 if (const auto *RefTy = PrivateVD->getType()->getAs<ReferenceType>()) 1139 PrivateAddr = 1140 Address(Builder.CreateLoad(PrivateAddr), 1141 CGM.getNaturalTypeAlignment(RefTy->getPointeeType())); 1142 // Store the last value to the private copy in the last iteration. 1143 if (C->getKind() == OMPC_LASTPRIVATE_conditional) 1144 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate( 1145 *this, MakeAddrLValue(PrivateAddr, (*IRef)->getType()), PrivateVD, 1146 (*IRef)->getExprLoc()); 1147 // Get the address of the original variable. 1148 Address OriginalAddr = GetAddrOfLocalVar(DestVD); 1149 EmitOMPCopy(Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp); 1150 } 1151 ++IRef; 1152 ++ISrcRef; 1153 ++IDestRef; 1154 } 1155 if (const Expr *PostUpdate = C->getPostUpdateExpr()) 1156 EmitIgnoredExpr(PostUpdate); 1157 } 1158 if (IsLastIterCond) 1159 EmitBlock(DoneBB, /*IsFinished=*/true); 1160 } 1161 1162 void CodeGenFunction::EmitOMPReductionClauseInit( 1163 const OMPExecutableDirective &D, 1164 CodeGenFunction::OMPPrivateScope &PrivateScope, bool ForInscan) { 1165 if (!HaveInsertPoint()) 1166 return; 1167 SmallVector<const Expr *, 4> Shareds; 1168 SmallVector<const Expr *, 4> Privates; 1169 SmallVector<const Expr *, 4> ReductionOps; 1170 SmallVector<const Expr *, 4> LHSs; 1171 SmallVector<const Expr *, 4> RHSs; 1172 OMPTaskDataTy Data; 1173 SmallVector<const Expr *, 4> TaskLHSs; 1174 SmallVector<const Expr *, 4> TaskRHSs; 1175 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) { 1176 if (ForInscan != (C->getModifier() == OMPC_REDUCTION_inscan)) 1177 continue; 1178 Shareds.append(C->varlist_begin(), C->varlist_end()); 1179 Privates.append(C->privates().begin(), C->privates().end()); 1180 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end()); 1181 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end()); 1182 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end()); 1183 if (C->getModifier() == OMPC_REDUCTION_task) { 1184 Data.ReductionVars.append(C->privates().begin(), C->privates().end()); 1185 Data.ReductionOrigs.append(C->varlist_begin(), C->varlist_end()); 1186 Data.ReductionCopies.append(C->privates().begin(), C->privates().end()); 1187 Data.ReductionOps.append(C->reduction_ops().begin(), 1188 C->reduction_ops().end()); 1189 TaskLHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end()); 1190 TaskRHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end()); 1191 } 1192 } 1193 ReductionCodeGen RedCG(Shareds, Shareds, Privates, ReductionOps); 1194 unsigned Count = 0; 1195 auto *ILHS = LHSs.begin(); 1196 auto *IRHS = RHSs.begin(); 1197 auto *IPriv = Privates.begin(); 1198 for (const Expr *IRef : Shareds) { 1199 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl()); 1200 // Emit private VarDecl with reduction init. 1201 RedCG.emitSharedOrigLValue(*this, Count); 1202 RedCG.emitAggregateType(*this, Count); 1203 AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD); 1204 RedCG.emitInitialization(*this, Count, Emission.getAllocatedAddress(), 1205 RedCG.getSharedLValue(Count), 1206 [&Emission](CodeGenFunction &CGF) { 1207 CGF.EmitAutoVarInit(Emission); 1208 return true; 1209 }); 1210 EmitAutoVarCleanups(Emission); 1211 Address BaseAddr = RedCG.adjustPrivateAddress( 1212 *this, Count, Emission.getAllocatedAddress()); 1213 bool IsRegistered = PrivateScope.addPrivate( 1214 RedCG.getBaseDecl(Count), [BaseAddr]() { return BaseAddr; }); 1215 assert(IsRegistered && "private var already registered as private"); 1216 // Silence the warning about unused variable. 1217 (void)IsRegistered; 1218 1219 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 1220 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 1221 QualType Type = PrivateVD->getType(); 1222 bool isaOMPArraySectionExpr = isa<OMPArraySectionExpr>(IRef); 1223 if (isaOMPArraySectionExpr && Type->isVariablyModifiedType()) { 1224 // Store the address of the original variable associated with the LHS 1225 // implicit variable. 1226 PrivateScope.addPrivate(LHSVD, [&RedCG, Count, this]() { 1227 return RedCG.getSharedLValue(Count).getAddress(*this); 1228 }); 1229 PrivateScope.addPrivate( 1230 RHSVD, [this, PrivateVD]() { return GetAddrOfLocalVar(PrivateVD); }); 1231 } else if ((isaOMPArraySectionExpr && Type->isScalarType()) || 1232 isa<ArraySubscriptExpr>(IRef)) { 1233 // Store the address of the original variable associated with the LHS 1234 // implicit variable. 1235 PrivateScope.addPrivate(LHSVD, [&RedCG, Count, this]() { 1236 return RedCG.getSharedLValue(Count).getAddress(*this); 1237 }); 1238 PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() { 1239 return Builder.CreateElementBitCast(GetAddrOfLocalVar(PrivateVD), 1240 ConvertTypeForMem(RHSVD->getType()), 1241 "rhs.begin"); 1242 }); 1243 } else { 1244 QualType Type = PrivateVD->getType(); 1245 bool IsArray = getContext().getAsArrayType(Type) != nullptr; 1246 Address OriginalAddr = RedCG.getSharedLValue(Count).getAddress(*this); 1247 // Store the address of the original variable associated with the LHS 1248 // implicit variable. 1249 if (IsArray) { 1250 OriginalAddr = Builder.CreateElementBitCast( 1251 OriginalAddr, ConvertTypeForMem(LHSVD->getType()), "lhs.begin"); 1252 } 1253 PrivateScope.addPrivate(LHSVD, [OriginalAddr]() { return OriginalAddr; }); 1254 PrivateScope.addPrivate( 1255 RHSVD, [this, PrivateVD, RHSVD, IsArray]() { 1256 return IsArray 1257 ? Builder.CreateElementBitCast( 1258 GetAddrOfLocalVar(PrivateVD), 1259 ConvertTypeForMem(RHSVD->getType()), "rhs.begin") 1260 : GetAddrOfLocalVar(PrivateVD); 1261 }); 1262 } 1263 ++ILHS; 1264 ++IRHS; 1265 ++IPriv; 1266 ++Count; 1267 } 1268 if (!Data.ReductionVars.empty()) { 1269 Data.IsReductionWithTaskMod = true; 1270 Data.IsWorksharingReduction = 1271 isOpenMPWorksharingDirective(D.getDirectiveKind()); 1272 llvm::Value *ReductionDesc = CGM.getOpenMPRuntime().emitTaskReductionInit( 1273 *this, D.getBeginLoc(), TaskLHSs, TaskRHSs, Data); 1274 const Expr *TaskRedRef = nullptr; 1275 switch (D.getDirectiveKind()) { 1276 case OMPD_parallel: 1277 TaskRedRef = cast<OMPParallelDirective>(D).getTaskReductionRefExpr(); 1278 break; 1279 case OMPD_for: 1280 TaskRedRef = cast<OMPForDirective>(D).getTaskReductionRefExpr(); 1281 break; 1282 case OMPD_sections: 1283 TaskRedRef = cast<OMPSectionsDirective>(D).getTaskReductionRefExpr(); 1284 break; 1285 case OMPD_parallel_for: 1286 TaskRedRef = cast<OMPParallelForDirective>(D).getTaskReductionRefExpr(); 1287 break; 1288 case OMPD_parallel_master: 1289 TaskRedRef = 1290 cast<OMPParallelMasterDirective>(D).getTaskReductionRefExpr(); 1291 break; 1292 case OMPD_parallel_sections: 1293 TaskRedRef = 1294 cast<OMPParallelSectionsDirective>(D).getTaskReductionRefExpr(); 1295 break; 1296 case OMPD_target_parallel: 1297 TaskRedRef = 1298 cast<OMPTargetParallelDirective>(D).getTaskReductionRefExpr(); 1299 break; 1300 case OMPD_target_parallel_for: 1301 TaskRedRef = 1302 cast<OMPTargetParallelForDirective>(D).getTaskReductionRefExpr(); 1303 break; 1304 case OMPD_distribute_parallel_for: 1305 TaskRedRef = 1306 cast<OMPDistributeParallelForDirective>(D).getTaskReductionRefExpr(); 1307 break; 1308 case OMPD_teams_distribute_parallel_for: 1309 TaskRedRef = cast<OMPTeamsDistributeParallelForDirective>(D) 1310 .getTaskReductionRefExpr(); 1311 break; 1312 case OMPD_target_teams_distribute_parallel_for: 1313 TaskRedRef = cast<OMPTargetTeamsDistributeParallelForDirective>(D) 1314 .getTaskReductionRefExpr(); 1315 break; 1316 case OMPD_simd: 1317 case OMPD_for_simd: 1318 case OMPD_section: 1319 case OMPD_single: 1320 case OMPD_master: 1321 case OMPD_critical: 1322 case OMPD_parallel_for_simd: 1323 case OMPD_task: 1324 case OMPD_taskyield: 1325 case OMPD_barrier: 1326 case OMPD_taskwait: 1327 case OMPD_taskgroup: 1328 case OMPD_flush: 1329 case OMPD_depobj: 1330 case OMPD_scan: 1331 case OMPD_ordered: 1332 case OMPD_atomic: 1333 case OMPD_teams: 1334 case OMPD_target: 1335 case OMPD_cancellation_point: 1336 case OMPD_cancel: 1337 case OMPD_target_data: 1338 case OMPD_target_enter_data: 1339 case OMPD_target_exit_data: 1340 case OMPD_taskloop: 1341 case OMPD_taskloop_simd: 1342 case OMPD_master_taskloop: 1343 case OMPD_master_taskloop_simd: 1344 case OMPD_parallel_master_taskloop: 1345 case OMPD_parallel_master_taskloop_simd: 1346 case OMPD_distribute: 1347 case OMPD_target_update: 1348 case OMPD_distribute_parallel_for_simd: 1349 case OMPD_distribute_simd: 1350 case OMPD_target_parallel_for_simd: 1351 case OMPD_target_simd: 1352 case OMPD_teams_distribute: 1353 case OMPD_teams_distribute_simd: 1354 case OMPD_teams_distribute_parallel_for_simd: 1355 case OMPD_target_teams: 1356 case OMPD_target_teams_distribute: 1357 case OMPD_target_teams_distribute_parallel_for_simd: 1358 case OMPD_target_teams_distribute_simd: 1359 case OMPD_declare_target: 1360 case OMPD_end_declare_target: 1361 case OMPD_threadprivate: 1362 case OMPD_allocate: 1363 case OMPD_declare_reduction: 1364 case OMPD_declare_mapper: 1365 case OMPD_declare_simd: 1366 case OMPD_requires: 1367 case OMPD_declare_variant: 1368 case OMPD_begin_declare_variant: 1369 case OMPD_end_declare_variant: 1370 case OMPD_unknown: 1371 llvm_unreachable("Enexpected directive with task reductions."); 1372 } 1373 1374 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(TaskRedRef)->getDecl()); 1375 EmitVarDecl(*VD); 1376 EmitStoreOfScalar(ReductionDesc, GetAddrOfLocalVar(VD), 1377 /*Volatile=*/false, TaskRedRef->getType()); 1378 } 1379 } 1380 1381 void CodeGenFunction::EmitOMPReductionClauseFinal( 1382 const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind) { 1383 if (!HaveInsertPoint()) 1384 return; 1385 llvm::SmallVector<const Expr *, 8> Privates; 1386 llvm::SmallVector<const Expr *, 8> LHSExprs; 1387 llvm::SmallVector<const Expr *, 8> RHSExprs; 1388 llvm::SmallVector<const Expr *, 8> ReductionOps; 1389 bool HasAtLeastOneReduction = false; 1390 bool IsReductionWithTaskMod = false; 1391 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) { 1392 // Do not emit for inscan reductions. 1393 if (C->getModifier() == OMPC_REDUCTION_inscan) 1394 continue; 1395 HasAtLeastOneReduction = true; 1396 Privates.append(C->privates().begin(), C->privates().end()); 1397 LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end()); 1398 RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end()); 1399 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end()); 1400 IsReductionWithTaskMod = 1401 IsReductionWithTaskMod || C->getModifier() == OMPC_REDUCTION_task; 1402 } 1403 if (HasAtLeastOneReduction) { 1404 if (IsReductionWithTaskMod) { 1405 CGM.getOpenMPRuntime().emitTaskReductionFini( 1406 *this, D.getBeginLoc(), 1407 isOpenMPWorksharingDirective(D.getDirectiveKind())); 1408 } 1409 bool WithNowait = D.getSingleClause<OMPNowaitClause>() || 1410 isOpenMPParallelDirective(D.getDirectiveKind()) || 1411 ReductionKind == OMPD_simd; 1412 bool SimpleReduction = ReductionKind == OMPD_simd; 1413 // Emit nowait reduction if nowait clause is present or directive is a 1414 // parallel directive (it always has implicit barrier). 1415 CGM.getOpenMPRuntime().emitReduction( 1416 *this, D.getEndLoc(), Privates, LHSExprs, RHSExprs, ReductionOps, 1417 {WithNowait, SimpleReduction, ReductionKind}); 1418 } 1419 } 1420 1421 static void emitPostUpdateForReductionClause( 1422 CodeGenFunction &CGF, const OMPExecutableDirective &D, 1423 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) { 1424 if (!CGF.HaveInsertPoint()) 1425 return; 1426 llvm::BasicBlock *DoneBB = nullptr; 1427 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) { 1428 if (const Expr *PostUpdate = C->getPostUpdateExpr()) { 1429 if (!DoneBB) { 1430 if (llvm::Value *Cond = CondGen(CGF)) { 1431 // If the first post-update expression is found, emit conditional 1432 // block if it was requested. 1433 llvm::BasicBlock *ThenBB = CGF.createBasicBlock(".omp.reduction.pu"); 1434 DoneBB = CGF.createBasicBlock(".omp.reduction.pu.done"); 1435 CGF.Builder.CreateCondBr(Cond, ThenBB, DoneBB); 1436 CGF.EmitBlock(ThenBB); 1437 } 1438 } 1439 CGF.EmitIgnoredExpr(PostUpdate); 1440 } 1441 } 1442 if (DoneBB) 1443 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 1444 } 1445 1446 namespace { 1447 /// Codegen lambda for appending distribute lower and upper bounds to outlined 1448 /// parallel function. This is necessary for combined constructs such as 1449 /// 'distribute parallel for' 1450 typedef llvm::function_ref<void(CodeGenFunction &, 1451 const OMPExecutableDirective &, 1452 llvm::SmallVectorImpl<llvm::Value *> &)> 1453 CodeGenBoundParametersTy; 1454 } // anonymous namespace 1455 1456 static void 1457 checkForLastprivateConditionalUpdate(CodeGenFunction &CGF, 1458 const OMPExecutableDirective &S) { 1459 if (CGF.getLangOpts().OpenMP < 50) 1460 return; 1461 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls; 1462 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 1463 for (const Expr *Ref : C->varlists()) { 1464 if (!Ref->getType()->isScalarType()) 1465 continue; 1466 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 1467 if (!DRE) 1468 continue; 1469 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl())); 1470 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref); 1471 } 1472 } 1473 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 1474 for (const Expr *Ref : C->varlists()) { 1475 if (!Ref->getType()->isScalarType()) 1476 continue; 1477 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 1478 if (!DRE) 1479 continue; 1480 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl())); 1481 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref); 1482 } 1483 } 1484 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 1485 for (const Expr *Ref : C->varlists()) { 1486 if (!Ref->getType()->isScalarType()) 1487 continue; 1488 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 1489 if (!DRE) 1490 continue; 1491 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl())); 1492 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref); 1493 } 1494 } 1495 // Privates should ne analyzed since they are not captured at all. 1496 // Task reductions may be skipped - tasks are ignored. 1497 // Firstprivates do not return value but may be passed by reference - no need 1498 // to check for updated lastprivate conditional. 1499 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 1500 for (const Expr *Ref : C->varlists()) { 1501 if (!Ref->getType()->isScalarType()) 1502 continue; 1503 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 1504 if (!DRE) 1505 continue; 1506 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl())); 1507 } 1508 } 1509 CGF.CGM.getOpenMPRuntime().checkAndEmitSharedLastprivateConditional( 1510 CGF, S, PrivateDecls); 1511 } 1512 1513 static void emitCommonOMPParallelDirective( 1514 CodeGenFunction &CGF, const OMPExecutableDirective &S, 1515 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1516 const CodeGenBoundParametersTy &CodeGenBoundParameters) { 1517 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel); 1518 llvm::Function *OutlinedFn = 1519 CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction( 1520 S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen); 1521 if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) { 1522 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 1523 llvm::Value *NumThreads = 1524 CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(), 1525 /*IgnoreResultAssign=*/true); 1526 CGF.CGM.getOpenMPRuntime().emitNumThreadsClause( 1527 CGF, NumThreads, NumThreadsClause->getBeginLoc()); 1528 } 1529 if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) { 1530 CodeGenFunction::RunCleanupsScope ProcBindScope(CGF); 1531 CGF.CGM.getOpenMPRuntime().emitProcBindClause( 1532 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc()); 1533 } 1534 const Expr *IfCond = nullptr; 1535 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { 1536 if (C->getNameModifier() == OMPD_unknown || 1537 C->getNameModifier() == OMPD_parallel) { 1538 IfCond = C->getCondition(); 1539 break; 1540 } 1541 } 1542 1543 OMPParallelScope Scope(CGF, S); 1544 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 1545 // Combining 'distribute' with 'for' requires sharing each 'distribute' chunk 1546 // lower and upper bounds with the pragma 'for' chunking mechanism. 1547 // The following lambda takes care of appending the lower and upper bound 1548 // parameters when necessary 1549 CodeGenBoundParameters(CGF, S, CapturedVars); 1550 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars); 1551 CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getBeginLoc(), OutlinedFn, 1552 CapturedVars, IfCond); 1553 } 1554 1555 static void emitEmptyBoundParameters(CodeGenFunction &, 1556 const OMPExecutableDirective &, 1557 llvm::SmallVectorImpl<llvm::Value *> &) {} 1558 1559 void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) { 1560 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) { 1561 // Check if we have any if clause associated with the directive. 1562 llvm::Value *IfCond = nullptr; 1563 if (const auto *C = S.getSingleClause<OMPIfClause>()) 1564 IfCond = EmitScalarExpr(C->getCondition(), 1565 /*IgnoreResultAssign=*/true); 1566 1567 llvm::Value *NumThreads = nullptr; 1568 if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) 1569 NumThreads = EmitScalarExpr(NumThreadsClause->getNumThreads(), 1570 /*IgnoreResultAssign=*/true); 1571 1572 ProcBindKind ProcBind = OMP_PROC_BIND_default; 1573 if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) 1574 ProcBind = ProcBindClause->getProcBindKind(); 1575 1576 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; 1577 1578 // The cleanup callback that finalizes all variabels at the given location, 1579 // thus calls destructors etc. 1580 auto FiniCB = [this](InsertPointTy IP) { 1581 OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP); 1582 }; 1583 1584 // Privatization callback that performs appropriate action for 1585 // shared/private/firstprivate/lastprivate/copyin/... variables. 1586 // 1587 // TODO: This defaults to shared right now. 1588 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 1589 llvm::Value &Val, llvm::Value *&ReplVal) { 1590 // The next line is appropriate only for variables (Val) with the 1591 // data-sharing attribute "shared". 1592 ReplVal = &Val; 1593 1594 return CodeGenIP; 1595 }; 1596 1597 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel); 1598 const Stmt *ParallelRegionBodyStmt = CS->getCapturedStmt(); 1599 1600 auto BodyGenCB = [ParallelRegionBodyStmt, 1601 this](InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 1602 llvm::BasicBlock &ContinuationBB) { 1603 OMPBuilderCBHelpers::OutlinedRegionBodyRAII ORB(*this, AllocaIP, 1604 ContinuationBB); 1605 OMPBuilderCBHelpers::EmitOMPRegionBody(*this, ParallelRegionBodyStmt, 1606 CodeGenIP, ContinuationBB); 1607 }; 1608 1609 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP); 1610 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI); 1611 Builder.restoreIP(OMPBuilder->CreateParallel(Builder, BodyGenCB, PrivCB, 1612 FiniCB, IfCond, NumThreads, 1613 ProcBind, S.hasCancel())); 1614 return; 1615 } 1616 1617 // Emit parallel region as a standalone region. 1618 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 1619 Action.Enter(CGF); 1620 OMPPrivateScope PrivateScope(CGF); 1621 bool Copyins = CGF.EmitOMPCopyinClause(S); 1622 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); 1623 if (Copyins) { 1624 // Emit implicit barrier to synchronize threads and avoid data races on 1625 // propagation master's thread values of threadprivate variables to local 1626 // instances of that variables of all other implicit threads. 1627 CGF.CGM.getOpenMPRuntime().emitBarrierCall( 1628 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false, 1629 /*ForceSimpleCall=*/true); 1630 } 1631 CGF.EmitOMPPrivateClause(S, PrivateScope); 1632 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 1633 (void)PrivateScope.Privatize(); 1634 CGF.EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt()); 1635 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel); 1636 }; 1637 { 1638 auto LPCRegion = 1639 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 1640 emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen, 1641 emitEmptyBoundParameters); 1642 emitPostUpdateForReductionClause(*this, S, 1643 [](CodeGenFunction &) { return nullptr; }); 1644 } 1645 // Check for outer lastprivate conditional update. 1646 checkForLastprivateConditionalUpdate(*this, S); 1647 } 1648 1649 static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop, 1650 int MaxLevel, int Level = 0) { 1651 assert(Level < MaxLevel && "Too deep lookup during loop body codegen."); 1652 const Stmt *SimplifiedS = S->IgnoreContainers(); 1653 if (const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) { 1654 PrettyStackTraceLoc CrashInfo( 1655 CGF.getContext().getSourceManager(), CS->getLBracLoc(), 1656 "LLVM IR generation of compound statement ('{}')"); 1657 1658 // Keep track of the current cleanup stack depth, including debug scopes. 1659 CodeGenFunction::LexicalScope Scope(CGF, S->getSourceRange()); 1660 for (const Stmt *CurStmt : CS->body()) 1661 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level); 1662 return; 1663 } 1664 if (SimplifiedS == NextLoop) { 1665 if (const auto *For = dyn_cast<ForStmt>(SimplifiedS)) { 1666 S = For->getBody(); 1667 } else { 1668 assert(isa<CXXForRangeStmt>(SimplifiedS) && 1669 "Expected canonical for loop or range-based for loop."); 1670 const auto *CXXFor = cast<CXXForRangeStmt>(SimplifiedS); 1671 CGF.EmitStmt(CXXFor->getLoopVarStmt()); 1672 S = CXXFor->getBody(); 1673 } 1674 if (Level + 1 < MaxLevel) { 1675 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop( 1676 S, /*TryImperfectlyNestedLoops=*/true); 1677 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1); 1678 return; 1679 } 1680 } 1681 CGF.EmitStmt(S); 1682 } 1683 1684 void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D, 1685 JumpDest LoopExit) { 1686 RunCleanupsScope BodyScope(*this); 1687 // Update counters values on current iteration. 1688 for (const Expr *UE : D.updates()) 1689 EmitIgnoredExpr(UE); 1690 // Update the linear variables. 1691 // In distribute directives only loop counters may be marked as linear, no 1692 // need to generate the code for them. 1693 if (!isOpenMPDistributeDirective(D.getDirectiveKind())) { 1694 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { 1695 for (const Expr *UE : C->updates()) 1696 EmitIgnoredExpr(UE); 1697 } 1698 } 1699 1700 // On a continue in the body, jump to the end. 1701 JumpDest Continue = getJumpDestInCurrentScope("omp.body.continue"); 1702 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); 1703 for (const Expr *E : D.finals_conditions()) { 1704 if (!E) 1705 continue; 1706 // Check that loop counter in non-rectangular nest fits into the iteration 1707 // space. 1708 llvm::BasicBlock *NextBB = createBasicBlock("omp.body.next"); 1709 EmitBranchOnBoolExpr(E, NextBB, Continue.getBlock(), 1710 getProfileCount(D.getBody())); 1711 EmitBlock(NextBB); 1712 } 1713 1714 OMPPrivateScope InscanScope(*this); 1715 EmitOMPReductionClauseInit(D, InscanScope, /*ForInscan=*/true); 1716 bool IsInscanRegion = InscanScope.Privatize(); 1717 if (IsInscanRegion) { 1718 // Need to remember the block before and after scan directive 1719 // to dispatch them correctly depending on the clause used in 1720 // this directive, inclusive or exclusive. For inclusive scan the natural 1721 // order of the blocks is used, for exclusive clause the blocks must be 1722 // executed in reverse order. 1723 OMPBeforeScanBlock = createBasicBlock("omp.before.scan.bb"); 1724 OMPAfterScanBlock = createBasicBlock("omp.after.scan.bb"); 1725 OMPScanExitBlock = createBasicBlock("omp.exit.inscan.bb"); 1726 OMPScanDispatch = createBasicBlock("omp.inscan.dispatch"); 1727 EmitBranch(OMPScanDispatch); 1728 EmitBlock(OMPBeforeScanBlock); 1729 } 1730 1731 // Emit loop variables for C++ range loops. 1732 const Stmt *Body = 1733 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers(); 1734 // Emit loop body. 1735 emitBody(*this, Body, 1736 OMPLoopDirective::tryToFindNextInnerLoop( 1737 Body, /*TryImperfectlyNestedLoops=*/true), 1738 D.getCollapsedNumber()); 1739 1740 // Jump to the dispatcher at the end of the loop body. 1741 if (IsInscanRegion) 1742 EmitBranch(OMPScanExitBlock); 1743 1744 // The end (updates/cleanups). 1745 EmitBlock(Continue.getBlock()); 1746 BreakContinueStack.pop_back(); 1747 } 1748 1749 void CodeGenFunction::EmitOMPInnerLoop( 1750 const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond, 1751 const Expr *IncExpr, 1752 const llvm::function_ref<void(CodeGenFunction &)> BodyGen, 1753 const llvm::function_ref<void(CodeGenFunction &)> PostIncGen) { 1754 auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end"); 1755 1756 // Start the loop with a block that tests the condition. 1757 auto CondBlock = createBasicBlock("omp.inner.for.cond"); 1758 EmitBlock(CondBlock); 1759 const SourceRange R = S.getSourceRange(); 1760 1761 // If attributes are attached, push to the basic block with them. 1762 const auto &OMPED = cast<OMPExecutableDirective>(S); 1763 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt(); 1764 const Stmt *SS = ICS->getCapturedStmt(); 1765 const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(SS); 1766 if (AS) 1767 LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), 1768 AS->getAttrs(), SourceLocToDebugLoc(R.getBegin()), 1769 SourceLocToDebugLoc(R.getEnd())); 1770 else 1771 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()), 1772 SourceLocToDebugLoc(R.getEnd())); 1773 1774 // If there are any cleanups between here and the loop-exit scope, 1775 // create a block to stage a loop exit along. 1776 llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); 1777 if (RequiresCleanup) 1778 ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup"); 1779 1780 llvm::BasicBlock *LoopBody = createBasicBlock("omp.inner.for.body"); 1781 1782 // Emit condition. 1783 EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S)); 1784 if (ExitBlock != LoopExit.getBlock()) { 1785 EmitBlock(ExitBlock); 1786 EmitBranchThroughCleanup(LoopExit); 1787 } 1788 1789 EmitBlock(LoopBody); 1790 incrementProfileCounter(&S); 1791 1792 // Create a block for the increment. 1793 JumpDest Continue = getJumpDestInCurrentScope("omp.inner.for.inc"); 1794 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); 1795 1796 BodyGen(*this); 1797 1798 // Emit "IV = IV + 1" and a back-edge to the condition block. 1799 EmitBlock(Continue.getBlock()); 1800 EmitIgnoredExpr(IncExpr); 1801 PostIncGen(*this); 1802 BreakContinueStack.pop_back(); 1803 EmitBranch(CondBlock); 1804 LoopStack.pop(); 1805 // Emit the fall-through block. 1806 EmitBlock(LoopExit.getBlock()); 1807 } 1808 1809 bool CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) { 1810 if (!HaveInsertPoint()) 1811 return false; 1812 // Emit inits for the linear variables. 1813 bool HasLinears = false; 1814 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { 1815 for (const Expr *Init : C->inits()) { 1816 HasLinears = true; 1817 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl()); 1818 if (const auto *Ref = 1819 dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) { 1820 AutoVarEmission Emission = EmitAutoVarAlloca(*VD); 1821 const auto *OrigVD = cast<VarDecl>(Ref->getDecl()); 1822 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), 1823 CapturedStmtInfo->lookup(OrigVD) != nullptr, 1824 VD->getInit()->getType(), VK_LValue, 1825 VD->getInit()->getExprLoc()); 1826 EmitExprAsInit(&DRE, VD, MakeAddrLValue(Emission.getAllocatedAddress(), 1827 VD->getType()), 1828 /*capturedByInit=*/false); 1829 EmitAutoVarCleanups(Emission); 1830 } else { 1831 EmitVarDecl(*VD); 1832 } 1833 } 1834 // Emit the linear steps for the linear clauses. 1835 // If a step is not constant, it is pre-calculated before the loop. 1836 if (const auto *CS = cast_or_null<BinaryOperator>(C->getCalcStep())) 1837 if (const auto *SaveRef = cast<DeclRefExpr>(CS->getLHS())) { 1838 EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl())); 1839 // Emit calculation of the linear step. 1840 EmitIgnoredExpr(CS); 1841 } 1842 } 1843 return HasLinears; 1844 } 1845 1846 void CodeGenFunction::EmitOMPLinearClauseFinal( 1847 const OMPLoopDirective &D, 1848 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) { 1849 if (!HaveInsertPoint()) 1850 return; 1851 llvm::BasicBlock *DoneBB = nullptr; 1852 // Emit the final values of the linear variables. 1853 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { 1854 auto IC = C->varlist_begin(); 1855 for (const Expr *F : C->finals()) { 1856 if (!DoneBB) { 1857 if (llvm::Value *Cond = CondGen(*this)) { 1858 // If the first post-update expression is found, emit conditional 1859 // block if it was requested. 1860 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.linear.pu"); 1861 DoneBB = createBasicBlock(".omp.linear.pu.done"); 1862 Builder.CreateCondBr(Cond, ThenBB, DoneBB); 1863 EmitBlock(ThenBB); 1864 } 1865 } 1866 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl()); 1867 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), 1868 CapturedStmtInfo->lookup(OrigVD) != nullptr, 1869 (*IC)->getType(), VK_LValue, (*IC)->getExprLoc()); 1870 Address OrigAddr = EmitLValue(&DRE).getAddress(*this); 1871 CodeGenFunction::OMPPrivateScope VarScope(*this); 1872 VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; }); 1873 (void)VarScope.Privatize(); 1874 EmitIgnoredExpr(F); 1875 ++IC; 1876 } 1877 if (const Expr *PostUpdate = C->getPostUpdateExpr()) 1878 EmitIgnoredExpr(PostUpdate); 1879 } 1880 if (DoneBB) 1881 EmitBlock(DoneBB, /*IsFinished=*/true); 1882 } 1883 1884 static void emitAlignedClause(CodeGenFunction &CGF, 1885 const OMPExecutableDirective &D) { 1886 if (!CGF.HaveInsertPoint()) 1887 return; 1888 for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) { 1889 llvm::APInt ClauseAlignment(64, 0); 1890 if (const Expr *AlignmentExpr = Clause->getAlignment()) { 1891 auto *AlignmentCI = 1892 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr)); 1893 ClauseAlignment = AlignmentCI->getValue(); 1894 } 1895 for (const Expr *E : Clause->varlists()) { 1896 llvm::APInt Alignment(ClauseAlignment); 1897 if (Alignment == 0) { 1898 // OpenMP [2.8.1, Description] 1899 // If no optional parameter is specified, implementation-defined default 1900 // alignments for SIMD instructions on the target platforms are assumed. 1901 Alignment = 1902 CGF.getContext() 1903 .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign( 1904 E->getType()->getPointeeType())) 1905 .getQuantity(); 1906 } 1907 assert((Alignment == 0 || Alignment.isPowerOf2()) && 1908 "alignment is not power of 2"); 1909 if (Alignment != 0) { 1910 llvm::Value *PtrValue = CGF.EmitScalarExpr(E); 1911 CGF.emitAlignmentAssumption( 1912 PtrValue, E, /*No second loc needed*/ SourceLocation(), 1913 llvm::ConstantInt::get(CGF.getLLVMContext(), Alignment)); 1914 } 1915 } 1916 } 1917 } 1918 1919 void CodeGenFunction::EmitOMPPrivateLoopCounters( 1920 const OMPLoopDirective &S, CodeGenFunction::OMPPrivateScope &LoopScope) { 1921 if (!HaveInsertPoint()) 1922 return; 1923 auto I = S.private_counters().begin(); 1924 for (const Expr *E : S.counters()) { 1925 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 1926 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()); 1927 // Emit var without initialization. 1928 AutoVarEmission VarEmission = EmitAutoVarAlloca(*PrivateVD); 1929 EmitAutoVarCleanups(VarEmission); 1930 LocalDeclMap.erase(PrivateVD); 1931 (void)LoopScope.addPrivate(VD, [&VarEmission]() { 1932 return VarEmission.getAllocatedAddress(); 1933 }); 1934 if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) || 1935 VD->hasGlobalStorage()) { 1936 (void)LoopScope.addPrivate(PrivateVD, [this, VD, E]() { 1937 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD), 1938 LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD), 1939 E->getType(), VK_LValue, E->getExprLoc()); 1940 return EmitLValue(&DRE).getAddress(*this); 1941 }); 1942 } else { 1943 (void)LoopScope.addPrivate(PrivateVD, [&VarEmission]() { 1944 return VarEmission.getAllocatedAddress(); 1945 }); 1946 } 1947 ++I; 1948 } 1949 // Privatize extra loop counters used in loops for ordered(n) clauses. 1950 for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) { 1951 if (!C->getNumForLoops()) 1952 continue; 1953 for (unsigned I = S.getCollapsedNumber(), 1954 E = C->getLoopNumIterations().size(); 1955 I < E; ++I) { 1956 const auto *DRE = cast<DeclRefExpr>(C->getLoopCounter(I)); 1957 const auto *VD = cast<VarDecl>(DRE->getDecl()); 1958 // Override only those variables that can be captured to avoid re-emission 1959 // of the variables declared within the loops. 1960 if (DRE->refersToEnclosingVariableOrCapture()) { 1961 (void)LoopScope.addPrivate(VD, [this, DRE, VD]() { 1962 return CreateMemTemp(DRE->getType(), VD->getName()); 1963 }); 1964 } 1965 } 1966 } 1967 } 1968 1969 static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, 1970 const Expr *Cond, llvm::BasicBlock *TrueBlock, 1971 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) { 1972 if (!CGF.HaveInsertPoint()) 1973 return; 1974 { 1975 CodeGenFunction::OMPPrivateScope PreCondScope(CGF); 1976 CGF.EmitOMPPrivateLoopCounters(S, PreCondScope); 1977 (void)PreCondScope.Privatize(); 1978 // Get initial values of real counters. 1979 for (const Expr *I : S.inits()) { 1980 CGF.EmitIgnoredExpr(I); 1981 } 1982 } 1983 // Create temp loop control variables with their init values to support 1984 // non-rectangular loops. 1985 CodeGenFunction::OMPMapVars PreCondVars; 1986 for (const Expr * E: S.dependent_counters()) { 1987 if (!E) 1988 continue; 1989 assert(!E->getType().getNonReferenceType()->isRecordType() && 1990 "dependent counter must not be an iterator."); 1991 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 1992 Address CounterAddr = 1993 CGF.CreateMemTemp(VD->getType().getNonReferenceType()); 1994 (void)PreCondVars.setVarAddr(CGF, VD, CounterAddr); 1995 } 1996 (void)PreCondVars.apply(CGF); 1997 for (const Expr *E : S.dependent_inits()) { 1998 if (!E) 1999 continue; 2000 CGF.EmitIgnoredExpr(E); 2001 } 2002 // Check that loop is executed at least one time. 2003 CGF.EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount); 2004 PreCondVars.restore(CGF); 2005 } 2006 2007 void CodeGenFunction::EmitOMPLinearClause( 2008 const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope) { 2009 if (!HaveInsertPoint()) 2010 return; 2011 llvm::DenseSet<const VarDecl *> SIMDLCVs; 2012 if (isOpenMPSimdDirective(D.getDirectiveKind())) { 2013 const auto *LoopDirective = cast<OMPLoopDirective>(&D); 2014 for (const Expr *C : LoopDirective->counters()) { 2015 SIMDLCVs.insert( 2016 cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl()); 2017 } 2018 } 2019 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) { 2020 auto CurPrivate = C->privates().begin(); 2021 for (const Expr *E : C->varlists()) { 2022 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2023 const auto *PrivateVD = 2024 cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl()); 2025 if (!SIMDLCVs.count(VD->getCanonicalDecl())) { 2026 bool IsRegistered = PrivateScope.addPrivate(VD, [this, PrivateVD]() { 2027 // Emit private VarDecl with copy init. 2028 EmitVarDecl(*PrivateVD); 2029 return GetAddrOfLocalVar(PrivateVD); 2030 }); 2031 assert(IsRegistered && "linear var already registered as private"); 2032 // Silence the warning about unused variable. 2033 (void)IsRegistered; 2034 } else { 2035 EmitVarDecl(*PrivateVD); 2036 } 2037 ++CurPrivate; 2038 } 2039 } 2040 } 2041 2042 static void emitSimdlenSafelenClause(CodeGenFunction &CGF, 2043 const OMPExecutableDirective &D, 2044 bool IsMonotonic) { 2045 if (!CGF.HaveInsertPoint()) 2046 return; 2047 if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) { 2048 RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(), 2049 /*ignoreResult=*/true); 2050 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal()); 2051 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue()); 2052 // In presence of finite 'safelen', it may be unsafe to mark all 2053 // the memory instructions parallel, because loop-carried 2054 // dependences of 'safelen' iterations are possible. 2055 if (!IsMonotonic) 2056 CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>()); 2057 } else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) { 2058 RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(), 2059 /*ignoreResult=*/true); 2060 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal()); 2061 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue()); 2062 // In presence of finite 'safelen', it may be unsafe to mark all 2063 // the memory instructions parallel, because loop-carried 2064 // dependences of 'safelen' iterations are possible. 2065 CGF.LoopStack.setParallel(/*Enable=*/false); 2066 } 2067 } 2068 2069 void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D, 2070 bool IsMonotonic) { 2071 // Walk clauses and process safelen/lastprivate. 2072 LoopStack.setParallel(!IsMonotonic); 2073 LoopStack.setVectorizeEnable(); 2074 emitSimdlenSafelenClause(*this, D, IsMonotonic); 2075 if (const auto *C = D.getSingleClause<OMPOrderClause>()) 2076 if (C->getKind() == OMPC_ORDER_concurrent) 2077 LoopStack.setParallel(/*Enable=*/true); 2078 if ((D.getDirectiveKind() == OMPD_simd || 2079 (getLangOpts().OpenMPSimd && 2080 isOpenMPSimdDirective(D.getDirectiveKind()))) && 2081 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(), 2082 [](const OMPReductionClause *C) { 2083 return C->getModifier() == OMPC_REDUCTION_inscan; 2084 })) 2085 // Disable parallel access in case of prefix sum. 2086 LoopStack.setParallel(/*Enable=*/false); 2087 } 2088 2089 void CodeGenFunction::EmitOMPSimdFinal( 2090 const OMPLoopDirective &D, 2091 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) { 2092 if (!HaveInsertPoint()) 2093 return; 2094 llvm::BasicBlock *DoneBB = nullptr; 2095 auto IC = D.counters().begin(); 2096 auto IPC = D.private_counters().begin(); 2097 for (const Expr *F : D.finals()) { 2098 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl()); 2099 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl()); 2100 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD); 2101 if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD) || 2102 OrigVD->hasGlobalStorage() || CED) { 2103 if (!DoneBB) { 2104 if (llvm::Value *Cond = CondGen(*this)) { 2105 // If the first post-update expression is found, emit conditional 2106 // block if it was requested. 2107 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.final.then"); 2108 DoneBB = createBasicBlock(".omp.final.done"); 2109 Builder.CreateCondBr(Cond, ThenBB, DoneBB); 2110 EmitBlock(ThenBB); 2111 } 2112 } 2113 Address OrigAddr = Address::invalid(); 2114 if (CED) { 2115 OrigAddr = 2116 EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress(*this); 2117 } else { 2118 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(PrivateVD), 2119 /*RefersToEnclosingVariableOrCapture=*/false, 2120 (*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc()); 2121 OrigAddr = EmitLValue(&DRE).getAddress(*this); 2122 } 2123 OMPPrivateScope VarScope(*this); 2124 VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; }); 2125 (void)VarScope.Privatize(); 2126 EmitIgnoredExpr(F); 2127 } 2128 ++IC; 2129 ++IPC; 2130 } 2131 if (DoneBB) 2132 EmitBlock(DoneBB, /*IsFinished=*/true); 2133 } 2134 2135 static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, 2136 const OMPLoopDirective &S, 2137 CodeGenFunction::JumpDest LoopExit) { 2138 CGF.EmitOMPLoopBody(S, LoopExit); 2139 CGF.EmitStopPoint(&S); 2140 } 2141 2142 /// Emit a helper variable and return corresponding lvalue. 2143 static LValue EmitOMPHelperVar(CodeGenFunction &CGF, 2144 const DeclRefExpr *Helper) { 2145 auto VDecl = cast<VarDecl>(Helper->getDecl()); 2146 CGF.EmitVarDecl(*VDecl); 2147 return CGF.EmitLValue(Helper); 2148 } 2149 2150 static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S, 2151 const RegionCodeGenTy &SimdInitGen, 2152 const RegionCodeGenTy &BodyCodeGen) { 2153 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](CodeGenFunction &CGF, 2154 PrePostActionTy &) { 2155 CGOpenMPRuntime::NontemporalDeclsRAII NontemporalsRegion(CGF.CGM, S); 2156 CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF); 2157 SimdInitGen(CGF); 2158 2159 BodyCodeGen(CGF); 2160 }; 2161 auto &&ElseGen = [&BodyCodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 2162 CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF); 2163 CGF.LoopStack.setVectorizeEnable(/*Enable=*/false); 2164 2165 BodyCodeGen(CGF); 2166 }; 2167 const Expr *IfCond = nullptr; 2168 if (isOpenMPSimdDirective(S.getDirectiveKind())) { 2169 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { 2170 if (CGF.getLangOpts().OpenMP >= 50 && 2171 (C->getNameModifier() == OMPD_unknown || 2172 C->getNameModifier() == OMPD_simd)) { 2173 IfCond = C->getCondition(); 2174 break; 2175 } 2176 } 2177 } 2178 if (IfCond) { 2179 CGF.CGM.getOpenMPRuntime().emitIfClause(CGF, IfCond, ThenGen, ElseGen); 2180 } else { 2181 RegionCodeGenTy ThenRCG(ThenGen); 2182 ThenRCG(CGF); 2183 } 2184 } 2185 2186 static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, 2187 PrePostActionTy &Action) { 2188 Action.Enter(CGF); 2189 assert(isOpenMPSimdDirective(S.getDirectiveKind()) && 2190 "Expected simd directive"); 2191 OMPLoopScope PreInitScope(CGF, S); 2192 // if (PreCond) { 2193 // for (IV in 0..LastIteration) BODY; 2194 // <Final counter/linear vars updates>; 2195 // } 2196 // 2197 if (isOpenMPDistributeDirective(S.getDirectiveKind()) || 2198 isOpenMPWorksharingDirective(S.getDirectiveKind()) || 2199 isOpenMPTaskLoopDirective(S.getDirectiveKind())) { 2200 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable())); 2201 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable())); 2202 } 2203 2204 // Emit: if (PreCond) - begin. 2205 // If the condition constant folds and can be elided, avoid emitting the 2206 // whole loop. 2207 bool CondConstant; 2208 llvm::BasicBlock *ContBlock = nullptr; 2209 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { 2210 if (!CondConstant) 2211 return; 2212 } else { 2213 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("simd.if.then"); 2214 ContBlock = CGF.createBasicBlock("simd.if.end"); 2215 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock, 2216 CGF.getProfileCount(&S)); 2217 CGF.EmitBlock(ThenBlock); 2218 CGF.incrementProfileCounter(&S); 2219 } 2220 2221 // Emit the loop iteration variable. 2222 const Expr *IVExpr = S.getIterationVariable(); 2223 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl()); 2224 CGF.EmitVarDecl(*IVDecl); 2225 CGF.EmitIgnoredExpr(S.getInit()); 2226 2227 // Emit the iterations count variable. 2228 // If it is not a variable, Sema decided to calculate iterations count on 2229 // each iteration (e.g., it is foldable into a constant). 2230 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { 2231 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); 2232 // Emit calculation of the iterations count. 2233 CGF.EmitIgnoredExpr(S.getCalcLastIteration()); 2234 } 2235 2236 emitAlignedClause(CGF, S); 2237 (void)CGF.EmitOMPLinearClauseInit(S); 2238 { 2239 CodeGenFunction::OMPPrivateScope LoopScope(CGF); 2240 CGF.EmitOMPPrivateLoopCounters(S, LoopScope); 2241 CGF.EmitOMPLinearClause(S, LoopScope); 2242 CGF.EmitOMPPrivateClause(S, LoopScope); 2243 CGF.EmitOMPReductionClauseInit(S, LoopScope); 2244 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion( 2245 CGF, S, CGF.EmitLValue(S.getIterationVariable())); 2246 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); 2247 (void)LoopScope.Privatize(); 2248 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) 2249 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); 2250 2251 emitCommonSimdLoop( 2252 CGF, S, 2253 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2254 CGF.EmitOMPSimdInit(S); 2255 }, 2256 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) { 2257 CGF.EmitOMPInnerLoop( 2258 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(), 2259 [&S](CodeGenFunction &CGF) { 2260 emitOMPLoopBodyWithStopPoint(CGF, S, 2261 CodeGenFunction::JumpDest()); 2262 }, 2263 [](CodeGenFunction &) {}); 2264 }); 2265 CGF.EmitOMPSimdFinal(S, [](CodeGenFunction &) { return nullptr; }); 2266 // Emit final copy of the lastprivate variables at the end of loops. 2267 if (HasLastprivateClause) 2268 CGF.EmitOMPLastprivateClauseFinal(S, /*NoFinals=*/true); 2269 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_simd); 2270 emitPostUpdateForReductionClause(CGF, S, 2271 [](CodeGenFunction &) { return nullptr; }); 2272 } 2273 CGF.EmitOMPLinearClauseFinal(S, [](CodeGenFunction &) { return nullptr; }); 2274 // Emit: if (PreCond) - end. 2275 if (ContBlock) { 2276 CGF.EmitBranch(ContBlock); 2277 CGF.EmitBlock(ContBlock, true); 2278 } 2279 } 2280 2281 void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) { 2282 ParentLoopDirectiveForScanRegion ScanRegion(*this, S); 2283 OMPFirstScanLoop = true; 2284 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 2285 emitOMPSimdRegion(CGF, S, Action); 2286 }; 2287 { 2288 auto LPCRegion = 2289 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 2290 OMPLexicalScope Scope(*this, S, OMPD_unknown); 2291 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen); 2292 } 2293 // Check for outer lastprivate conditional update. 2294 checkForLastprivateConditionalUpdate(*this, S); 2295 } 2296 2297 void CodeGenFunction::EmitOMPOuterLoop( 2298 bool DynamicOrOrdered, bool IsMonotonic, const OMPLoopDirective &S, 2299 CodeGenFunction::OMPPrivateScope &LoopScope, 2300 const CodeGenFunction::OMPLoopArguments &LoopArgs, 2301 const CodeGenFunction::CodeGenLoopTy &CodeGenLoop, 2302 const CodeGenFunction::CodeGenOrderedTy &CodeGenOrdered) { 2303 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime(); 2304 2305 const Expr *IVExpr = S.getIterationVariable(); 2306 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); 2307 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); 2308 2309 JumpDest LoopExit = getJumpDestInCurrentScope("omp.dispatch.end"); 2310 2311 // Start the loop with a block that tests the condition. 2312 llvm::BasicBlock *CondBlock = createBasicBlock("omp.dispatch.cond"); 2313 EmitBlock(CondBlock); 2314 const SourceRange R = S.getSourceRange(); 2315 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()), 2316 SourceLocToDebugLoc(R.getEnd())); 2317 2318 llvm::Value *BoolCondVal = nullptr; 2319 if (!DynamicOrOrdered) { 2320 // UB = min(UB, GlobalUB) or 2321 // UB = min(UB, PrevUB) for combined loop sharing constructs (e.g. 2322 // 'distribute parallel for') 2323 EmitIgnoredExpr(LoopArgs.EUB); 2324 // IV = LB 2325 EmitIgnoredExpr(LoopArgs.Init); 2326 // IV < UB 2327 BoolCondVal = EvaluateExprAsBool(LoopArgs.Cond); 2328 } else { 2329 BoolCondVal = 2330 RT.emitForNext(*this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL, 2331 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST); 2332 } 2333 2334 // If there are any cleanups between here and the loop-exit scope, 2335 // create a block to stage a loop exit along. 2336 llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); 2337 if (LoopScope.requiresCleanups()) 2338 ExitBlock = createBasicBlock("omp.dispatch.cleanup"); 2339 2340 llvm::BasicBlock *LoopBody = createBasicBlock("omp.dispatch.body"); 2341 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock); 2342 if (ExitBlock != LoopExit.getBlock()) { 2343 EmitBlock(ExitBlock); 2344 EmitBranchThroughCleanup(LoopExit); 2345 } 2346 EmitBlock(LoopBody); 2347 2348 // Emit "IV = LB" (in case of static schedule, we have already calculated new 2349 // LB for loop condition and emitted it above). 2350 if (DynamicOrOrdered) 2351 EmitIgnoredExpr(LoopArgs.Init); 2352 2353 // Create a block for the increment. 2354 JumpDest Continue = getJumpDestInCurrentScope("omp.dispatch.inc"); 2355 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); 2356 2357 emitCommonSimdLoop( 2358 *this, S, 2359 [&S, IsMonotonic](CodeGenFunction &CGF, PrePostActionTy &) { 2360 // Generate !llvm.loop.parallel metadata for loads and stores for loops 2361 // with dynamic/guided scheduling and without ordered clause. 2362 if (!isOpenMPSimdDirective(S.getDirectiveKind())) { 2363 CGF.LoopStack.setParallel(!IsMonotonic); 2364 if (const auto *C = S.getSingleClause<OMPOrderClause>()) 2365 if (C->getKind() == OMPC_ORDER_concurrent) 2366 CGF.LoopStack.setParallel(/*Enable=*/true); 2367 } else { 2368 CGF.EmitOMPSimdInit(S, IsMonotonic); 2369 } 2370 }, 2371 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered, 2372 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) { 2373 SourceLocation Loc = S.getBeginLoc(); 2374 // when 'distribute' is not combined with a 'for': 2375 // while (idx <= UB) { BODY; ++idx; } 2376 // when 'distribute' is combined with a 'for' 2377 // (e.g. 'distribute parallel for') 2378 // while (idx <= UB) { <CodeGen rest of pragma>; idx += ST; } 2379 CGF.EmitOMPInnerLoop( 2380 S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr, 2381 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) { 2382 CodeGenLoop(CGF, S, LoopExit); 2383 }, 2384 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) { 2385 CodeGenOrdered(CGF, Loc, IVSize, IVSigned); 2386 }); 2387 }); 2388 2389 EmitBlock(Continue.getBlock()); 2390 BreakContinueStack.pop_back(); 2391 if (!DynamicOrOrdered) { 2392 // Emit "LB = LB + Stride", "UB = UB + Stride". 2393 EmitIgnoredExpr(LoopArgs.NextLB); 2394 EmitIgnoredExpr(LoopArgs.NextUB); 2395 } 2396 2397 EmitBranch(CondBlock); 2398 LoopStack.pop(); 2399 // Emit the fall-through block. 2400 EmitBlock(LoopExit.getBlock()); 2401 2402 // Tell the runtime we are done. 2403 auto &&CodeGen = [DynamicOrOrdered, &S](CodeGenFunction &CGF) { 2404 if (!DynamicOrOrdered) 2405 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(), 2406 S.getDirectiveKind()); 2407 }; 2408 OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen); 2409 } 2410 2411 void CodeGenFunction::EmitOMPForOuterLoop( 2412 const OpenMPScheduleTy &ScheduleKind, bool IsMonotonic, 2413 const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered, 2414 const OMPLoopArguments &LoopArgs, 2415 const CodeGenDispatchBoundsTy &CGDispatchBounds) { 2416 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime(); 2417 2418 // Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime). 2419 const bool DynamicOrOrdered = 2420 Ordered || RT.isDynamic(ScheduleKind.Schedule); 2421 2422 assert((Ordered || 2423 !RT.isStaticNonchunked(ScheduleKind.Schedule, 2424 LoopArgs.Chunk != nullptr)) && 2425 "static non-chunked schedule does not need outer loop"); 2426 2427 // Emit outer loop. 2428 // 2429 // OpenMP [2.7.1, Loop Construct, Description, table 2-1] 2430 // When schedule(dynamic,chunk_size) is specified, the iterations are 2431 // distributed to threads in the team in chunks as the threads request them. 2432 // Each thread executes a chunk of iterations, then requests another chunk, 2433 // until no chunks remain to be distributed. Each chunk contains chunk_size 2434 // iterations, except for the last chunk to be distributed, which may have 2435 // fewer iterations. When no chunk_size is specified, it defaults to 1. 2436 // 2437 // When schedule(guided,chunk_size) is specified, the iterations are assigned 2438 // to threads in the team in chunks as the executing threads request them. 2439 // Each thread executes a chunk of iterations, then requests another chunk, 2440 // until no chunks remain to be assigned. For a chunk_size of 1, the size of 2441 // each chunk is proportional to the number of unassigned iterations divided 2442 // by the number of threads in the team, decreasing to 1. For a chunk_size 2443 // with value k (greater than 1), the size of each chunk is determined in the 2444 // same way, with the restriction that the chunks do not contain fewer than k 2445 // iterations (except for the last chunk to be assigned, which may have fewer 2446 // than k iterations). 2447 // 2448 // When schedule(auto) is specified, the decision regarding scheduling is 2449 // delegated to the compiler and/or runtime system. The programmer gives the 2450 // implementation the freedom to choose any possible mapping of iterations to 2451 // threads in the team. 2452 // 2453 // When schedule(runtime) is specified, the decision regarding scheduling is 2454 // deferred until run time, and the schedule and chunk size are taken from the 2455 // run-sched-var ICV. If the ICV is set to auto, the schedule is 2456 // implementation defined 2457 // 2458 // while(__kmpc_dispatch_next(&LB, &UB)) { 2459 // idx = LB; 2460 // while (idx <= UB) { BODY; ++idx; 2461 // __kmpc_dispatch_fini_(4|8)[u](); // For ordered loops only. 2462 // } // inner loop 2463 // } 2464 // 2465 // OpenMP [2.7.1, Loop Construct, Description, table 2-1] 2466 // When schedule(static, chunk_size) is specified, iterations are divided into 2467 // chunks of size chunk_size, and the chunks are assigned to the threads in 2468 // the team in a round-robin fashion in the order of the thread number. 2469 // 2470 // while(UB = min(UB, GlobalUB), idx = LB, idx < UB) { 2471 // while (idx <= UB) { BODY; ++idx; } // inner loop 2472 // LB = LB + ST; 2473 // UB = UB + ST; 2474 // } 2475 // 2476 2477 const Expr *IVExpr = S.getIterationVariable(); 2478 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); 2479 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); 2480 2481 if (DynamicOrOrdered) { 2482 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds = 2483 CGDispatchBounds(*this, S, LoopArgs.LB, LoopArgs.UB); 2484 llvm::Value *LBVal = DispatchBounds.first; 2485 llvm::Value *UBVal = DispatchBounds.second; 2486 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal, 2487 LoopArgs.Chunk}; 2488 RT.emitForDispatchInit(*this, S.getBeginLoc(), ScheduleKind, IVSize, 2489 IVSigned, Ordered, DipatchRTInputValues); 2490 } else { 2491 CGOpenMPRuntime::StaticRTInput StaticInit( 2492 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB, 2493 LoopArgs.ST, LoopArgs.Chunk); 2494 RT.emitForStaticInit(*this, S.getBeginLoc(), S.getDirectiveKind(), 2495 ScheduleKind, StaticInit); 2496 } 2497 2498 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc, 2499 const unsigned IVSize, 2500 const bool IVSigned) { 2501 if (Ordered) { 2502 CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd(CGF, Loc, IVSize, 2503 IVSigned); 2504 } 2505 }; 2506 2507 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST, 2508 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB); 2509 OuterLoopArgs.IncExpr = S.getInc(); 2510 OuterLoopArgs.Init = S.getInit(); 2511 OuterLoopArgs.Cond = S.getCond(); 2512 OuterLoopArgs.NextLB = S.getNextLowerBound(); 2513 OuterLoopArgs.NextUB = S.getNextUpperBound(); 2514 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs, 2515 emitOMPLoopBodyWithStopPoint, CodeGenOrdered); 2516 } 2517 2518 static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, 2519 const unsigned IVSize, const bool IVSigned) {} 2520 2521 void CodeGenFunction::EmitOMPDistributeOuterLoop( 2522 OpenMPDistScheduleClauseKind ScheduleKind, const OMPLoopDirective &S, 2523 OMPPrivateScope &LoopScope, const OMPLoopArguments &LoopArgs, 2524 const CodeGenLoopTy &CodeGenLoopContent) { 2525 2526 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime(); 2527 2528 // Emit outer loop. 2529 // Same behavior as a OMPForOuterLoop, except that schedule cannot be 2530 // dynamic 2531 // 2532 2533 const Expr *IVExpr = S.getIterationVariable(); 2534 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); 2535 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); 2536 2537 CGOpenMPRuntime::StaticRTInput StaticInit( 2538 IVSize, IVSigned, /* Ordered = */ false, LoopArgs.IL, LoopArgs.LB, 2539 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk); 2540 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind, StaticInit); 2541 2542 // for combined 'distribute' and 'for' the increment expression of distribute 2543 // is stored in DistInc. For 'distribute' alone, it is in Inc. 2544 Expr *IncExpr; 2545 if (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())) 2546 IncExpr = S.getDistInc(); 2547 else 2548 IncExpr = S.getInc(); 2549 2550 // this routine is shared by 'omp distribute parallel for' and 2551 // 'omp distribute': select the right EUB expression depending on the 2552 // directive 2553 OMPLoopArguments OuterLoopArgs; 2554 OuterLoopArgs.LB = LoopArgs.LB; 2555 OuterLoopArgs.UB = LoopArgs.UB; 2556 OuterLoopArgs.ST = LoopArgs.ST; 2557 OuterLoopArgs.IL = LoopArgs.IL; 2558 OuterLoopArgs.Chunk = LoopArgs.Chunk; 2559 OuterLoopArgs.EUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 2560 ? S.getCombinedEnsureUpperBound() 2561 : S.getEnsureUpperBound(); 2562 OuterLoopArgs.IncExpr = IncExpr; 2563 OuterLoopArgs.Init = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 2564 ? S.getCombinedInit() 2565 : S.getInit(); 2566 OuterLoopArgs.Cond = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 2567 ? S.getCombinedCond() 2568 : S.getCond(); 2569 OuterLoopArgs.NextLB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 2570 ? S.getCombinedNextLowerBound() 2571 : S.getNextLowerBound(); 2572 OuterLoopArgs.NextUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 2573 ? S.getCombinedNextUpperBound() 2574 : S.getNextUpperBound(); 2575 2576 EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false, S, 2577 LoopScope, OuterLoopArgs, CodeGenLoopContent, 2578 emitEmptyOrdered); 2579 } 2580 2581 static std::pair<LValue, LValue> 2582 emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, 2583 const OMPExecutableDirective &S) { 2584 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S); 2585 LValue LB = 2586 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable())); 2587 LValue UB = 2588 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable())); 2589 2590 // When composing 'distribute' with 'for' (e.g. as in 'distribute 2591 // parallel for') we need to use the 'distribute' 2592 // chunk lower and upper bounds rather than the whole loop iteration 2593 // space. These are parameters to the outlined function for 'parallel' 2594 // and we copy the bounds of the previous schedule into the 2595 // the current ones. 2596 LValue PrevLB = CGF.EmitLValue(LS.getPrevLowerBoundVariable()); 2597 LValue PrevUB = CGF.EmitLValue(LS.getPrevUpperBoundVariable()); 2598 llvm::Value *PrevLBVal = CGF.EmitLoadOfScalar( 2599 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc()); 2600 PrevLBVal = CGF.EmitScalarConversion( 2601 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(), 2602 LS.getIterationVariable()->getType(), 2603 LS.getPrevLowerBoundVariable()->getExprLoc()); 2604 llvm::Value *PrevUBVal = CGF.EmitLoadOfScalar( 2605 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc()); 2606 PrevUBVal = CGF.EmitScalarConversion( 2607 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(), 2608 LS.getIterationVariable()->getType(), 2609 LS.getPrevUpperBoundVariable()->getExprLoc()); 2610 2611 CGF.EmitStoreOfScalar(PrevLBVal, LB); 2612 CGF.EmitStoreOfScalar(PrevUBVal, UB); 2613 2614 return {LB, UB}; 2615 } 2616 2617 /// if the 'for' loop has a dispatch schedule (e.g. dynamic, guided) then 2618 /// we need to use the LB and UB expressions generated by the worksharing 2619 /// code generation support, whereas in non combined situations we would 2620 /// just emit 0 and the LastIteration expression 2621 /// This function is necessary due to the difference of the LB and UB 2622 /// types for the RT emission routines for 'for_static_init' and 2623 /// 'for_dispatch_init' 2624 static std::pair<llvm::Value *, llvm::Value *> 2625 emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF, 2626 const OMPExecutableDirective &S, 2627 Address LB, Address UB) { 2628 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S); 2629 const Expr *IVExpr = LS.getIterationVariable(); 2630 // when implementing a dynamic schedule for a 'for' combined with a 2631 // 'distribute' (e.g. 'distribute parallel for'), the 'for' loop 2632 // is not normalized as each team only executes its own assigned 2633 // distribute chunk 2634 QualType IteratorTy = IVExpr->getType(); 2635 llvm::Value *LBVal = 2636 CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy, S.getBeginLoc()); 2637 llvm::Value *UBVal = 2638 CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy, S.getBeginLoc()); 2639 return {LBVal, UBVal}; 2640 } 2641 2642 static void emitDistributeParallelForDistributeInnerBoundParams( 2643 CodeGenFunction &CGF, const OMPExecutableDirective &S, 2644 llvm::SmallVectorImpl<llvm::Value *> &CapturedVars) { 2645 const auto &Dir = cast<OMPLoopDirective>(S); 2646 LValue LB = 2647 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable())); 2648 llvm::Value *LBCast = 2649 CGF.Builder.CreateIntCast(CGF.Builder.CreateLoad(LB.getAddress(CGF)), 2650 CGF.SizeTy, /*isSigned=*/false); 2651 CapturedVars.push_back(LBCast); 2652 LValue UB = 2653 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable())); 2654 2655 llvm::Value *UBCast = 2656 CGF.Builder.CreateIntCast(CGF.Builder.CreateLoad(UB.getAddress(CGF)), 2657 CGF.SizeTy, /*isSigned=*/false); 2658 CapturedVars.push_back(UBCast); 2659 } 2660 2661 static void 2662 emitInnerParallelForWhenCombined(CodeGenFunction &CGF, 2663 const OMPLoopDirective &S, 2664 CodeGenFunction::JumpDest LoopExit) { 2665 auto &&CGInlinedWorksharingLoop = [&S](CodeGenFunction &CGF, 2666 PrePostActionTy &Action) { 2667 Action.Enter(CGF); 2668 bool HasCancel = false; 2669 if (!isOpenMPSimdDirective(S.getDirectiveKind())) { 2670 if (const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S)) 2671 HasCancel = D->hasCancel(); 2672 else if (const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S)) 2673 HasCancel = D->hasCancel(); 2674 else if (const auto *D = 2675 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S)) 2676 HasCancel = D->hasCancel(); 2677 } 2678 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, S.getDirectiveKind(), 2679 HasCancel); 2680 CGF.EmitOMPWorksharingLoop(S, S.getPrevEnsureUpperBound(), 2681 emitDistributeParallelForInnerBounds, 2682 emitDistributeParallelForDispatchBounds); 2683 }; 2684 2685 emitCommonOMPParallelDirective( 2686 CGF, S, 2687 isOpenMPSimdDirective(S.getDirectiveKind()) ? OMPD_for_simd : OMPD_for, 2688 CGInlinedWorksharingLoop, 2689 emitDistributeParallelForDistributeInnerBoundParams); 2690 } 2691 2692 void CodeGenFunction::EmitOMPDistributeParallelForDirective( 2693 const OMPDistributeParallelForDirective &S) { 2694 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2695 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, 2696 S.getDistInc()); 2697 }; 2698 OMPLexicalScope Scope(*this, S, OMPD_parallel); 2699 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen); 2700 } 2701 2702 void CodeGenFunction::EmitOMPDistributeParallelForSimdDirective( 2703 const OMPDistributeParallelForSimdDirective &S) { 2704 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2705 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, 2706 S.getDistInc()); 2707 }; 2708 OMPLexicalScope Scope(*this, S, OMPD_parallel); 2709 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen); 2710 } 2711 2712 void CodeGenFunction::EmitOMPDistributeSimdDirective( 2713 const OMPDistributeSimdDirective &S) { 2714 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2715 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); 2716 }; 2717 OMPLexicalScope Scope(*this, S, OMPD_unknown); 2718 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen); 2719 } 2720 2721 void CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 2722 CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S) { 2723 // Emit SPMD target parallel for region as a standalone region. 2724 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 2725 emitOMPSimdRegion(CGF, S, Action); 2726 }; 2727 llvm::Function *Fn; 2728 llvm::Constant *Addr; 2729 // Emit target region as a standalone region. 2730 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 2731 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 2732 assert(Fn && Addr && "Target device function emission failed."); 2733 } 2734 2735 void CodeGenFunction::EmitOMPTargetSimdDirective( 2736 const OMPTargetSimdDirective &S) { 2737 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 2738 emitOMPSimdRegion(CGF, S, Action); 2739 }; 2740 emitCommonOMPTargetDirective(*this, S, CodeGen); 2741 } 2742 2743 namespace { 2744 struct ScheduleKindModifiersTy { 2745 OpenMPScheduleClauseKind Kind; 2746 OpenMPScheduleClauseModifier M1; 2747 OpenMPScheduleClauseModifier M2; 2748 ScheduleKindModifiersTy(OpenMPScheduleClauseKind Kind, 2749 OpenMPScheduleClauseModifier M1, 2750 OpenMPScheduleClauseModifier M2) 2751 : Kind(Kind), M1(M1), M2(M2) {} 2752 }; 2753 } // namespace 2754 2755 bool CodeGenFunction::EmitOMPWorksharingLoop( 2756 const OMPLoopDirective &S, Expr *EUB, 2757 const CodeGenLoopBoundsTy &CodeGenLoopBounds, 2758 const CodeGenDispatchBoundsTy &CGDispatchBounds) { 2759 // Emit the loop iteration variable. 2760 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable()); 2761 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl()); 2762 EmitVarDecl(*IVDecl); 2763 2764 // Emit the iterations count variable. 2765 // If it is not a variable, Sema decided to calculate iterations count on each 2766 // iteration (e.g., it is foldable into a constant). 2767 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { 2768 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); 2769 // Emit calculation of the iterations count. 2770 EmitIgnoredExpr(S.getCalcLastIteration()); 2771 } 2772 2773 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime(); 2774 2775 bool HasLastprivateClause; 2776 // Check pre-condition. 2777 { 2778 OMPLoopScope PreInitScope(*this, S); 2779 // Skip the entire loop if we don't meet the precondition. 2780 // If the condition constant folds and can be elided, avoid emitting the 2781 // whole loop. 2782 bool CondConstant; 2783 llvm::BasicBlock *ContBlock = nullptr; 2784 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { 2785 if (!CondConstant) 2786 return false; 2787 } else { 2788 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then"); 2789 ContBlock = createBasicBlock("omp.precond.end"); 2790 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock, 2791 getProfileCount(&S)); 2792 EmitBlock(ThenBlock); 2793 incrementProfileCounter(&S); 2794 } 2795 2796 RunCleanupsScope DoacrossCleanupScope(*this); 2797 bool Ordered = false; 2798 if (const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) { 2799 if (OrderedClause->getNumForLoops()) 2800 RT.emitDoacrossInit(*this, S, OrderedClause->getLoopNumIterations()); 2801 else 2802 Ordered = true; 2803 } 2804 2805 llvm::DenseSet<const Expr *> EmittedFinals; 2806 emitAlignedClause(*this, S); 2807 bool HasLinears = EmitOMPLinearClauseInit(S); 2808 // Emit helper vars inits. 2809 2810 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*this, S); 2811 LValue LB = Bounds.first; 2812 LValue UB = Bounds.second; 2813 LValue ST = 2814 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable())); 2815 LValue IL = 2816 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable())); 2817 2818 // Emit 'then' code. 2819 { 2820 OMPPrivateScope LoopScope(*this); 2821 if (EmitOMPFirstprivateClause(S, LoopScope) || HasLinears) { 2822 // Emit implicit barrier to synchronize threads and avoid data races on 2823 // initialization of firstprivate variables and post-update of 2824 // lastprivate variables. 2825 CGM.getOpenMPRuntime().emitBarrierCall( 2826 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false, 2827 /*ForceSimpleCall=*/true); 2828 } 2829 EmitOMPPrivateClause(S, LoopScope); 2830 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion( 2831 *this, S, EmitLValue(S.getIterationVariable())); 2832 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope); 2833 EmitOMPReductionClauseInit(S, LoopScope); 2834 EmitOMPPrivateLoopCounters(S, LoopScope); 2835 EmitOMPLinearClause(S, LoopScope); 2836 (void)LoopScope.Privatize(); 2837 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) 2838 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S); 2839 2840 // Detect the loop schedule kind and chunk. 2841 const Expr *ChunkExpr = nullptr; 2842 OpenMPScheduleTy ScheduleKind; 2843 if (const auto *C = S.getSingleClause<OMPScheduleClause>()) { 2844 ScheduleKind.Schedule = C->getScheduleKind(); 2845 ScheduleKind.M1 = C->getFirstScheduleModifier(); 2846 ScheduleKind.M2 = C->getSecondScheduleModifier(); 2847 ChunkExpr = C->getChunkSize(); 2848 } else { 2849 // Default behaviour for schedule clause. 2850 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk( 2851 *this, S, ScheduleKind.Schedule, ChunkExpr); 2852 } 2853 bool HasChunkSizeOne = false; 2854 llvm::Value *Chunk = nullptr; 2855 if (ChunkExpr) { 2856 Chunk = EmitScalarExpr(ChunkExpr); 2857 Chunk = EmitScalarConversion(Chunk, ChunkExpr->getType(), 2858 S.getIterationVariable()->getType(), 2859 S.getBeginLoc()); 2860 Expr::EvalResult Result; 2861 if (ChunkExpr->EvaluateAsInt(Result, getContext())) { 2862 llvm::APSInt EvaluatedChunk = Result.Val.getInt(); 2863 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1); 2864 } 2865 } 2866 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); 2867 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); 2868 // OpenMP 4.5, 2.7.1 Loop Construct, Description. 2869 // If the static schedule kind is specified or if the ordered clause is 2870 // specified, and if no monotonic modifier is specified, the effect will 2871 // be as if the monotonic modifier was specified. 2872 bool StaticChunkedOne = RT.isStaticChunked(ScheduleKind.Schedule, 2873 /* Chunked */ Chunk != nullptr) && HasChunkSizeOne && 2874 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()); 2875 if ((RT.isStaticNonchunked(ScheduleKind.Schedule, 2876 /* Chunked */ Chunk != nullptr) || 2877 StaticChunkedOne) && 2878 !Ordered) { 2879 JumpDest LoopExit = 2880 getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit")); 2881 emitCommonSimdLoop( 2882 *this, S, 2883 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 2884 if (isOpenMPSimdDirective(S.getDirectiveKind())) { 2885 CGF.EmitOMPSimdInit(S, /*IsMonotonic=*/true); 2886 } else if (const auto *C = S.getSingleClause<OMPOrderClause>()) { 2887 if (C->getKind() == OMPC_ORDER_concurrent) 2888 CGF.LoopStack.setParallel(/*Enable=*/true); 2889 } 2890 }, 2891 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk, 2892 &S, ScheduleKind, LoopExit, 2893 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) { 2894 // OpenMP [2.7.1, Loop Construct, Description, table 2-1] 2895 // When no chunk_size is specified, the iteration space is divided 2896 // into chunks that are approximately equal in size, and at most 2897 // one chunk is distributed to each thread. Note that the size of 2898 // the chunks is unspecified in this case. 2899 CGOpenMPRuntime::StaticRTInput StaticInit( 2900 IVSize, IVSigned, Ordered, IL.getAddress(CGF), 2901 LB.getAddress(CGF), UB.getAddress(CGF), ST.getAddress(CGF), 2902 StaticChunkedOne ? Chunk : nullptr); 2903 CGF.CGM.getOpenMPRuntime().emitForStaticInit( 2904 CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind, 2905 StaticInit); 2906 // UB = min(UB, GlobalUB); 2907 if (!StaticChunkedOne) 2908 CGF.EmitIgnoredExpr(S.getEnsureUpperBound()); 2909 // IV = LB; 2910 CGF.EmitIgnoredExpr(S.getInit()); 2911 // For unchunked static schedule generate: 2912 // 2913 // while (idx <= UB) { 2914 // BODY; 2915 // ++idx; 2916 // } 2917 // 2918 // For static schedule with chunk one: 2919 // 2920 // while (IV <= PrevUB) { 2921 // BODY; 2922 // IV += ST; 2923 // } 2924 CGF.EmitOMPInnerLoop( 2925 S, LoopScope.requiresCleanups(), 2926 StaticChunkedOne ? S.getCombinedParForInDistCond() 2927 : S.getCond(), 2928 StaticChunkedOne ? S.getDistInc() : S.getInc(), 2929 [&S, LoopExit](CodeGenFunction &CGF) { 2930 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit); 2931 }, 2932 [](CodeGenFunction &) {}); 2933 }); 2934 EmitBlock(LoopExit.getBlock()); 2935 // Tell the runtime we are done. 2936 auto &&CodeGen = [&S](CodeGenFunction &CGF) { 2937 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(), 2938 S.getDirectiveKind()); 2939 }; 2940 OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen); 2941 } else { 2942 const bool IsMonotonic = 2943 Ordered || ScheduleKind.Schedule == OMPC_SCHEDULE_static || 2944 ScheduleKind.Schedule == OMPC_SCHEDULE_unknown || 2945 ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic || 2946 ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_monotonic; 2947 // Emit the outer loop, which requests its work chunk [LB..UB] from 2948 // runtime and runs the inner loop to process it. 2949 const OMPLoopArguments LoopArguments( 2950 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this), 2951 IL.getAddress(*this), Chunk, EUB); 2952 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered, 2953 LoopArguments, CGDispatchBounds); 2954 } 2955 if (isOpenMPSimdDirective(S.getDirectiveKind())) { 2956 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) { 2957 return CGF.Builder.CreateIsNotNull( 2958 CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); 2959 }); 2960 } 2961 EmitOMPReductionClauseFinal( 2962 S, /*ReductionKind=*/isOpenMPSimdDirective(S.getDirectiveKind()) 2963 ? /*Parallel and Simd*/ OMPD_parallel_for_simd 2964 : /*Parallel only*/ OMPD_parallel); 2965 // Emit post-update of the reduction variables if IsLastIter != 0. 2966 emitPostUpdateForReductionClause( 2967 *this, S, [IL, &S](CodeGenFunction &CGF) { 2968 return CGF.Builder.CreateIsNotNull( 2969 CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); 2970 }); 2971 // Emit final copy of the lastprivate variables if IsLastIter != 0. 2972 if (HasLastprivateClause) 2973 EmitOMPLastprivateClauseFinal( 2974 S, isOpenMPSimdDirective(S.getDirectiveKind()), 2975 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc()))); 2976 } 2977 EmitOMPLinearClauseFinal(S, [IL, &S](CodeGenFunction &CGF) { 2978 return CGF.Builder.CreateIsNotNull( 2979 CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); 2980 }); 2981 DoacrossCleanupScope.ForceCleanup(); 2982 // We're now done with the loop, so jump to the continuation block. 2983 if (ContBlock) { 2984 EmitBranch(ContBlock); 2985 EmitBlock(ContBlock, /*IsFinished=*/true); 2986 } 2987 } 2988 return HasLastprivateClause; 2989 } 2990 2991 /// The following two functions generate expressions for the loop lower 2992 /// and upper bounds in case of static and dynamic (dispatch) schedule 2993 /// of the associated 'for' or 'distribute' loop. 2994 static std::pair<LValue, LValue> 2995 emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S) { 2996 const auto &LS = cast<OMPLoopDirective>(S); 2997 LValue LB = 2998 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable())); 2999 LValue UB = 3000 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable())); 3001 return {LB, UB}; 3002 } 3003 3004 /// When dealing with dispatch schedules (e.g. dynamic, guided) we do not 3005 /// consider the lower and upper bound expressions generated by the 3006 /// worksharing loop support, but we use 0 and the iteration space size as 3007 /// constants 3008 static std::pair<llvm::Value *, llvm::Value *> 3009 emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, 3010 Address LB, Address UB) { 3011 const auto &LS = cast<OMPLoopDirective>(S); 3012 const Expr *IVExpr = LS.getIterationVariable(); 3013 const unsigned IVSize = CGF.getContext().getTypeSize(IVExpr->getType()); 3014 llvm::Value *LBVal = CGF.Builder.getIntN(IVSize, 0); 3015 llvm::Value *UBVal = CGF.EmitScalarExpr(LS.getLastIteration()); 3016 return {LBVal, UBVal}; 3017 } 3018 3019 /// Emits the code for the directive with inscan reductions. 3020 /// The code is the following: 3021 /// \code 3022 /// size num_iters = <num_iters>; 3023 /// <type> buffer[num_iters]; 3024 /// #pragma omp ... 3025 /// for (i: 0..<num_iters>) { 3026 /// <input phase>; 3027 /// buffer[i] = red; 3028 /// } 3029 /// for (int k = 0; k != ceil(log2(num_iters)); ++k) 3030 /// for (size cnt = last_iter; cnt >= pow(2, k); --k) 3031 /// buffer[i] op= buffer[i-pow(2,k)]; 3032 /// #pragma omp ... 3033 /// for (0..<num_iters>) { 3034 /// red = InclusiveScan ? buffer[i] : buffer[i-1]; 3035 /// <scan phase>; 3036 /// } 3037 /// \endcode 3038 static void emitScanBasedDirective( 3039 CodeGenFunction &CGF, const OMPLoopDirective &S, 3040 llvm::function_ref<llvm::Value *(CodeGenFunction &)> NumIteratorsGen, 3041 llvm::function_ref<void(CodeGenFunction &)> FirstGen, 3042 llvm::function_ref<void(CodeGenFunction &)> SecondGen) { 3043 llvm::Value *OMPScanNumIterations = CGF.Builder.CreateIntCast( 3044 NumIteratorsGen(CGF), CGF.SizeTy, /*isSigned=*/false); 3045 SmallVector<const Expr *, 4> Shareds; 3046 SmallVector<const Expr *, 4> Privates; 3047 SmallVector<const Expr *, 4> ReductionOps; 3048 SmallVector<const Expr *, 4> LHSs; 3049 SmallVector<const Expr *, 4> RHSs; 3050 SmallVector<const Expr *, 4> CopyOps; 3051 SmallVector<const Expr *, 4> CopyArrayTemps; 3052 SmallVector<const Expr *, 4> CopyArrayElems; 3053 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 3054 assert(C->getModifier() == OMPC_REDUCTION_inscan && 3055 "Only inscan reductions are expected."); 3056 Shareds.append(C->varlist_begin(), C->varlist_end()); 3057 Privates.append(C->privates().begin(), C->privates().end()); 3058 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end()); 3059 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end()); 3060 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end()); 3061 CopyOps.append(C->copy_ops().begin(), C->copy_ops().end()); 3062 CopyArrayTemps.append(C->copy_array_temps().begin(), 3063 C->copy_array_temps().end()); 3064 CopyArrayElems.append(C->copy_array_elems().begin(), 3065 C->copy_array_elems().end()); 3066 } 3067 { 3068 // Emit buffers for each reduction variables. 3069 // ReductionCodeGen is required to emit correctly the code for array 3070 // reductions. 3071 ReductionCodeGen RedCG(Shareds, Shareds, Privates, ReductionOps); 3072 unsigned Count = 0; 3073 auto *ITA = CopyArrayTemps.begin(); 3074 for (const Expr *IRef : Privates) { 3075 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl()); 3076 // Emit variably modified arrays, used for arrays/array sections 3077 // reductions. 3078 if (PrivateVD->getType()->isVariablyModifiedType()) { 3079 RedCG.emitSharedOrigLValue(CGF, Count); 3080 RedCG.emitAggregateType(CGF, Count); 3081 } 3082 CodeGenFunction::OpaqueValueMapping DimMapping( 3083 CGF, 3084 cast<OpaqueValueExpr>( 3085 cast<VariableArrayType>((*ITA)->getType()->getAsArrayTypeUnsafe()) 3086 ->getSizeExpr()), 3087 RValue::get(OMPScanNumIterations)); 3088 // Emit temp buffer. 3089 CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(*ITA)->getDecl())); 3090 ++ITA; 3091 ++Count; 3092 } 3093 } 3094 CodeGenFunction::ParentLoopDirectiveForScanRegion ScanRegion(CGF, S); 3095 { 3096 // Emit loop with input phase: 3097 // #pragma omp ... 3098 // for (i: 0..<num_iters>) { 3099 // <input phase>; 3100 // buffer[i] = red; 3101 // } 3102 CGF.OMPFirstScanLoop = true; 3103 CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF); 3104 FirstGen(CGF); 3105 } 3106 // Emit prefix reduction: 3107 // for (int k = 0; k <= ceil(log2(n)); ++k) 3108 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock(); 3109 llvm::BasicBlock *LoopBB = CGF.createBasicBlock("omp.outer.log.scan.body"); 3110 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("omp.outer.log.scan.exit"); 3111 llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy); 3112 llvm::Value *Arg = 3113 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy); 3114 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg); 3115 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy); 3116 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal); 3117 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy); 3118 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub( 3119 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1)); 3120 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, S.getBeginLoc()); 3121 CGF.EmitBlock(LoopBB); 3122 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2); 3123 // size pow2k = 1; 3124 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2); 3125 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB); 3126 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB); 3127 // for (size i = n - 1; i >= 2 ^ k; --i) 3128 // tmp[i] op= tmp[i-pow2k]; 3129 llvm::BasicBlock *InnerLoopBB = 3130 CGF.createBasicBlock("omp.inner.log.scan.body"); 3131 llvm::BasicBlock *InnerExitBB = 3132 CGF.createBasicBlock("omp.inner.log.scan.exit"); 3133 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K); 3134 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB); 3135 CGF.EmitBlock(InnerLoopBB); 3136 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2); 3137 IVal->addIncoming(NMin1, LoopBB); 3138 { 3139 CodeGenFunction::OMPPrivateScope PrivScope(CGF); 3140 auto *ILHS = LHSs.begin(); 3141 auto *IRHS = RHSs.begin(); 3142 for (const Expr *CopyArrayElem : CopyArrayElems) { 3143 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 3144 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 3145 Address LHSAddr = Address::invalid(); 3146 { 3147 CodeGenFunction::OpaqueValueMapping IdxMapping( 3148 CGF, 3149 cast<OpaqueValueExpr>( 3150 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()), 3151 RValue::get(IVal)); 3152 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress(CGF); 3153 } 3154 PrivScope.addPrivate(LHSVD, [LHSAddr]() { return LHSAddr; }); 3155 Address RHSAddr = Address::invalid(); 3156 { 3157 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K); 3158 CodeGenFunction::OpaqueValueMapping IdxMapping( 3159 CGF, 3160 cast<OpaqueValueExpr>( 3161 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()), 3162 RValue::get(OffsetIVal)); 3163 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress(CGF); 3164 } 3165 PrivScope.addPrivate(RHSVD, [RHSAddr]() { return RHSAddr; }); 3166 ++ILHS; 3167 ++IRHS; 3168 } 3169 PrivScope.Privatize(); 3170 CGF.CGM.getOpenMPRuntime().emitReduction( 3171 CGF, S.getEndLoc(), Privates, LHSs, RHSs, ReductionOps, 3172 {/*WithNowait=*/true, /*SimpleReduction=*/true, OMPD_unknown}); 3173 } 3174 llvm::Value *NextIVal = 3175 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1)); 3176 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock()); 3177 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K); 3178 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB); 3179 CGF.EmitBlock(InnerExitBB); 3180 llvm::Value *Next = 3181 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1)); 3182 Counter->addIncoming(Next, CGF.Builder.GetInsertBlock()); 3183 // pow2k <<= 1; 3184 llvm::Value *NextPow2K = CGF.Builder.CreateShl(Pow2K, 1, "", /*HasNUW=*/true); 3185 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock()); 3186 llvm::Value *Cmp = CGF.Builder.CreateICmpNE(Next, LogVal); 3187 CGF.Builder.CreateCondBr(Cmp, LoopBB, ExitBB); 3188 auto DL1 = ApplyDebugLocation::CreateDefaultArtificial(CGF, S.getEndLoc()); 3189 CGF.EmitBlock(ExitBB); 3190 3191 CGF.OMPFirstScanLoop = false; 3192 SecondGen(CGF); 3193 } 3194 3195 void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) { 3196 bool HasLastprivates = false; 3197 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF, 3198 PrePostActionTy &) { 3199 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(), 3200 [](const OMPReductionClause *C) { 3201 return C->getModifier() == OMPC_REDUCTION_inscan; 3202 })) { 3203 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) { 3204 OMPLocalDeclMapRAII Scope(CGF); 3205 OMPLoopScope LoopScope(CGF, S); 3206 return CGF.EmitScalarExpr(S.getNumIterations()); 3207 }; 3208 const auto &&FirstGen = [&S](CodeGenFunction &CGF) { 3209 OMPCancelStackRAII CancelRegion(CGF, OMPD_for, S.hasCancel()); 3210 (void)CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), 3211 emitForLoopBounds, 3212 emitDispatchForLoopBounds); 3213 // Emit an implicit barrier at the end. 3214 CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, S.getBeginLoc(), 3215 OMPD_for); 3216 }; 3217 const auto &&SecondGen = [&S, &HasLastprivates](CodeGenFunction &CGF) { 3218 OMPCancelStackRAII CancelRegion(CGF, OMPD_for, S.hasCancel()); 3219 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), 3220 emitForLoopBounds, 3221 emitDispatchForLoopBounds); 3222 }; 3223 emitScanBasedDirective(CGF, S, NumIteratorsGen, FirstGen, SecondGen); 3224 } else { 3225 OMPCancelStackRAII CancelRegion(CGF, OMPD_for, S.hasCancel()); 3226 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), 3227 emitForLoopBounds, 3228 emitDispatchForLoopBounds); 3229 } 3230 }; 3231 { 3232 auto LPCRegion = 3233 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 3234 OMPLexicalScope Scope(*this, S, OMPD_unknown); 3235 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen, 3236 S.hasCancel()); 3237 } 3238 3239 // Emit an implicit barrier at the end. 3240 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) 3241 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for); 3242 // Check for outer lastprivate conditional update. 3243 checkForLastprivateConditionalUpdate(*this, S); 3244 } 3245 3246 void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) { 3247 bool HasLastprivates = false; 3248 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF, 3249 PrePostActionTy &) { 3250 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), 3251 emitForLoopBounds, 3252 emitDispatchForLoopBounds); 3253 }; 3254 { 3255 auto LPCRegion = 3256 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 3257 OMPLexicalScope Scope(*this, S, OMPD_unknown); 3258 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen); 3259 } 3260 3261 // Emit an implicit barrier at the end. 3262 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates) 3263 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for); 3264 // Check for outer lastprivate conditional update. 3265 checkForLastprivateConditionalUpdate(*this, S); 3266 } 3267 3268 static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, 3269 const Twine &Name, 3270 llvm::Value *Init = nullptr) { 3271 LValue LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty); 3272 if (Init) 3273 CGF.EmitStoreThroughLValue(RValue::get(Init), LVal, /*isInit*/ true); 3274 return LVal; 3275 } 3276 3277 void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { 3278 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt(); 3279 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt); 3280 bool HasLastprivates = false; 3281 auto &&CodeGen = [&S, CapturedStmt, CS, 3282 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) { 3283 const ASTContext &C = CGF.getContext(); 3284 QualType KmpInt32Ty = 3285 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3286 // Emit helper vars inits. 3287 LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.", 3288 CGF.Builder.getInt32(0)); 3289 llvm::ConstantInt *GlobalUBVal = CS != nullptr 3290 ? CGF.Builder.getInt32(CS->size() - 1) 3291 : CGF.Builder.getInt32(0); 3292 LValue UB = 3293 createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal); 3294 LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.", 3295 CGF.Builder.getInt32(1)); 3296 LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.", 3297 CGF.Builder.getInt32(0)); 3298 // Loop counter. 3299 LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv."); 3300 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue); 3301 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV); 3302 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue); 3303 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB); 3304 // Generate condition for loop. 3305 BinaryOperator *Cond = BinaryOperator::Create( 3306 C, &IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue, OK_Ordinary, 3307 S.getBeginLoc(), FPOptions(C.getLangOpts())); 3308 // Increment for loop counter. 3309 UnaryOperator *Inc = UnaryOperator::Create( 3310 C, &IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary, 3311 S.getBeginLoc(), true, FPOptions(C.getLangOpts())); 3312 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) { 3313 // Iterate through all sections and emit a switch construct: 3314 // switch (IV) { 3315 // case 0: 3316 // <SectionStmt[0]>; 3317 // break; 3318 // ... 3319 // case <NumSection> - 1: 3320 // <SectionStmt[<NumSection> - 1]>; 3321 // break; 3322 // } 3323 // .omp.sections.exit: 3324 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".omp.sections.exit"); 3325 llvm::SwitchInst *SwitchStmt = 3326 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getBeginLoc()), 3327 ExitBB, CS == nullptr ? 1 : CS->size()); 3328 if (CS) { 3329 unsigned CaseNumber = 0; 3330 for (const Stmt *SubStmt : CS->children()) { 3331 auto CaseBB = CGF.createBasicBlock(".omp.sections.case"); 3332 CGF.EmitBlock(CaseBB); 3333 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB); 3334 CGF.EmitStmt(SubStmt); 3335 CGF.EmitBranch(ExitBB); 3336 ++CaseNumber; 3337 } 3338 } else { 3339 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(".omp.sections.case"); 3340 CGF.EmitBlock(CaseBB); 3341 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB); 3342 CGF.EmitStmt(CapturedStmt); 3343 CGF.EmitBranch(ExitBB); 3344 } 3345 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 3346 }; 3347 3348 CodeGenFunction::OMPPrivateScope LoopScope(CGF); 3349 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) { 3350 // Emit implicit barrier to synchronize threads and avoid data races on 3351 // initialization of firstprivate variables and post-update of lastprivate 3352 // variables. 3353 CGF.CGM.getOpenMPRuntime().emitBarrierCall( 3354 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false, 3355 /*ForceSimpleCall=*/true); 3356 } 3357 CGF.EmitOMPPrivateClause(S, LoopScope); 3358 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV); 3359 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); 3360 CGF.EmitOMPReductionClauseInit(S, LoopScope); 3361 (void)LoopScope.Privatize(); 3362 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) 3363 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); 3364 3365 // Emit static non-chunked loop. 3366 OpenMPScheduleTy ScheduleKind; 3367 ScheduleKind.Schedule = OMPC_SCHEDULE_static; 3368 CGOpenMPRuntime::StaticRTInput StaticInit( 3369 /*IVSize=*/32, /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(CGF), 3370 LB.getAddress(CGF), UB.getAddress(CGF), ST.getAddress(CGF)); 3371 CGF.CGM.getOpenMPRuntime().emitForStaticInit( 3372 CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind, StaticInit); 3373 // UB = min(UB, GlobalUB); 3374 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getBeginLoc()); 3375 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect( 3376 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal); 3377 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB); 3378 // IV = LB; 3379 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV); 3380 // while (idx <= UB) { BODY; ++idx; } 3381 CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, Cond, Inc, BodyGen, 3382 [](CodeGenFunction &) {}); 3383 // Tell the runtime we are done. 3384 auto &&CodeGen = [&S](CodeGenFunction &CGF) { 3385 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(), 3386 S.getDirectiveKind()); 3387 }; 3388 CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen); 3389 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel); 3390 // Emit post-update of the reduction variables if IsLastIter != 0. 3391 emitPostUpdateForReductionClause(CGF, S, [IL, &S](CodeGenFunction &CGF) { 3392 return CGF.Builder.CreateIsNotNull( 3393 CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); 3394 }); 3395 3396 // Emit final copy of the lastprivate variables if IsLastIter != 0. 3397 if (HasLastprivates) 3398 CGF.EmitOMPLastprivateClauseFinal( 3399 S, /*NoFinals=*/false, 3400 CGF.Builder.CreateIsNotNull( 3401 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()))); 3402 }; 3403 3404 bool HasCancel = false; 3405 if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S)) 3406 HasCancel = OSD->hasCancel(); 3407 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S)) 3408 HasCancel = OPSD->hasCancel(); 3409 OMPCancelStackRAII CancelRegion(*this, S.getDirectiveKind(), HasCancel); 3410 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen, 3411 HasCancel); 3412 // Emit barrier for lastprivates only if 'sections' directive has 'nowait' 3413 // clause. Otherwise the barrier will be generated by the codegen for the 3414 // directive. 3415 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) { 3416 // Emit implicit barrier to synchronize threads and avoid data races on 3417 // initialization of firstprivate variables. 3418 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), 3419 OMPD_unknown); 3420 } 3421 } 3422 3423 void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) { 3424 { 3425 auto LPCRegion = 3426 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 3427 OMPLexicalScope Scope(*this, S, OMPD_unknown); 3428 EmitSections(S); 3429 } 3430 // Emit an implicit barrier at the end. 3431 if (!S.getSingleClause<OMPNowaitClause>()) { 3432 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), 3433 OMPD_sections); 3434 } 3435 // Check for outer lastprivate conditional update. 3436 checkForLastprivateConditionalUpdate(*this, S); 3437 } 3438 3439 void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) { 3440 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 3441 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); 3442 }; 3443 OMPLexicalScope Scope(*this, S, OMPD_unknown); 3444 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen, 3445 S.hasCancel()); 3446 } 3447 3448 void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) { 3449 llvm::SmallVector<const Expr *, 8> CopyprivateVars; 3450 llvm::SmallVector<const Expr *, 8> DestExprs; 3451 llvm::SmallVector<const Expr *, 8> SrcExprs; 3452 llvm::SmallVector<const Expr *, 8> AssignmentOps; 3453 // Check if there are any 'copyprivate' clauses associated with this 3454 // 'single' construct. 3455 // Build a list of copyprivate variables along with helper expressions 3456 // (<source>, <destination>, <destination>=<source> expressions) 3457 for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) { 3458 CopyprivateVars.append(C->varlists().begin(), C->varlists().end()); 3459 DestExprs.append(C->destination_exprs().begin(), 3460 C->destination_exprs().end()); 3461 SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end()); 3462 AssignmentOps.append(C->assignment_ops().begin(), 3463 C->assignment_ops().end()); 3464 } 3465 // Emit code for 'single' region along with 'copyprivate' clauses 3466 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 3467 Action.Enter(CGF); 3468 OMPPrivateScope SingleScope(CGF); 3469 (void)CGF.EmitOMPFirstprivateClause(S, SingleScope); 3470 CGF.EmitOMPPrivateClause(S, SingleScope); 3471 (void)SingleScope.Privatize(); 3472 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); 3473 }; 3474 { 3475 auto LPCRegion = 3476 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 3477 OMPLexicalScope Scope(*this, S, OMPD_unknown); 3478 CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getBeginLoc(), 3479 CopyprivateVars, DestExprs, 3480 SrcExprs, AssignmentOps); 3481 } 3482 // Emit an implicit barrier at the end (to avoid data race on firstprivate 3483 // init or if no 'nowait' clause was specified and no 'copyprivate' clause). 3484 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) { 3485 CGM.getOpenMPRuntime().emitBarrierCall( 3486 *this, S.getBeginLoc(), 3487 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single); 3488 } 3489 // Check for outer lastprivate conditional update. 3490 checkForLastprivateConditionalUpdate(*this, S); 3491 } 3492 3493 static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S) { 3494 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 3495 Action.Enter(CGF); 3496 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); 3497 }; 3498 CGF.CGM.getOpenMPRuntime().emitMasterRegion(CGF, CodeGen, S.getBeginLoc()); 3499 } 3500 3501 void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) { 3502 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) { 3503 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; 3504 3505 const CapturedStmt *CS = S.getInnermostCapturedStmt(); 3506 const Stmt *MasterRegionBodyStmt = CS->getCapturedStmt(); 3507 3508 auto FiniCB = [this](InsertPointTy IP) { 3509 OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP); 3510 }; 3511 3512 auto BodyGenCB = [MasterRegionBodyStmt, this](InsertPointTy AllocaIP, 3513 InsertPointTy CodeGenIP, 3514 llvm::BasicBlock &FiniBB) { 3515 OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP, FiniBB); 3516 OMPBuilderCBHelpers::EmitOMPRegionBody(*this, MasterRegionBodyStmt, 3517 CodeGenIP, FiniBB); 3518 }; 3519 3520 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP); 3521 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI); 3522 Builder.restoreIP(OMPBuilder->CreateMaster(Builder, BodyGenCB, FiniCB)); 3523 3524 return; 3525 } 3526 OMPLexicalScope Scope(*this, S, OMPD_unknown); 3527 emitMaster(*this, S); 3528 } 3529 3530 void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) { 3531 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) { 3532 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; 3533 3534 const CapturedStmt *CS = S.getInnermostCapturedStmt(); 3535 const Stmt *CriticalRegionBodyStmt = CS->getCapturedStmt(); 3536 const Expr *Hint = nullptr; 3537 if (const auto *HintClause = S.getSingleClause<OMPHintClause>()) 3538 Hint = HintClause->getHint(); 3539 3540 // TODO: This is slightly different from what's currently being done in 3541 // clang. Fix the Int32Ty to IntPtrTy (pointer width size) when everything 3542 // about typing is final. 3543 llvm::Value *HintInst = nullptr; 3544 if (Hint) 3545 HintInst = 3546 Builder.CreateIntCast(EmitScalarExpr(Hint), CGM.Int32Ty, false); 3547 3548 auto FiniCB = [this](InsertPointTy IP) { 3549 OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP); 3550 }; 3551 3552 auto BodyGenCB = [CriticalRegionBodyStmt, this](InsertPointTy AllocaIP, 3553 InsertPointTy CodeGenIP, 3554 llvm::BasicBlock &FiniBB) { 3555 OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP, FiniBB); 3556 OMPBuilderCBHelpers::EmitOMPRegionBody(*this, CriticalRegionBodyStmt, 3557 CodeGenIP, FiniBB); 3558 }; 3559 3560 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP); 3561 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI); 3562 Builder.restoreIP(OMPBuilder->CreateCritical( 3563 Builder, BodyGenCB, FiniCB, S.getDirectiveName().getAsString(), 3564 HintInst)); 3565 3566 return; 3567 } 3568 3569 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 3570 Action.Enter(CGF); 3571 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); 3572 }; 3573 const Expr *Hint = nullptr; 3574 if (const auto *HintClause = S.getSingleClause<OMPHintClause>()) 3575 Hint = HintClause->getHint(); 3576 OMPLexicalScope Scope(*this, S, OMPD_unknown); 3577 CGM.getOpenMPRuntime().emitCriticalRegion(*this, 3578 S.getDirectiveName().getAsString(), 3579 CodeGen, S.getBeginLoc(), Hint); 3580 } 3581 3582 void CodeGenFunction::EmitOMPParallelForDirective( 3583 const OMPParallelForDirective &S) { 3584 // Emit directive as a combined directive that consists of two implicit 3585 // directives: 'parallel' with 'for' directive. 3586 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 3587 Action.Enter(CGF); 3588 OMPCancelStackRAII CancelRegion(CGF, OMPD_parallel_for, S.hasCancel()); 3589 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds, 3590 emitDispatchForLoopBounds); 3591 }; 3592 { 3593 auto LPCRegion = 3594 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 3595 emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen, 3596 emitEmptyBoundParameters); 3597 } 3598 // Check for outer lastprivate conditional update. 3599 checkForLastprivateConditionalUpdate(*this, S); 3600 } 3601 3602 void CodeGenFunction::EmitOMPParallelForSimdDirective( 3603 const OMPParallelForSimdDirective &S) { 3604 // Emit directive as a combined directive that consists of two implicit 3605 // directives: 'parallel' with 'for' directive. 3606 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 3607 Action.Enter(CGF); 3608 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds, 3609 emitDispatchForLoopBounds); 3610 }; 3611 { 3612 auto LPCRegion = 3613 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 3614 emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen, 3615 emitEmptyBoundParameters); 3616 } 3617 // Check for outer lastprivate conditional update. 3618 checkForLastprivateConditionalUpdate(*this, S); 3619 } 3620 3621 void CodeGenFunction::EmitOMPParallelMasterDirective( 3622 const OMPParallelMasterDirective &S) { 3623 // Emit directive as a combined directive that consists of two implicit 3624 // directives: 'parallel' with 'master' directive. 3625 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 3626 Action.Enter(CGF); 3627 OMPPrivateScope PrivateScope(CGF); 3628 bool Copyins = CGF.EmitOMPCopyinClause(S); 3629 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); 3630 if (Copyins) { 3631 // Emit implicit barrier to synchronize threads and avoid data races on 3632 // propagation master's thread values of threadprivate variables to local 3633 // instances of that variables of all other implicit threads. 3634 CGF.CGM.getOpenMPRuntime().emitBarrierCall( 3635 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false, 3636 /*ForceSimpleCall=*/true); 3637 } 3638 CGF.EmitOMPPrivateClause(S, PrivateScope); 3639 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 3640 (void)PrivateScope.Privatize(); 3641 emitMaster(CGF, S); 3642 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel); 3643 }; 3644 { 3645 auto LPCRegion = 3646 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 3647 emitCommonOMPParallelDirective(*this, S, OMPD_master, CodeGen, 3648 emitEmptyBoundParameters); 3649 emitPostUpdateForReductionClause(*this, S, 3650 [](CodeGenFunction &) { return nullptr; }); 3651 } 3652 // Check for outer lastprivate conditional update. 3653 checkForLastprivateConditionalUpdate(*this, S); 3654 } 3655 3656 void CodeGenFunction::EmitOMPParallelSectionsDirective( 3657 const OMPParallelSectionsDirective &S) { 3658 // Emit directive as a combined directive that consists of two implicit 3659 // directives: 'parallel' with 'sections' directive. 3660 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 3661 Action.Enter(CGF); 3662 CGF.EmitSections(S); 3663 }; 3664 { 3665 auto LPCRegion = 3666 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 3667 emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen, 3668 emitEmptyBoundParameters); 3669 } 3670 // Check for outer lastprivate conditional update. 3671 checkForLastprivateConditionalUpdate(*this, S); 3672 } 3673 3674 void CodeGenFunction::EmitOMPTaskBasedDirective( 3675 const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, 3676 const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, 3677 OMPTaskDataTy &Data) { 3678 // Emit outlined function for task construct. 3679 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion); 3680 auto I = CS->getCapturedDecl()->param_begin(); 3681 auto PartId = std::next(I); 3682 auto TaskT = std::next(I, 4); 3683 // Check if the task is final 3684 if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) { 3685 // If the condition constant folds and can be elided, try to avoid emitting 3686 // the condition and the dead arm of the if/else. 3687 const Expr *Cond = Clause->getCondition(); 3688 bool CondConstant; 3689 if (ConstantFoldsToSimpleInteger(Cond, CondConstant)) 3690 Data.Final.setInt(CondConstant); 3691 else 3692 Data.Final.setPointer(EvaluateExprAsBool(Cond)); 3693 } else { 3694 // By default the task is not final. 3695 Data.Final.setInt(/*IntVal=*/false); 3696 } 3697 // Check if the task has 'priority' clause. 3698 if (const auto *Clause = S.getSingleClause<OMPPriorityClause>()) { 3699 const Expr *Prio = Clause->getPriority(); 3700 Data.Priority.setInt(/*IntVal=*/true); 3701 Data.Priority.setPointer(EmitScalarConversion( 3702 EmitScalarExpr(Prio), Prio->getType(), 3703 getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1), 3704 Prio->getExprLoc())); 3705 } 3706 // The first function argument for tasks is a thread id, the second one is a 3707 // part id (0 for tied tasks, >=0 for untied task). 3708 llvm::DenseSet<const VarDecl *> EmittedAsPrivate; 3709 // Get list of private variables. 3710 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 3711 auto IRef = C->varlist_begin(); 3712 for (const Expr *IInit : C->private_copies()) { 3713 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 3714 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { 3715 Data.PrivateVars.push_back(*IRef); 3716 Data.PrivateCopies.push_back(IInit); 3717 } 3718 ++IRef; 3719 } 3720 } 3721 EmittedAsPrivate.clear(); 3722 // Get list of firstprivate variables. 3723 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 3724 auto IRef = C->varlist_begin(); 3725 auto IElemInitRef = C->inits().begin(); 3726 for (const Expr *IInit : C->private_copies()) { 3727 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 3728 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { 3729 Data.FirstprivateVars.push_back(*IRef); 3730 Data.FirstprivateCopies.push_back(IInit); 3731 Data.FirstprivateInits.push_back(*IElemInitRef); 3732 } 3733 ++IRef; 3734 ++IElemInitRef; 3735 } 3736 } 3737 // Get list of lastprivate variables (for taskloops). 3738 llvm::DenseMap<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs; 3739 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 3740 auto IRef = C->varlist_begin(); 3741 auto ID = C->destination_exprs().begin(); 3742 for (const Expr *IInit : C->private_copies()) { 3743 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl()); 3744 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) { 3745 Data.LastprivateVars.push_back(*IRef); 3746 Data.LastprivateCopies.push_back(IInit); 3747 } 3748 LastprivateDstsOrigs.insert( 3749 {cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()), 3750 cast<DeclRefExpr>(*IRef)}); 3751 ++IRef; 3752 ++ID; 3753 } 3754 } 3755 SmallVector<const Expr *, 4> LHSs; 3756 SmallVector<const Expr *, 4> RHSs; 3757 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 3758 Data.ReductionVars.append(C->varlist_begin(), C->varlist_end()); 3759 Data.ReductionOrigs.append(C->varlist_begin(), C->varlist_end()); 3760 Data.ReductionCopies.append(C->privates().begin(), C->privates().end()); 3761 Data.ReductionOps.append(C->reduction_ops().begin(), 3762 C->reduction_ops().end()); 3763 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end()); 3764 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end()); 3765 } 3766 Data.Reductions = CGM.getOpenMPRuntime().emitTaskReductionInit( 3767 *this, S.getBeginLoc(), LHSs, RHSs, Data); 3768 // Build list of dependences. 3769 for (const auto *C : S.getClausesOfKind<OMPDependClause>()) { 3770 OMPTaskDataTy::DependData &DD = 3771 Data.Dependences.emplace_back(C->getDependencyKind(), C->getModifier()); 3772 DD.DepExprs.append(C->varlist_begin(), C->varlist_end()); 3773 } 3774 auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs, 3775 CapturedRegion](CodeGenFunction &CGF, 3776 PrePostActionTy &Action) { 3777 // Set proper addresses for generated private copies. 3778 OMPPrivateScope Scope(CGF); 3779 llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> FirstprivatePtrs; 3780 if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() || 3781 !Data.LastprivateVars.empty()) { 3782 llvm::FunctionType *CopyFnTy = llvm::FunctionType::get( 3783 CGF.Builder.getVoidTy(), {CGF.Builder.getInt8PtrTy()}, true); 3784 enum { PrivatesParam = 2, CopyFnParam = 3 }; 3785 llvm::Value *CopyFn = CGF.Builder.CreateLoad( 3786 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam))); 3787 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar( 3788 CS->getCapturedDecl()->getParam(PrivatesParam))); 3789 // Map privates. 3790 llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs; 3791 llvm::SmallVector<llvm::Value *, 16> CallArgs; 3792 CallArgs.push_back(PrivatesPtr); 3793 for (const Expr *E : Data.PrivateVars) { 3794 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3795 Address PrivatePtr = CGF.CreateMemTemp( 3796 CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr"); 3797 PrivatePtrs.emplace_back(VD, PrivatePtr); 3798 CallArgs.push_back(PrivatePtr.getPointer()); 3799 } 3800 for (const Expr *E : Data.FirstprivateVars) { 3801 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3802 Address PrivatePtr = 3803 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), 3804 ".firstpriv.ptr.addr"); 3805 PrivatePtrs.emplace_back(VD, PrivatePtr); 3806 FirstprivatePtrs.emplace_back(VD, PrivatePtr); 3807 CallArgs.push_back(PrivatePtr.getPointer()); 3808 } 3809 for (const Expr *E : Data.LastprivateVars) { 3810 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3811 Address PrivatePtr = 3812 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), 3813 ".lastpriv.ptr.addr"); 3814 PrivatePtrs.emplace_back(VD, PrivatePtr); 3815 CallArgs.push_back(PrivatePtr.getPointer()); 3816 } 3817 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall( 3818 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs); 3819 for (const auto &Pair : LastprivateDstsOrigs) { 3820 const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl()); 3821 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(OrigVD), 3822 /*RefersToEnclosingVariableOrCapture=*/ 3823 CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr, 3824 Pair.second->getType(), VK_LValue, 3825 Pair.second->getExprLoc()); 3826 Scope.addPrivate(Pair.first, [&CGF, &DRE]() { 3827 return CGF.EmitLValue(&DRE).getAddress(CGF); 3828 }); 3829 } 3830 for (const auto &Pair : PrivatePtrs) { 3831 Address Replacement(CGF.Builder.CreateLoad(Pair.second), 3832 CGF.getContext().getDeclAlign(Pair.first)); 3833 Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; }); 3834 } 3835 } 3836 if (Data.Reductions) { 3837 OMPPrivateScope FirstprivateScope(CGF); 3838 for (const auto &Pair : FirstprivatePtrs) { 3839 Address Replacement(CGF.Builder.CreateLoad(Pair.second), 3840 CGF.getContext().getDeclAlign(Pair.first)); 3841 FirstprivateScope.addPrivate(Pair.first, 3842 [Replacement]() { return Replacement; }); 3843 } 3844 (void)FirstprivateScope.Privatize(); 3845 OMPLexicalScope LexScope(CGF, S, CapturedRegion); 3846 ReductionCodeGen RedCG(Data.ReductionVars, Data.ReductionVars, 3847 Data.ReductionCopies, Data.ReductionOps); 3848 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad( 3849 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(9))); 3850 for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) { 3851 RedCG.emitSharedOrigLValue(CGF, Cnt); 3852 RedCG.emitAggregateType(CGF, Cnt); 3853 // FIXME: This must removed once the runtime library is fixed. 3854 // Emit required threadprivate variables for 3855 // initializer/combiner/finalizer. 3856 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(), 3857 RedCG, Cnt); 3858 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( 3859 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); 3860 Replacement = 3861 Address(CGF.EmitScalarConversion( 3862 Replacement.getPointer(), CGF.getContext().VoidPtrTy, 3863 CGF.getContext().getPointerType( 3864 Data.ReductionCopies[Cnt]->getType()), 3865 Data.ReductionCopies[Cnt]->getExprLoc()), 3866 Replacement.getAlignment()); 3867 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); 3868 Scope.addPrivate(RedCG.getBaseDecl(Cnt), 3869 [Replacement]() { return Replacement; }); 3870 } 3871 } 3872 // Privatize all private variables except for in_reduction items. 3873 (void)Scope.Privatize(); 3874 SmallVector<const Expr *, 4> InRedVars; 3875 SmallVector<const Expr *, 4> InRedPrivs; 3876 SmallVector<const Expr *, 4> InRedOps; 3877 SmallVector<const Expr *, 4> TaskgroupDescriptors; 3878 for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) { 3879 auto IPriv = C->privates().begin(); 3880 auto IRed = C->reduction_ops().begin(); 3881 auto ITD = C->taskgroup_descriptors().begin(); 3882 for (const Expr *Ref : C->varlists()) { 3883 InRedVars.emplace_back(Ref); 3884 InRedPrivs.emplace_back(*IPriv); 3885 InRedOps.emplace_back(*IRed); 3886 TaskgroupDescriptors.emplace_back(*ITD); 3887 std::advance(IPriv, 1); 3888 std::advance(IRed, 1); 3889 std::advance(ITD, 1); 3890 } 3891 } 3892 // Privatize in_reduction items here, because taskgroup descriptors must be 3893 // privatized earlier. 3894 OMPPrivateScope InRedScope(CGF); 3895 if (!InRedVars.empty()) { 3896 ReductionCodeGen RedCG(InRedVars, InRedVars, InRedPrivs, InRedOps); 3897 for (unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) { 3898 RedCG.emitSharedOrigLValue(CGF, Cnt); 3899 RedCG.emitAggregateType(CGF, Cnt); 3900 // The taskgroup descriptor variable is always implicit firstprivate and 3901 // privatized already during processing of the firstprivates. 3902 // FIXME: This must removed once the runtime library is fixed. 3903 // Emit required threadprivate variables for 3904 // initializer/combiner/finalizer. 3905 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(), 3906 RedCG, Cnt); 3907 llvm::Value *ReductionsPtr; 3908 if (const Expr *TRExpr = TaskgroupDescriptors[Cnt]) { 3909 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr), 3910 TRExpr->getExprLoc()); 3911 } else { 3912 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3913 } 3914 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( 3915 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); 3916 Replacement = Address( 3917 CGF.EmitScalarConversion( 3918 Replacement.getPointer(), CGF.getContext().VoidPtrTy, 3919 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), 3920 InRedPrivs[Cnt]->getExprLoc()), 3921 Replacement.getAlignment()); 3922 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); 3923 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt), 3924 [Replacement]() { return Replacement; }); 3925 } 3926 } 3927 (void)InRedScope.Privatize(); 3928 3929 Action.Enter(CGF); 3930 BodyGen(CGF); 3931 }; 3932 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction( 3933 S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, Data.Tied, 3934 Data.NumberOfParts); 3935 OMPLexicalScope Scope(*this, S, llvm::None, 3936 !isOpenMPParallelDirective(S.getDirectiveKind()) && 3937 !isOpenMPSimdDirective(S.getDirectiveKind())); 3938 TaskGen(*this, OutlinedFn, Data); 3939 } 3940 3941 static ImplicitParamDecl * 3942 createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data, 3943 QualType Ty, CapturedDecl *CD, 3944 SourceLocation Loc) { 3945 auto *OrigVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty, 3946 ImplicitParamDecl::Other); 3947 auto *OrigRef = DeclRefExpr::Create( 3948 C, NestedNameSpecifierLoc(), SourceLocation(), OrigVD, 3949 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue); 3950 auto *PrivateVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty, 3951 ImplicitParamDecl::Other); 3952 auto *PrivateRef = DeclRefExpr::Create( 3953 C, NestedNameSpecifierLoc(), SourceLocation(), PrivateVD, 3954 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue); 3955 QualType ElemType = C.getBaseElementType(Ty); 3956 auto *InitVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, ElemType, 3957 ImplicitParamDecl::Other); 3958 auto *InitRef = DeclRefExpr::Create( 3959 C, NestedNameSpecifierLoc(), SourceLocation(), InitVD, 3960 /*RefersToEnclosingVariableOrCapture=*/false, Loc, ElemType, VK_LValue); 3961 PrivateVD->setInitStyle(VarDecl::CInit); 3962 PrivateVD->setInit(ImplicitCastExpr::Create(C, ElemType, CK_LValueToRValue, 3963 InitRef, /*BasePath=*/nullptr, 3964 VK_RValue)); 3965 Data.FirstprivateVars.emplace_back(OrigRef); 3966 Data.FirstprivateCopies.emplace_back(PrivateRef); 3967 Data.FirstprivateInits.emplace_back(InitRef); 3968 return OrigVD; 3969 } 3970 3971 void CodeGenFunction::EmitOMPTargetTaskBasedDirective( 3972 const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, 3973 OMPTargetDataInfo &InputInfo) { 3974 // Emit outlined function for task construct. 3975 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task); 3976 Address CapturedStruct = GenerateCapturedStmtArgument(*CS); 3977 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); 3978 auto I = CS->getCapturedDecl()->param_begin(); 3979 auto PartId = std::next(I); 3980 auto TaskT = std::next(I, 4); 3981 OMPTaskDataTy Data; 3982 // The task is not final. 3983 Data.Final.setInt(/*IntVal=*/false); 3984 // Get list of firstprivate variables. 3985 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 3986 auto IRef = C->varlist_begin(); 3987 auto IElemInitRef = C->inits().begin(); 3988 for (auto *IInit : C->private_copies()) { 3989 Data.FirstprivateVars.push_back(*IRef); 3990 Data.FirstprivateCopies.push_back(IInit); 3991 Data.FirstprivateInits.push_back(*IElemInitRef); 3992 ++IRef; 3993 ++IElemInitRef; 3994 } 3995 } 3996 OMPPrivateScope TargetScope(*this); 3997 VarDecl *BPVD = nullptr; 3998 VarDecl *PVD = nullptr; 3999 VarDecl *SVD = nullptr; 4000 if (InputInfo.NumberOfTargetItems > 0) { 4001 auto *CD = CapturedDecl::Create( 4002 getContext(), getContext().getTranslationUnitDecl(), /*NumParams=*/0); 4003 llvm::APInt ArrSize(/*numBits=*/32, InputInfo.NumberOfTargetItems); 4004 QualType BaseAndPointersType = getContext().getConstantArrayType( 4005 getContext().VoidPtrTy, ArrSize, nullptr, ArrayType::Normal, 4006 /*IndexTypeQuals=*/0); 4007 BPVD = createImplicitFirstprivateForType( 4008 getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc()); 4009 PVD = createImplicitFirstprivateForType( 4010 getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc()); 4011 QualType SizesType = getContext().getConstantArrayType( 4012 getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1), 4013 ArrSize, nullptr, ArrayType::Normal, 4014 /*IndexTypeQuals=*/0); 4015 SVD = createImplicitFirstprivateForType(getContext(), Data, SizesType, CD, 4016 S.getBeginLoc()); 4017 TargetScope.addPrivate( 4018 BPVD, [&InputInfo]() { return InputInfo.BasePointersArray; }); 4019 TargetScope.addPrivate(PVD, 4020 [&InputInfo]() { return InputInfo.PointersArray; }); 4021 TargetScope.addPrivate(SVD, 4022 [&InputInfo]() { return InputInfo.SizesArray; }); 4023 } 4024 (void)TargetScope.Privatize(); 4025 // Build list of dependences. 4026 for (const auto *C : S.getClausesOfKind<OMPDependClause>()) { 4027 OMPTaskDataTy::DependData &DD = 4028 Data.Dependences.emplace_back(C->getDependencyKind(), C->getModifier()); 4029 DD.DepExprs.append(C->varlist_begin(), C->varlist_end()); 4030 } 4031 auto &&CodeGen = [&Data, &S, CS, &BodyGen, BPVD, PVD, SVD, 4032 &InputInfo](CodeGenFunction &CGF, PrePostActionTy &Action) { 4033 // Set proper addresses for generated private copies. 4034 OMPPrivateScope Scope(CGF); 4035 if (!Data.FirstprivateVars.empty()) { 4036 llvm::FunctionType *CopyFnTy = llvm::FunctionType::get( 4037 CGF.Builder.getVoidTy(), {CGF.Builder.getInt8PtrTy()}, true); 4038 enum { PrivatesParam = 2, CopyFnParam = 3 }; 4039 llvm::Value *CopyFn = CGF.Builder.CreateLoad( 4040 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam))); 4041 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar( 4042 CS->getCapturedDecl()->getParam(PrivatesParam))); 4043 // Map privates. 4044 llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs; 4045 llvm::SmallVector<llvm::Value *, 16> CallArgs; 4046 CallArgs.push_back(PrivatesPtr); 4047 for (const Expr *E : Data.FirstprivateVars) { 4048 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4049 Address PrivatePtr = 4050 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), 4051 ".firstpriv.ptr.addr"); 4052 PrivatePtrs.emplace_back(VD, PrivatePtr); 4053 CallArgs.push_back(PrivatePtr.getPointer()); 4054 } 4055 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall( 4056 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs); 4057 for (const auto &Pair : PrivatePtrs) { 4058 Address Replacement(CGF.Builder.CreateLoad(Pair.second), 4059 CGF.getContext().getDeclAlign(Pair.first)); 4060 Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; }); 4061 } 4062 } 4063 // Privatize all private variables except for in_reduction items. 4064 (void)Scope.Privatize(); 4065 if (InputInfo.NumberOfTargetItems > 0) { 4066 InputInfo.BasePointersArray = CGF.Builder.CreateConstArrayGEP( 4067 CGF.GetAddrOfLocalVar(BPVD), /*Index=*/0); 4068 InputInfo.PointersArray = CGF.Builder.CreateConstArrayGEP( 4069 CGF.GetAddrOfLocalVar(PVD), /*Index=*/0); 4070 InputInfo.SizesArray = CGF.Builder.CreateConstArrayGEP( 4071 CGF.GetAddrOfLocalVar(SVD), /*Index=*/0); 4072 } 4073 4074 Action.Enter(CGF); 4075 OMPLexicalScope LexScope(CGF, S, OMPD_task, /*EmitPreInitStmt=*/false); 4076 BodyGen(CGF); 4077 }; 4078 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction( 4079 S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, /*Tied=*/true, 4080 Data.NumberOfParts); 4081 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0); 4082 IntegerLiteral IfCond(getContext(), TrueOrFalse, 4083 getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 4084 SourceLocation()); 4085 4086 CGM.getOpenMPRuntime().emitTaskCall(*this, S.getBeginLoc(), S, OutlinedFn, 4087 SharedsTy, CapturedStruct, &IfCond, Data); 4088 } 4089 4090 void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) { 4091 // Emit outlined function for task construct. 4092 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task); 4093 Address CapturedStruct = GenerateCapturedStmtArgument(*CS); 4094 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); 4095 const Expr *IfCond = nullptr; 4096 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { 4097 if (C->getNameModifier() == OMPD_unknown || 4098 C->getNameModifier() == OMPD_task) { 4099 IfCond = C->getCondition(); 4100 break; 4101 } 4102 } 4103 4104 OMPTaskDataTy Data; 4105 // Check if we should emit tied or untied task. 4106 Data.Tied = !S.getSingleClause<OMPUntiedClause>(); 4107 auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) { 4108 CGF.EmitStmt(CS->getCapturedStmt()); 4109 }; 4110 auto &&TaskGen = [&S, SharedsTy, CapturedStruct, 4111 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn, 4112 const OMPTaskDataTy &Data) { 4113 CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getBeginLoc(), S, OutlinedFn, 4114 SharedsTy, CapturedStruct, IfCond, 4115 Data); 4116 }; 4117 auto LPCRegion = 4118 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 4119 EmitOMPTaskBasedDirective(S, OMPD_task, BodyGen, TaskGen, Data); 4120 } 4121 4122 void CodeGenFunction::EmitOMPTaskyieldDirective( 4123 const OMPTaskyieldDirective &S) { 4124 CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getBeginLoc()); 4125 } 4126 4127 void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) { 4128 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_barrier); 4129 } 4130 4131 void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) { 4132 CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc()); 4133 } 4134 4135 void CodeGenFunction::EmitOMPTaskgroupDirective( 4136 const OMPTaskgroupDirective &S) { 4137 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 4138 Action.Enter(CGF); 4139 if (const Expr *E = S.getReductionRef()) { 4140 SmallVector<const Expr *, 4> LHSs; 4141 SmallVector<const Expr *, 4> RHSs; 4142 OMPTaskDataTy Data; 4143 for (const auto *C : S.getClausesOfKind<OMPTaskReductionClause>()) { 4144 Data.ReductionVars.append(C->varlist_begin(), C->varlist_end()); 4145 Data.ReductionOrigs.append(C->varlist_begin(), C->varlist_end()); 4146 Data.ReductionCopies.append(C->privates().begin(), C->privates().end()); 4147 Data.ReductionOps.append(C->reduction_ops().begin(), 4148 C->reduction_ops().end()); 4149 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end()); 4150 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end()); 4151 } 4152 llvm::Value *ReductionDesc = 4153 CGF.CGM.getOpenMPRuntime().emitTaskReductionInit(CGF, S.getBeginLoc(), 4154 LHSs, RHSs, Data); 4155 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4156 CGF.EmitVarDecl(*VD); 4157 CGF.EmitStoreOfScalar(ReductionDesc, CGF.GetAddrOfLocalVar(VD), 4158 /*Volatile=*/false, E->getType()); 4159 } 4160 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); 4161 }; 4162 OMPLexicalScope Scope(*this, S, OMPD_unknown); 4163 CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getBeginLoc()); 4164 } 4165 4166 void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) { 4167 llvm::AtomicOrdering AO = S.getSingleClause<OMPFlushClause>() 4168 ? llvm::AtomicOrdering::NotAtomic 4169 : llvm::AtomicOrdering::AcquireRelease; 4170 CGM.getOpenMPRuntime().emitFlush( 4171 *this, 4172 [&S]() -> ArrayRef<const Expr *> { 4173 if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>()) 4174 return llvm::makeArrayRef(FlushClause->varlist_begin(), 4175 FlushClause->varlist_end()); 4176 return llvm::None; 4177 }(), 4178 S.getBeginLoc(), AO); 4179 } 4180 4181 void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) { 4182 const auto *DO = S.getSingleClause<OMPDepobjClause>(); 4183 LValue DOLVal = EmitLValue(DO->getDepobj()); 4184 if (const auto *DC = S.getSingleClause<OMPDependClause>()) { 4185 OMPTaskDataTy::DependData Dependencies(DC->getDependencyKind(), 4186 DC->getModifier()); 4187 Dependencies.DepExprs.append(DC->varlist_begin(), DC->varlist_end()); 4188 Address DepAddr = CGM.getOpenMPRuntime().emitDepobjDependClause( 4189 *this, Dependencies, DC->getBeginLoc()); 4190 EmitStoreOfScalar(DepAddr.getPointer(), DOLVal); 4191 return; 4192 } 4193 if (const auto *DC = S.getSingleClause<OMPDestroyClause>()) { 4194 CGM.getOpenMPRuntime().emitDestroyClause(*this, DOLVal, DC->getBeginLoc()); 4195 return; 4196 } 4197 if (const auto *UC = S.getSingleClause<OMPUpdateClause>()) { 4198 CGM.getOpenMPRuntime().emitUpdateClause( 4199 *this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc()); 4200 return; 4201 } 4202 } 4203 4204 void CodeGenFunction::EmitOMPScanDirective(const OMPScanDirective &S) { 4205 if (!OMPParentLoopDirectiveForScan) 4206 return; 4207 const OMPExecutableDirective &ParentDir = *OMPParentLoopDirectiveForScan; 4208 bool IsInclusive = S.hasClausesOfKind<OMPInclusiveClause>(); 4209 SmallVector<const Expr *, 4> Shareds; 4210 SmallVector<const Expr *, 4> Privates; 4211 SmallVector<const Expr *, 4> LHSs; 4212 SmallVector<const Expr *, 4> RHSs; 4213 SmallVector<const Expr *, 4> ReductionOps; 4214 SmallVector<const Expr *, 4> CopyOps; 4215 SmallVector<const Expr *, 4> CopyArrayTemps; 4216 SmallVector<const Expr *, 4> CopyArrayElems; 4217 for (const auto *C : ParentDir.getClausesOfKind<OMPReductionClause>()) { 4218 if (C->getModifier() != OMPC_REDUCTION_inscan) 4219 continue; 4220 Shareds.append(C->varlist_begin(), C->varlist_end()); 4221 Privates.append(C->privates().begin(), C->privates().end()); 4222 LHSs.append(C->lhs_exprs().begin(), C->lhs_exprs().end()); 4223 RHSs.append(C->rhs_exprs().begin(), C->rhs_exprs().end()); 4224 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end()); 4225 CopyOps.append(C->copy_ops().begin(), C->copy_ops().end()); 4226 CopyArrayTemps.append(C->copy_array_temps().begin(), 4227 C->copy_array_temps().end()); 4228 CopyArrayElems.append(C->copy_array_elems().begin(), 4229 C->copy_array_elems().end()); 4230 } 4231 if (ParentDir.getDirectiveKind() == OMPD_simd || 4232 (getLangOpts().OpenMPSimd && 4233 isOpenMPSimdDirective(ParentDir.getDirectiveKind()))) { 4234 // For simd directive and simd-based directives in simd only mode, use the 4235 // following codegen: 4236 // int x = 0; 4237 // #pragma omp simd reduction(inscan, +: x) 4238 // for (..) { 4239 // <first part> 4240 // #pragma omp scan inclusive(x) 4241 // <second part> 4242 // } 4243 // is transformed to: 4244 // int x = 0; 4245 // for (..) { 4246 // int x_priv = 0; 4247 // <first part> 4248 // x = x_priv + x; 4249 // x_priv = x; 4250 // <second part> 4251 // } 4252 // and 4253 // int x = 0; 4254 // #pragma omp simd reduction(inscan, +: x) 4255 // for (..) { 4256 // <first part> 4257 // #pragma omp scan exclusive(x) 4258 // <second part> 4259 // } 4260 // to 4261 // int x = 0; 4262 // for (..) { 4263 // int x_priv = 0; 4264 // <second part> 4265 // int temp = x; 4266 // x = x_priv + x; 4267 // x_priv = temp; 4268 // <first part> 4269 // } 4270 llvm::BasicBlock *OMPScanReduce = createBasicBlock("omp.inscan.reduce"); 4271 EmitBranch(IsInclusive 4272 ? OMPScanReduce 4273 : BreakContinueStack.back().ContinueBlock.getBlock()); 4274 EmitBlock(OMPScanDispatch); 4275 { 4276 // New scope for correct construction/destruction of temp variables for 4277 // exclusive scan. 4278 LexicalScope Scope(*this, S.getSourceRange()); 4279 EmitBranch(IsInclusive ? OMPBeforeScanBlock : OMPAfterScanBlock); 4280 EmitBlock(OMPScanReduce); 4281 if (!IsInclusive) { 4282 // Create temp var and copy LHS value to this temp value. 4283 // TMP = LHS; 4284 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) { 4285 const Expr *PrivateExpr = Privates[I]; 4286 const Expr *TempExpr = CopyArrayTemps[I]; 4287 EmitAutoVarDecl( 4288 *cast<VarDecl>(cast<DeclRefExpr>(TempExpr)->getDecl())); 4289 LValue DestLVal = EmitLValue(TempExpr); 4290 LValue SrcLVal = EmitLValue(LHSs[I]); 4291 EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(*this), 4292 SrcLVal.getAddress(*this), 4293 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()), 4294 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), 4295 CopyOps[I]); 4296 } 4297 } 4298 CGM.getOpenMPRuntime().emitReduction( 4299 *this, ParentDir.getEndLoc(), Privates, LHSs, RHSs, ReductionOps, 4300 {/*WithNowait=*/true, /*SimpleReduction=*/true, OMPD_simd}); 4301 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) { 4302 const Expr *PrivateExpr = Privates[I]; 4303 LValue DestLVal; 4304 LValue SrcLVal; 4305 if (IsInclusive) { 4306 DestLVal = EmitLValue(RHSs[I]); 4307 SrcLVal = EmitLValue(LHSs[I]); 4308 } else { 4309 const Expr *TempExpr = CopyArrayTemps[I]; 4310 DestLVal = EmitLValue(RHSs[I]); 4311 SrcLVal = EmitLValue(TempExpr); 4312 } 4313 EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(*this), 4314 SrcLVal.getAddress(*this), 4315 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()), 4316 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), 4317 CopyOps[I]); 4318 } 4319 } 4320 EmitBranch(IsInclusive ? OMPAfterScanBlock : OMPBeforeScanBlock); 4321 OMPScanExitBlock = IsInclusive 4322 ? BreakContinueStack.back().ContinueBlock.getBlock() 4323 : OMPScanReduce; 4324 EmitBlock(OMPAfterScanBlock); 4325 return; 4326 } 4327 if (!IsInclusive) { 4328 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock()); 4329 EmitBlock(OMPScanExitBlock); 4330 } 4331 if (OMPFirstScanLoop) { 4332 // Emit buffer[i] = red; at the end of the input phase. 4333 const auto *IVExpr = cast<OMPLoopDirective>(ParentDir) 4334 .getIterationVariable() 4335 ->IgnoreParenImpCasts(); 4336 LValue IdxLVal = EmitLValue(IVExpr); 4337 llvm::Value *IdxVal = EmitLoadOfScalar(IdxLVal, IVExpr->getExprLoc()); 4338 IdxVal = Builder.CreateIntCast(IdxVal, SizeTy, /*isSigned=*/false); 4339 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) { 4340 const Expr *PrivateExpr = Privates[I]; 4341 const Expr *OrigExpr = Shareds[I]; 4342 const Expr *CopyArrayElem = CopyArrayElems[I]; 4343 OpaqueValueMapping IdxMapping( 4344 *this, 4345 cast<OpaqueValueExpr>( 4346 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()), 4347 RValue::get(IdxVal)); 4348 LValue DestLVal = EmitLValue(CopyArrayElem); 4349 LValue SrcLVal = EmitLValue(OrigExpr); 4350 EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(*this), 4351 SrcLVal.getAddress(*this), 4352 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()), 4353 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), 4354 CopyOps[I]); 4355 } 4356 } 4357 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock()); 4358 if (IsInclusive) { 4359 EmitBlock(OMPScanExitBlock); 4360 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock()); 4361 } 4362 EmitBlock(OMPScanDispatch); 4363 if (!OMPFirstScanLoop) { 4364 // Emit red = buffer[i]; at the entrance to the scan phase. 4365 const auto *IVExpr = cast<OMPLoopDirective>(ParentDir) 4366 .getIterationVariable() 4367 ->IgnoreParenImpCasts(); 4368 LValue IdxLVal = EmitLValue(IVExpr); 4369 llvm::Value *IdxVal = EmitLoadOfScalar(IdxLVal, IVExpr->getExprLoc()); 4370 IdxVal = Builder.CreateIntCast(IdxVal, SizeTy, /*isSigned=*/false); 4371 llvm::BasicBlock *ExclusiveExitBB = nullptr; 4372 if (!IsInclusive) { 4373 llvm::BasicBlock *ContBB = createBasicBlock("omp.exclusive.dec"); 4374 ExclusiveExitBB = createBasicBlock("omp.exclusive.copy.exit"); 4375 llvm::Value *Cmp = Builder.CreateIsNull(IdxVal); 4376 Builder.CreateCondBr(Cmp, ExclusiveExitBB, ContBB); 4377 EmitBlock(ContBB); 4378 // Use idx - 1 iteration for exclusive scan. 4379 IdxVal = Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(SizeTy, 1)); 4380 } 4381 for (unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) { 4382 const Expr *PrivateExpr = Privates[I]; 4383 const Expr *OrigExpr = Shareds[I]; 4384 const Expr *CopyArrayElem = CopyArrayElems[I]; 4385 OpaqueValueMapping IdxMapping( 4386 *this, 4387 cast<OpaqueValueExpr>( 4388 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()), 4389 RValue::get(IdxVal)); 4390 LValue SrcLVal = EmitLValue(CopyArrayElem); 4391 LValue DestLVal = EmitLValue(OrigExpr); 4392 EmitOMPCopy(PrivateExpr->getType(), DestLVal.getAddress(*this), 4393 SrcLVal.getAddress(*this), 4394 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()), 4395 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), 4396 CopyOps[I]); 4397 } 4398 if (!IsInclusive) { 4399 EmitBlock(ExclusiveExitBB); 4400 } 4401 } 4402 EmitBranch((OMPFirstScanLoop == IsInclusive) ? OMPBeforeScanBlock 4403 : OMPAfterScanBlock); 4404 EmitBlock(OMPAfterScanBlock); 4405 } 4406 4407 void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S, 4408 const CodeGenLoopTy &CodeGenLoop, 4409 Expr *IncExpr) { 4410 // Emit the loop iteration variable. 4411 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable()); 4412 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl()); 4413 EmitVarDecl(*IVDecl); 4414 4415 // Emit the iterations count variable. 4416 // If it is not a variable, Sema decided to calculate iterations count on each 4417 // iteration (e.g., it is foldable into a constant). 4418 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { 4419 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); 4420 // Emit calculation of the iterations count. 4421 EmitIgnoredExpr(S.getCalcLastIteration()); 4422 } 4423 4424 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime(); 4425 4426 bool HasLastprivateClause = false; 4427 // Check pre-condition. 4428 { 4429 OMPLoopScope PreInitScope(*this, S); 4430 // Skip the entire loop if we don't meet the precondition. 4431 // If the condition constant folds and can be elided, avoid emitting the 4432 // whole loop. 4433 bool CondConstant; 4434 llvm::BasicBlock *ContBlock = nullptr; 4435 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { 4436 if (!CondConstant) 4437 return; 4438 } else { 4439 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then"); 4440 ContBlock = createBasicBlock("omp.precond.end"); 4441 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock, 4442 getProfileCount(&S)); 4443 EmitBlock(ThenBlock); 4444 incrementProfileCounter(&S); 4445 } 4446 4447 emitAlignedClause(*this, S); 4448 // Emit 'then' code. 4449 { 4450 // Emit helper vars inits. 4451 4452 LValue LB = EmitOMPHelperVar( 4453 *this, cast<DeclRefExpr>( 4454 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 4455 ? S.getCombinedLowerBoundVariable() 4456 : S.getLowerBoundVariable()))); 4457 LValue UB = EmitOMPHelperVar( 4458 *this, cast<DeclRefExpr>( 4459 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 4460 ? S.getCombinedUpperBoundVariable() 4461 : S.getUpperBoundVariable()))); 4462 LValue ST = 4463 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable())); 4464 LValue IL = 4465 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable())); 4466 4467 OMPPrivateScope LoopScope(*this); 4468 if (EmitOMPFirstprivateClause(S, LoopScope)) { 4469 // Emit implicit barrier to synchronize threads and avoid data races 4470 // on initialization of firstprivate variables and post-update of 4471 // lastprivate variables. 4472 CGM.getOpenMPRuntime().emitBarrierCall( 4473 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false, 4474 /*ForceSimpleCall=*/true); 4475 } 4476 EmitOMPPrivateClause(S, LoopScope); 4477 if (isOpenMPSimdDirective(S.getDirectiveKind()) && 4478 !isOpenMPParallelDirective(S.getDirectiveKind()) && 4479 !isOpenMPTeamsDirective(S.getDirectiveKind())) 4480 EmitOMPReductionClauseInit(S, LoopScope); 4481 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope); 4482 EmitOMPPrivateLoopCounters(S, LoopScope); 4483 (void)LoopScope.Privatize(); 4484 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) 4485 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S); 4486 4487 // Detect the distribute schedule kind and chunk. 4488 llvm::Value *Chunk = nullptr; 4489 OpenMPDistScheduleClauseKind ScheduleKind = OMPC_DIST_SCHEDULE_unknown; 4490 if (const auto *C = S.getSingleClause<OMPDistScheduleClause>()) { 4491 ScheduleKind = C->getDistScheduleKind(); 4492 if (const Expr *Ch = C->getChunkSize()) { 4493 Chunk = EmitScalarExpr(Ch); 4494 Chunk = EmitScalarConversion(Chunk, Ch->getType(), 4495 S.getIterationVariable()->getType(), 4496 S.getBeginLoc()); 4497 } 4498 } else { 4499 // Default behaviour for dist_schedule clause. 4500 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk( 4501 *this, S, ScheduleKind, Chunk); 4502 } 4503 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); 4504 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); 4505 4506 // OpenMP [2.10.8, distribute Construct, Description] 4507 // If dist_schedule is specified, kind must be static. If specified, 4508 // iterations are divided into chunks of size chunk_size, chunks are 4509 // assigned to the teams of the league in a round-robin fashion in the 4510 // order of the team number. When no chunk_size is specified, the 4511 // iteration space is divided into chunks that are approximately equal 4512 // in size, and at most one chunk is distributed to each team of the 4513 // league. The size of the chunks is unspecified in this case. 4514 bool StaticChunked = RT.isStaticChunked( 4515 ScheduleKind, /* Chunked */ Chunk != nullptr) && 4516 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()); 4517 if (RT.isStaticNonchunked(ScheduleKind, 4518 /* Chunked */ Chunk != nullptr) || 4519 StaticChunked) { 4520 CGOpenMPRuntime::StaticRTInput StaticInit( 4521 IVSize, IVSigned, /* Ordered = */ false, IL.getAddress(*this), 4522 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this), 4523 StaticChunked ? Chunk : nullptr); 4524 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind, 4525 StaticInit); 4526 JumpDest LoopExit = 4527 getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit")); 4528 // UB = min(UB, GlobalUB); 4529 EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 4530 ? S.getCombinedEnsureUpperBound() 4531 : S.getEnsureUpperBound()); 4532 // IV = LB; 4533 EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 4534 ? S.getCombinedInit() 4535 : S.getInit()); 4536 4537 const Expr *Cond = 4538 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) 4539 ? S.getCombinedCond() 4540 : S.getCond(); 4541 4542 if (StaticChunked) 4543 Cond = S.getCombinedDistCond(); 4544 4545 // For static unchunked schedules generate: 4546 // 4547 // 1. For distribute alone, codegen 4548 // while (idx <= UB) { 4549 // BODY; 4550 // ++idx; 4551 // } 4552 // 4553 // 2. When combined with 'for' (e.g. as in 'distribute parallel for') 4554 // while (idx <= UB) { 4555 // <CodeGen rest of pragma>(LB, UB); 4556 // idx += ST; 4557 // } 4558 // 4559 // For static chunk one schedule generate: 4560 // 4561 // while (IV <= GlobalUB) { 4562 // <CodeGen rest of pragma>(LB, UB); 4563 // LB += ST; 4564 // UB += ST; 4565 // UB = min(UB, GlobalUB); 4566 // IV = LB; 4567 // } 4568 // 4569 emitCommonSimdLoop( 4570 *this, S, 4571 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 4572 if (isOpenMPSimdDirective(S.getDirectiveKind())) 4573 CGF.EmitOMPSimdInit(S, /*IsMonotonic=*/true); 4574 }, 4575 [&S, &LoopScope, Cond, IncExpr, LoopExit, &CodeGenLoop, 4576 StaticChunked](CodeGenFunction &CGF, PrePostActionTy &) { 4577 CGF.EmitOMPInnerLoop( 4578 S, LoopScope.requiresCleanups(), Cond, IncExpr, 4579 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) { 4580 CodeGenLoop(CGF, S, LoopExit); 4581 }, 4582 [&S, StaticChunked](CodeGenFunction &CGF) { 4583 if (StaticChunked) { 4584 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound()); 4585 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound()); 4586 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound()); 4587 CGF.EmitIgnoredExpr(S.getCombinedInit()); 4588 } 4589 }); 4590 }); 4591 EmitBlock(LoopExit.getBlock()); 4592 // Tell the runtime we are done. 4593 RT.emitForStaticFinish(*this, S.getEndLoc(), S.getDirectiveKind()); 4594 } else { 4595 // Emit the outer loop, which requests its work chunk [LB..UB] from 4596 // runtime and runs the inner loop to process it. 4597 const OMPLoopArguments LoopArguments = { 4598 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this), 4599 IL.getAddress(*this), Chunk}; 4600 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments, 4601 CodeGenLoop); 4602 } 4603 if (isOpenMPSimdDirective(S.getDirectiveKind())) { 4604 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) { 4605 return CGF.Builder.CreateIsNotNull( 4606 CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); 4607 }); 4608 } 4609 if (isOpenMPSimdDirective(S.getDirectiveKind()) && 4610 !isOpenMPParallelDirective(S.getDirectiveKind()) && 4611 !isOpenMPTeamsDirective(S.getDirectiveKind())) { 4612 EmitOMPReductionClauseFinal(S, OMPD_simd); 4613 // Emit post-update of the reduction variables if IsLastIter != 0. 4614 emitPostUpdateForReductionClause( 4615 *this, S, [IL, &S](CodeGenFunction &CGF) { 4616 return CGF.Builder.CreateIsNotNull( 4617 CGF.EmitLoadOfScalar(IL, S.getBeginLoc())); 4618 }); 4619 } 4620 // Emit final copy of the lastprivate variables if IsLastIter != 0. 4621 if (HasLastprivateClause) { 4622 EmitOMPLastprivateClauseFinal( 4623 S, /*NoFinals=*/false, 4624 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc()))); 4625 } 4626 } 4627 4628 // We're now done with the loop, so jump to the continuation block. 4629 if (ContBlock) { 4630 EmitBranch(ContBlock); 4631 EmitBlock(ContBlock, true); 4632 } 4633 } 4634 } 4635 4636 void CodeGenFunction::EmitOMPDistributeDirective( 4637 const OMPDistributeDirective &S) { 4638 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 4639 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); 4640 }; 4641 OMPLexicalScope Scope(*this, S, OMPD_unknown); 4642 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen); 4643 } 4644 4645 static llvm::Function *emitOutlinedOrderedFunction(CodeGenModule &CGM, 4646 const CapturedStmt *S, 4647 SourceLocation Loc) { 4648 CodeGenFunction CGF(CGM, /*suppressNewContext=*/true); 4649 CodeGenFunction::CGCapturedStmtInfo CapStmtInfo; 4650 CGF.CapturedStmtInfo = &CapStmtInfo; 4651 llvm::Function *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S, Loc); 4652 Fn->setDoesNotRecurse(); 4653 return Fn; 4654 } 4655 4656 void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) { 4657 if (S.hasClausesOfKind<OMPDependClause>()) { 4658 assert(!S.getAssociatedStmt() && 4659 "No associated statement must be in ordered depend construct."); 4660 for (const auto *DC : S.getClausesOfKind<OMPDependClause>()) 4661 CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC); 4662 return; 4663 } 4664 const auto *C = S.getSingleClause<OMPSIMDClause>(); 4665 auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF, 4666 PrePostActionTy &Action) { 4667 const CapturedStmt *CS = S.getInnermostCapturedStmt(); 4668 if (C) { 4669 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 4670 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars); 4671 llvm::Function *OutlinedFn = 4672 emitOutlinedOrderedFunction(CGM, CS, S.getBeginLoc()); 4673 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(), 4674 OutlinedFn, CapturedVars); 4675 } else { 4676 Action.Enter(CGF); 4677 CGF.EmitStmt(CS->getCapturedStmt()); 4678 } 4679 }; 4680 OMPLexicalScope Scope(*this, S, OMPD_unknown); 4681 CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getBeginLoc(), !C); 4682 } 4683 4684 static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val, 4685 QualType SrcType, QualType DestType, 4686 SourceLocation Loc) { 4687 assert(CGF.hasScalarEvaluationKind(DestType) && 4688 "DestType must have scalar evaluation kind."); 4689 assert(!Val.isAggregate() && "Must be a scalar or complex."); 4690 return Val.isScalar() ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType, 4691 DestType, Loc) 4692 : CGF.EmitComplexToScalarConversion( 4693 Val.getComplexVal(), SrcType, DestType, Loc); 4694 } 4695 4696 static CodeGenFunction::ComplexPairTy 4697 convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, 4698 QualType DestType, SourceLocation Loc) { 4699 assert(CGF.getEvaluationKind(DestType) == TEK_Complex && 4700 "DestType must have complex evaluation kind."); 4701 CodeGenFunction::ComplexPairTy ComplexVal; 4702 if (Val.isScalar()) { 4703 // Convert the input element to the element type of the complex. 4704 QualType DestElementType = 4705 DestType->castAs<ComplexType>()->getElementType(); 4706 llvm::Value *ScalarVal = CGF.EmitScalarConversion( 4707 Val.getScalarVal(), SrcType, DestElementType, Loc); 4708 ComplexVal = CodeGenFunction::ComplexPairTy( 4709 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType())); 4710 } else { 4711 assert(Val.isComplex() && "Must be a scalar or complex."); 4712 QualType SrcElementType = SrcType->castAs<ComplexType>()->getElementType(); 4713 QualType DestElementType = 4714 DestType->castAs<ComplexType>()->getElementType(); 4715 ComplexVal.first = CGF.EmitScalarConversion( 4716 Val.getComplexVal().first, SrcElementType, DestElementType, Loc); 4717 ComplexVal.second = CGF.EmitScalarConversion( 4718 Val.getComplexVal().second, SrcElementType, DestElementType, Loc); 4719 } 4720 return ComplexVal; 4721 } 4722 4723 static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO, 4724 LValue LVal, RValue RVal) { 4725 if (LVal.isGlobalReg()) 4726 CGF.EmitStoreThroughGlobalRegLValue(RVal, LVal); 4727 else 4728 CGF.EmitAtomicStore(RVal, LVal, AO, LVal.isVolatile(), /*isInit=*/false); 4729 } 4730 4731 static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF, 4732 llvm::AtomicOrdering AO, LValue LVal, 4733 SourceLocation Loc) { 4734 if (LVal.isGlobalReg()) 4735 return CGF.EmitLoadOfLValue(LVal, Loc); 4736 return CGF.EmitAtomicLoad( 4737 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO), 4738 LVal.isVolatile()); 4739 } 4740 4741 void CodeGenFunction::emitOMPSimpleStore(LValue LVal, RValue RVal, 4742 QualType RValTy, SourceLocation Loc) { 4743 switch (getEvaluationKind(LVal.getType())) { 4744 case TEK_Scalar: 4745 EmitStoreThroughLValue(RValue::get(convertToScalarValue( 4746 *this, RVal, RValTy, LVal.getType(), Loc)), 4747 LVal); 4748 break; 4749 case TEK_Complex: 4750 EmitStoreOfComplex( 4751 convertToComplexValue(*this, RVal, RValTy, LVal.getType(), Loc), LVal, 4752 /*isInit=*/false); 4753 break; 4754 case TEK_Aggregate: 4755 llvm_unreachable("Must be a scalar or complex."); 4756 } 4757 } 4758 4759 static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, 4760 const Expr *X, const Expr *V, 4761 SourceLocation Loc) { 4762 // v = x; 4763 assert(V->isLValue() && "V of 'omp atomic read' is not lvalue"); 4764 assert(X->isLValue() && "X of 'omp atomic read' is not lvalue"); 4765 LValue XLValue = CGF.EmitLValue(X); 4766 LValue VLValue = CGF.EmitLValue(V); 4767 RValue Res = emitSimpleAtomicLoad(CGF, AO, XLValue, Loc); 4768 // OpenMP, 2.17.7, atomic Construct 4769 // If the read or capture clause is specified and the acquire, acq_rel, or 4770 // seq_cst clause is specified then the strong flush on exit from the atomic 4771 // operation is also an acquire flush. 4772 switch (AO) { 4773 case llvm::AtomicOrdering::Acquire: 4774 case llvm::AtomicOrdering::AcquireRelease: 4775 case llvm::AtomicOrdering::SequentiallyConsistent: 4776 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc, 4777 llvm::AtomicOrdering::Acquire); 4778 break; 4779 case llvm::AtomicOrdering::Monotonic: 4780 case llvm::AtomicOrdering::Release: 4781 break; 4782 case llvm::AtomicOrdering::NotAtomic: 4783 case llvm::AtomicOrdering::Unordered: 4784 llvm_unreachable("Unexpected ordering."); 4785 } 4786 CGF.emitOMPSimpleStore(VLValue, Res, X->getType().getNonReferenceType(), Loc); 4787 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, V); 4788 } 4789 4790 static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, 4791 llvm::AtomicOrdering AO, const Expr *X, 4792 const Expr *E, SourceLocation Loc) { 4793 // x = expr; 4794 assert(X->isLValue() && "X of 'omp atomic write' is not lvalue"); 4795 emitSimpleAtomicStore(CGF, AO, CGF.EmitLValue(X), CGF.EmitAnyExpr(E)); 4796 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X); 4797 // OpenMP, 2.17.7, atomic Construct 4798 // If the write, update, or capture clause is specified and the release, 4799 // acq_rel, or seq_cst clause is specified then the strong flush on entry to 4800 // the atomic operation is also a release flush. 4801 switch (AO) { 4802 case llvm::AtomicOrdering::Release: 4803 case llvm::AtomicOrdering::AcquireRelease: 4804 case llvm::AtomicOrdering::SequentiallyConsistent: 4805 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc, 4806 llvm::AtomicOrdering::Release); 4807 break; 4808 case llvm::AtomicOrdering::Acquire: 4809 case llvm::AtomicOrdering::Monotonic: 4810 break; 4811 case llvm::AtomicOrdering::NotAtomic: 4812 case llvm::AtomicOrdering::Unordered: 4813 llvm_unreachable("Unexpected ordering."); 4814 } 4815 } 4816 4817 static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, 4818 RValue Update, 4819 BinaryOperatorKind BO, 4820 llvm::AtomicOrdering AO, 4821 bool IsXLHSInRHSPart) { 4822 ASTContext &Context = CGF.getContext(); 4823 // Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x' 4824 // expression is simple and atomic is allowed for the given type for the 4825 // target platform. 4826 if (BO == BO_Comma || !Update.isScalar() || 4827 !Update.getScalarVal()->getType()->isIntegerTy() || !X.isSimple() || 4828 (!isa<llvm::ConstantInt>(Update.getScalarVal()) && 4829 (Update.getScalarVal()->getType() != 4830 X.getAddress(CGF).getElementType())) || 4831 !X.getAddress(CGF).getElementType()->isIntegerTy() || 4832 !Context.getTargetInfo().hasBuiltinAtomic( 4833 Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment()))) 4834 return std::make_pair(false, RValue::get(nullptr)); 4835 4836 llvm::AtomicRMWInst::BinOp RMWOp; 4837 switch (BO) { 4838 case BO_Add: 4839 RMWOp = llvm::AtomicRMWInst::Add; 4840 break; 4841 case BO_Sub: 4842 if (!IsXLHSInRHSPart) 4843 return std::make_pair(false, RValue::get(nullptr)); 4844 RMWOp = llvm::AtomicRMWInst::Sub; 4845 break; 4846 case BO_And: 4847 RMWOp = llvm::AtomicRMWInst::And; 4848 break; 4849 case BO_Or: 4850 RMWOp = llvm::AtomicRMWInst::Or; 4851 break; 4852 case BO_Xor: 4853 RMWOp = llvm::AtomicRMWInst::Xor; 4854 break; 4855 case BO_LT: 4856 RMWOp = X.getType()->hasSignedIntegerRepresentation() 4857 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min 4858 : llvm::AtomicRMWInst::Max) 4859 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin 4860 : llvm::AtomicRMWInst::UMax); 4861 break; 4862 case BO_GT: 4863 RMWOp = X.getType()->hasSignedIntegerRepresentation() 4864 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max 4865 : llvm::AtomicRMWInst::Min) 4866 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax 4867 : llvm::AtomicRMWInst::UMin); 4868 break; 4869 case BO_Assign: 4870 RMWOp = llvm::AtomicRMWInst::Xchg; 4871 break; 4872 case BO_Mul: 4873 case BO_Div: 4874 case BO_Rem: 4875 case BO_Shl: 4876 case BO_Shr: 4877 case BO_LAnd: 4878 case BO_LOr: 4879 return std::make_pair(false, RValue::get(nullptr)); 4880 case BO_PtrMemD: 4881 case BO_PtrMemI: 4882 case BO_LE: 4883 case BO_GE: 4884 case BO_EQ: 4885 case BO_NE: 4886 case BO_Cmp: 4887 case BO_AddAssign: 4888 case BO_SubAssign: 4889 case BO_AndAssign: 4890 case BO_OrAssign: 4891 case BO_XorAssign: 4892 case BO_MulAssign: 4893 case BO_DivAssign: 4894 case BO_RemAssign: 4895 case BO_ShlAssign: 4896 case BO_ShrAssign: 4897 case BO_Comma: 4898 llvm_unreachable("Unsupported atomic update operation"); 4899 } 4900 llvm::Value *UpdateVal = Update.getScalarVal(); 4901 if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) { 4902 UpdateVal = CGF.Builder.CreateIntCast( 4903 IC, X.getAddress(CGF).getElementType(), 4904 X.getType()->hasSignedIntegerRepresentation()); 4905 } 4906 llvm::Value *Res = 4907 CGF.Builder.CreateAtomicRMW(RMWOp, X.getPointer(CGF), UpdateVal, AO); 4908 return std::make_pair(true, RValue::get(Res)); 4909 } 4910 4911 std::pair<bool, RValue> CodeGenFunction::EmitOMPAtomicSimpleUpdateExpr( 4912 LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, 4913 llvm::AtomicOrdering AO, SourceLocation Loc, 4914 const llvm::function_ref<RValue(RValue)> CommonGen) { 4915 // Update expressions are allowed to have the following forms: 4916 // x binop= expr; -> xrval + expr; 4917 // x++, ++x -> xrval + 1; 4918 // x--, --x -> xrval - 1; 4919 // x = x binop expr; -> xrval binop expr 4920 // x = expr Op x; - > expr binop xrval; 4921 auto Res = emitOMPAtomicRMW(*this, X, E, BO, AO, IsXLHSInRHSPart); 4922 if (!Res.first) { 4923 if (X.isGlobalReg()) { 4924 // Emit an update expression: 'xrval' binop 'expr' or 'expr' binop 4925 // 'xrval'. 4926 EmitStoreThroughLValue(CommonGen(EmitLoadOfLValue(X, Loc)), X); 4927 } else { 4928 // Perform compare-and-swap procedure. 4929 EmitAtomicUpdate(X, AO, CommonGen, X.getType().isVolatileQualified()); 4930 } 4931 } 4932 return Res; 4933 } 4934 4935 static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, 4936 llvm::AtomicOrdering AO, const Expr *X, 4937 const Expr *E, const Expr *UE, 4938 bool IsXLHSInRHSPart, SourceLocation Loc) { 4939 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) && 4940 "Update expr in 'atomic update' must be a binary operator."); 4941 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts()); 4942 // Update expressions are allowed to have the following forms: 4943 // x binop= expr; -> xrval + expr; 4944 // x++, ++x -> xrval + 1; 4945 // x--, --x -> xrval - 1; 4946 // x = x binop expr; -> xrval binop expr 4947 // x = expr Op x; - > expr binop xrval; 4948 assert(X->isLValue() && "X of 'omp atomic update' is not lvalue"); 4949 LValue XLValue = CGF.EmitLValue(X); 4950 RValue ExprRValue = CGF.EmitAnyExpr(E); 4951 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts()); 4952 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts()); 4953 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS; 4954 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS; 4955 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) { 4956 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue); 4957 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue); 4958 return CGF.EmitAnyExpr(UE); 4959 }; 4960 (void)CGF.EmitOMPAtomicSimpleUpdateExpr( 4961 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen); 4962 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X); 4963 // OpenMP, 2.17.7, atomic Construct 4964 // If the write, update, or capture clause is specified and the release, 4965 // acq_rel, or seq_cst clause is specified then the strong flush on entry to 4966 // the atomic operation is also a release flush. 4967 switch (AO) { 4968 case llvm::AtomicOrdering::Release: 4969 case llvm::AtomicOrdering::AcquireRelease: 4970 case llvm::AtomicOrdering::SequentiallyConsistent: 4971 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc, 4972 llvm::AtomicOrdering::Release); 4973 break; 4974 case llvm::AtomicOrdering::Acquire: 4975 case llvm::AtomicOrdering::Monotonic: 4976 break; 4977 case llvm::AtomicOrdering::NotAtomic: 4978 case llvm::AtomicOrdering::Unordered: 4979 llvm_unreachable("Unexpected ordering."); 4980 } 4981 } 4982 4983 static RValue convertToType(CodeGenFunction &CGF, RValue Value, 4984 QualType SourceType, QualType ResType, 4985 SourceLocation Loc) { 4986 switch (CGF.getEvaluationKind(ResType)) { 4987 case TEK_Scalar: 4988 return RValue::get( 4989 convertToScalarValue(CGF, Value, SourceType, ResType, Loc)); 4990 case TEK_Complex: { 4991 auto Res = convertToComplexValue(CGF, Value, SourceType, ResType, Loc); 4992 return RValue::getComplex(Res.first, Res.second); 4993 } 4994 case TEK_Aggregate: 4995 break; 4996 } 4997 llvm_unreachable("Must be a scalar or complex."); 4998 } 4999 5000 static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, 5001 llvm::AtomicOrdering AO, 5002 bool IsPostfixUpdate, const Expr *V, 5003 const Expr *X, const Expr *E, 5004 const Expr *UE, bool IsXLHSInRHSPart, 5005 SourceLocation Loc) { 5006 assert(X->isLValue() && "X of 'omp atomic capture' is not lvalue"); 5007 assert(V->isLValue() && "V of 'omp atomic capture' is not lvalue"); 5008 RValue NewVVal; 5009 LValue VLValue = CGF.EmitLValue(V); 5010 LValue XLValue = CGF.EmitLValue(X); 5011 RValue ExprRValue = CGF.EmitAnyExpr(E); 5012 QualType NewVValType; 5013 if (UE) { 5014 // 'x' is updated with some additional value. 5015 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) && 5016 "Update expr in 'atomic capture' must be a binary operator."); 5017 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts()); 5018 // Update expressions are allowed to have the following forms: 5019 // x binop= expr; -> xrval + expr; 5020 // x++, ++x -> xrval + 1; 5021 // x--, --x -> xrval - 1; 5022 // x = x binop expr; -> xrval binop expr 5023 // x = expr Op x; - > expr binop xrval; 5024 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts()); 5025 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts()); 5026 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS; 5027 NewVValType = XRValExpr->getType(); 5028 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS; 5029 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr, 5030 IsPostfixUpdate](RValue XRValue) { 5031 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue); 5032 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue); 5033 RValue Res = CGF.EmitAnyExpr(UE); 5034 NewVVal = IsPostfixUpdate ? XRValue : Res; 5035 return Res; 5036 }; 5037 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr( 5038 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen); 5039 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X); 5040 if (Res.first) { 5041 // 'atomicrmw' instruction was generated. 5042 if (IsPostfixUpdate) { 5043 // Use old value from 'atomicrmw'. 5044 NewVVal = Res.second; 5045 } else { 5046 // 'atomicrmw' does not provide new value, so evaluate it using old 5047 // value of 'x'. 5048 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue); 5049 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second); 5050 NewVVal = CGF.EmitAnyExpr(UE); 5051 } 5052 } 5053 } else { 5054 // 'x' is simply rewritten with some 'expr'. 5055 NewVValType = X->getType().getNonReferenceType(); 5056 ExprRValue = convertToType(CGF, ExprRValue, E->getType(), 5057 X->getType().getNonReferenceType(), Loc); 5058 auto &&Gen = [&NewVVal, ExprRValue](RValue XRValue) { 5059 NewVVal = XRValue; 5060 return ExprRValue; 5061 }; 5062 // Try to perform atomicrmw xchg, otherwise simple exchange. 5063 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr( 5064 XLValue, ExprRValue, /*BO=*/BO_Assign, /*IsXLHSInRHSPart=*/false, AO, 5065 Loc, Gen); 5066 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X); 5067 if (Res.first) { 5068 // 'atomicrmw' instruction was generated. 5069 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue; 5070 } 5071 } 5072 // Emit post-update store to 'v' of old/new 'x' value. 5073 CGF.emitOMPSimpleStore(VLValue, NewVVal, NewVValType, Loc); 5074 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, V); 5075 // OpenMP, 2.17.7, atomic Construct 5076 // If the write, update, or capture clause is specified and the release, 5077 // acq_rel, or seq_cst clause is specified then the strong flush on entry to 5078 // the atomic operation is also a release flush. 5079 // If the read or capture clause is specified and the acquire, acq_rel, or 5080 // seq_cst clause is specified then the strong flush on exit from the atomic 5081 // operation is also an acquire flush. 5082 switch (AO) { 5083 case llvm::AtomicOrdering::Release: 5084 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc, 5085 llvm::AtomicOrdering::Release); 5086 break; 5087 case llvm::AtomicOrdering::Acquire: 5088 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc, 5089 llvm::AtomicOrdering::Acquire); 5090 break; 5091 case llvm::AtomicOrdering::AcquireRelease: 5092 case llvm::AtomicOrdering::SequentiallyConsistent: 5093 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc, 5094 llvm::AtomicOrdering::AcquireRelease); 5095 break; 5096 case llvm::AtomicOrdering::Monotonic: 5097 break; 5098 case llvm::AtomicOrdering::NotAtomic: 5099 case llvm::AtomicOrdering::Unordered: 5100 llvm_unreachable("Unexpected ordering."); 5101 } 5102 } 5103 5104 static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, 5105 llvm::AtomicOrdering AO, bool IsPostfixUpdate, 5106 const Expr *X, const Expr *V, const Expr *E, 5107 const Expr *UE, bool IsXLHSInRHSPart, 5108 SourceLocation Loc) { 5109 switch (Kind) { 5110 case OMPC_read: 5111 emitOMPAtomicReadExpr(CGF, AO, X, V, Loc); 5112 break; 5113 case OMPC_write: 5114 emitOMPAtomicWriteExpr(CGF, AO, X, E, Loc); 5115 break; 5116 case OMPC_unknown: 5117 case OMPC_update: 5118 emitOMPAtomicUpdateExpr(CGF, AO, X, E, UE, IsXLHSInRHSPart, Loc); 5119 break; 5120 case OMPC_capture: 5121 emitOMPAtomicCaptureExpr(CGF, AO, IsPostfixUpdate, V, X, E, UE, 5122 IsXLHSInRHSPart, Loc); 5123 break; 5124 case OMPC_if: 5125 case OMPC_final: 5126 case OMPC_num_threads: 5127 case OMPC_private: 5128 case OMPC_firstprivate: 5129 case OMPC_lastprivate: 5130 case OMPC_reduction: 5131 case OMPC_task_reduction: 5132 case OMPC_in_reduction: 5133 case OMPC_safelen: 5134 case OMPC_simdlen: 5135 case OMPC_allocator: 5136 case OMPC_allocate: 5137 case OMPC_collapse: 5138 case OMPC_default: 5139 case OMPC_seq_cst: 5140 case OMPC_acq_rel: 5141 case OMPC_acquire: 5142 case OMPC_release: 5143 case OMPC_relaxed: 5144 case OMPC_shared: 5145 case OMPC_linear: 5146 case OMPC_aligned: 5147 case OMPC_copyin: 5148 case OMPC_copyprivate: 5149 case OMPC_flush: 5150 case OMPC_depobj: 5151 case OMPC_proc_bind: 5152 case OMPC_schedule: 5153 case OMPC_ordered: 5154 case OMPC_nowait: 5155 case OMPC_untied: 5156 case OMPC_threadprivate: 5157 case OMPC_depend: 5158 case OMPC_mergeable: 5159 case OMPC_device: 5160 case OMPC_threads: 5161 case OMPC_simd: 5162 case OMPC_map: 5163 case OMPC_num_teams: 5164 case OMPC_thread_limit: 5165 case OMPC_priority: 5166 case OMPC_grainsize: 5167 case OMPC_nogroup: 5168 case OMPC_num_tasks: 5169 case OMPC_hint: 5170 case OMPC_dist_schedule: 5171 case OMPC_defaultmap: 5172 case OMPC_uniform: 5173 case OMPC_to: 5174 case OMPC_from: 5175 case OMPC_use_device_ptr: 5176 case OMPC_use_device_addr: 5177 case OMPC_is_device_ptr: 5178 case OMPC_unified_address: 5179 case OMPC_unified_shared_memory: 5180 case OMPC_reverse_offload: 5181 case OMPC_dynamic_allocators: 5182 case OMPC_atomic_default_mem_order: 5183 case OMPC_device_type: 5184 case OMPC_match: 5185 case OMPC_nontemporal: 5186 case OMPC_order: 5187 case OMPC_destroy: 5188 case OMPC_detach: 5189 case OMPC_inclusive: 5190 case OMPC_exclusive: 5191 case OMPC_uses_allocators: 5192 case OMPC_affinity: 5193 llvm_unreachable("Clause is not allowed in 'omp atomic'."); 5194 } 5195 } 5196 5197 void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) { 5198 llvm::AtomicOrdering AO = llvm::AtomicOrdering::Monotonic; 5199 bool MemOrderingSpecified = false; 5200 if (S.getSingleClause<OMPSeqCstClause>()) { 5201 AO = llvm::AtomicOrdering::SequentiallyConsistent; 5202 MemOrderingSpecified = true; 5203 } else if (S.getSingleClause<OMPAcqRelClause>()) { 5204 AO = llvm::AtomicOrdering::AcquireRelease; 5205 MemOrderingSpecified = true; 5206 } else if (S.getSingleClause<OMPAcquireClause>()) { 5207 AO = llvm::AtomicOrdering::Acquire; 5208 MemOrderingSpecified = true; 5209 } else if (S.getSingleClause<OMPReleaseClause>()) { 5210 AO = llvm::AtomicOrdering::Release; 5211 MemOrderingSpecified = true; 5212 } else if (S.getSingleClause<OMPRelaxedClause>()) { 5213 AO = llvm::AtomicOrdering::Monotonic; 5214 MemOrderingSpecified = true; 5215 } 5216 OpenMPClauseKind Kind = OMPC_unknown; 5217 for (const OMPClause *C : S.clauses()) { 5218 // Find first clause (skip seq_cst|acq_rel|aqcuire|release|relaxed clause, 5219 // if it is first). 5220 if (C->getClauseKind() != OMPC_seq_cst && 5221 C->getClauseKind() != OMPC_acq_rel && 5222 C->getClauseKind() != OMPC_acquire && 5223 C->getClauseKind() != OMPC_release && 5224 C->getClauseKind() != OMPC_relaxed) { 5225 Kind = C->getClauseKind(); 5226 break; 5227 } 5228 } 5229 if (!MemOrderingSpecified) { 5230 llvm::AtomicOrdering DefaultOrder = 5231 CGM.getOpenMPRuntime().getDefaultMemoryOrdering(); 5232 if (DefaultOrder == llvm::AtomicOrdering::Monotonic || 5233 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent || 5234 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease && 5235 Kind == OMPC_capture)) { 5236 AO = DefaultOrder; 5237 } else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) { 5238 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) { 5239 AO = llvm::AtomicOrdering::Release; 5240 } else if (Kind == OMPC_read) { 5241 assert(Kind == OMPC_read && "Unexpected atomic kind."); 5242 AO = llvm::AtomicOrdering::Acquire; 5243 } 5244 } 5245 } 5246 5247 const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers(); 5248 if (const auto *FE = dyn_cast<FullExpr>(CS)) 5249 enterFullExpression(FE); 5250 // Processing for statements under 'atomic capture'. 5251 if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) { 5252 for (const Stmt *C : Compound->body()) { 5253 if (const auto *FE = dyn_cast<FullExpr>(C)) 5254 enterFullExpression(FE); 5255 } 5256 } 5257 5258 auto &&CodeGen = [&S, Kind, AO, CS](CodeGenFunction &CGF, 5259 PrePostActionTy &) { 5260 CGF.EmitStopPoint(CS); 5261 emitOMPAtomicExpr(CGF, Kind, AO, S.isPostfixUpdate(), S.getX(), S.getV(), 5262 S.getExpr(), S.getUpdateExpr(), S.isXLHSInRHSPart(), 5263 S.getBeginLoc()); 5264 }; 5265 OMPLexicalScope Scope(*this, S, OMPD_unknown); 5266 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen); 5267 } 5268 5269 static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, 5270 const OMPExecutableDirective &S, 5271 const RegionCodeGenTy &CodeGen) { 5272 assert(isOpenMPTargetExecutionDirective(S.getDirectiveKind())); 5273 CodeGenModule &CGM = CGF.CGM; 5274 5275 // On device emit this construct as inlined code. 5276 if (CGM.getLangOpts().OpenMPIsDevice) { 5277 OMPLexicalScope Scope(CGF, S, OMPD_target); 5278 CGM.getOpenMPRuntime().emitInlinedDirective( 5279 CGF, OMPD_target, [&S](CodeGenFunction &CGF, PrePostActionTy &) { 5280 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); 5281 }); 5282 return; 5283 } 5284 5285 auto LPCRegion = 5286 CGOpenMPRuntime::LastprivateConditionalRAII::disable(CGF, S); 5287 llvm::Function *Fn = nullptr; 5288 llvm::Constant *FnID = nullptr; 5289 5290 const Expr *IfCond = nullptr; 5291 // Check for the at most one if clause associated with the target region. 5292 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { 5293 if (C->getNameModifier() == OMPD_unknown || 5294 C->getNameModifier() == OMPD_target) { 5295 IfCond = C->getCondition(); 5296 break; 5297 } 5298 } 5299 5300 // Check if we have any device clause associated with the directive. 5301 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device( 5302 nullptr, OMPC_DEVICE_unknown); 5303 if (auto *C = S.getSingleClause<OMPDeviceClause>()) 5304 Device.setPointerAndInt(C->getDevice(), C->getModifier()); 5305 5306 // Check if we have an if clause whose conditional always evaluates to false 5307 // or if we do not have any targets specified. If so the target region is not 5308 // an offload entry point. 5309 bool IsOffloadEntry = true; 5310 if (IfCond) { 5311 bool Val; 5312 if (CGF.ConstantFoldsToSimpleInteger(IfCond, Val) && !Val) 5313 IsOffloadEntry = false; 5314 } 5315 if (CGM.getLangOpts().OMPTargetTriples.empty()) 5316 IsOffloadEntry = false; 5317 5318 assert(CGF.CurFuncDecl && "No parent declaration for target region!"); 5319 StringRef ParentName; 5320 // In case we have Ctors/Dtors we use the complete type variant to produce 5321 // the mangling of the device outlined kernel. 5322 if (const auto *D = dyn_cast<CXXConstructorDecl>(CGF.CurFuncDecl)) 5323 ParentName = CGM.getMangledName(GlobalDecl(D, Ctor_Complete)); 5324 else if (const auto *D = dyn_cast<CXXDestructorDecl>(CGF.CurFuncDecl)) 5325 ParentName = CGM.getMangledName(GlobalDecl(D, Dtor_Complete)); 5326 else 5327 ParentName = 5328 CGM.getMangledName(GlobalDecl(cast<FunctionDecl>(CGF.CurFuncDecl))); 5329 5330 // Emit target region as a standalone region. 5331 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID, 5332 IsOffloadEntry, CodeGen); 5333 OMPLexicalScope Scope(CGF, S, OMPD_task); 5334 auto &&SizeEmitter = 5335 [IsOffloadEntry](CodeGenFunction &CGF, 5336 const OMPLoopDirective &D) -> llvm::Value * { 5337 if (IsOffloadEntry) { 5338 OMPLoopScope(CGF, D); 5339 // Emit calculation of the iterations count. 5340 llvm::Value *NumIterations = CGF.EmitScalarExpr(D.getNumIterations()); 5341 NumIterations = CGF.Builder.CreateIntCast(NumIterations, CGF.Int64Ty, 5342 /*isSigned=*/false); 5343 return NumIterations; 5344 } 5345 return nullptr; 5346 }; 5347 CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device, 5348 SizeEmitter); 5349 } 5350 5351 static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, 5352 PrePostActionTy &Action) { 5353 Action.Enter(CGF); 5354 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5355 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); 5356 CGF.EmitOMPPrivateClause(S, PrivateScope); 5357 (void)PrivateScope.Privatize(); 5358 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) 5359 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); 5360 5361 CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt()); 5362 } 5363 5364 void CodeGenFunction::EmitOMPTargetDeviceFunction(CodeGenModule &CGM, 5365 StringRef ParentName, 5366 const OMPTargetDirective &S) { 5367 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5368 emitTargetRegion(CGF, S, Action); 5369 }; 5370 llvm::Function *Fn; 5371 llvm::Constant *Addr; 5372 // Emit target region as a standalone region. 5373 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 5374 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 5375 assert(Fn && Addr && "Target device function emission failed."); 5376 } 5377 5378 void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &S) { 5379 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5380 emitTargetRegion(CGF, S, Action); 5381 }; 5382 emitCommonOMPTargetDirective(*this, S, CodeGen); 5383 } 5384 5385 static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF, 5386 const OMPExecutableDirective &S, 5387 OpenMPDirectiveKind InnermostKind, 5388 const RegionCodeGenTy &CodeGen) { 5389 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams); 5390 llvm::Function *OutlinedFn = 5391 CGF.CGM.getOpenMPRuntime().emitTeamsOutlinedFunction( 5392 S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen); 5393 5394 const auto *NT = S.getSingleClause<OMPNumTeamsClause>(); 5395 const auto *TL = S.getSingleClause<OMPThreadLimitClause>(); 5396 if (NT || TL) { 5397 const Expr *NumTeams = NT ? NT->getNumTeams() : nullptr; 5398 const Expr *ThreadLimit = TL ? TL->getThreadLimit() : nullptr; 5399 5400 CGF.CGM.getOpenMPRuntime().emitNumTeamsClause(CGF, NumTeams, ThreadLimit, 5401 S.getBeginLoc()); 5402 } 5403 5404 OMPTeamsScope Scope(CGF, S); 5405 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 5406 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars); 5407 CGF.CGM.getOpenMPRuntime().emitTeamsCall(CGF, S, S.getBeginLoc(), OutlinedFn, 5408 CapturedVars); 5409 } 5410 5411 void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &S) { 5412 // Emit teams region as a standalone region. 5413 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5414 Action.Enter(CGF); 5415 OMPPrivateScope PrivateScope(CGF); 5416 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); 5417 CGF.EmitOMPPrivateClause(S, PrivateScope); 5418 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 5419 (void)PrivateScope.Privatize(); 5420 CGF.EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt()); 5421 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); 5422 }; 5423 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen); 5424 emitPostUpdateForReductionClause(*this, S, 5425 [](CodeGenFunction &) { return nullptr; }); 5426 } 5427 5428 static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action, 5429 const OMPTargetTeamsDirective &S) { 5430 auto *CS = S.getCapturedStmt(OMPD_teams); 5431 Action.Enter(CGF); 5432 // Emit teams region as a standalone region. 5433 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) { 5434 Action.Enter(CGF); 5435 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5436 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); 5437 CGF.EmitOMPPrivateClause(S, PrivateScope); 5438 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 5439 (void)PrivateScope.Privatize(); 5440 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) 5441 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); 5442 CGF.EmitStmt(CS->getCapturedStmt()); 5443 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); 5444 }; 5445 emitCommonOMPTeamsDirective(CGF, S, OMPD_teams, CodeGen); 5446 emitPostUpdateForReductionClause(CGF, S, 5447 [](CodeGenFunction &) { return nullptr; }); 5448 } 5449 5450 void CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 5451 CodeGenModule &CGM, StringRef ParentName, 5452 const OMPTargetTeamsDirective &S) { 5453 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5454 emitTargetTeamsRegion(CGF, Action, S); 5455 }; 5456 llvm::Function *Fn; 5457 llvm::Constant *Addr; 5458 // Emit target region as a standalone region. 5459 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 5460 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 5461 assert(Fn && Addr && "Target device function emission failed."); 5462 } 5463 5464 void CodeGenFunction::EmitOMPTargetTeamsDirective( 5465 const OMPTargetTeamsDirective &S) { 5466 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5467 emitTargetTeamsRegion(CGF, Action, S); 5468 }; 5469 emitCommonOMPTargetDirective(*this, S, CodeGen); 5470 } 5471 5472 static void 5473 emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action, 5474 const OMPTargetTeamsDistributeDirective &S) { 5475 Action.Enter(CGF); 5476 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 5477 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); 5478 }; 5479 5480 // Emit teams region as a standalone region. 5481 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, 5482 PrePostActionTy &Action) { 5483 Action.Enter(CGF); 5484 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5485 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 5486 (void)PrivateScope.Privatize(); 5487 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute, 5488 CodeGenDistribute); 5489 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); 5490 }; 5491 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute, CodeGen); 5492 emitPostUpdateForReductionClause(CGF, S, 5493 [](CodeGenFunction &) { return nullptr; }); 5494 } 5495 5496 void CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 5497 CodeGenModule &CGM, StringRef ParentName, 5498 const OMPTargetTeamsDistributeDirective &S) { 5499 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5500 emitTargetTeamsDistributeRegion(CGF, Action, S); 5501 }; 5502 llvm::Function *Fn; 5503 llvm::Constant *Addr; 5504 // Emit target region as a standalone region. 5505 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 5506 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 5507 assert(Fn && Addr && "Target device function emission failed."); 5508 } 5509 5510 void CodeGenFunction::EmitOMPTargetTeamsDistributeDirective( 5511 const OMPTargetTeamsDistributeDirective &S) { 5512 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5513 emitTargetTeamsDistributeRegion(CGF, Action, S); 5514 }; 5515 emitCommonOMPTargetDirective(*this, S, CodeGen); 5516 } 5517 5518 static void emitTargetTeamsDistributeSimdRegion( 5519 CodeGenFunction &CGF, PrePostActionTy &Action, 5520 const OMPTargetTeamsDistributeSimdDirective &S) { 5521 Action.Enter(CGF); 5522 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 5523 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); 5524 }; 5525 5526 // Emit teams region as a standalone region. 5527 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, 5528 PrePostActionTy &Action) { 5529 Action.Enter(CGF); 5530 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5531 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 5532 (void)PrivateScope.Privatize(); 5533 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute, 5534 CodeGenDistribute); 5535 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); 5536 }; 5537 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_simd, CodeGen); 5538 emitPostUpdateForReductionClause(CGF, S, 5539 [](CodeGenFunction &) { return nullptr; }); 5540 } 5541 5542 void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 5543 CodeGenModule &CGM, StringRef ParentName, 5544 const OMPTargetTeamsDistributeSimdDirective &S) { 5545 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5546 emitTargetTeamsDistributeSimdRegion(CGF, Action, S); 5547 }; 5548 llvm::Function *Fn; 5549 llvm::Constant *Addr; 5550 // Emit target region as a standalone region. 5551 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 5552 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 5553 assert(Fn && Addr && "Target device function emission failed."); 5554 } 5555 5556 void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDirective( 5557 const OMPTargetTeamsDistributeSimdDirective &S) { 5558 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5559 emitTargetTeamsDistributeSimdRegion(CGF, Action, S); 5560 }; 5561 emitCommonOMPTargetDirective(*this, S, CodeGen); 5562 } 5563 5564 void CodeGenFunction::EmitOMPTeamsDistributeDirective( 5565 const OMPTeamsDistributeDirective &S) { 5566 5567 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 5568 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); 5569 }; 5570 5571 // Emit teams region as a standalone region. 5572 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, 5573 PrePostActionTy &Action) { 5574 Action.Enter(CGF); 5575 OMPPrivateScope PrivateScope(CGF); 5576 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 5577 (void)PrivateScope.Privatize(); 5578 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute, 5579 CodeGenDistribute); 5580 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); 5581 }; 5582 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen); 5583 emitPostUpdateForReductionClause(*this, S, 5584 [](CodeGenFunction &) { return nullptr; }); 5585 } 5586 5587 void CodeGenFunction::EmitOMPTeamsDistributeSimdDirective( 5588 const OMPTeamsDistributeSimdDirective &S) { 5589 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 5590 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc()); 5591 }; 5592 5593 // Emit teams region as a standalone region. 5594 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, 5595 PrePostActionTy &Action) { 5596 Action.Enter(CGF); 5597 OMPPrivateScope PrivateScope(CGF); 5598 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 5599 (void)PrivateScope.Privatize(); 5600 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd, 5601 CodeGenDistribute); 5602 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); 5603 }; 5604 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_simd, CodeGen); 5605 emitPostUpdateForReductionClause(*this, S, 5606 [](CodeGenFunction &) { return nullptr; }); 5607 } 5608 5609 void CodeGenFunction::EmitOMPTeamsDistributeParallelForDirective( 5610 const OMPTeamsDistributeParallelForDirective &S) { 5611 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 5612 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, 5613 S.getDistInc()); 5614 }; 5615 5616 // Emit teams region as a standalone region. 5617 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, 5618 PrePostActionTy &Action) { 5619 Action.Enter(CGF); 5620 OMPPrivateScope PrivateScope(CGF); 5621 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 5622 (void)PrivateScope.Privatize(); 5623 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute, 5624 CodeGenDistribute); 5625 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); 5626 }; 5627 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for, CodeGen); 5628 emitPostUpdateForReductionClause(*this, S, 5629 [](CodeGenFunction &) { return nullptr; }); 5630 } 5631 5632 void CodeGenFunction::EmitOMPTeamsDistributeParallelForSimdDirective( 5633 const OMPTeamsDistributeParallelForSimdDirective &S) { 5634 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 5635 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, 5636 S.getDistInc()); 5637 }; 5638 5639 // Emit teams region as a standalone region. 5640 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF, 5641 PrePostActionTy &Action) { 5642 Action.Enter(CGF); 5643 OMPPrivateScope PrivateScope(CGF); 5644 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 5645 (void)PrivateScope.Privatize(); 5646 CGF.CGM.getOpenMPRuntime().emitInlinedDirective( 5647 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false); 5648 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); 5649 }; 5650 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for_simd, 5651 CodeGen); 5652 emitPostUpdateForReductionClause(*this, S, 5653 [](CodeGenFunction &) { return nullptr; }); 5654 } 5655 5656 static void emitTargetTeamsDistributeParallelForRegion( 5657 CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S, 5658 PrePostActionTy &Action) { 5659 Action.Enter(CGF); 5660 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 5661 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, 5662 S.getDistInc()); 5663 }; 5664 5665 // Emit teams region as a standalone region. 5666 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF, 5667 PrePostActionTy &Action) { 5668 Action.Enter(CGF); 5669 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5670 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 5671 (void)PrivateScope.Privatize(); 5672 CGF.CGM.getOpenMPRuntime().emitInlinedDirective( 5673 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false); 5674 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); 5675 }; 5676 5677 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for, 5678 CodeGenTeams); 5679 emitPostUpdateForReductionClause(CGF, S, 5680 [](CodeGenFunction &) { return nullptr; }); 5681 } 5682 5683 void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 5684 CodeGenModule &CGM, StringRef ParentName, 5685 const OMPTargetTeamsDistributeParallelForDirective &S) { 5686 // Emit SPMD target teams distribute parallel for region as a standalone 5687 // region. 5688 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5689 emitTargetTeamsDistributeParallelForRegion(CGF, S, Action); 5690 }; 5691 llvm::Function *Fn; 5692 llvm::Constant *Addr; 5693 // Emit target region as a standalone region. 5694 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 5695 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 5696 assert(Fn && Addr && "Target device function emission failed."); 5697 } 5698 5699 void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDirective( 5700 const OMPTargetTeamsDistributeParallelForDirective &S) { 5701 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5702 emitTargetTeamsDistributeParallelForRegion(CGF, S, Action); 5703 }; 5704 emitCommonOMPTargetDirective(*this, S, CodeGen); 5705 } 5706 5707 static void emitTargetTeamsDistributeParallelForSimdRegion( 5708 CodeGenFunction &CGF, 5709 const OMPTargetTeamsDistributeParallelForSimdDirective &S, 5710 PrePostActionTy &Action) { 5711 Action.Enter(CGF); 5712 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 5713 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined, 5714 S.getDistInc()); 5715 }; 5716 5717 // Emit teams region as a standalone region. 5718 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF, 5719 PrePostActionTy &Action) { 5720 Action.Enter(CGF); 5721 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5722 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 5723 (void)PrivateScope.Privatize(); 5724 CGF.CGM.getOpenMPRuntime().emitInlinedDirective( 5725 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false); 5726 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams); 5727 }; 5728 5729 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for_simd, 5730 CodeGenTeams); 5731 emitPostUpdateForReductionClause(CGF, S, 5732 [](CodeGenFunction &) { return nullptr; }); 5733 } 5734 5735 void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 5736 CodeGenModule &CGM, StringRef ParentName, 5737 const OMPTargetTeamsDistributeParallelForSimdDirective &S) { 5738 // Emit SPMD target teams distribute parallel for simd region as a standalone 5739 // region. 5740 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5741 emitTargetTeamsDistributeParallelForSimdRegion(CGF, S, Action); 5742 }; 5743 llvm::Function *Fn; 5744 llvm::Constant *Addr; 5745 // Emit target region as a standalone region. 5746 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 5747 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 5748 assert(Fn && Addr && "Target device function emission failed."); 5749 } 5750 5751 void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDirective( 5752 const OMPTargetTeamsDistributeParallelForSimdDirective &S) { 5753 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 5754 emitTargetTeamsDistributeParallelForSimdRegion(CGF, S, Action); 5755 }; 5756 emitCommonOMPTargetDirective(*this, S, CodeGen); 5757 } 5758 5759 void CodeGenFunction::EmitOMPCancellationPointDirective( 5760 const OMPCancellationPointDirective &S) { 5761 CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getBeginLoc(), 5762 S.getCancelRegion()); 5763 } 5764 5765 void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) { 5766 const Expr *IfCond = nullptr; 5767 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { 5768 if (C->getNameModifier() == OMPD_unknown || 5769 C->getNameModifier() == OMPD_cancel) { 5770 IfCond = C->getCondition(); 5771 break; 5772 } 5773 } 5774 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) { 5775 // TODO: This check is necessary as we only generate `omp parallel` through 5776 // the OpenMPIRBuilder for now. 5777 if (S.getCancelRegion() == OMPD_parallel) { 5778 llvm::Value *IfCondition = nullptr; 5779 if (IfCond) 5780 IfCondition = EmitScalarExpr(IfCond, 5781 /*IgnoreResultAssign=*/true); 5782 return Builder.restoreIP( 5783 OMPBuilder->CreateCancel(Builder, IfCondition, S.getCancelRegion())); 5784 } 5785 } 5786 5787 CGM.getOpenMPRuntime().emitCancelCall(*this, S.getBeginLoc(), IfCond, 5788 S.getCancelRegion()); 5789 } 5790 5791 CodeGenFunction::JumpDest 5792 CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) { 5793 if (Kind == OMPD_parallel || Kind == OMPD_task || 5794 Kind == OMPD_target_parallel || Kind == OMPD_taskloop || 5795 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop) 5796 return ReturnBlock; 5797 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections || 5798 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for || 5799 Kind == OMPD_distribute_parallel_for || 5800 Kind == OMPD_target_parallel_for || 5801 Kind == OMPD_teams_distribute_parallel_for || 5802 Kind == OMPD_target_teams_distribute_parallel_for); 5803 return OMPCancelStack.getExitBlock(); 5804 } 5805 5806 void CodeGenFunction::EmitOMPUseDevicePtrClause( 5807 const OMPClause &NC, OMPPrivateScope &PrivateScope, 5808 const llvm::DenseMap<const ValueDecl *, Address> &CaptureDeviceAddrMap) { 5809 const auto &C = cast<OMPUseDevicePtrClause>(NC); 5810 auto OrigVarIt = C.varlist_begin(); 5811 auto InitIt = C.inits().begin(); 5812 for (const Expr *PvtVarIt : C.private_copies()) { 5813 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*OrigVarIt)->getDecl()); 5814 const auto *InitVD = cast<VarDecl>(cast<DeclRefExpr>(*InitIt)->getDecl()); 5815 const auto *PvtVD = cast<VarDecl>(cast<DeclRefExpr>(PvtVarIt)->getDecl()); 5816 5817 // In order to identify the right initializer we need to match the 5818 // declaration used by the mapping logic. In some cases we may get 5819 // OMPCapturedExprDecl that refers to the original declaration. 5820 const ValueDecl *MatchingVD = OrigVD; 5821 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) { 5822 // OMPCapturedExprDecl are used to privative fields of the current 5823 // structure. 5824 const auto *ME = cast<MemberExpr>(OED->getInit()); 5825 assert(isa<CXXThisExpr>(ME->getBase()) && 5826 "Base should be the current struct!"); 5827 MatchingVD = ME->getMemberDecl(); 5828 } 5829 5830 // If we don't have information about the current list item, move on to 5831 // the next one. 5832 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD); 5833 if (InitAddrIt == CaptureDeviceAddrMap.end()) 5834 continue; 5835 5836 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, OrigVD, 5837 InitAddrIt, InitVD, 5838 PvtVD]() { 5839 // Initialize the temporary initialization variable with the address we 5840 // get from the runtime library. We have to cast the source address 5841 // because it is always a void *. References are materialized in the 5842 // privatization scope, so the initialization here disregards the fact 5843 // the original variable is a reference. 5844 QualType AddrQTy = 5845 getContext().getPointerType(OrigVD->getType().getNonReferenceType()); 5846 llvm::Type *AddrTy = ConvertTypeForMem(AddrQTy); 5847 Address InitAddr = Builder.CreateBitCast(InitAddrIt->second, AddrTy); 5848 setAddrOfLocalVar(InitVD, InitAddr); 5849 5850 // Emit private declaration, it will be initialized by the value we 5851 // declaration we just added to the local declarations map. 5852 EmitDecl(*PvtVD); 5853 5854 // The initialization variables reached its purpose in the emission 5855 // of the previous declaration, so we don't need it anymore. 5856 LocalDeclMap.erase(InitVD); 5857 5858 // Return the address of the private variable. 5859 return GetAddrOfLocalVar(PvtVD); 5860 }); 5861 assert(IsRegistered && "firstprivate var already registered as private"); 5862 // Silence the warning about unused variable. 5863 (void)IsRegistered; 5864 5865 ++OrigVarIt; 5866 ++InitIt; 5867 } 5868 } 5869 5870 // Generate the instructions for '#pragma omp target data' directive. 5871 void CodeGenFunction::EmitOMPTargetDataDirective( 5872 const OMPTargetDataDirective &S) { 5873 CGOpenMPRuntime::TargetDataInfo Info(/*RequiresDevicePointerInfo=*/true); 5874 5875 // Create a pre/post action to signal the privatization of the device pointer. 5876 // This action can be replaced by the OpenMP runtime code generation to 5877 // deactivate privatization. 5878 bool PrivatizeDevicePointers = false; 5879 class DevicePointerPrivActionTy : public PrePostActionTy { 5880 bool &PrivatizeDevicePointers; 5881 5882 public: 5883 explicit DevicePointerPrivActionTy(bool &PrivatizeDevicePointers) 5884 : PrePostActionTy(), PrivatizeDevicePointers(PrivatizeDevicePointers) {} 5885 void Enter(CodeGenFunction &CGF) override { 5886 PrivatizeDevicePointers = true; 5887 } 5888 }; 5889 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers); 5890 5891 auto &&CodeGen = [&S, &Info, &PrivatizeDevicePointers]( 5892 CodeGenFunction &CGF, PrePostActionTy &Action) { 5893 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) { 5894 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt()); 5895 }; 5896 5897 // Codegen that selects whether to generate the privatization code or not. 5898 auto &&PrivCodeGen = [&S, &Info, &PrivatizeDevicePointers, 5899 &InnermostCodeGen](CodeGenFunction &CGF, 5900 PrePostActionTy &Action) { 5901 RegionCodeGenTy RCG(InnermostCodeGen); 5902 PrivatizeDevicePointers = false; 5903 5904 // Call the pre-action to change the status of PrivatizeDevicePointers if 5905 // needed. 5906 Action.Enter(CGF); 5907 5908 if (PrivatizeDevicePointers) { 5909 OMPPrivateScope PrivateScope(CGF); 5910 // Emit all instances of the use_device_ptr clause. 5911 for (const auto *C : S.getClausesOfKind<OMPUseDevicePtrClause>()) 5912 CGF.EmitOMPUseDevicePtrClause(*C, PrivateScope, 5913 Info.CaptureDeviceAddrMap); 5914 (void)PrivateScope.Privatize(); 5915 RCG(CGF); 5916 } else { 5917 RCG(CGF); 5918 } 5919 }; 5920 5921 // Forward the provided action to the privatization codegen. 5922 RegionCodeGenTy PrivRCG(PrivCodeGen); 5923 PrivRCG.setAction(Action); 5924 5925 // Notwithstanding the body of the region is emitted as inlined directive, 5926 // we don't use an inline scope as changes in the references inside the 5927 // region are expected to be visible outside, so we do not privative them. 5928 OMPLexicalScope Scope(CGF, S); 5929 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data, 5930 PrivRCG); 5931 }; 5932 5933 RegionCodeGenTy RCG(CodeGen); 5934 5935 // If we don't have target devices, don't bother emitting the data mapping 5936 // code. 5937 if (CGM.getLangOpts().OMPTargetTriples.empty()) { 5938 RCG(*this); 5939 return; 5940 } 5941 5942 // Check if we have any if clause associated with the directive. 5943 const Expr *IfCond = nullptr; 5944 if (const auto *C = S.getSingleClause<OMPIfClause>()) 5945 IfCond = C->getCondition(); 5946 5947 // Check if we have any device clause associated with the directive. 5948 const Expr *Device = nullptr; 5949 if (const auto *C = S.getSingleClause<OMPDeviceClause>()) 5950 Device = C->getDevice(); 5951 5952 // Set the action to signal privatization of device pointers. 5953 RCG.setAction(PrivAction); 5954 5955 // Emit region code. 5956 CGM.getOpenMPRuntime().emitTargetDataCalls(*this, S, IfCond, Device, RCG, 5957 Info); 5958 } 5959 5960 void CodeGenFunction::EmitOMPTargetEnterDataDirective( 5961 const OMPTargetEnterDataDirective &S) { 5962 // If we don't have target devices, don't bother emitting the data mapping 5963 // code. 5964 if (CGM.getLangOpts().OMPTargetTriples.empty()) 5965 return; 5966 5967 // Check if we have any if clause associated with the directive. 5968 const Expr *IfCond = nullptr; 5969 if (const auto *C = S.getSingleClause<OMPIfClause>()) 5970 IfCond = C->getCondition(); 5971 5972 // Check if we have any device clause associated with the directive. 5973 const Expr *Device = nullptr; 5974 if (const auto *C = S.getSingleClause<OMPDeviceClause>()) 5975 Device = C->getDevice(); 5976 5977 OMPLexicalScope Scope(*this, S, OMPD_task); 5978 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device); 5979 } 5980 5981 void CodeGenFunction::EmitOMPTargetExitDataDirective( 5982 const OMPTargetExitDataDirective &S) { 5983 // If we don't have target devices, don't bother emitting the data mapping 5984 // code. 5985 if (CGM.getLangOpts().OMPTargetTriples.empty()) 5986 return; 5987 5988 // Check if we have any if clause associated with the directive. 5989 const Expr *IfCond = nullptr; 5990 if (const auto *C = S.getSingleClause<OMPIfClause>()) 5991 IfCond = C->getCondition(); 5992 5993 // Check if we have any device clause associated with the directive. 5994 const Expr *Device = nullptr; 5995 if (const auto *C = S.getSingleClause<OMPDeviceClause>()) 5996 Device = C->getDevice(); 5997 5998 OMPLexicalScope Scope(*this, S, OMPD_task); 5999 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device); 6000 } 6001 6002 static void emitTargetParallelRegion(CodeGenFunction &CGF, 6003 const OMPTargetParallelDirective &S, 6004 PrePostActionTy &Action) { 6005 // Get the captured statement associated with the 'parallel' region. 6006 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel); 6007 Action.Enter(CGF); 6008 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) { 6009 Action.Enter(CGF); 6010 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6011 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope); 6012 CGF.EmitOMPPrivateClause(S, PrivateScope); 6013 CGF.EmitOMPReductionClauseInit(S, PrivateScope); 6014 (void)PrivateScope.Privatize(); 6015 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind())) 6016 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S); 6017 // TODO: Add support for clauses. 6018 CGF.EmitStmt(CS->getCapturedStmt()); 6019 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel); 6020 }; 6021 emitCommonOMPParallelDirective(CGF, S, OMPD_parallel, CodeGen, 6022 emitEmptyBoundParameters); 6023 emitPostUpdateForReductionClause(CGF, S, 6024 [](CodeGenFunction &) { return nullptr; }); 6025 } 6026 6027 void CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 6028 CodeGenModule &CGM, StringRef ParentName, 6029 const OMPTargetParallelDirective &S) { 6030 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6031 emitTargetParallelRegion(CGF, S, Action); 6032 }; 6033 llvm::Function *Fn; 6034 llvm::Constant *Addr; 6035 // Emit target region as a standalone region. 6036 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 6037 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 6038 assert(Fn && Addr && "Target device function emission failed."); 6039 } 6040 6041 void CodeGenFunction::EmitOMPTargetParallelDirective( 6042 const OMPTargetParallelDirective &S) { 6043 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6044 emitTargetParallelRegion(CGF, S, Action); 6045 }; 6046 emitCommonOMPTargetDirective(*this, S, CodeGen); 6047 } 6048 6049 static void emitTargetParallelForRegion(CodeGenFunction &CGF, 6050 const OMPTargetParallelForDirective &S, 6051 PrePostActionTy &Action) { 6052 Action.Enter(CGF); 6053 // Emit directive as a combined directive that consists of two implicit 6054 // directives: 'parallel' with 'for' directive. 6055 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6056 Action.Enter(CGF); 6057 CodeGenFunction::OMPCancelStackRAII CancelRegion( 6058 CGF, OMPD_target_parallel_for, S.hasCancel()); 6059 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds, 6060 emitDispatchForLoopBounds); 6061 }; 6062 emitCommonOMPParallelDirective(CGF, S, OMPD_for, CodeGen, 6063 emitEmptyBoundParameters); 6064 } 6065 6066 void CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 6067 CodeGenModule &CGM, StringRef ParentName, 6068 const OMPTargetParallelForDirective &S) { 6069 // Emit SPMD target parallel for region as a standalone region. 6070 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6071 emitTargetParallelForRegion(CGF, S, Action); 6072 }; 6073 llvm::Function *Fn; 6074 llvm::Constant *Addr; 6075 // Emit target region as a standalone region. 6076 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 6077 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 6078 assert(Fn && Addr && "Target device function emission failed."); 6079 } 6080 6081 void CodeGenFunction::EmitOMPTargetParallelForDirective( 6082 const OMPTargetParallelForDirective &S) { 6083 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6084 emitTargetParallelForRegion(CGF, S, Action); 6085 }; 6086 emitCommonOMPTargetDirective(*this, S, CodeGen); 6087 } 6088 6089 static void 6090 emitTargetParallelForSimdRegion(CodeGenFunction &CGF, 6091 const OMPTargetParallelForSimdDirective &S, 6092 PrePostActionTy &Action) { 6093 Action.Enter(CGF); 6094 // Emit directive as a combined directive that consists of two implicit 6095 // directives: 'parallel' with 'for' directive. 6096 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6097 Action.Enter(CGF); 6098 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds, 6099 emitDispatchForLoopBounds); 6100 }; 6101 emitCommonOMPParallelDirective(CGF, S, OMPD_simd, CodeGen, 6102 emitEmptyBoundParameters); 6103 } 6104 6105 void CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 6106 CodeGenModule &CGM, StringRef ParentName, 6107 const OMPTargetParallelForSimdDirective &S) { 6108 // Emit SPMD target parallel for region as a standalone region. 6109 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6110 emitTargetParallelForSimdRegion(CGF, S, Action); 6111 }; 6112 llvm::Function *Fn; 6113 llvm::Constant *Addr; 6114 // Emit target region as a standalone region. 6115 CGM.getOpenMPRuntime().emitTargetOutlinedFunction( 6116 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen); 6117 assert(Fn && Addr && "Target device function emission failed."); 6118 } 6119 6120 void CodeGenFunction::EmitOMPTargetParallelForSimdDirective( 6121 const OMPTargetParallelForSimdDirective &S) { 6122 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6123 emitTargetParallelForSimdRegion(CGF, S, Action); 6124 }; 6125 emitCommonOMPTargetDirective(*this, S, CodeGen); 6126 } 6127 6128 /// Emit a helper variable and return corresponding lvalue. 6129 static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper, 6130 const ImplicitParamDecl *PVD, 6131 CodeGenFunction::OMPPrivateScope &Privates) { 6132 const auto *VDecl = cast<VarDecl>(Helper->getDecl()); 6133 Privates.addPrivate(VDecl, 6134 [&CGF, PVD]() { return CGF.GetAddrOfLocalVar(PVD); }); 6135 } 6136 6137 void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) { 6138 assert(isOpenMPTaskLoopDirective(S.getDirectiveKind())); 6139 // Emit outlined function for task construct. 6140 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop); 6141 Address CapturedStruct = Address::invalid(); 6142 { 6143 OMPLexicalScope Scope(*this, S, OMPD_taskloop, /*EmitPreInitStmt=*/false); 6144 CapturedStruct = GenerateCapturedStmtArgument(*CS); 6145 } 6146 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); 6147 const Expr *IfCond = nullptr; 6148 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) { 6149 if (C->getNameModifier() == OMPD_unknown || 6150 C->getNameModifier() == OMPD_taskloop) { 6151 IfCond = C->getCondition(); 6152 break; 6153 } 6154 } 6155 6156 OMPTaskDataTy Data; 6157 // Check if taskloop must be emitted without taskgroup. 6158 Data.Nogroup = S.getSingleClause<OMPNogroupClause>(); 6159 // TODO: Check if we should emit tied or untied task. 6160 Data.Tied = true; 6161 // Set scheduling for taskloop 6162 if (const auto* Clause = S.getSingleClause<OMPGrainsizeClause>()) { 6163 // grainsize clause 6164 Data.Schedule.setInt(/*IntVal=*/false); 6165 Data.Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize())); 6166 } else if (const auto* Clause = S.getSingleClause<OMPNumTasksClause>()) { 6167 // num_tasks clause 6168 Data.Schedule.setInt(/*IntVal=*/true); 6169 Data.Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks())); 6170 } 6171 6172 auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) { 6173 // if (PreCond) { 6174 // for (IV in 0..LastIteration) BODY; 6175 // <Final counter/linear vars updates>; 6176 // } 6177 // 6178 6179 // Emit: if (PreCond) - begin. 6180 // If the condition constant folds and can be elided, avoid emitting the 6181 // whole loop. 6182 bool CondConstant; 6183 llvm::BasicBlock *ContBlock = nullptr; 6184 OMPLoopScope PreInitScope(CGF, S); 6185 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) { 6186 if (!CondConstant) 6187 return; 6188 } else { 6189 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("taskloop.if.then"); 6190 ContBlock = CGF.createBasicBlock("taskloop.if.end"); 6191 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock, 6192 CGF.getProfileCount(&S)); 6193 CGF.EmitBlock(ThenBlock); 6194 CGF.incrementProfileCounter(&S); 6195 } 6196 6197 (void)CGF.EmitOMPLinearClauseInit(S); 6198 6199 OMPPrivateScope LoopScope(CGF); 6200 // Emit helper vars inits. 6201 enum { LowerBound = 5, UpperBound, Stride, LastIter }; 6202 auto *I = CS->getCapturedDecl()->param_begin(); 6203 auto *LBP = std::next(I, LowerBound); 6204 auto *UBP = std::next(I, UpperBound); 6205 auto *STP = std::next(I, Stride); 6206 auto *LIP = std::next(I, LastIter); 6207 mapParam(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()), *LBP, 6208 LoopScope); 6209 mapParam(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()), *UBP, 6210 LoopScope); 6211 mapParam(CGF, cast<DeclRefExpr>(S.getStrideVariable()), *STP, LoopScope); 6212 mapParam(CGF, cast<DeclRefExpr>(S.getIsLastIterVariable()), *LIP, 6213 LoopScope); 6214 CGF.EmitOMPPrivateLoopCounters(S, LoopScope); 6215 CGF.EmitOMPLinearClause(S, LoopScope); 6216 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope); 6217 (void)LoopScope.Privatize(); 6218 // Emit the loop iteration variable. 6219 const Expr *IVExpr = S.getIterationVariable(); 6220 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl()); 6221 CGF.EmitVarDecl(*IVDecl); 6222 CGF.EmitIgnoredExpr(S.getInit()); 6223 6224 // Emit the iterations count variable. 6225 // If it is not a variable, Sema decided to calculate iterations count on 6226 // each iteration (e.g., it is foldable into a constant). 6227 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) { 6228 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl())); 6229 // Emit calculation of the iterations count. 6230 CGF.EmitIgnoredExpr(S.getCalcLastIteration()); 6231 } 6232 6233 { 6234 OMPLexicalScope Scope(CGF, S, OMPD_taskloop, /*EmitPreInitStmt=*/false); 6235 emitCommonSimdLoop( 6236 CGF, S, 6237 [&S](CodeGenFunction &CGF, PrePostActionTy &) { 6238 if (isOpenMPSimdDirective(S.getDirectiveKind())) 6239 CGF.EmitOMPSimdInit(S); 6240 }, 6241 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) { 6242 CGF.EmitOMPInnerLoop( 6243 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(), 6244 [&S](CodeGenFunction &CGF) { 6245 emitOMPLoopBodyWithStopPoint(CGF, S, 6246 CodeGenFunction::JumpDest()); 6247 }, 6248 [](CodeGenFunction &) {}); 6249 }); 6250 } 6251 // Emit: if (PreCond) - end. 6252 if (ContBlock) { 6253 CGF.EmitBranch(ContBlock); 6254 CGF.EmitBlock(ContBlock, true); 6255 } 6256 // Emit final copy of the lastprivate variables if IsLastIter != 0. 6257 if (HasLastprivateClause) { 6258 CGF.EmitOMPLastprivateClauseFinal( 6259 S, isOpenMPSimdDirective(S.getDirectiveKind()), 6260 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar( 6261 CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false, 6262 (*LIP)->getType(), S.getBeginLoc()))); 6263 } 6264 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) { 6265 return CGF.Builder.CreateIsNotNull( 6266 CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false, 6267 (*LIP)->getType(), S.getBeginLoc())); 6268 }); 6269 }; 6270 auto &&TaskGen = [&S, SharedsTy, CapturedStruct, 6271 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn, 6272 const OMPTaskDataTy &Data) { 6273 auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond, 6274 &Data](CodeGenFunction &CGF, PrePostActionTy &) { 6275 OMPLoopScope PreInitScope(CGF, S); 6276 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S, 6277 OutlinedFn, SharedsTy, 6278 CapturedStruct, IfCond, Data); 6279 }; 6280 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop, 6281 CodeGen); 6282 }; 6283 if (Data.Nogroup) { 6284 EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, Data); 6285 } else { 6286 CGM.getOpenMPRuntime().emitTaskgroupRegion( 6287 *this, 6288 [&S, &BodyGen, &TaskGen, &Data](CodeGenFunction &CGF, 6289 PrePostActionTy &Action) { 6290 Action.Enter(CGF); 6291 CGF.EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, 6292 Data); 6293 }, 6294 S.getBeginLoc()); 6295 } 6296 } 6297 6298 void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) { 6299 auto LPCRegion = 6300 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 6301 EmitOMPTaskLoopBasedDirective(S); 6302 } 6303 6304 void CodeGenFunction::EmitOMPTaskLoopSimdDirective( 6305 const OMPTaskLoopSimdDirective &S) { 6306 auto LPCRegion = 6307 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 6308 OMPLexicalScope Scope(*this, S); 6309 EmitOMPTaskLoopBasedDirective(S); 6310 } 6311 6312 void CodeGenFunction::EmitOMPMasterTaskLoopDirective( 6313 const OMPMasterTaskLoopDirective &S) { 6314 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6315 Action.Enter(CGF); 6316 EmitOMPTaskLoopBasedDirective(S); 6317 }; 6318 auto LPCRegion = 6319 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 6320 OMPLexicalScope Scope(*this, S, llvm::None, /*EmitPreInitStmt=*/false); 6321 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc()); 6322 } 6323 6324 void CodeGenFunction::EmitOMPMasterTaskLoopSimdDirective( 6325 const OMPMasterTaskLoopSimdDirective &S) { 6326 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6327 Action.Enter(CGF); 6328 EmitOMPTaskLoopBasedDirective(S); 6329 }; 6330 auto LPCRegion = 6331 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 6332 OMPLexicalScope Scope(*this, S); 6333 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc()); 6334 } 6335 6336 void CodeGenFunction::EmitOMPParallelMasterTaskLoopDirective( 6337 const OMPParallelMasterTaskLoopDirective &S) { 6338 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6339 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF, 6340 PrePostActionTy &Action) { 6341 Action.Enter(CGF); 6342 CGF.EmitOMPTaskLoopBasedDirective(S); 6343 }; 6344 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false); 6345 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen, 6346 S.getBeginLoc()); 6347 }; 6348 auto LPCRegion = 6349 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 6350 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop, CodeGen, 6351 emitEmptyBoundParameters); 6352 } 6353 6354 void CodeGenFunction::EmitOMPParallelMasterTaskLoopSimdDirective( 6355 const OMPParallelMasterTaskLoopSimdDirective &S) { 6356 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) { 6357 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF, 6358 PrePostActionTy &Action) { 6359 Action.Enter(CGF); 6360 CGF.EmitOMPTaskLoopBasedDirective(S); 6361 }; 6362 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false); 6363 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen, 6364 S.getBeginLoc()); 6365 }; 6366 auto LPCRegion = 6367 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S); 6368 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop_simd, CodeGen, 6369 emitEmptyBoundParameters); 6370 } 6371 6372 // Generate the instructions for '#pragma omp target update' directive. 6373 void CodeGenFunction::EmitOMPTargetUpdateDirective( 6374 const OMPTargetUpdateDirective &S) { 6375 // If we don't have target devices, don't bother emitting the data mapping 6376 // code. 6377 if (CGM.getLangOpts().OMPTargetTriples.empty()) 6378 return; 6379 6380 // Check if we have any if clause associated with the directive. 6381 const Expr *IfCond = nullptr; 6382 if (const auto *C = S.getSingleClause<OMPIfClause>()) 6383 IfCond = C->getCondition(); 6384 6385 // Check if we have any device clause associated with the directive. 6386 const Expr *Device = nullptr; 6387 if (const auto *C = S.getSingleClause<OMPDeviceClause>()) 6388 Device = C->getDevice(); 6389 6390 OMPLexicalScope Scope(*this, S, OMPD_task); 6391 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device); 6392 } 6393 6394 void CodeGenFunction::EmitSimpleOMPExecutableDirective( 6395 const OMPExecutableDirective &D) { 6396 if (const auto *SD = dyn_cast<OMPScanDirective>(&D)) { 6397 EmitOMPScanDirective(*SD); 6398 return; 6399 } 6400 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt()) 6401 return; 6402 auto &&CodeGen = [&D](CodeGenFunction &CGF, PrePostActionTy &Action) { 6403 OMPPrivateScope GlobalsScope(CGF); 6404 if (isOpenMPTaskingDirective(D.getDirectiveKind())) { 6405 // Capture global firstprivates to avoid crash. 6406 for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) { 6407 for (const Expr *Ref : C->varlists()) { 6408 const auto *DRE = cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 6409 if (!DRE) 6410 continue; 6411 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); 6412 if (!VD || VD->hasLocalStorage()) 6413 continue; 6414 if (!CGF.LocalDeclMap.count(VD)) { 6415 LValue GlobLVal = CGF.EmitLValue(Ref); 6416 GlobalsScope.addPrivate( 6417 VD, [&GlobLVal, &CGF]() { return GlobLVal.getAddress(CGF); }); 6418 } 6419 } 6420 } 6421 } 6422 if (isOpenMPSimdDirective(D.getDirectiveKind())) { 6423 (void)GlobalsScope.Privatize(); 6424 ParentLoopDirectiveForScanRegion ScanRegion(CGF, D); 6425 emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action); 6426 } else { 6427 if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) { 6428 for (const Expr *E : LD->counters()) { 6429 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 6430 if (!VD->hasLocalStorage() && !CGF.LocalDeclMap.count(VD)) { 6431 LValue GlobLVal = CGF.EmitLValue(E); 6432 GlobalsScope.addPrivate( 6433 VD, [&GlobLVal, &CGF]() { return GlobLVal.getAddress(CGF); }); 6434 } 6435 if (isa<OMPCapturedExprDecl>(VD)) { 6436 // Emit only those that were not explicitly referenced in clauses. 6437 if (!CGF.LocalDeclMap.count(VD)) 6438 CGF.EmitVarDecl(*VD); 6439 } 6440 } 6441 for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) { 6442 if (!C->getNumForLoops()) 6443 continue; 6444 for (unsigned I = LD->getCollapsedNumber(), 6445 E = C->getLoopNumIterations().size(); 6446 I < E; ++I) { 6447 if (const auto *VD = dyn_cast<OMPCapturedExprDecl>( 6448 cast<DeclRefExpr>(C->getLoopCounter(I))->getDecl())) { 6449 // Emit only those that were not explicitly referenced in clauses. 6450 if (!CGF.LocalDeclMap.count(VD)) 6451 CGF.EmitVarDecl(*VD); 6452 } 6453 } 6454 } 6455 } 6456 (void)GlobalsScope.Privatize(); 6457 CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt()); 6458 } 6459 }; 6460 { 6461 auto LPCRegion = 6462 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, D); 6463 OMPSimdLexicalScope Scope(*this, D); 6464 CGM.getOpenMPRuntime().emitInlinedDirective( 6465 *this, 6466 isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd 6467 : D.getDirectiveKind(), 6468 CodeGen); 6469 } 6470 // Check for outer lastprivate conditional update. 6471 checkForLastprivateConditionalUpdate(*this, D); 6472 } 6473