1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 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 provides a class for OpenMP runtime code generation. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "CGOpenMPRuntime.h" 15 #include "CodeGenFunction.h" 16 #include "CGCleanup.h" 17 #include "clang/AST/Decl.h" 18 #include "clang/AST/StmtOpenMP.h" 19 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/IR/CallSite.h" 21 #include "llvm/IR/DerivedTypes.h" 22 #include "llvm/IR/GlobalValue.h" 23 #include "llvm/IR/Value.h" 24 #include "llvm/Support/raw_ostream.h" 25 #include <cassert> 26 27 using namespace clang; 28 using namespace CodeGen; 29 30 namespace { 31 /// \brief Base class for handling code generation inside OpenMP regions. 32 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 33 public: 34 /// \brief Kinds of OpenMP regions used in codegen. 35 enum CGOpenMPRegionKind { 36 /// \brief Region with outlined function for standalone 'parallel' 37 /// directive. 38 ParallelOutlinedRegion, 39 /// \brief Region with outlined function for standalone 'task' directive. 40 TaskOutlinedRegion, 41 /// \brief Region for constructs that do not require function outlining, 42 /// like 'for', 'sections', 'atomic' etc. directives. 43 InlinedRegion, 44 }; 45 46 CGOpenMPRegionInfo(const CapturedStmt &CS, 47 const CGOpenMPRegionKind RegionKind, 48 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind) 49 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 50 CodeGen(CodeGen), Kind(Kind) {} 51 52 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 53 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind) 54 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 55 Kind(Kind) {} 56 57 /// \brief Get a variable or parameter for storing global thread id 58 /// inside OpenMP construct. 59 virtual const VarDecl *getThreadIDVariable() const = 0; 60 61 /// \brief Emit the captured statement body. 62 virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 63 64 /// \brief Get an LValue for the current ThreadID variable. 65 /// \return LValue for thread id variable. This LValue always has type int32*. 66 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 67 68 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 69 70 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 71 72 static bool classof(const CGCapturedStmtInfo *Info) { 73 return Info->getKind() == CR_OpenMP; 74 } 75 76 protected: 77 CGOpenMPRegionKind RegionKind; 78 const RegionCodeGenTy &CodeGen; 79 OpenMPDirectiveKind Kind; 80 }; 81 82 /// \brief API for captured statement code generation in OpenMP constructs. 83 class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo { 84 public: 85 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 86 const RegionCodeGenTy &CodeGen, 87 OpenMPDirectiveKind Kind) 88 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind), 89 ThreadIDVar(ThreadIDVar) { 90 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 91 } 92 /// \brief Get a variable or parameter for storing global thread id 93 /// inside OpenMP construct. 94 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 95 96 /// \brief Get the name of the capture helper. 97 StringRef getHelperName() const override { return ".omp_outlined."; } 98 99 static bool classof(const CGCapturedStmtInfo *Info) { 100 return CGOpenMPRegionInfo::classof(Info) && 101 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 102 ParallelOutlinedRegion; 103 } 104 105 private: 106 /// \brief A variable or parameter storing global thread id for OpenMP 107 /// constructs. 108 const VarDecl *ThreadIDVar; 109 }; 110 111 /// \brief API for captured statement code generation in OpenMP constructs. 112 class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo { 113 public: 114 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 115 const VarDecl *ThreadIDVar, 116 const RegionCodeGenTy &CodeGen, 117 OpenMPDirectiveKind Kind) 118 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind), 119 ThreadIDVar(ThreadIDVar) { 120 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 121 } 122 /// \brief Get a variable or parameter for storing global thread id 123 /// inside OpenMP construct. 124 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 125 126 /// \brief Get an LValue for the current ThreadID variable. 127 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 128 129 /// \brief Get the name of the capture helper. 130 StringRef getHelperName() const override { return ".omp_outlined."; } 131 132 static bool classof(const CGCapturedStmtInfo *Info) { 133 return CGOpenMPRegionInfo::classof(Info) && 134 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 135 TaskOutlinedRegion; 136 } 137 138 private: 139 /// \brief A variable or parameter storing global thread id for OpenMP 140 /// constructs. 141 const VarDecl *ThreadIDVar; 142 }; 143 144 /// \brief API for inlined captured statement code generation in OpenMP 145 /// constructs. 146 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 147 public: 148 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 149 const RegionCodeGenTy &CodeGen, 150 OpenMPDirectiveKind Kind) 151 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind), OldCSI(OldCSI), 152 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 153 // \brief Retrieve the value of the context parameter. 154 llvm::Value *getContextValue() const override { 155 if (OuterRegionInfo) 156 return OuterRegionInfo->getContextValue(); 157 llvm_unreachable("No context value for inlined OpenMP region"); 158 } 159 virtual void setContextValue(llvm::Value *V) override { 160 if (OuterRegionInfo) { 161 OuterRegionInfo->setContextValue(V); 162 return; 163 } 164 llvm_unreachable("No context value for inlined OpenMP region"); 165 } 166 /// \brief Lookup the captured field decl for a variable. 167 const FieldDecl *lookup(const VarDecl *VD) const override { 168 if (OuterRegionInfo) 169 return OuterRegionInfo->lookup(VD); 170 // If there is no outer outlined region,no need to lookup in a list of 171 // captured variables, we can use the original one. 172 return nullptr; 173 } 174 FieldDecl *getThisFieldDecl() const override { 175 if (OuterRegionInfo) 176 return OuterRegionInfo->getThisFieldDecl(); 177 return nullptr; 178 } 179 /// \brief Get a variable or parameter for storing global thread id 180 /// inside OpenMP construct. 181 const VarDecl *getThreadIDVariable() const override { 182 if (OuterRegionInfo) 183 return OuterRegionInfo->getThreadIDVariable(); 184 return nullptr; 185 } 186 187 /// \brief Get the name of the capture helper. 188 StringRef getHelperName() const override { 189 if (auto *OuterRegionInfo = getOldCSI()) 190 return OuterRegionInfo->getHelperName(); 191 llvm_unreachable("No helper name for inlined OpenMP construct"); 192 } 193 194 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 195 196 static bool classof(const CGCapturedStmtInfo *Info) { 197 return CGOpenMPRegionInfo::classof(Info) && 198 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 199 } 200 201 private: 202 /// \brief CodeGen info about outer OpenMP region. 203 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 204 CGOpenMPRegionInfo *OuterRegionInfo; 205 }; 206 207 /// \brief RAII for emitting code of OpenMP constructs. 208 class InlinedOpenMPRegionRAII { 209 CodeGenFunction &CGF; 210 211 public: 212 /// \brief Constructs region for combined constructs. 213 /// \param CodeGen Code generation sequence for combined directives. Includes 214 /// a list of functions used for code generation of implicitly inlined 215 /// regions. 216 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 217 OpenMPDirectiveKind Kind) 218 : CGF(CGF) { 219 // Start emission for the construct. 220 CGF.CapturedStmtInfo = 221 new CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, CodeGen, Kind); 222 } 223 ~InlinedOpenMPRegionRAII() { 224 // Restore original CapturedStmtInfo only if we're done with code emission. 225 auto *OldCSI = 226 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 227 delete CGF.CapturedStmtInfo; 228 CGF.CapturedStmtInfo = OldCSI; 229 } 230 }; 231 232 } // namespace 233 234 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 235 return CGF.MakeNaturalAlignAddrLValue( 236 CGF.Builder.CreateAlignedLoad( 237 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 238 CGF.PointerAlignInBytes), 239 getThreadIDVariable() 240 ->getType() 241 ->castAs<PointerType>() 242 ->getPointeeType()); 243 } 244 245 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 246 // 1.2.2 OpenMP Language Terminology 247 // Structured block - An executable statement with a single entry at the 248 // top and a single exit at the bottom. 249 // The point of exit cannot be a branch out of the structured block. 250 // longjmp() and throw() must not violate the entry/exit criteria. 251 CGF.EHStack.pushTerminate(); 252 { 253 CodeGenFunction::RunCleanupsScope Scope(CGF); 254 CodeGen(CGF); 255 } 256 CGF.EHStack.popTerminate(); 257 } 258 259 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 260 CodeGenFunction &CGF) { 261 return CGF.MakeNaturalAlignAddrLValue( 262 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 263 getThreadIDVariable()->getType()); 264 } 265 266 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) 267 : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr) { 268 IdentTy = llvm::StructType::create( 269 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */, 270 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */, 271 CGM.Int8PtrTy /* psource */, nullptr); 272 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 273 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 274 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 275 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 276 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 277 } 278 279 void CGOpenMPRuntime::clear() { 280 InternalVars.clear(); 281 } 282 283 llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction( 284 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 285 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 286 assert(ThreadIDVar->getType()->isPointerType() && 287 "thread id variable must be of type kmp_int32 *"); 288 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt()); 289 CodeGenFunction CGF(CGM, true); 290 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind); 291 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 292 return CGF.GenerateCapturedStmtFunction(*CS); 293 } 294 295 llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction( 296 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 297 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 298 assert(!ThreadIDVar->getType()->isPointerType() && 299 "thread id variable must be of type kmp_int32 for tasks"); 300 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt()); 301 CodeGenFunction CGF(CGM, true); 302 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 303 InnermostKind); 304 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 305 return CGF.GenerateCapturedStmtFunction(*CS); 306 } 307 308 llvm::Value * 309 CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) { 310 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags); 311 if (!Entry) { 312 if (!DefaultOpenMPPSource) { 313 // Initialize default location for psource field of ident_t structure of 314 // all ident_t objects. Format is ";file;function;line;column;;". 315 // Taken from 316 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c 317 DefaultOpenMPPSource = 318 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;"); 319 DefaultOpenMPPSource = 320 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 321 } 322 auto DefaultOpenMPLocation = new llvm::GlobalVariable( 323 CGM.getModule(), IdentTy, /*isConstant*/ true, 324 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr); 325 DefaultOpenMPLocation->setUnnamedAddr(true); 326 327 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true); 328 llvm::Constant *Values[] = {Zero, 329 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 330 Zero, Zero, DefaultOpenMPPSource}; 331 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values); 332 DefaultOpenMPLocation->setInitializer(Init); 333 OpenMPDefaultLocMap[Flags] = DefaultOpenMPLocation; 334 return DefaultOpenMPLocation; 335 } 336 return Entry; 337 } 338 339 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 340 SourceLocation Loc, 341 OpenMPLocationFlags Flags) { 342 // If no debug info is generated - return global default location. 343 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo || 344 Loc.isInvalid()) 345 return getOrCreateDefaultLocation(Flags); 346 347 assert(CGF.CurFn && "No function in current CodeGenFunction."); 348 349 llvm::Value *LocValue = nullptr; 350 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 351 if (I != OpenMPLocThreadIDMap.end()) 352 LocValue = I->second.DebugLoc; 353 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 354 // GetOpenMPThreadID was called before this routine. 355 if (LocValue == nullptr) { 356 // Generate "ident_t .kmpc_loc.addr;" 357 llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr"); 358 AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy)); 359 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 360 Elem.second.DebugLoc = AI; 361 LocValue = AI; 362 363 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 364 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 365 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 366 llvm::ConstantExpr::getSizeOf(IdentTy), 367 CGM.PointerAlignInBytes); 368 } 369 370 // char **psource = &.kmpc_loc_<flags>.addr.psource; 371 auto *PSource = CGF.Builder.CreateConstInBoundsGEP2_32(IdentTy, LocValue, 0, 372 IdentField_PSource); 373 374 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 375 if (OMPDebugLoc == nullptr) { 376 SmallString<128> Buffer2; 377 llvm::raw_svector_ostream OS2(Buffer2); 378 // Build debug location 379 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 380 OS2 << ";" << PLoc.getFilename() << ";"; 381 if (const FunctionDecl *FD = 382 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) { 383 OS2 << FD->getQualifiedNameAsString(); 384 } 385 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 386 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 387 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 388 } 389 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 390 CGF.Builder.CreateStore(OMPDebugLoc, PSource); 391 392 return LocValue; 393 } 394 395 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 396 SourceLocation Loc) { 397 assert(CGF.CurFn && "No function in current CodeGenFunction."); 398 399 llvm::Value *ThreadID = nullptr; 400 // Check whether we've already cached a load of the thread id in this 401 // function. 402 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 403 if (I != OpenMPLocThreadIDMap.end()) { 404 ThreadID = I->second.ThreadID; 405 if (ThreadID != nullptr) 406 return ThreadID; 407 } 408 if (auto OMPRegionInfo = 409 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 410 if (OMPRegionInfo->getThreadIDVariable()) { 411 // Check if this an outlined function with thread id passed as argument. 412 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 413 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal(); 414 // If value loaded in entry block, cache it and use it everywhere in 415 // function. 416 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 417 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 418 Elem.second.ThreadID = ThreadID; 419 } 420 return ThreadID; 421 } 422 } 423 424 // This is not an outlined function region - need to call __kmpc_int32 425 // kmpc_global_thread_num(ident_t *loc). 426 // Generate thread id value and cache this value for use across the 427 // function. 428 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 429 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 430 ThreadID = 431 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 432 emitUpdateLocation(CGF, Loc)); 433 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 434 Elem.second.ThreadID = ThreadID; 435 return ThreadID; 436 } 437 438 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 439 assert(CGF.CurFn && "No function in current CodeGenFunction."); 440 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) 441 OpenMPLocThreadIDMap.erase(CGF.CurFn); 442 } 443 444 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 445 return llvm::PointerType::getUnqual(IdentTy); 446 } 447 448 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 449 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 450 } 451 452 llvm::Constant * 453 CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) { 454 llvm::Constant *RTLFn = nullptr; 455 switch (Function) { 456 case OMPRTL__kmpc_fork_call: { 457 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 458 // microtask, ...); 459 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 460 getKmpc_MicroPointerTy()}; 461 llvm::FunctionType *FnTy = 462 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 463 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 464 break; 465 } 466 case OMPRTL__kmpc_global_thread_num: { 467 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 468 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 469 llvm::FunctionType *FnTy = 470 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 471 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 472 break; 473 } 474 case OMPRTL__kmpc_threadprivate_cached: { 475 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 476 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 477 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 478 CGM.VoidPtrTy, CGM.SizeTy, 479 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 480 llvm::FunctionType *FnTy = 481 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 482 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 483 break; 484 } 485 case OMPRTL__kmpc_critical: { 486 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 487 // kmp_critical_name *crit); 488 llvm::Type *TypeParams[] = { 489 getIdentTyPointerTy(), CGM.Int32Ty, 490 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 491 llvm::FunctionType *FnTy = 492 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 493 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 494 break; 495 } 496 case OMPRTL__kmpc_threadprivate_register: { 497 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 498 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 499 // typedef void *(*kmpc_ctor)(void *); 500 auto KmpcCtorTy = 501 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 502 /*isVarArg*/ false)->getPointerTo(); 503 // typedef void *(*kmpc_cctor)(void *, void *); 504 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 505 auto KmpcCopyCtorTy = 506 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 507 /*isVarArg*/ false)->getPointerTo(); 508 // typedef void (*kmpc_dtor)(void *); 509 auto KmpcDtorTy = 510 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 511 ->getPointerTo(); 512 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 513 KmpcCopyCtorTy, KmpcDtorTy}; 514 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 515 /*isVarArg*/ false); 516 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 517 break; 518 } 519 case OMPRTL__kmpc_end_critical: { 520 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 521 // kmp_critical_name *crit); 522 llvm::Type *TypeParams[] = { 523 getIdentTyPointerTy(), CGM.Int32Ty, 524 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 525 llvm::FunctionType *FnTy = 526 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 527 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 528 break; 529 } 530 case OMPRTL__kmpc_cancel_barrier: { 531 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 532 // global_tid); 533 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 534 llvm::FunctionType *FnTy = 535 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 536 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 537 break; 538 } 539 case OMPRTL__kmpc_barrier: { 540 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 541 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 542 llvm::FunctionType *FnTy = 543 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 544 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 545 break; 546 } 547 case OMPRTL__kmpc_for_static_fini: { 548 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 549 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 550 llvm::FunctionType *FnTy = 551 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 552 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 553 break; 554 } 555 case OMPRTL__kmpc_push_num_threads: { 556 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 557 // kmp_int32 num_threads) 558 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 559 CGM.Int32Ty}; 560 llvm::FunctionType *FnTy = 561 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 562 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 563 break; 564 } 565 case OMPRTL__kmpc_serialized_parallel: { 566 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 567 // global_tid); 568 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 569 llvm::FunctionType *FnTy = 570 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 571 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 572 break; 573 } 574 case OMPRTL__kmpc_end_serialized_parallel: { 575 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 576 // global_tid); 577 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 578 llvm::FunctionType *FnTy = 579 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 580 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 581 break; 582 } 583 case OMPRTL__kmpc_flush: { 584 // Build void __kmpc_flush(ident_t *loc); 585 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 586 llvm::FunctionType *FnTy = 587 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 588 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 589 break; 590 } 591 case OMPRTL__kmpc_master: { 592 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 593 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 594 llvm::FunctionType *FnTy = 595 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 596 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 597 break; 598 } 599 case OMPRTL__kmpc_end_master: { 600 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 601 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 602 llvm::FunctionType *FnTy = 603 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 604 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 605 break; 606 } 607 case OMPRTL__kmpc_omp_taskyield: { 608 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 609 // int end_part); 610 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 611 llvm::FunctionType *FnTy = 612 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 613 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 614 break; 615 } 616 case OMPRTL__kmpc_single: { 617 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 618 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 619 llvm::FunctionType *FnTy = 620 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 621 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 622 break; 623 } 624 case OMPRTL__kmpc_end_single: { 625 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 626 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 627 llvm::FunctionType *FnTy = 628 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 629 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 630 break; 631 } 632 case OMPRTL__kmpc_omp_task_alloc: { 633 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 634 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 635 // kmp_routine_entry_t *task_entry); 636 assert(KmpRoutineEntryPtrTy != nullptr && 637 "Type kmp_routine_entry_t must be created."); 638 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 639 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 640 // Return void * and then cast to particular kmp_task_t type. 641 llvm::FunctionType *FnTy = 642 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 643 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 644 break; 645 } 646 case OMPRTL__kmpc_omp_task: { 647 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 648 // *new_task); 649 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 650 CGM.VoidPtrTy}; 651 llvm::FunctionType *FnTy = 652 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 653 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 654 break; 655 } 656 case OMPRTL__kmpc_copyprivate: { 657 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 658 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 659 // kmp_int32 didit); 660 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 661 auto *CpyFnTy = 662 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 663 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 664 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 665 CGM.Int32Ty}; 666 llvm::FunctionType *FnTy = 667 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 668 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 669 break; 670 } 671 case OMPRTL__kmpc_reduce: { 672 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 673 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 674 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 675 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 676 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 677 /*isVarArg=*/false); 678 llvm::Type *TypeParams[] = { 679 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 680 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 681 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 682 llvm::FunctionType *FnTy = 683 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 684 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 685 break; 686 } 687 case OMPRTL__kmpc_reduce_nowait: { 688 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 689 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 690 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 691 // *lck); 692 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 693 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 694 /*isVarArg=*/false); 695 llvm::Type *TypeParams[] = { 696 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 697 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 698 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 699 llvm::FunctionType *FnTy = 700 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 701 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 702 break; 703 } 704 case OMPRTL__kmpc_end_reduce: { 705 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 706 // kmp_critical_name *lck); 707 llvm::Type *TypeParams[] = { 708 getIdentTyPointerTy(), CGM.Int32Ty, 709 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 710 llvm::FunctionType *FnTy = 711 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 712 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 713 break; 714 } 715 case OMPRTL__kmpc_end_reduce_nowait: { 716 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 717 // kmp_critical_name *lck); 718 llvm::Type *TypeParams[] = { 719 getIdentTyPointerTy(), CGM.Int32Ty, 720 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 721 llvm::FunctionType *FnTy = 722 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 723 RTLFn = 724 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 725 break; 726 } 727 case OMPRTL__kmpc_omp_task_begin_if0: { 728 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 729 // *new_task); 730 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 731 CGM.VoidPtrTy}; 732 llvm::FunctionType *FnTy = 733 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 734 RTLFn = 735 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 736 break; 737 } 738 case OMPRTL__kmpc_omp_task_complete_if0: { 739 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 740 // *new_task); 741 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 742 CGM.VoidPtrTy}; 743 llvm::FunctionType *FnTy = 744 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 745 RTLFn = CGM.CreateRuntimeFunction(FnTy, 746 /*Name=*/"__kmpc_omp_task_complete_if0"); 747 break; 748 } 749 case OMPRTL__kmpc_ordered: { 750 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 751 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 752 llvm::FunctionType *FnTy = 753 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 754 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 755 break; 756 } 757 case OMPRTL__kmpc_end_ordered: { 758 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 759 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 760 llvm::FunctionType *FnTy = 761 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 762 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 763 break; 764 } 765 case OMPRTL__kmpc_omp_taskwait: { 766 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 767 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 768 llvm::FunctionType *FnTy = 769 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 770 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 771 break; 772 } 773 case OMPRTL__kmpc_taskgroup: { 774 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 775 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 776 llvm::FunctionType *FnTy = 777 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 778 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 779 break; 780 } 781 case OMPRTL__kmpc_end_taskgroup: { 782 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 783 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 784 llvm::FunctionType *FnTy = 785 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 786 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 787 break; 788 } 789 case OMPRTL__kmpc_push_proc_bind: { 790 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 791 // int proc_bind) 792 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 793 llvm::FunctionType *FnTy = 794 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 795 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 796 break; 797 } 798 case OMPRTL__kmpc_omp_task_with_deps: { 799 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 800 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 801 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 802 llvm::Type *TypeParams[] = { 803 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 804 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 805 llvm::FunctionType *FnTy = 806 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 807 RTLFn = 808 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 809 break; 810 } 811 case OMPRTL__kmpc_omp_wait_deps: { 812 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 813 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 814 // kmp_depend_info_t *noalias_dep_list); 815 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 816 CGM.Int32Ty, CGM.VoidPtrTy, 817 CGM.Int32Ty, CGM.VoidPtrTy}; 818 llvm::FunctionType *FnTy = 819 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 820 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 821 break; 822 } 823 case OMPRTL__kmpc_cancellationpoint: { 824 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 825 // global_tid, kmp_int32 cncl_kind) 826 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 827 llvm::FunctionType *FnTy = 828 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 829 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 830 break; 831 } 832 case OMPRTL__kmpc_cancel: { 833 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 834 // kmp_int32 cncl_kind) 835 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 836 llvm::FunctionType *FnTy = 837 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 838 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 839 break; 840 } 841 } 842 return RTLFn; 843 } 844 845 llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, 846 bool IVSigned) { 847 assert((IVSize == 32 || IVSize == 64) && 848 "IV size is not compatible with the omp runtime"); 849 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 850 : "__kmpc_for_static_init_4u") 851 : (IVSigned ? "__kmpc_for_static_init_8" 852 : "__kmpc_for_static_init_8u"); 853 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 854 auto PtrTy = llvm::PointerType::getUnqual(ITy); 855 llvm::Type *TypeParams[] = { 856 getIdentTyPointerTy(), // loc 857 CGM.Int32Ty, // tid 858 CGM.Int32Ty, // schedtype 859 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 860 PtrTy, // p_lower 861 PtrTy, // p_upper 862 PtrTy, // p_stride 863 ITy, // incr 864 ITy // chunk 865 }; 866 llvm::FunctionType *FnTy = 867 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 868 return CGM.CreateRuntimeFunction(FnTy, Name); 869 } 870 871 llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, 872 bool IVSigned) { 873 assert((IVSize == 32 || IVSize == 64) && 874 "IV size is not compatible with the omp runtime"); 875 auto Name = 876 IVSize == 32 877 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 878 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 879 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 880 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 881 CGM.Int32Ty, // tid 882 CGM.Int32Ty, // schedtype 883 ITy, // lower 884 ITy, // upper 885 ITy, // stride 886 ITy // chunk 887 }; 888 llvm::FunctionType *FnTy = 889 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 890 return CGM.CreateRuntimeFunction(FnTy, Name); 891 } 892 893 llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, 894 bool IVSigned) { 895 assert((IVSize == 32 || IVSize == 64) && 896 "IV size is not compatible with the omp runtime"); 897 auto Name = 898 IVSize == 32 899 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 900 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 901 llvm::Type *TypeParams[] = { 902 getIdentTyPointerTy(), // loc 903 CGM.Int32Ty, // tid 904 }; 905 llvm::FunctionType *FnTy = 906 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 907 return CGM.CreateRuntimeFunction(FnTy, Name); 908 } 909 910 llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, 911 bool IVSigned) { 912 assert((IVSize == 32 || IVSize == 64) && 913 "IV size is not compatible with the omp runtime"); 914 auto Name = 915 IVSize == 32 916 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 917 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 918 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 919 auto PtrTy = llvm::PointerType::getUnqual(ITy); 920 llvm::Type *TypeParams[] = { 921 getIdentTyPointerTy(), // loc 922 CGM.Int32Ty, // tid 923 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 924 PtrTy, // p_lower 925 PtrTy, // p_upper 926 PtrTy // p_stride 927 }; 928 llvm::FunctionType *FnTy = 929 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 930 return CGM.CreateRuntimeFunction(FnTy, Name); 931 } 932 933 llvm::Constant * 934 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 935 // Lookup the entry, lazily creating it if necessary. 936 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy, 937 Twine(CGM.getMangledName(VD)) + ".cache."); 938 } 939 940 llvm::Value *CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 941 const VarDecl *VD, 942 llvm::Value *VDAddr, 943 SourceLocation Loc) { 944 auto VarTy = VDAddr->getType()->getPointerElementType(); 945 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 946 CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy), 947 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 948 getOrCreateThreadPrivateCache(VD)}; 949 return CGF.EmitRuntimeCall( 950 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args); 951 } 952 953 void CGOpenMPRuntime::emitThreadPrivateVarInit( 954 CodeGenFunction &CGF, llvm::Value *VDAddr, llvm::Value *Ctor, 955 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 956 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 957 // library. 958 auto OMPLoc = emitUpdateLocation(CGF, Loc); 959 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 960 OMPLoc); 961 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 962 // to register constructor/destructor for variable. 963 llvm::Value *Args[] = {OMPLoc, 964 CGF.Builder.CreatePointerCast(VDAddr, CGM.VoidPtrTy), 965 Ctor, CopyCtor, Dtor}; 966 CGF.EmitRuntimeCall( 967 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 968 } 969 970 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 971 const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc, 972 bool PerformInit, CodeGenFunction *CGF) { 973 VD = VD->getDefinition(CGM.getContext()); 974 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) { 975 ThreadPrivateWithDefinition.insert(VD); 976 QualType ASTTy = VD->getType(); 977 978 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 979 auto Init = VD->getAnyInitializer(); 980 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 981 // Generate function that re-emits the declaration's initializer into the 982 // threadprivate copy of the variable VD 983 CodeGenFunction CtorCGF(CGM); 984 FunctionArgList Args; 985 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), 986 /*Id=*/nullptr, CGM.getContext().VoidPtrTy); 987 Args.push_back(&Dst); 988 989 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( 990 CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(), 991 /*isVariadic=*/false); 992 auto FTy = CGM.getTypes().GetFunctionType(FI); 993 auto Fn = CGM.CreateGlobalInitOrDestructFunction( 994 FTy, ".__kmpc_global_ctor_.", Loc); 995 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 996 Args, SourceLocation()); 997 auto ArgVal = CtorCGF.EmitLoadOfScalar( 998 CtorCGF.GetAddrOfLocalVar(&Dst), 999 /*Volatile=*/false, CGM.PointerAlignInBytes, 1000 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1001 auto Arg = CtorCGF.Builder.CreatePointerCast( 1002 ArgVal, 1003 CtorCGF.ConvertTypeForMem(CGM.getContext().getPointerType(ASTTy))); 1004 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 1005 /*IsInitializer=*/true); 1006 ArgVal = CtorCGF.EmitLoadOfScalar( 1007 CtorCGF.GetAddrOfLocalVar(&Dst), 1008 /*Volatile=*/false, CGM.PointerAlignInBytes, 1009 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1010 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 1011 CtorCGF.FinishFunction(); 1012 Ctor = Fn; 1013 } 1014 if (VD->getType().isDestructedType() != QualType::DK_none) { 1015 // Generate function that emits destructor call for the threadprivate copy 1016 // of the variable VD 1017 CodeGenFunction DtorCGF(CGM); 1018 FunctionArgList Args; 1019 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), 1020 /*Id=*/nullptr, CGM.getContext().VoidPtrTy); 1021 Args.push_back(&Dst); 1022 1023 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( 1024 CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(), 1025 /*isVariadic=*/false); 1026 auto FTy = CGM.getTypes().GetFunctionType(FI); 1027 auto Fn = CGM.CreateGlobalInitOrDestructFunction( 1028 FTy, ".__kmpc_global_dtor_.", Loc); 1029 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 1030 SourceLocation()); 1031 auto ArgVal = DtorCGF.EmitLoadOfScalar( 1032 DtorCGF.GetAddrOfLocalVar(&Dst), 1033 /*Volatile=*/false, CGM.PointerAlignInBytes, 1034 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1035 DtorCGF.emitDestroy(ArgVal, ASTTy, 1036 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1037 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1038 DtorCGF.FinishFunction(); 1039 Dtor = Fn; 1040 } 1041 // Do not emit init function if it is not required. 1042 if (!Ctor && !Dtor) 1043 return nullptr; 1044 1045 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1046 auto CopyCtorTy = 1047 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 1048 /*isVarArg=*/false)->getPointerTo(); 1049 // Copying constructor for the threadprivate variable. 1050 // Must be NULL - reserved by runtime, but currently it requires that this 1051 // parameter is always NULL. Otherwise it fires assertion. 1052 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 1053 if (Ctor == nullptr) { 1054 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1055 /*isVarArg=*/false)->getPointerTo(); 1056 Ctor = llvm::Constant::getNullValue(CtorTy); 1057 } 1058 if (Dtor == nullptr) { 1059 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 1060 /*isVarArg=*/false)->getPointerTo(); 1061 Dtor = llvm::Constant::getNullValue(DtorTy); 1062 } 1063 if (!CGF) { 1064 auto InitFunctionTy = 1065 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 1066 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction( 1067 InitFunctionTy, ".__omp_threadprivate_init_."); 1068 CodeGenFunction InitCGF(CGM); 1069 FunctionArgList ArgList; 1070 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 1071 CGM.getTypes().arrangeNullaryFunction(), ArgList, 1072 Loc); 1073 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1074 InitCGF.FinishFunction(); 1075 return InitFunction; 1076 } 1077 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1078 } 1079 return nullptr; 1080 } 1081 1082 /// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen 1083 /// function. Here is the logic: 1084 /// if (Cond) { 1085 /// ThenGen(); 1086 /// } else { 1087 /// ElseGen(); 1088 /// } 1089 static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, 1090 const RegionCodeGenTy &ThenGen, 1091 const RegionCodeGenTy &ElseGen) { 1092 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 1093 1094 // If the condition constant folds and can be elided, try to avoid emitting 1095 // the condition and the dead arm of the if/else. 1096 bool CondConstant; 1097 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 1098 CodeGenFunction::RunCleanupsScope Scope(CGF); 1099 if (CondConstant) { 1100 ThenGen(CGF); 1101 } else { 1102 ElseGen(CGF); 1103 } 1104 return; 1105 } 1106 1107 // Otherwise, the condition did not fold, or we couldn't elide it. Just 1108 // emit the conditional branch. 1109 auto ThenBlock = CGF.createBasicBlock("omp_if.then"); 1110 auto ElseBlock = CGF.createBasicBlock("omp_if.else"); 1111 auto ContBlock = CGF.createBasicBlock("omp_if.end"); 1112 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 1113 1114 // Emit the 'then' code. 1115 CGF.EmitBlock(ThenBlock); 1116 { 1117 CodeGenFunction::RunCleanupsScope ThenScope(CGF); 1118 ThenGen(CGF); 1119 } 1120 CGF.EmitBranch(ContBlock); 1121 // Emit the 'else' code if present. 1122 { 1123 // There is no need to emit line number for unconditional branch. 1124 auto NL = ApplyDebugLocation::CreateEmpty(CGF); 1125 CGF.EmitBlock(ElseBlock); 1126 } 1127 { 1128 CodeGenFunction::RunCleanupsScope ThenScope(CGF); 1129 ElseGen(CGF); 1130 } 1131 { 1132 // There is no need to emit line number for unconditional branch. 1133 auto NL = ApplyDebugLocation::CreateEmpty(CGF); 1134 CGF.EmitBranch(ContBlock); 1135 } 1136 // Emit the continuation block for code after the if. 1137 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 1138 } 1139 1140 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 1141 llvm::Value *OutlinedFn, 1142 llvm::Value *CapturedStruct, 1143 const Expr *IfCond) { 1144 auto *RTLoc = emitUpdateLocation(CGF, Loc); 1145 auto &&ThenGen = 1146 [this, OutlinedFn, CapturedStruct, RTLoc](CodeGenFunction &CGF) { 1147 // Build call __kmpc_fork_call(loc, 1, microtask, 1148 // captured_struct/*context*/) 1149 llvm::Value *Args[] = { 1150 RTLoc, 1151 CGF.Builder.getInt32( 1152 1), // Number of arguments after 'microtask' argument 1153 // (there is only one additional argument - 'context') 1154 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()), 1155 CGF.EmitCastToVoidPtr(CapturedStruct)}; 1156 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call); 1157 CGF.EmitRuntimeCall(RTLFn, Args); 1158 }; 1159 auto &&ElseGen = [this, OutlinedFn, CapturedStruct, RTLoc, Loc]( 1160 CodeGenFunction &CGF) { 1161 auto ThreadID = getThreadID(CGF, Loc); 1162 // Build calls: 1163 // __kmpc_serialized_parallel(&Loc, GTid); 1164 llvm::Value *Args[] = {RTLoc, ThreadID}; 1165 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), 1166 Args); 1167 1168 // OutlinedFn(>id, &zero, CapturedStruct); 1169 auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc); 1170 auto Int32Ty = CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, 1171 /*Signed*/ true); 1172 auto ZeroAddr = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".zero.addr"); 1173 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); 1174 llvm::Value *OutlinedFnArgs[] = {ThreadIDAddr, ZeroAddr, CapturedStruct}; 1175 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs); 1176 1177 // __kmpc_end_serialized_parallel(&Loc, GTid); 1178 llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID}; 1179 CGF.EmitRuntimeCall( 1180 createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs); 1181 }; 1182 if (IfCond) { 1183 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 1184 } else { 1185 CodeGenFunction::RunCleanupsScope Scope(CGF); 1186 ThenGen(CGF); 1187 } 1188 } 1189 1190 // If we're inside an (outlined) parallel region, use the region info's 1191 // thread-ID variable (it is passed in a first argument of the outlined function 1192 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 1193 // regular serial code region, get thread ID by calling kmp_int32 1194 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 1195 // return the address of that temp. 1196 llvm::Value *CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 1197 SourceLocation Loc) { 1198 if (auto OMPRegionInfo = 1199 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 1200 if (OMPRegionInfo->getThreadIDVariable()) 1201 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); 1202 1203 auto ThreadID = getThreadID(CGF, Loc); 1204 auto Int32Ty = 1205 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 1206 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 1207 CGF.EmitStoreOfScalar(ThreadID, 1208 CGF.MakeNaturalAlignAddrLValue(ThreadIDTemp, Int32Ty)); 1209 1210 return ThreadIDTemp; 1211 } 1212 1213 llvm::Constant * 1214 CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty, 1215 const llvm::Twine &Name) { 1216 SmallString<256> Buffer; 1217 llvm::raw_svector_ostream Out(Buffer); 1218 Out << Name; 1219 auto RuntimeName = Out.str(); 1220 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first; 1221 if (Elem.second) { 1222 assert(Elem.second->getType()->getPointerElementType() == Ty && 1223 "OMP internal variable has different type than requested"); 1224 return &*Elem.second; 1225 } 1226 1227 return Elem.second = new llvm::GlobalVariable( 1228 CGM.getModule(), Ty, /*IsConstant*/ false, 1229 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 1230 Elem.first()); 1231 } 1232 1233 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 1234 llvm::Twine Name(".gomp_critical_user_", CriticalName); 1235 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var")); 1236 } 1237 1238 namespace { 1239 template <size_t N> class CallEndCleanup : public EHScopeStack::Cleanup { 1240 llvm::Value *Callee; 1241 llvm::Value *Args[N]; 1242 1243 public: 1244 CallEndCleanup(llvm::Value *Callee, ArrayRef<llvm::Value *> CleanupArgs) 1245 : Callee(Callee) { 1246 assert(CleanupArgs.size() == N); 1247 std::copy(CleanupArgs.begin(), CleanupArgs.end(), std::begin(Args)); 1248 } 1249 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 1250 CGF.EmitRuntimeCall(Callee, Args); 1251 } 1252 }; 1253 } // namespace 1254 1255 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 1256 StringRef CriticalName, 1257 const RegionCodeGenTy &CriticalOpGen, 1258 SourceLocation Loc) { 1259 // __kmpc_critical(ident_t *, gtid, Lock); 1260 // CriticalOpGen(); 1261 // __kmpc_end_critical(ident_t *, gtid, Lock); 1262 // Prepare arguments and build a call to __kmpc_critical 1263 { 1264 CodeGenFunction::RunCleanupsScope Scope(CGF); 1265 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1266 getCriticalRegionLock(CriticalName)}; 1267 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args); 1268 // Build a call to __kmpc_end_critical 1269 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( 1270 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_critical), 1271 llvm::makeArrayRef(Args)); 1272 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 1273 } 1274 } 1275 1276 static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond, 1277 OpenMPDirectiveKind Kind, 1278 const RegionCodeGenTy &BodyOpGen) { 1279 llvm::Value *CallBool = CGF.EmitScalarConversion( 1280 IfCond, 1281 CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true), 1282 CGF.getContext().BoolTy); 1283 1284 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 1285 auto *ContBlock = CGF.createBasicBlock("omp_if.end"); 1286 // Generate the branch (If-stmt) 1287 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 1288 CGF.EmitBlock(ThenBlock); 1289 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, Kind, BodyOpGen); 1290 // Emit the rest of bblocks/branches 1291 CGF.EmitBranch(ContBlock); 1292 CGF.EmitBlock(ContBlock, true); 1293 } 1294 1295 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 1296 const RegionCodeGenTy &MasterOpGen, 1297 SourceLocation Loc) { 1298 // if(__kmpc_master(ident_t *, gtid)) { 1299 // MasterOpGen(); 1300 // __kmpc_end_master(ident_t *, gtid); 1301 // } 1302 // Prepare arguments and build a call to __kmpc_master 1303 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 1304 auto *IsMaster = 1305 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args); 1306 typedef CallEndCleanup<std::extent<decltype(Args)>::value> 1307 MasterCallEndCleanup; 1308 emitIfStmt(CGF, IsMaster, OMPD_master, [&](CodeGenFunction &CGF) -> void { 1309 CodeGenFunction::RunCleanupsScope Scope(CGF); 1310 CGF.EHStack.pushCleanup<MasterCallEndCleanup>( 1311 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_master), 1312 llvm::makeArrayRef(Args)); 1313 MasterOpGen(CGF); 1314 }); 1315 } 1316 1317 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 1318 SourceLocation Loc) { 1319 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 1320 llvm::Value *Args[] = { 1321 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1322 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 1323 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 1324 } 1325 1326 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 1327 const RegionCodeGenTy &TaskgroupOpGen, 1328 SourceLocation Loc) { 1329 // __kmpc_taskgroup(ident_t *, gtid); 1330 // TaskgroupOpGen(); 1331 // __kmpc_end_taskgroup(ident_t *, gtid); 1332 // Prepare arguments and build a call to __kmpc_taskgroup 1333 { 1334 CodeGenFunction::RunCleanupsScope Scope(CGF); 1335 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 1336 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args); 1337 // Build a call to __kmpc_end_taskgroup 1338 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( 1339 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 1340 llvm::makeArrayRef(Args)); 1341 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 1342 } 1343 } 1344 1345 static llvm::Value *emitCopyprivateCopyFunction( 1346 CodeGenModule &CGM, llvm::Type *ArgsType, 1347 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 1348 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) { 1349 auto &C = CGM.getContext(); 1350 // void copy_func(void *LHSArg, void *RHSArg); 1351 FunctionArgList Args; 1352 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 1353 C.VoidPtrTy); 1354 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 1355 C.VoidPtrTy); 1356 Args.push_back(&LHSArg); 1357 Args.push_back(&RHSArg); 1358 FunctionType::ExtInfo EI; 1359 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration( 1360 C.VoidTy, Args, EI, /*isVariadic=*/false); 1361 auto *Fn = llvm::Function::Create( 1362 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, 1363 ".omp.copyprivate.copy_func", &CGM.getModule()); 1364 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn); 1365 CodeGenFunction CGF(CGM); 1366 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args); 1367 // Dest = (void*[n])(LHSArg); 1368 // Src = (void*[n])(RHSArg); 1369 auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1370 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg), 1371 CGF.PointerAlignInBytes), 1372 ArgsType); 1373 auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1374 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg), 1375 CGF.PointerAlignInBytes), 1376 ArgsType); 1377 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 1378 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 1379 // ... 1380 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 1381 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 1382 auto *DestAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1383 CGF.Builder.CreateAlignedLoad( 1384 CGF.Builder.CreateStructGEP(nullptr, LHS, I), 1385 CGM.PointerAlignInBytes), 1386 CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType()))); 1387 auto *SrcAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1388 CGF.Builder.CreateAlignedLoad( 1389 CGF.Builder.CreateStructGEP(nullptr, RHS, I), 1390 CGM.PointerAlignInBytes), 1391 CGF.ConvertTypeForMem(C.getPointerType(SrcExprs[I]->getType()))); 1392 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 1393 QualType Type = VD->getType(); 1394 CGF.EmitOMPCopy(CGF, Type, DestAddr, SrcAddr, 1395 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()), 1396 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()), 1397 AssignmentOps[I]); 1398 } 1399 CGF.FinishFunction(); 1400 return Fn; 1401 } 1402 1403 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 1404 const RegionCodeGenTy &SingleOpGen, 1405 SourceLocation Loc, 1406 ArrayRef<const Expr *> CopyprivateVars, 1407 ArrayRef<const Expr *> SrcExprs, 1408 ArrayRef<const Expr *> DstExprs, 1409 ArrayRef<const Expr *> AssignmentOps) { 1410 assert(CopyprivateVars.size() == SrcExprs.size() && 1411 CopyprivateVars.size() == DstExprs.size() && 1412 CopyprivateVars.size() == AssignmentOps.size()); 1413 auto &C = CGM.getContext(); 1414 // int32 did_it = 0; 1415 // if(__kmpc_single(ident_t *, gtid)) { 1416 // SingleOpGen(); 1417 // __kmpc_end_single(ident_t *, gtid); 1418 // did_it = 1; 1419 // } 1420 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 1421 // <copy_func>, did_it); 1422 1423 llvm::AllocaInst *DidIt = nullptr; 1424 if (!CopyprivateVars.empty()) { 1425 // int32 did_it = 0; 1426 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1427 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 1428 CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(0), DidIt, 1429 DidIt->getAlignment()); 1430 } 1431 // Prepare arguments and build a call to __kmpc_single 1432 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 1433 auto *IsSingle = 1434 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args); 1435 typedef CallEndCleanup<std::extent<decltype(Args)>::value> 1436 SingleCallEndCleanup; 1437 emitIfStmt(CGF, IsSingle, OMPD_single, [&](CodeGenFunction &CGF) -> void { 1438 CodeGenFunction::RunCleanupsScope Scope(CGF); 1439 CGF.EHStack.pushCleanup<SingleCallEndCleanup>( 1440 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_single), 1441 llvm::makeArrayRef(Args)); 1442 SingleOpGen(CGF); 1443 if (DidIt) { 1444 // did_it = 1; 1445 CGF.Builder.CreateAlignedStore(CGF.Builder.getInt32(1), DidIt, 1446 DidIt->getAlignment()); 1447 } 1448 }); 1449 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 1450 // <copy_func>, did_it); 1451 if (DidIt) { 1452 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 1453 auto CopyprivateArrayTy = 1454 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 1455 /*IndexTypeQuals=*/0); 1456 // Create a list of all private variables for copyprivate. 1457 auto *CopyprivateList = 1458 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 1459 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 1460 auto *Elem = CGF.Builder.CreateStructGEP( 1461 CopyprivateList->getAllocatedType(), CopyprivateList, I); 1462 CGF.Builder.CreateAlignedStore( 1463 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1464 CGF.EmitLValue(CopyprivateVars[I]).getAddress(), CGF.VoidPtrTy), 1465 Elem, CGM.PointerAlignInBytes); 1466 } 1467 // Build function that copies private values from single region to all other 1468 // threads in the corresponding parallel region. 1469 auto *CpyFn = emitCopyprivateCopyFunction( 1470 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 1471 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps); 1472 auto *BufSize = llvm::ConstantInt::get( 1473 CGM.SizeTy, C.getTypeSizeInChars(CopyprivateArrayTy).getQuantity()); 1474 auto *CL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 1475 CGF.VoidPtrTy); 1476 auto *DidItVal = 1477 CGF.Builder.CreateAlignedLoad(DidIt, CGF.PointerAlignInBytes); 1478 llvm::Value *Args[] = { 1479 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 1480 getThreadID(CGF, Loc), // i32 <gtid> 1481 BufSize, // size_t <buf_size> 1482 CL, // void *<copyprivate list> 1483 CpyFn, // void (*) (void *, void *) <copy_func> 1484 DidItVal // i32 did_it 1485 }; 1486 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 1487 } 1488 } 1489 1490 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 1491 const RegionCodeGenTy &OrderedOpGen, 1492 SourceLocation Loc) { 1493 // __kmpc_ordered(ident_t *, gtid); 1494 // OrderedOpGen(); 1495 // __kmpc_end_ordered(ident_t *, gtid); 1496 // Prepare arguments and build a call to __kmpc_ordered 1497 { 1498 CodeGenFunction::RunCleanupsScope Scope(CGF); 1499 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 1500 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_ordered), Args); 1501 // Build a call to __kmpc_end_ordered 1502 CGF.EHStack.pushCleanup<CallEndCleanup<std::extent<decltype(Args)>::value>>( 1503 NormalAndEHCleanup, createRuntimeFunction(OMPRTL__kmpc_end_ordered), 1504 llvm::makeArrayRef(Args)); 1505 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 1506 } 1507 } 1508 1509 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 1510 OpenMPDirectiveKind Kind, 1511 bool CheckForCancel) { 1512 // Build call __kmpc_cancel_barrier(loc, thread_id); 1513 // Build call __kmpc_barrier(loc, thread_id); 1514 OpenMPLocationFlags Flags = OMP_IDENT_KMPC; 1515 if (Kind == OMPD_for) { 1516 Flags = 1517 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_FOR); 1518 } else if (Kind == OMPD_sections) { 1519 Flags = static_cast<OpenMPLocationFlags>(Flags | 1520 OMP_IDENT_BARRIER_IMPL_SECTIONS); 1521 } else if (Kind == OMPD_single) { 1522 Flags = 1523 static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL_SINGLE); 1524 } else if (Kind == OMPD_barrier) { 1525 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_EXPL); 1526 } else { 1527 Flags = static_cast<OpenMPLocationFlags>(Flags | OMP_IDENT_BARRIER_IMPL); 1528 } 1529 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 1530 // thread_id); 1531 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 1532 getThreadID(CGF, Loc)}; 1533 if (auto *OMPRegionInfo = 1534 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1535 auto CancelDestination = 1536 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 1537 if (CancelDestination.isValid()) { 1538 auto *Result = CGF.EmitRuntimeCall( 1539 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 1540 if (CheckForCancel) { 1541 // if (__kmpc_cancel_barrier()) { 1542 // exit from construct; 1543 // } 1544 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 1545 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 1546 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 1547 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 1548 CGF.EmitBlock(ExitBB); 1549 // exit from construct; 1550 CGF.EmitBranchThroughCleanup(CancelDestination); 1551 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 1552 } 1553 return; 1554 } 1555 } 1556 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 1557 } 1558 1559 /// \brief Schedule types for 'omp for' loops (these enumerators are taken from 1560 /// the enum sched_type in kmp.h). 1561 enum OpenMPSchedType { 1562 /// \brief Lower bound for default (unordered) versions. 1563 OMP_sch_lower = 32, 1564 OMP_sch_static_chunked = 33, 1565 OMP_sch_static = 34, 1566 OMP_sch_dynamic_chunked = 35, 1567 OMP_sch_guided_chunked = 36, 1568 OMP_sch_runtime = 37, 1569 OMP_sch_auto = 38, 1570 /// \brief Lower bound for 'ordered' versions. 1571 OMP_ord_lower = 64, 1572 OMP_ord_static_chunked = 65, 1573 OMP_ord_static = 66, 1574 OMP_ord_dynamic_chunked = 67, 1575 OMP_ord_guided_chunked = 68, 1576 OMP_ord_runtime = 69, 1577 OMP_ord_auto = 70, 1578 OMP_sch_default = OMP_sch_static, 1579 }; 1580 1581 /// \brief Map the OpenMP loop schedule to the runtime enumeration. 1582 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 1583 bool Chunked, bool Ordered) { 1584 switch (ScheduleKind) { 1585 case OMPC_SCHEDULE_static: 1586 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 1587 : (Ordered ? OMP_ord_static : OMP_sch_static); 1588 case OMPC_SCHEDULE_dynamic: 1589 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 1590 case OMPC_SCHEDULE_guided: 1591 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 1592 case OMPC_SCHEDULE_runtime: 1593 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 1594 case OMPC_SCHEDULE_auto: 1595 return Ordered ? OMP_ord_auto : OMP_sch_auto; 1596 case OMPC_SCHEDULE_unknown: 1597 assert(!Chunked && "chunk was specified but schedule kind not known"); 1598 return Ordered ? OMP_ord_static : OMP_sch_static; 1599 } 1600 llvm_unreachable("Unexpected runtime schedule"); 1601 } 1602 1603 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 1604 bool Chunked) const { 1605 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 1606 return Schedule == OMP_sch_static; 1607 } 1608 1609 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 1610 auto Schedule = 1611 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 1612 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 1613 return Schedule != OMP_sch_static; 1614 } 1615 1616 void CGOpenMPRuntime::emitForInit(CodeGenFunction &CGF, SourceLocation Loc, 1617 OpenMPScheduleClauseKind ScheduleKind, 1618 unsigned IVSize, bool IVSigned, bool Ordered, 1619 llvm::Value *IL, llvm::Value *LB, 1620 llvm::Value *UB, llvm::Value *ST, 1621 llvm::Value *Chunk) { 1622 OpenMPSchedType Schedule = 1623 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered); 1624 if (Ordered || 1625 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 1626 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked)) { 1627 // Call __kmpc_dispatch_init( 1628 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 1629 // kmp_int[32|64] lower, kmp_int[32|64] upper, 1630 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 1631 1632 // If the Chunk was not specified in the clause - use default value 1. 1633 if (Chunk == nullptr) 1634 Chunk = CGF.Builder.getIntN(IVSize, 1); 1635 llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), 1636 getThreadID(CGF, Loc), 1637 CGF.Builder.getInt32(Schedule), // Schedule type 1638 CGF.Builder.getIntN(IVSize, 0), // Lower 1639 UB, // Upper 1640 CGF.Builder.getIntN(IVSize, 1), // Stride 1641 Chunk // Chunk 1642 }; 1643 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 1644 } else { 1645 // Call __kmpc_for_static_init( 1646 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 1647 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 1648 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 1649 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 1650 if (Chunk == nullptr) { 1651 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static) && 1652 "expected static non-chunked schedule"); 1653 // If the Chunk was not specified in the clause - use default value 1. 1654 Chunk = CGF.Builder.getIntN(IVSize, 1); 1655 } else 1656 assert((Schedule == OMP_sch_static_chunked || 1657 Schedule == OMP_ord_static_chunked) && 1658 "expected static chunked schedule"); 1659 llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), 1660 getThreadID(CGF, Loc), 1661 CGF.Builder.getInt32(Schedule), // Schedule type 1662 IL, // &isLastIter 1663 LB, // &LB 1664 UB, // &UB 1665 ST, // &Stride 1666 CGF.Builder.getIntN(IVSize, 1), // Incr 1667 Chunk // Chunk 1668 }; 1669 CGF.EmitRuntimeCall(createForStaticInitFunction(IVSize, IVSigned), Args); 1670 } 1671 } 1672 1673 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 1674 SourceLocation Loc) { 1675 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 1676 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), 1677 getThreadID(CGF, Loc)}; 1678 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 1679 Args); 1680 } 1681 1682 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 1683 SourceLocation Loc, 1684 unsigned IVSize, 1685 bool IVSigned) { 1686 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 1687 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), 1688 getThreadID(CGF, Loc)}; 1689 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 1690 } 1691 1692 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 1693 SourceLocation Loc, unsigned IVSize, 1694 bool IVSigned, llvm::Value *IL, 1695 llvm::Value *LB, llvm::Value *UB, 1696 llvm::Value *ST) { 1697 // Call __kmpc_dispatch_next( 1698 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 1699 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 1700 // kmp_int[32|64] *p_stride); 1701 llvm::Value *Args[] = { 1702 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), getThreadID(CGF, Loc), 1703 IL, // &isLastIter 1704 LB, // &Lower 1705 UB, // &Upper 1706 ST // &Stride 1707 }; 1708 llvm::Value *Call = 1709 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 1710 return CGF.EmitScalarConversion( 1711 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true), 1712 CGF.getContext().BoolTy); 1713 } 1714 1715 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 1716 llvm::Value *NumThreads, 1717 SourceLocation Loc) { 1718 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 1719 llvm::Value *Args[] = { 1720 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1721 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 1722 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 1723 Args); 1724 } 1725 1726 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 1727 OpenMPProcBindClauseKind ProcBind, 1728 SourceLocation Loc) { 1729 // Constants for proc bind value accepted by the runtime. 1730 enum ProcBindTy { 1731 ProcBindFalse = 0, 1732 ProcBindTrue, 1733 ProcBindMaster, 1734 ProcBindClose, 1735 ProcBindSpread, 1736 ProcBindIntel, 1737 ProcBindDefault 1738 } RuntimeProcBind; 1739 switch (ProcBind) { 1740 case OMPC_PROC_BIND_master: 1741 RuntimeProcBind = ProcBindMaster; 1742 break; 1743 case OMPC_PROC_BIND_close: 1744 RuntimeProcBind = ProcBindClose; 1745 break; 1746 case OMPC_PROC_BIND_spread: 1747 RuntimeProcBind = ProcBindSpread; 1748 break; 1749 case OMPC_PROC_BIND_unknown: 1750 llvm_unreachable("Unsupported proc_bind value."); 1751 } 1752 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 1753 llvm::Value *Args[] = { 1754 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1755 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; 1756 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 1757 } 1758 1759 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 1760 SourceLocation Loc) { 1761 // Build call void __kmpc_flush(ident_t *loc) 1762 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 1763 emitUpdateLocation(CGF, Loc)); 1764 } 1765 1766 namespace { 1767 /// \brief Indexes of fields for type kmp_task_t. 1768 enum KmpTaskTFields { 1769 /// \brief List of shared variables. 1770 KmpTaskTShareds, 1771 /// \brief Task routine. 1772 KmpTaskTRoutine, 1773 /// \brief Partition id for the untied tasks. 1774 KmpTaskTPartId, 1775 /// \brief Function with call of destructors for private variables. 1776 KmpTaskTDestructors, 1777 }; 1778 } // namespace 1779 1780 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 1781 if (!KmpRoutineEntryPtrTy) { 1782 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 1783 auto &C = CGM.getContext(); 1784 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 1785 FunctionProtoType::ExtProtoInfo EPI; 1786 KmpRoutineEntryPtrQTy = C.getPointerType( 1787 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 1788 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 1789 } 1790 } 1791 1792 static void addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1793 QualType FieldTy) { 1794 auto *Field = FieldDecl::Create( 1795 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1796 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1797 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1798 Field->setAccess(AS_public); 1799 DC->addDecl(Field); 1800 } 1801 1802 namespace { 1803 struct PrivateHelpersTy { 1804 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 1805 const VarDecl *PrivateElemInit) 1806 : Original(Original), PrivateCopy(PrivateCopy), 1807 PrivateElemInit(PrivateElemInit) {} 1808 const VarDecl *Original; 1809 const VarDecl *PrivateCopy; 1810 const VarDecl *PrivateElemInit; 1811 }; 1812 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 1813 } // namespace 1814 1815 static RecordDecl * 1816 createPrivatesRecordDecl(CodeGenModule &CGM, 1817 const ArrayRef<PrivateDataTy> Privates) { 1818 if (!Privates.empty()) { 1819 auto &C = CGM.getContext(); 1820 // Build struct .kmp_privates_t. { 1821 // /* private vars */ 1822 // }; 1823 auto *RD = C.buildImplicitRecord(".kmp_privates.t"); 1824 RD->startDefinition(); 1825 for (auto &&Pair : Privates) { 1826 auto Type = Pair.second.Original->getType(); 1827 Type = Type.getNonReferenceType(); 1828 addFieldToRecordDecl(C, RD, Type); 1829 } 1830 RD->completeDefinition(); 1831 return RD; 1832 } 1833 return nullptr; 1834 } 1835 1836 static RecordDecl * 1837 createKmpTaskTRecordDecl(CodeGenModule &CGM, QualType KmpInt32Ty, 1838 QualType KmpRoutineEntryPointerQTy) { 1839 auto &C = CGM.getContext(); 1840 // Build struct kmp_task_t { 1841 // void * shareds; 1842 // kmp_routine_entry_t routine; 1843 // kmp_int32 part_id; 1844 // kmp_routine_entry_t destructors; 1845 // }; 1846 auto *RD = C.buildImplicitRecord("kmp_task_t"); 1847 RD->startDefinition(); 1848 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1849 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 1850 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1851 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 1852 RD->completeDefinition(); 1853 return RD; 1854 } 1855 1856 static RecordDecl * 1857 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 1858 const ArrayRef<PrivateDataTy> Privates) { 1859 auto &C = CGM.getContext(); 1860 // Build struct kmp_task_t_with_privates { 1861 // kmp_task_t task_data; 1862 // .kmp_privates_t. privates; 1863 // }; 1864 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 1865 RD->startDefinition(); 1866 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 1867 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) { 1868 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 1869 } 1870 RD->completeDefinition(); 1871 return RD; 1872 } 1873 1874 /// \brief Emit a proxy function which accepts kmp_task_t as the second 1875 /// argument. 1876 /// \code 1877 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 1878 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, 1879 /// tt->shareds); 1880 /// return 0; 1881 /// } 1882 /// \endcode 1883 static llvm::Value * 1884 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 1885 QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, 1886 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 1887 QualType SharedsPtrTy, llvm::Value *TaskFunction, 1888 llvm::Value *TaskPrivatesMap) { 1889 auto &C = CGM.getContext(); 1890 FunctionArgList Args; 1891 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty); 1892 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, 1893 /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy); 1894 Args.push_back(&GtidArg); 1895 Args.push_back(&TaskTypeArg); 1896 FunctionType::ExtInfo Info; 1897 auto &TaskEntryFnInfo = 1898 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info, 1899 /*isVariadic=*/false); 1900 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 1901 auto *TaskEntry = 1902 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage, 1903 ".omp_task_entry.", &CGM.getModule()); 1904 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskEntryFnInfo, TaskEntry); 1905 CodeGenFunction CGF(CGM); 1906 CGF.disableDebugInfo(); 1907 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args); 1908 1909 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 1910 // tt->task_data.shareds); 1911 auto *GtidParam = CGF.EmitLoadOfScalar( 1912 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, 1913 C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc); 1914 auto *TaskTypeArgAddr = CGF.Builder.CreateAlignedLoad( 1915 CGF.GetAddrOfLocalVar(&TaskTypeArg), CGM.PointerAlignInBytes); 1916 LValue TDBase = 1917 CGF.MakeNaturalAlignAddrLValue(TaskTypeArgAddr, KmpTaskTWithPrivatesQTy); 1918 auto *KmpTaskTWithPrivatesQTyRD = 1919 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 1920 LValue Base = 1921 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 1922 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 1923 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 1924 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 1925 auto *PartidParam = CGF.EmitLoadOfLValue(PartIdLVal, Loc).getScalarVal(); 1926 1927 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 1928 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 1929 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1930 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(), 1931 CGF.ConvertTypeForMem(SharedsPtrTy)); 1932 1933 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 1934 llvm::Value *PrivatesParam; 1935 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 1936 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 1937 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1938 PrivatesLVal.getAddress(), CGF.VoidPtrTy); 1939 } else { 1940 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 1941 } 1942 1943 llvm::Value *CallArgs[] = {GtidParam, PartidParam, PrivatesParam, 1944 TaskPrivatesMap, SharedsParam}; 1945 CGF.EmitCallOrInvoke(TaskFunction, CallArgs); 1946 CGF.EmitStoreThroughLValue( 1947 RValue::get(CGF.Builder.getInt32(/*C=*/0)), 1948 CGF.MakeNaturalAlignAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 1949 CGF.FinishFunction(); 1950 return TaskEntry; 1951 } 1952 1953 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 1954 SourceLocation Loc, 1955 QualType KmpInt32Ty, 1956 QualType KmpTaskTWithPrivatesPtrQTy, 1957 QualType KmpTaskTWithPrivatesQTy) { 1958 auto &C = CGM.getContext(); 1959 FunctionArgList Args; 1960 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty); 1961 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, 1962 /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy); 1963 Args.push_back(&GtidArg); 1964 Args.push_back(&TaskTypeArg); 1965 FunctionType::ExtInfo Info; 1966 auto &DestructorFnInfo = 1967 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info, 1968 /*isVariadic=*/false); 1969 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo); 1970 auto *DestructorFn = 1971 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 1972 ".omp_task_destructor.", &CGM.getModule()); 1973 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, DestructorFnInfo, DestructorFn); 1974 CodeGenFunction CGF(CGM); 1975 CGF.disableDebugInfo(); 1976 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 1977 Args); 1978 1979 auto *TaskTypeArgAddr = CGF.Builder.CreateAlignedLoad( 1980 CGF.GetAddrOfLocalVar(&TaskTypeArg), CGM.PointerAlignInBytes); 1981 LValue Base = 1982 CGF.MakeNaturalAlignAddrLValue(TaskTypeArgAddr, KmpTaskTWithPrivatesQTy); 1983 auto *KmpTaskTWithPrivatesQTyRD = 1984 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 1985 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 1986 Base = CGF.EmitLValueForField(Base, *FI); 1987 for (auto *Field : 1988 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 1989 if (auto DtorKind = Field->getType().isDestructedType()) { 1990 auto FieldLValue = CGF.EmitLValueForField(Base, Field); 1991 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType()); 1992 } 1993 } 1994 CGF.FinishFunction(); 1995 return DestructorFn; 1996 } 1997 1998 /// \brief Emit a privates mapping function for correct handling of private and 1999 /// firstprivate variables. 2000 /// \code 2001 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 2002 /// **noalias priv1,..., <tyn> **noalias privn) { 2003 /// *priv1 = &.privates.priv1; 2004 /// ...; 2005 /// *privn = &.privates.privn; 2006 /// } 2007 /// \endcode 2008 static llvm::Value * 2009 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 2010 const ArrayRef<const Expr *> PrivateVars, 2011 const ArrayRef<const Expr *> FirstprivateVars, 2012 QualType PrivatesQTy, 2013 const ArrayRef<PrivateDataTy> Privates) { 2014 auto &C = CGM.getContext(); 2015 FunctionArgList Args; 2016 ImplicitParamDecl TaskPrivatesArg( 2017 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 2018 C.getPointerType(PrivatesQTy).withConst().withRestrict()); 2019 Args.push_back(&TaskPrivatesArg); 2020 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 2021 unsigned Counter = 1; 2022 for (auto *E: PrivateVars) { 2023 Args.push_back(ImplicitParamDecl::Create( 2024 C, /*DC=*/nullptr, Loc, 2025 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) 2026 .withConst() 2027 .withRestrict())); 2028 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2029 PrivateVarsPos[VD] = Counter; 2030 ++Counter; 2031 } 2032 for (auto *E : FirstprivateVars) { 2033 Args.push_back(ImplicitParamDecl::Create( 2034 C, /*DC=*/nullptr, Loc, 2035 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) 2036 .withConst() 2037 .withRestrict())); 2038 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2039 PrivateVarsPos[VD] = Counter; 2040 ++Counter; 2041 } 2042 FunctionType::ExtInfo Info; 2043 auto &TaskPrivatesMapFnInfo = 2044 CGM.getTypes().arrangeFreeFunctionDeclaration(C.VoidTy, Args, Info, 2045 /*isVariadic=*/false); 2046 auto *TaskPrivatesMapTy = 2047 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 2048 auto *TaskPrivatesMap = llvm::Function::Create( 2049 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, 2050 ".omp_task_privates_map.", &CGM.getModule()); 2051 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskPrivatesMapFnInfo, 2052 TaskPrivatesMap); 2053 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 2054 CodeGenFunction CGF(CGM); 2055 CGF.disableDebugInfo(); 2056 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 2057 TaskPrivatesMapFnInfo, Args); 2058 2059 // *privi = &.privates.privi; 2060 auto *TaskPrivatesArgAddr = CGF.Builder.CreateAlignedLoad( 2061 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), CGM.PointerAlignInBytes); 2062 LValue Base = 2063 CGF.MakeNaturalAlignAddrLValue(TaskPrivatesArgAddr, PrivatesQTy); 2064 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 2065 Counter = 0; 2066 for (auto *Field : PrivatesQTyRD->fields()) { 2067 auto FieldLVal = CGF.EmitLValueForField(Base, Field); 2068 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 2069 auto RefLVal = CGF.MakeNaturalAlignAddrLValue(CGF.GetAddrOfLocalVar(VD), 2070 VD->getType()); 2071 auto RefLoadRVal = CGF.EmitLoadOfLValue(RefLVal, Loc); 2072 CGF.EmitStoreOfScalar( 2073 FieldLVal.getAddress(), 2074 CGF.MakeNaturalAlignAddrLValue(RefLoadRVal.getScalarVal(), 2075 RefLVal.getType()->getPointeeType())); 2076 ++Counter; 2077 } 2078 CGF.FinishFunction(); 2079 return TaskPrivatesMap; 2080 } 2081 2082 static int array_pod_sort_comparator(const PrivateDataTy *P1, 2083 const PrivateDataTy *P2) { 2084 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0); 2085 } 2086 2087 void CGOpenMPRuntime::emitTaskCall( 2088 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, 2089 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, 2090 llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds, 2091 const Expr *IfCond, ArrayRef<const Expr *> PrivateVars, 2092 ArrayRef<const Expr *> PrivateCopies, 2093 ArrayRef<const Expr *> FirstprivateVars, 2094 ArrayRef<const Expr *> FirstprivateCopies, 2095 ArrayRef<const Expr *> FirstprivateInits, 2096 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) { 2097 auto &C = CGM.getContext(); 2098 llvm::SmallVector<PrivateDataTy, 8> Privates; 2099 // Aggregate privates and sort them by the alignment. 2100 auto I = PrivateCopies.begin(); 2101 for (auto *E : PrivateVars) { 2102 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2103 Privates.push_back(std::make_pair( 2104 C.getTypeAlignInChars(VD->getType()), 2105 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 2106 /*PrivateElemInit=*/nullptr))); 2107 ++I; 2108 } 2109 I = FirstprivateCopies.begin(); 2110 auto IElemInitRef = FirstprivateInits.begin(); 2111 for (auto *E : FirstprivateVars) { 2112 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 2113 Privates.push_back(std::make_pair( 2114 C.getTypeAlignInChars(VD->getType()), 2115 PrivateHelpersTy( 2116 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 2117 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())))); 2118 ++I, ++IElemInitRef; 2119 } 2120 llvm::array_pod_sort(Privates.begin(), Privates.end(), 2121 array_pod_sort_comparator); 2122 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2123 // Build type kmp_routine_entry_t (if not built yet). 2124 emitKmpRoutineEntryT(KmpInt32Ty); 2125 // Build type kmp_task_t (if not built yet). 2126 if (KmpTaskTQTy.isNull()) { 2127 KmpTaskTQTy = C.getRecordType( 2128 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy)); 2129 } 2130 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 2131 // Build particular struct kmp_task_t for the given task. 2132 auto *KmpTaskTWithPrivatesQTyRD = 2133 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 2134 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 2135 QualType KmpTaskTWithPrivatesPtrQTy = 2136 C.getPointerType(KmpTaskTWithPrivatesQTy); 2137 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 2138 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo(); 2139 auto KmpTaskTWithPrivatesTySize = 2140 CGM.getSize(C.getTypeSizeInChars(KmpTaskTWithPrivatesQTy)); 2141 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 2142 2143 // Emit initial values for private copies (if any). 2144 llvm::Value *TaskPrivatesMap = nullptr; 2145 auto *TaskPrivatesMapTy = 2146 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(), 2147 3) 2148 ->getType(); 2149 if (!Privates.empty()) { 2150 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 2151 TaskPrivatesMap = emitTaskPrivateMappingFunction( 2152 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates); 2153 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2154 TaskPrivatesMap, TaskPrivatesMapTy); 2155 } else { 2156 TaskPrivatesMap = llvm::ConstantPointerNull::get( 2157 cast<llvm::PointerType>(TaskPrivatesMapTy)); 2158 } 2159 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 2160 // kmp_task_t *tt); 2161 auto *TaskEntry = emitProxyTaskFunction( 2162 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTy, 2163 KmpTaskTQTy, SharedsPtrTy, TaskFunction, TaskPrivatesMap); 2164 2165 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 2166 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2167 // kmp_routine_entry_t *task_entry); 2168 // Task flags. Format is taken from 2169 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h, 2170 // description of kmp_tasking_flags struct. 2171 const unsigned TiedFlag = 0x1; 2172 const unsigned FinalFlag = 0x2; 2173 unsigned Flags = Tied ? TiedFlag : 0; 2174 auto *TaskFlags = 2175 Final.getPointer() 2176 ? CGF.Builder.CreateSelect(Final.getPointer(), 2177 CGF.Builder.getInt32(FinalFlag), 2178 CGF.Builder.getInt32(/*C=*/0)) 2179 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0); 2180 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 2181 auto SharedsSize = C.getTypeSizeInChars(SharedsTy); 2182 llvm::Value *AllocArgs[] = { 2183 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), TaskFlags, 2184 KmpTaskTWithPrivatesTySize, CGM.getSize(SharedsSize), 2185 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskEntry, 2186 KmpRoutineEntryPtrTy)}; 2187 auto *NewTask = CGF.EmitRuntimeCall( 2188 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 2189 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2190 NewTask, KmpTaskTWithPrivatesPtrTy); 2191 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 2192 KmpTaskTWithPrivatesQTy); 2193 LValue TDBase = 2194 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 2195 // Fill the data in the resulting kmp_task_t record. 2196 // Copy shareds if there are any. 2197 llvm::Value *KmpTaskSharedsPtr = nullptr; 2198 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 2199 KmpTaskSharedsPtr = CGF.EmitLoadOfScalar( 2200 CGF.EmitLValueForField( 2201 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)), 2202 Loc); 2203 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy); 2204 } 2205 // Emit initial values for private copies (if any). 2206 bool NeedsCleanup = false; 2207 if (!Privates.empty()) { 2208 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 2209 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI); 2210 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 2211 LValue SharedsBase; 2212 if (!FirstprivateVars.empty()) { 2213 SharedsBase = CGF.MakeNaturalAlignAddrLValue( 2214 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2215 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 2216 SharedsTy); 2217 } 2218 CodeGenFunction::CGCapturedStmtInfo CapturesInfo( 2219 cast<CapturedStmt>(*D.getAssociatedStmt())); 2220 for (auto &&Pair : Privates) { 2221 auto *VD = Pair.second.PrivateCopy; 2222 auto *Init = VD->getAnyInitializer(); 2223 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 2224 if (Init) { 2225 if (auto *Elem = Pair.second.PrivateElemInit) { 2226 auto *OriginalVD = Pair.second.Original; 2227 auto *SharedField = CapturesInfo.lookup(OriginalVD); 2228 auto SharedRefLValue = 2229 CGF.EmitLValueForField(SharedsBase, SharedField); 2230 QualType Type = OriginalVD->getType(); 2231 if (Type->isArrayType()) { 2232 // Initialize firstprivate array. 2233 if (!isa<CXXConstructExpr>(Init) || 2234 CGF.isTrivialInitializer(Init)) { 2235 // Perform simple memcpy. 2236 CGF.EmitAggregateAssign(PrivateLValue.getAddress(), 2237 SharedRefLValue.getAddress(), Type); 2238 } else { 2239 // Initialize firstprivate array using element-by-element 2240 // intialization. 2241 CGF.EmitOMPAggregateAssign( 2242 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), 2243 Type, [&CGF, Elem, Init, &CapturesInfo]( 2244 llvm::Value *DestElement, llvm::Value *SrcElement) { 2245 // Clean up any temporaries needed by the initialization. 2246 CodeGenFunction::OMPPrivateScope InitScope(CGF); 2247 InitScope.addPrivate(Elem, [SrcElement]() -> llvm::Value *{ 2248 return SrcElement; 2249 }); 2250 (void)InitScope.Privatize(); 2251 // Emit initialization for single element. 2252 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 2253 CGF, &CapturesInfo); 2254 CGF.EmitAnyExprToMem(Init, DestElement, 2255 Init->getType().getQualifiers(), 2256 /*IsInitializer=*/false); 2257 }); 2258 } 2259 } else { 2260 CodeGenFunction::OMPPrivateScope InitScope(CGF); 2261 InitScope.addPrivate(Elem, [SharedRefLValue]() -> llvm::Value *{ 2262 return SharedRefLValue.getAddress(); 2263 }); 2264 (void)InitScope.Privatize(); 2265 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 2266 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 2267 /*capturedByInit=*/false); 2268 } 2269 } else { 2270 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 2271 } 2272 } 2273 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType(); 2274 ++FI; 2275 } 2276 } 2277 // Provide pointer to function with destructors for privates. 2278 llvm::Value *DestructorFn = 2279 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty, 2280 KmpTaskTWithPrivatesPtrQTy, 2281 KmpTaskTWithPrivatesQTy) 2282 : llvm::ConstantPointerNull::get( 2283 cast<llvm::PointerType>(KmpRoutineEntryPtrTy)); 2284 LValue Destructor = CGF.EmitLValueForField( 2285 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors)); 2286 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2287 DestructorFn, KmpRoutineEntryPtrTy), 2288 Destructor); 2289 2290 // Process list of dependences. 2291 llvm::Value *DependInfo = nullptr; 2292 unsigned DependencesNumber = Dependences.size(); 2293 if (!Dependences.empty()) { 2294 // Dependence kind for RTL. 2295 enum RTLDependenceKindTy { DepIn = 1, DepOut = 2, DepInOut = 3 }; 2296 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 2297 RecordDecl *KmpDependInfoRD; 2298 QualType FlagsTy = C.getIntTypeForBitwidth( 2299 C.toBits(C.getTypeSizeInChars(C.BoolTy)), /*Signed=*/false); 2300 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 2301 if (KmpDependInfoTy.isNull()) { 2302 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 2303 KmpDependInfoRD->startDefinition(); 2304 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 2305 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 2306 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 2307 KmpDependInfoRD->completeDefinition(); 2308 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 2309 } else { 2310 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 2311 } 2312 // Define type kmp_depend_info[<Dependences.size()>]; 2313 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 2314 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, Dependences.size()), 2315 ArrayType::Normal, /*IndexTypeQuals=*/0); 2316 // kmp_depend_info[<Dependences.size()>] deps; 2317 DependInfo = CGF.CreateMemTemp(KmpDependInfoArrayTy); 2318 for (unsigned i = 0; i < DependencesNumber; ++i) { 2319 auto Addr = CGF.EmitLValue(Dependences[i].second); 2320 auto *Size = llvm::ConstantInt::get( 2321 CGF.SizeTy, 2322 C.getTypeSizeInChars(Dependences[i].second->getType()).getQuantity()); 2323 auto Base = CGF.MakeNaturalAlignAddrLValue( 2324 CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, i), 2325 KmpDependInfoTy); 2326 // deps[i].base_addr = &<Dependences[i].second>; 2327 auto BaseAddrLVal = CGF.EmitLValueForField( 2328 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 2329 CGF.EmitStoreOfScalar( 2330 CGF.Builder.CreatePtrToInt(Addr.getAddress(), CGF.IntPtrTy), 2331 BaseAddrLVal); 2332 // deps[i].len = sizeof(<Dependences[i].second>); 2333 auto LenLVal = CGF.EmitLValueForField( 2334 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 2335 CGF.EmitStoreOfScalar(Size, LenLVal); 2336 // deps[i].flags = <Dependences[i].first>; 2337 RTLDependenceKindTy DepKind; 2338 switch (Dependences[i].first) { 2339 case OMPC_DEPEND_in: 2340 DepKind = DepIn; 2341 break; 2342 case OMPC_DEPEND_out: 2343 DepKind = DepOut; 2344 break; 2345 case OMPC_DEPEND_inout: 2346 DepKind = DepInOut; 2347 break; 2348 case OMPC_DEPEND_unknown: 2349 llvm_unreachable("Unknown task dependence type"); 2350 } 2351 auto FlagsLVal = CGF.EmitLValueForField( 2352 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 2353 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 2354 FlagsLVal); 2355 } 2356 DependInfo = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2357 CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, DependInfo, 0), 2358 CGF.VoidPtrTy); 2359 } 2360 2361 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc() 2362 // libcall. 2363 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2364 // *new_task); 2365 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2366 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2367 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 2368 // list is not empty 2369 auto *ThreadID = getThreadID(CGF, Loc); 2370 auto *UpLoc = emitUpdateLocation(CGF, Loc); 2371 llvm::Value *TaskArgs[] = {UpLoc, ThreadID, NewTask}; 2372 llvm::Value *DepTaskArgs[] = { 2373 UpLoc, 2374 ThreadID, 2375 NewTask, 2376 DependInfo ? CGF.Builder.getInt32(DependencesNumber) : nullptr, 2377 DependInfo, 2378 DependInfo ? CGF.Builder.getInt32(0) : nullptr, 2379 DependInfo ? llvm::ConstantPointerNull::get(CGF.VoidPtrTy) : nullptr}; 2380 auto &&ThenCodeGen = [this, DependInfo, &TaskArgs, 2381 &DepTaskArgs](CodeGenFunction &CGF) { 2382 // TODO: add check for untied tasks. 2383 CGF.EmitRuntimeCall( 2384 createRuntimeFunction(DependInfo ? OMPRTL__kmpc_omp_task_with_deps 2385 : OMPRTL__kmpc_omp_task), 2386 DependInfo ? makeArrayRef(DepTaskArgs) : makeArrayRef(TaskArgs)); 2387 }; 2388 typedef CallEndCleanup<std::extent<decltype(TaskArgs)>::value> 2389 IfCallEndCleanup; 2390 llvm::Value *DepWaitTaskArgs[] = { 2391 UpLoc, 2392 ThreadID, 2393 DependInfo ? CGF.Builder.getInt32(DependencesNumber) : nullptr, 2394 DependInfo, 2395 DependInfo ? CGF.Builder.getInt32(0) : nullptr, 2396 DependInfo ? llvm::ConstantPointerNull::get(CGF.VoidPtrTy) : nullptr}; 2397 auto &&ElseCodeGen = [this, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 2398 DependInfo, &DepWaitTaskArgs](CodeGenFunction &CGF) { 2399 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 2400 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2401 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 2402 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 2403 // is specified. 2404 if (DependInfo) 2405 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 2406 DepWaitTaskArgs); 2407 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 2408 // kmp_task_t *new_task); 2409 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), 2410 TaskArgs); 2411 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 2412 // kmp_task_t *new_task); 2413 CGF.EHStack.pushCleanup<IfCallEndCleanup>( 2414 NormalAndEHCleanup, 2415 createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), 2416 llvm::makeArrayRef(TaskArgs)); 2417 2418 // Call proxy_task_entry(gtid, new_task); 2419 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 2420 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs); 2421 }; 2422 if (IfCond) { 2423 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 2424 } else { 2425 CodeGenFunction::RunCleanupsScope Scope(CGF); 2426 ThenCodeGen(CGF); 2427 } 2428 } 2429 2430 static llvm::Value *emitReductionFunction(CodeGenModule &CGM, 2431 llvm::Type *ArgsType, 2432 ArrayRef<const Expr *> LHSExprs, 2433 ArrayRef<const Expr *> RHSExprs, 2434 ArrayRef<const Expr *> ReductionOps) { 2435 auto &C = CGM.getContext(); 2436 2437 // void reduction_func(void *LHSArg, void *RHSArg); 2438 FunctionArgList Args; 2439 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 2440 C.VoidPtrTy); 2441 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 2442 C.VoidPtrTy); 2443 Args.push_back(&LHSArg); 2444 Args.push_back(&RHSArg); 2445 FunctionType::ExtInfo EI; 2446 auto &CGFI = CGM.getTypes().arrangeFreeFunctionDeclaration( 2447 C.VoidTy, Args, EI, /*isVariadic=*/false); 2448 auto *Fn = llvm::Function::Create( 2449 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, 2450 ".omp.reduction.reduction_func", &CGM.getModule()); 2451 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, CGFI, Fn); 2452 CodeGenFunction CGF(CGM); 2453 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args); 2454 2455 // Dst = (void*[n])(LHSArg); 2456 // Src = (void*[n])(RHSArg); 2457 auto *LHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2458 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&LHSArg), 2459 CGF.PointerAlignInBytes), 2460 ArgsType); 2461 auto *RHS = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2462 CGF.Builder.CreateAlignedLoad(CGF.GetAddrOfLocalVar(&RHSArg), 2463 CGF.PointerAlignInBytes), 2464 ArgsType); 2465 2466 // ... 2467 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 2468 // ... 2469 CodeGenFunction::OMPPrivateScope Scope(CGF); 2470 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I) { 2471 Scope.addPrivate( 2472 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()), 2473 [&]() -> llvm::Value *{ 2474 return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2475 CGF.Builder.CreateAlignedLoad( 2476 CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, RHS, I), 2477 CGM.PointerAlignInBytes), 2478 CGF.ConvertTypeForMem(C.getPointerType(RHSExprs[I]->getType()))); 2479 }); 2480 Scope.addPrivate( 2481 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()), 2482 [&]() -> llvm::Value *{ 2483 return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2484 CGF.Builder.CreateAlignedLoad( 2485 CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, LHS, I), 2486 CGM.PointerAlignInBytes), 2487 CGF.ConvertTypeForMem(C.getPointerType(LHSExprs[I]->getType()))); 2488 }); 2489 } 2490 Scope.Privatize(); 2491 for (auto *E : ReductionOps) { 2492 CGF.EmitIgnoredExpr(E); 2493 } 2494 Scope.ForceCleanup(); 2495 CGF.FinishFunction(); 2496 return Fn; 2497 } 2498 2499 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 2500 ArrayRef<const Expr *> LHSExprs, 2501 ArrayRef<const Expr *> RHSExprs, 2502 ArrayRef<const Expr *> ReductionOps, 2503 bool WithNowait, bool SimpleReduction) { 2504 // Next code should be emitted for reduction: 2505 // 2506 // static kmp_critical_name lock = { 0 }; 2507 // 2508 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 2509 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 2510 // ... 2511 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 2512 // *(Type<n>-1*)rhs[<n>-1]); 2513 // } 2514 // 2515 // ... 2516 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 2517 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 2518 // RedList, reduce_func, &<lock>)) { 2519 // case 1: 2520 // ... 2521 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 2522 // ... 2523 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 2524 // break; 2525 // case 2: 2526 // ... 2527 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 2528 // ... 2529 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 2530 // break; 2531 // default:; 2532 // } 2533 // 2534 // if SimpleReduction is true, only the next code is generated: 2535 // ... 2536 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 2537 // ... 2538 2539 auto &C = CGM.getContext(); 2540 2541 if (SimpleReduction) { 2542 CodeGenFunction::RunCleanupsScope Scope(CGF); 2543 for (auto *E : ReductionOps) { 2544 CGF.EmitIgnoredExpr(E); 2545 } 2546 return; 2547 } 2548 2549 // 1. Build a list of reduction variables. 2550 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 2551 llvm::APInt ArraySize(/*unsigned int numBits=*/32, RHSExprs.size()); 2552 QualType ReductionArrayTy = 2553 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 2554 /*IndexTypeQuals=*/0); 2555 auto *ReductionList = 2556 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 2557 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I) { 2558 auto *Elem = CGF.Builder.CreateStructGEP(/*Ty=*/nullptr, ReductionList, I); 2559 CGF.Builder.CreateAlignedStore( 2560 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2561 CGF.EmitLValue(RHSExprs[I]).getAddress(), CGF.VoidPtrTy), 2562 Elem, CGM.PointerAlignInBytes); 2563 } 2564 2565 // 2. Emit reduce_func(). 2566 auto *ReductionFn = emitReductionFunction( 2567 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), LHSExprs, 2568 RHSExprs, ReductionOps); 2569 2570 // 3. Create static kmp_critical_name lock = { 0 }; 2571 auto *Lock = getCriticalRegionLock(".reduction"); 2572 2573 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 2574 // RedList, reduce_func, &<lock>); 2575 auto *IdentTLoc = emitUpdateLocation( 2576 CGF, Loc, 2577 static_cast<OpenMPLocationFlags>(OMP_IDENT_KMPC | OMP_ATOMIC_REDUCE)); 2578 auto *ThreadId = getThreadID(CGF, Loc); 2579 auto *ReductionArrayTySize = llvm::ConstantInt::get( 2580 CGM.SizeTy, C.getTypeSizeInChars(ReductionArrayTy).getQuantity()); 2581 auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, 2582 CGF.VoidPtrTy); 2583 llvm::Value *Args[] = { 2584 IdentTLoc, // ident_t *<loc> 2585 ThreadId, // i32 <gtid> 2586 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 2587 ReductionArrayTySize, // size_type sizeof(RedList) 2588 RL, // void *RedList 2589 ReductionFn, // void (*) (void *, void *) <reduce_func> 2590 Lock // kmp_critical_name *&<lock> 2591 }; 2592 auto Res = CGF.EmitRuntimeCall( 2593 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 2594 : OMPRTL__kmpc_reduce), 2595 Args); 2596 2597 // 5. Build switch(res) 2598 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 2599 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 2600 2601 // 6. Build case 1: 2602 // ... 2603 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 2604 // ... 2605 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 2606 // break; 2607 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 2608 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 2609 CGF.EmitBlock(Case1BB); 2610 2611 { 2612 CodeGenFunction::RunCleanupsScope Scope(CGF); 2613 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 2614 llvm::Value *EndArgs[] = { 2615 IdentTLoc, // ident_t *<loc> 2616 ThreadId, // i32 <gtid> 2617 Lock // kmp_critical_name *&<lock> 2618 }; 2619 CGF.EHStack 2620 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>( 2621 NormalAndEHCleanup, 2622 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 2623 : OMPRTL__kmpc_end_reduce), 2624 llvm::makeArrayRef(EndArgs)); 2625 for (auto *E : ReductionOps) { 2626 CGF.EmitIgnoredExpr(E); 2627 } 2628 } 2629 2630 CGF.EmitBranch(DefaultBB); 2631 2632 // 7. Build case 2: 2633 // ... 2634 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 2635 // ... 2636 // break; 2637 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 2638 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 2639 CGF.EmitBlock(Case2BB); 2640 2641 { 2642 CodeGenFunction::RunCleanupsScope Scope(CGF); 2643 if (!WithNowait) { 2644 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 2645 llvm::Value *EndArgs[] = { 2646 IdentTLoc, // ident_t *<loc> 2647 ThreadId, // i32 <gtid> 2648 Lock // kmp_critical_name *&<lock> 2649 }; 2650 CGF.EHStack 2651 .pushCleanup<CallEndCleanup<std::extent<decltype(EndArgs)>::value>>( 2652 NormalAndEHCleanup, 2653 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 2654 llvm::makeArrayRef(EndArgs)); 2655 } 2656 auto I = LHSExprs.begin(); 2657 for (auto *E : ReductionOps) { 2658 const Expr *XExpr = nullptr; 2659 const Expr *EExpr = nullptr; 2660 const Expr *UpExpr = nullptr; 2661 BinaryOperatorKind BO = BO_Comma; 2662 if (auto *BO = dyn_cast<BinaryOperator>(E)) { 2663 if (BO->getOpcode() == BO_Assign) { 2664 XExpr = BO->getLHS(); 2665 UpExpr = BO->getRHS(); 2666 } 2667 } 2668 // Try to emit update expression as a simple atomic. 2669 auto *RHSExpr = UpExpr; 2670 if (RHSExpr) { 2671 // Analyze RHS part of the whole expression. 2672 if (auto *ACO = dyn_cast<AbstractConditionalOperator>( 2673 RHSExpr->IgnoreParenImpCasts())) { 2674 // If this is a conditional operator, analyze its condition for 2675 // min/max reduction operator. 2676 RHSExpr = ACO->getCond(); 2677 } 2678 if (auto *BORHS = 2679 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 2680 EExpr = BORHS->getRHS(); 2681 BO = BORHS->getOpcode(); 2682 } 2683 } 2684 if (XExpr) { 2685 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()); 2686 LValue X = CGF.EmitLValue(XExpr); 2687 RValue E; 2688 if (EExpr) 2689 E = CGF.EmitAnyExpr(EExpr); 2690 CGF.EmitOMPAtomicSimpleUpdateExpr( 2691 X, E, BO, /*IsXLHSInRHSPart=*/true, llvm::Monotonic, Loc, 2692 [&CGF, UpExpr, VD](RValue XRValue) { 2693 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 2694 PrivateScope.addPrivate( 2695 VD, [&CGF, VD, XRValue]() -> llvm::Value *{ 2696 auto *LHSTemp = CGF.CreateMemTemp(VD->getType()); 2697 CGF.EmitStoreThroughLValue( 2698 XRValue, 2699 CGF.MakeNaturalAlignAddrLValue(LHSTemp, VD->getType())); 2700 return LHSTemp; 2701 }); 2702 (void)PrivateScope.Privatize(); 2703 return CGF.EmitAnyExpr(UpExpr); 2704 }); 2705 } else { 2706 // Emit as a critical region. 2707 emitCriticalRegion(CGF, ".atomic_reduction", [E](CodeGenFunction &CGF) { 2708 CGF.EmitIgnoredExpr(E); 2709 }, Loc); 2710 } 2711 ++I; 2712 } 2713 } 2714 2715 CGF.EmitBranch(DefaultBB); 2716 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 2717 } 2718 2719 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 2720 SourceLocation Loc) { 2721 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 2722 // global_tid); 2723 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2724 // Ignore return result until untied tasks are supported. 2725 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 2726 } 2727 2728 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 2729 OpenMPDirectiveKind InnerKind, 2730 const RegionCodeGenTy &CodeGen) { 2731 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind); 2732 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 2733 } 2734 2735 namespace { 2736 enum RTCancelKind { 2737 CancelNoreq = 0, 2738 CancelParallel = 1, 2739 CancelLoop = 2, 2740 CancelSections = 3, 2741 CancelTaskgroup = 4 2742 }; 2743 } 2744 2745 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 2746 RTCancelKind CancelKind = CancelNoreq; 2747 if (CancelRegion == OMPD_parallel) 2748 CancelKind = CancelParallel; 2749 else if (CancelRegion == OMPD_for) 2750 CancelKind = CancelLoop; 2751 else if (CancelRegion == OMPD_sections) 2752 CancelKind = CancelSections; 2753 else { 2754 assert(CancelRegion == OMPD_taskgroup); 2755 CancelKind = CancelTaskgroup; 2756 } 2757 return CancelKind; 2758 } 2759 2760 void CGOpenMPRuntime::emitCancellationPointCall( 2761 CodeGenFunction &CGF, SourceLocation Loc, 2762 OpenMPDirectiveKind CancelRegion) { 2763 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2764 // global_tid, kmp_int32 cncl_kind); 2765 if (auto *OMPRegionInfo = 2766 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 2767 auto CancelDest = 2768 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 2769 if (CancelDest.isValid()) { 2770 llvm::Value *Args[] = { 2771 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2772 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 2773 // Ignore return result until untied tasks are supported. 2774 auto *Result = CGF.EmitRuntimeCall( 2775 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 2776 // if (__kmpc_cancellationpoint()) { 2777 // __kmpc_cancel_barrier(); 2778 // exit from construct; 2779 // } 2780 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 2781 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 2782 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 2783 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 2784 CGF.EmitBlock(ExitBB); 2785 // __kmpc_cancel_barrier(); 2786 emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false); 2787 // exit from construct; 2788 CGF.EmitBranchThroughCleanup(CancelDest); 2789 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 2790 } 2791 } 2792 } 2793 2794 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 2795 OpenMPDirectiveKind CancelRegion) { 2796 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2797 // kmp_int32 cncl_kind); 2798 if (auto *OMPRegionInfo = 2799 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 2800 auto CancelDest = 2801 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 2802 if (CancelDest.isValid()) { 2803 llvm::Value *Args[] = { 2804 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2805 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 2806 // Ignore return result until untied tasks are supported. 2807 auto *Result = 2808 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 2809 // if (__kmpc_cancel()) { 2810 // __kmpc_cancel_barrier(); 2811 // exit from construct; 2812 // } 2813 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 2814 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 2815 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 2816 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 2817 CGF.EmitBlock(ExitBB); 2818 // __kmpc_cancel_barrier(); 2819 emitBarrierCall(CGF, Loc, OMPD_unknown, /*CheckForCancel=*/false); 2820 // exit from construct; 2821 CGF.EmitBranchThroughCleanup(CancelDest); 2822 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 2823 } 2824 } 2825 } 2826 2827