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