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