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 "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "CGOpenMPRuntime.h" 17 #include "CodeGenFunction.h" 18 #include "clang/AST/Decl.h" 19 #include "clang/AST/StmtOpenMP.h" 20 #include "llvm/ADT/ArrayRef.h" 21 #include "llvm/Bitcode/ReaderWriter.h" 22 #include "llvm/IR/CallSite.h" 23 #include "llvm/IR/DerivedTypes.h" 24 #include "llvm/IR/GlobalValue.h" 25 #include "llvm/IR/Value.h" 26 #include "llvm/Support/Format.h" 27 #include "llvm/Support/raw_ostream.h" 28 #include <cassert> 29 30 using namespace clang; 31 using namespace CodeGen; 32 33 namespace { 34 /// \brief Base class for handling code generation inside OpenMP regions. 35 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 36 public: 37 /// \brief Kinds of OpenMP regions used in codegen. 38 enum CGOpenMPRegionKind { 39 /// \brief Region with outlined function for standalone 'parallel' 40 /// directive. 41 ParallelOutlinedRegion, 42 /// \brief Region with outlined function for standalone 'task' directive. 43 TaskOutlinedRegion, 44 /// \brief Region for constructs that do not require function outlining, 45 /// like 'for', 'sections', 'atomic' etc. directives. 46 InlinedRegion, 47 /// \brief Region with outlined function for standalone 'target' directive. 48 TargetRegion, 49 }; 50 51 CGOpenMPRegionInfo(const CapturedStmt &CS, 52 const CGOpenMPRegionKind RegionKind, 53 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 54 bool HasCancel) 55 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 56 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 57 58 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 59 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 60 bool HasCancel) 61 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 62 Kind(Kind), HasCancel(HasCancel) {} 63 64 /// \brief Get a variable or parameter for storing global thread id 65 /// inside OpenMP construct. 66 virtual const VarDecl *getThreadIDVariable() const = 0; 67 68 /// \brief Emit the captured statement body. 69 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 70 71 /// \brief Get an LValue for the current ThreadID variable. 72 /// \return LValue for thread id variable. This LValue always has type int32*. 73 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 74 75 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 76 77 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 78 79 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 80 81 bool hasCancel() const { return HasCancel; } 82 83 static bool classof(const CGCapturedStmtInfo *Info) { 84 return Info->getKind() == CR_OpenMP; 85 } 86 87 ~CGOpenMPRegionInfo() override = default; 88 89 protected: 90 CGOpenMPRegionKind RegionKind; 91 RegionCodeGenTy CodeGen; 92 OpenMPDirectiveKind Kind; 93 bool HasCancel; 94 }; 95 96 /// \brief API for captured statement code generation in OpenMP constructs. 97 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 98 public: 99 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 100 const RegionCodeGenTy &CodeGen, 101 OpenMPDirectiveKind Kind, bool HasCancel) 102 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 103 HasCancel), 104 ThreadIDVar(ThreadIDVar) { 105 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 106 } 107 108 /// \brief Get a variable or parameter for storing global thread id 109 /// inside OpenMP construct. 110 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 111 112 /// \brief Get the name of the capture helper. 113 StringRef getHelperName() const override { return ".omp_outlined."; } 114 115 static bool classof(const CGCapturedStmtInfo *Info) { 116 return CGOpenMPRegionInfo::classof(Info) && 117 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 118 ParallelOutlinedRegion; 119 } 120 121 private: 122 /// \brief A variable or parameter storing global thread id for OpenMP 123 /// constructs. 124 const VarDecl *ThreadIDVar; 125 }; 126 127 /// \brief API for captured statement code generation in OpenMP constructs. 128 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 129 public: 130 class UntiedTaskActionTy final : public PrePostActionTy { 131 bool Untied; 132 const VarDecl *PartIDVar; 133 const RegionCodeGenTy UntiedCodeGen; 134 llvm::SwitchInst *UntiedSwitch = nullptr; 135 136 public: 137 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 138 const RegionCodeGenTy &UntiedCodeGen) 139 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 140 void Enter(CodeGenFunction &CGF) override { 141 if (Untied) { 142 // Emit task switching point. 143 auto PartIdLVal = CGF.EmitLoadOfPointerLValue( 144 CGF.GetAddrOfLocalVar(PartIDVar), 145 PartIDVar->getType()->castAs<PointerType>()); 146 auto *Res = CGF.EmitLoadOfScalar(PartIdLVal, SourceLocation()); 147 auto *DoneBB = CGF.createBasicBlock(".untied.done."); 148 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 149 CGF.EmitBlock(DoneBB); 150 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 151 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 152 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 153 CGF.Builder.GetInsertBlock()); 154 emitUntiedSwitch(CGF); 155 } 156 } 157 void emitUntiedSwitch(CodeGenFunction &CGF) const { 158 if (Untied) { 159 auto PartIdLVal = CGF.EmitLoadOfPointerLValue( 160 CGF.GetAddrOfLocalVar(PartIDVar), 161 PartIDVar->getType()->castAs<PointerType>()); 162 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 163 PartIdLVal); 164 UntiedCodeGen(CGF); 165 CodeGenFunction::JumpDest CurPoint = 166 CGF.getJumpDestInCurrentScope(".untied.next."); 167 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 168 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 169 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 170 CGF.Builder.GetInsertBlock()); 171 CGF.EmitBranchThroughCleanup(CurPoint); 172 CGF.EmitBlock(CurPoint.getBlock()); 173 } 174 } 175 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 176 }; 177 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 178 const VarDecl *ThreadIDVar, 179 const RegionCodeGenTy &CodeGen, 180 OpenMPDirectiveKind Kind, bool HasCancel, 181 const UntiedTaskActionTy &Action) 182 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 183 ThreadIDVar(ThreadIDVar), Action(Action) { 184 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 185 } 186 187 /// \brief Get a variable or parameter for storing global thread id 188 /// inside OpenMP construct. 189 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 190 191 /// \brief Get an LValue for the current ThreadID variable. 192 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 193 194 /// \brief Get the name of the capture helper. 195 StringRef getHelperName() const override { return ".omp_outlined."; } 196 197 void emitUntiedSwitch(CodeGenFunction &CGF) override { 198 Action.emitUntiedSwitch(CGF); 199 } 200 201 static bool classof(const CGCapturedStmtInfo *Info) { 202 return CGOpenMPRegionInfo::classof(Info) && 203 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 204 TaskOutlinedRegion; 205 } 206 207 private: 208 /// \brief A variable or parameter storing global thread id for OpenMP 209 /// constructs. 210 const VarDecl *ThreadIDVar; 211 /// Action for emitting code for untied tasks. 212 const UntiedTaskActionTy &Action; 213 }; 214 215 /// \brief API for inlined captured statement code generation in OpenMP 216 /// constructs. 217 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 218 public: 219 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 220 const RegionCodeGenTy &CodeGen, 221 OpenMPDirectiveKind Kind, bool HasCancel) 222 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 223 OldCSI(OldCSI), 224 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 225 226 // \brief Retrieve the value of the context parameter. 227 llvm::Value *getContextValue() const override { 228 if (OuterRegionInfo) 229 return OuterRegionInfo->getContextValue(); 230 llvm_unreachable("No context value for inlined OpenMP region"); 231 } 232 233 void setContextValue(llvm::Value *V) override { 234 if (OuterRegionInfo) { 235 OuterRegionInfo->setContextValue(V); 236 return; 237 } 238 llvm_unreachable("No context value for inlined OpenMP region"); 239 } 240 241 /// \brief Lookup the captured field decl for a variable. 242 const FieldDecl *lookup(const VarDecl *VD) const override { 243 if (OuterRegionInfo) 244 return OuterRegionInfo->lookup(VD); 245 // If there is no outer outlined region,no need to lookup in a list of 246 // captured variables, we can use the original one. 247 return nullptr; 248 } 249 250 FieldDecl *getThisFieldDecl() const override { 251 if (OuterRegionInfo) 252 return OuterRegionInfo->getThisFieldDecl(); 253 return nullptr; 254 } 255 256 /// \brief Get a variable or parameter for storing global thread id 257 /// inside OpenMP construct. 258 const VarDecl *getThreadIDVariable() const override { 259 if (OuterRegionInfo) 260 return OuterRegionInfo->getThreadIDVariable(); 261 return nullptr; 262 } 263 264 /// \brief Get the name of the capture helper. 265 StringRef getHelperName() const override { 266 if (auto *OuterRegionInfo = getOldCSI()) 267 return OuterRegionInfo->getHelperName(); 268 llvm_unreachable("No helper name for inlined OpenMP construct"); 269 } 270 271 void emitUntiedSwitch(CodeGenFunction &CGF) override { 272 if (OuterRegionInfo) 273 OuterRegionInfo->emitUntiedSwitch(CGF); 274 } 275 276 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 277 278 static bool classof(const CGCapturedStmtInfo *Info) { 279 return CGOpenMPRegionInfo::classof(Info) && 280 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 281 } 282 283 ~CGOpenMPInlinedRegionInfo() override = default; 284 285 private: 286 /// \brief CodeGen info about outer OpenMP region. 287 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 288 CGOpenMPRegionInfo *OuterRegionInfo; 289 }; 290 291 /// \brief API for captured statement code generation in OpenMP target 292 /// constructs. For this captures, implicit parameters are used instead of the 293 /// captured fields. The name of the target region has to be unique in a given 294 /// application so it is provided by the client, because only the client has 295 /// the information to generate that. 296 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 297 public: 298 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 299 const RegionCodeGenTy &CodeGen, StringRef HelperName) 300 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 301 /*HasCancel=*/false), 302 HelperName(HelperName) {} 303 304 /// \brief This is unused for target regions because each starts executing 305 /// with a single thread. 306 const VarDecl *getThreadIDVariable() const override { return nullptr; } 307 308 /// \brief Get the name of the capture helper. 309 StringRef getHelperName() const override { return HelperName; } 310 311 static bool classof(const CGCapturedStmtInfo *Info) { 312 return CGOpenMPRegionInfo::classof(Info) && 313 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 314 } 315 316 private: 317 StringRef HelperName; 318 }; 319 320 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 321 llvm_unreachable("No codegen for expressions"); 322 } 323 /// \brief API for generation of expressions captured in a innermost OpenMP 324 /// region. 325 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 326 public: 327 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 328 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 329 OMPD_unknown, 330 /*HasCancel=*/false), 331 PrivScope(CGF) { 332 // Make sure the globals captured in the provided statement are local by 333 // using the privatization logic. We assume the same variable is not 334 // captured more than once. 335 for (auto &C : CS.captures()) { 336 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 337 continue; 338 339 const VarDecl *VD = C.getCapturedVar(); 340 if (VD->isLocalVarDeclOrParm()) 341 continue; 342 343 DeclRefExpr DRE(const_cast<VarDecl *>(VD), 344 /*RefersToEnclosingVariableOrCapture=*/false, 345 VD->getType().getNonReferenceType(), VK_LValue, 346 SourceLocation()); 347 PrivScope.addPrivate(VD, [&CGF, &DRE]() -> Address { 348 return CGF.EmitLValue(&DRE).getAddress(); 349 }); 350 } 351 (void)PrivScope.Privatize(); 352 } 353 354 /// \brief Lookup the captured field decl for a variable. 355 const FieldDecl *lookup(const VarDecl *VD) const override { 356 if (auto *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 357 return FD; 358 return nullptr; 359 } 360 361 /// \brief Emit the captured statement body. 362 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 363 llvm_unreachable("No body for expressions"); 364 } 365 366 /// \brief Get a variable or parameter for storing global thread id 367 /// inside OpenMP construct. 368 const VarDecl *getThreadIDVariable() const override { 369 llvm_unreachable("No thread id for expressions"); 370 } 371 372 /// \brief Get the name of the capture helper. 373 StringRef getHelperName() const override { 374 llvm_unreachable("No helper name for expressions"); 375 } 376 377 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 378 379 private: 380 /// Private scope to capture global variables. 381 CodeGenFunction::OMPPrivateScope PrivScope; 382 }; 383 384 /// \brief RAII for emitting code of OpenMP constructs. 385 class InlinedOpenMPRegionRAII { 386 CodeGenFunction &CGF; 387 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 388 FieldDecl *LambdaThisCaptureField = nullptr; 389 390 public: 391 /// \brief Constructs region for combined constructs. 392 /// \param CodeGen Code generation sequence for combined directives. Includes 393 /// a list of functions used for code generation of implicitly inlined 394 /// regions. 395 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 396 OpenMPDirectiveKind Kind, bool HasCancel) 397 : CGF(CGF) { 398 // Start emission for the construct. 399 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 400 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 401 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 402 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 403 CGF.LambdaThisCaptureField = nullptr; 404 } 405 406 ~InlinedOpenMPRegionRAII() { 407 // Restore original CapturedStmtInfo only if we're done with code emission. 408 auto *OldCSI = 409 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 410 delete CGF.CapturedStmtInfo; 411 CGF.CapturedStmtInfo = OldCSI; 412 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 413 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 414 } 415 }; 416 417 /// \brief Values for bit flags used in the ident_t to describe the fields. 418 /// All enumeric elements are named and described in accordance with the code 419 /// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h 420 enum OpenMPLocationFlags { 421 /// \brief Use trampoline for internal microtask. 422 OMP_IDENT_IMD = 0x01, 423 /// \brief Use c-style ident structure. 424 OMP_IDENT_KMPC = 0x02, 425 /// \brief Atomic reduction option for kmpc_reduce. 426 OMP_ATOMIC_REDUCE = 0x10, 427 /// \brief Explicit 'barrier' directive. 428 OMP_IDENT_BARRIER_EXPL = 0x20, 429 /// \brief Implicit barrier in code. 430 OMP_IDENT_BARRIER_IMPL = 0x40, 431 /// \brief Implicit barrier in 'for' directive. 432 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 433 /// \brief Implicit barrier in 'sections' directive. 434 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 435 /// \brief Implicit barrier in 'single' directive. 436 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140 437 }; 438 439 /// \brief Describes ident structure that describes a source location. 440 /// All descriptions are taken from 441 /// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h 442 /// Original structure: 443 /// typedef struct ident { 444 /// kmp_int32 reserved_1; /**< might be used in Fortran; 445 /// see above */ 446 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 447 /// KMP_IDENT_KMPC identifies this union 448 /// member */ 449 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 450 /// see above */ 451 ///#if USE_ITT_BUILD 452 /// /* but currently used for storing 453 /// region-specific ITT */ 454 /// /* contextual information. */ 455 ///#endif /* USE_ITT_BUILD */ 456 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 457 /// C++ */ 458 /// char const *psource; /**< String describing the source location. 459 /// The string is composed of semi-colon separated 460 // fields which describe the source file, 461 /// the function and a pair of line numbers that 462 /// delimit the construct. 463 /// */ 464 /// } ident_t; 465 enum IdentFieldIndex { 466 /// \brief might be used in Fortran 467 IdentField_Reserved_1, 468 /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 469 IdentField_Flags, 470 /// \brief Not really used in Fortran any more 471 IdentField_Reserved_2, 472 /// \brief Source[4] in Fortran, do not use for C++ 473 IdentField_Reserved_3, 474 /// \brief String describing the source location. The string is composed of 475 /// semi-colon separated fields which describe the source file, the function 476 /// and a pair of line numbers that delimit the construct. 477 IdentField_PSource 478 }; 479 480 /// \brief Schedule types for 'omp for' loops (these enumerators are taken from 481 /// the enum sched_type in kmp.h). 482 enum OpenMPSchedType { 483 /// \brief Lower bound for default (unordered) versions. 484 OMP_sch_lower = 32, 485 OMP_sch_static_chunked = 33, 486 OMP_sch_static = 34, 487 OMP_sch_dynamic_chunked = 35, 488 OMP_sch_guided_chunked = 36, 489 OMP_sch_runtime = 37, 490 OMP_sch_auto = 38, 491 /// \brief Lower bound for 'ordered' versions. 492 OMP_ord_lower = 64, 493 OMP_ord_static_chunked = 65, 494 OMP_ord_static = 66, 495 OMP_ord_dynamic_chunked = 67, 496 OMP_ord_guided_chunked = 68, 497 OMP_ord_runtime = 69, 498 OMP_ord_auto = 70, 499 OMP_sch_default = OMP_sch_static, 500 /// \brief dist_schedule types 501 OMP_dist_sch_static_chunked = 91, 502 OMP_dist_sch_static = 92, 503 }; 504 505 enum OpenMPRTLFunction { 506 /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 507 /// kmpc_micro microtask, ...); 508 OMPRTL__kmpc_fork_call, 509 /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc, 510 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 511 OMPRTL__kmpc_threadprivate_cached, 512 /// \brief Call to void __kmpc_threadprivate_register( ident_t *, 513 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 514 OMPRTL__kmpc_threadprivate_register, 515 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 516 OMPRTL__kmpc_global_thread_num, 517 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 518 // kmp_critical_name *crit); 519 OMPRTL__kmpc_critical, 520 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 521 // global_tid, kmp_critical_name *crit, uintptr_t hint); 522 OMPRTL__kmpc_critical_with_hint, 523 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 524 // kmp_critical_name *crit); 525 OMPRTL__kmpc_end_critical, 526 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 527 // global_tid); 528 OMPRTL__kmpc_cancel_barrier, 529 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 530 OMPRTL__kmpc_barrier, 531 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 532 OMPRTL__kmpc_for_static_fini, 533 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 534 // global_tid); 535 OMPRTL__kmpc_serialized_parallel, 536 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 537 // global_tid); 538 OMPRTL__kmpc_end_serialized_parallel, 539 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 540 // kmp_int32 num_threads); 541 OMPRTL__kmpc_push_num_threads, 542 // Call to void __kmpc_flush(ident_t *loc); 543 OMPRTL__kmpc_flush, 544 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 545 OMPRTL__kmpc_master, 546 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 547 OMPRTL__kmpc_end_master, 548 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 549 // int end_part); 550 OMPRTL__kmpc_omp_taskyield, 551 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 552 OMPRTL__kmpc_single, 553 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 554 OMPRTL__kmpc_end_single, 555 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 556 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 557 // kmp_routine_entry_t *task_entry); 558 OMPRTL__kmpc_omp_task_alloc, 559 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 560 // new_task); 561 OMPRTL__kmpc_omp_task, 562 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 563 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 564 // kmp_int32 didit); 565 OMPRTL__kmpc_copyprivate, 566 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 567 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 568 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 569 OMPRTL__kmpc_reduce, 570 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 571 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 572 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 573 // *lck); 574 OMPRTL__kmpc_reduce_nowait, 575 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 576 // kmp_critical_name *lck); 577 OMPRTL__kmpc_end_reduce, 578 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 579 // kmp_critical_name *lck); 580 OMPRTL__kmpc_end_reduce_nowait, 581 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 582 // kmp_task_t * new_task); 583 OMPRTL__kmpc_omp_task_begin_if0, 584 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 585 // kmp_task_t * new_task); 586 OMPRTL__kmpc_omp_task_complete_if0, 587 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 588 OMPRTL__kmpc_ordered, 589 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 590 OMPRTL__kmpc_end_ordered, 591 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 592 // global_tid); 593 OMPRTL__kmpc_omp_taskwait, 594 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 595 OMPRTL__kmpc_taskgroup, 596 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 597 OMPRTL__kmpc_end_taskgroup, 598 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 599 // int proc_bind); 600 OMPRTL__kmpc_push_proc_bind, 601 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 602 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 603 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 604 OMPRTL__kmpc_omp_task_with_deps, 605 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 606 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 607 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 608 OMPRTL__kmpc_omp_wait_deps, 609 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 610 // global_tid, kmp_int32 cncl_kind); 611 OMPRTL__kmpc_cancellationpoint, 612 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 613 // kmp_int32 cncl_kind); 614 OMPRTL__kmpc_cancel, 615 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 616 // kmp_int32 num_teams, kmp_int32 thread_limit); 617 OMPRTL__kmpc_push_num_teams, 618 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 619 // microtask, ...); 620 OMPRTL__kmpc_fork_teams, 621 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 622 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 623 // sched, kmp_uint64 grainsize, void *task_dup); 624 OMPRTL__kmpc_taskloop, 625 626 // 627 // Offloading related calls 628 // 629 // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t 630 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t 631 // *arg_types); 632 OMPRTL__tgt_target, 633 // Call to int32_t __tgt_target_teams(int32_t device_id, void *host_ptr, 634 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, 635 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit); 636 OMPRTL__tgt_target_teams, 637 // Call to void __tgt_register_lib(__tgt_bin_desc *desc); 638 OMPRTL__tgt_register_lib, 639 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); 640 OMPRTL__tgt_unregister_lib, 641 }; 642 643 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 644 /// region. 645 class CleanupTy final : public EHScopeStack::Cleanup { 646 PrePostActionTy *Action; 647 648 public: 649 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 650 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 651 if (!CGF.HaveInsertPoint()) 652 return; 653 Action->Exit(CGF); 654 } 655 }; 656 657 } // anonymous namespace 658 659 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 660 CodeGenFunction::RunCleanupsScope Scope(CGF); 661 if (PrePostAction) { 662 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 663 Callback(CodeGen, CGF, *PrePostAction); 664 } else { 665 PrePostActionTy Action; 666 Callback(CodeGen, CGF, Action); 667 } 668 } 669 670 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 671 return CGF.EmitLoadOfPointerLValue( 672 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 673 getThreadIDVariable()->getType()->castAs<PointerType>()); 674 } 675 676 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 677 if (!CGF.HaveInsertPoint()) 678 return; 679 // 1.2.2 OpenMP Language Terminology 680 // Structured block - An executable statement with a single entry at the 681 // top and a single exit at the bottom. 682 // The point of exit cannot be a branch out of the structured block. 683 // longjmp() and throw() must not violate the entry/exit criteria. 684 CGF.EHStack.pushTerminate(); 685 CodeGen(CGF); 686 CGF.EHStack.popTerminate(); 687 } 688 689 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 690 CodeGenFunction &CGF) { 691 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 692 getThreadIDVariable()->getType(), 693 AlignmentSource::Decl); 694 } 695 696 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) 697 : CGM(CGM), OffloadEntriesInfoManager(CGM) { 698 IdentTy = llvm::StructType::create( 699 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */, 700 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */, 701 CGM.Int8PtrTy /* psource */, nullptr); 702 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 703 704 loadOffloadInfoMetadata(); 705 } 706 707 void CGOpenMPRuntime::clear() { 708 InternalVars.clear(); 709 } 710 711 static llvm::Function * 712 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 713 const Expr *CombinerInitializer, const VarDecl *In, 714 const VarDecl *Out, bool IsCombiner) { 715 // void .omp_combiner.(Ty *in, Ty *out); 716 auto &C = CGM.getContext(); 717 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 718 FunctionArgList Args; 719 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 720 /*Id=*/nullptr, PtrTy); 721 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 722 /*Id=*/nullptr, PtrTy); 723 Args.push_back(&OmpOutParm); 724 Args.push_back(&OmpInParm); 725 auto &FnInfo = 726 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 727 auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 728 auto *Fn = llvm::Function::Create( 729 FnTy, llvm::GlobalValue::InternalLinkage, 730 IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule()); 731 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo); 732 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 733 CodeGenFunction CGF(CGM); 734 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 735 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 736 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args); 737 CodeGenFunction::OMPPrivateScope Scope(CGF); 738 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 739 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() -> Address { 740 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 741 .getAddress(); 742 }); 743 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 744 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() -> Address { 745 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 746 .getAddress(); 747 }); 748 (void)Scope.Privatize(); 749 CGF.EmitIgnoredExpr(CombinerInitializer); 750 Scope.ForceCleanup(); 751 CGF.FinishFunction(); 752 return Fn; 753 } 754 755 void CGOpenMPRuntime::emitUserDefinedReduction( 756 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 757 if (UDRMap.count(D) > 0) 758 return; 759 auto &C = CGM.getContext(); 760 if (!In || !Out) { 761 In = &C.Idents.get("omp_in"); 762 Out = &C.Idents.get("omp_out"); 763 } 764 llvm::Function *Combiner = emitCombinerOrInitializer( 765 CGM, D->getType(), D->getCombiner(), cast<VarDecl>(D->lookup(In).front()), 766 cast<VarDecl>(D->lookup(Out).front()), 767 /*IsCombiner=*/true); 768 llvm::Function *Initializer = nullptr; 769 if (auto *Init = D->getInitializer()) { 770 if (!Priv || !Orig) { 771 Priv = &C.Idents.get("omp_priv"); 772 Orig = &C.Idents.get("omp_orig"); 773 } 774 Initializer = emitCombinerOrInitializer( 775 CGM, D->getType(), Init, cast<VarDecl>(D->lookup(Orig).front()), 776 cast<VarDecl>(D->lookup(Priv).front()), 777 /*IsCombiner=*/false); 778 } 779 UDRMap.insert(std::make_pair(D, std::make_pair(Combiner, Initializer))); 780 if (CGF) { 781 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 782 Decls.second.push_back(D); 783 } 784 } 785 786 std::pair<llvm::Function *, llvm::Function *> 787 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 788 auto I = UDRMap.find(D); 789 if (I != UDRMap.end()) 790 return I->second; 791 emitUserDefinedReduction(/*CGF=*/nullptr, D); 792 return UDRMap.lookup(D); 793 } 794 795 // Layout information for ident_t. 796 static CharUnits getIdentAlign(CodeGenModule &CGM) { 797 return CGM.getPointerAlign(); 798 } 799 static CharUnits getIdentSize(CodeGenModule &CGM) { 800 assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign())); 801 return CharUnits::fromQuantity(16) + CGM.getPointerSize(); 802 } 803 static CharUnits getOffsetOfIdentField(IdentFieldIndex Field) { 804 // All the fields except the last are i32, so this works beautifully. 805 return unsigned(Field) * CharUnits::fromQuantity(4); 806 } 807 static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr, 808 IdentFieldIndex Field, 809 const llvm::Twine &Name = "") { 810 auto Offset = getOffsetOfIdentField(Field); 811 return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name); 812 } 813 814 llvm::Value *CGOpenMPRuntime::emitParallelOrTeamsOutlinedFunction( 815 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 816 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 817 assert(ThreadIDVar->getType()->isPointerType() && 818 "thread id variable must be of type kmp_int32 *"); 819 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt()); 820 CodeGenFunction CGF(CGM, true); 821 bool HasCancel = false; 822 if (auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 823 HasCancel = OPD->hasCancel(); 824 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 825 HasCancel = OPSD->hasCancel(); 826 else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 827 HasCancel = OPFD->hasCancel(); 828 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 829 HasCancel); 830 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 831 return CGF.GenerateOpenMPCapturedStmtFunction(*CS); 832 } 833 834 llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction( 835 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 836 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 837 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 838 bool Tied, unsigned &NumberOfParts) { 839 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 840 PrePostActionTy &) { 841 auto *ThreadID = getThreadID(CGF, D.getLocStart()); 842 auto *UpLoc = emitUpdateLocation(CGF, D.getLocStart()); 843 llvm::Value *TaskArgs[] = { 844 UpLoc, ThreadID, 845 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 846 TaskTVar->getType()->castAs<PointerType>()) 847 .getPointer()}; 848 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 849 }; 850 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 851 UntiedCodeGen); 852 CodeGen.setAction(Action); 853 assert(!ThreadIDVar->getType()->isPointerType() && 854 "thread id variable must be of type kmp_int32 for tasks"); 855 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt()); 856 auto *TD = dyn_cast<OMPTaskDirective>(&D); 857 CodeGenFunction CGF(CGM, true); 858 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 859 InnermostKind, 860 TD ? TD->hasCancel() : false, Action); 861 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 862 auto *Res = CGF.GenerateCapturedStmtFunction(*CS); 863 if (!Tied) 864 NumberOfParts = Action.getNumberOfParts(); 865 return Res; 866 } 867 868 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 869 CharUnits Align = getIdentAlign(CGM); 870 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags); 871 if (!Entry) { 872 if (!DefaultOpenMPPSource) { 873 // Initialize default location for psource field of ident_t structure of 874 // all ident_t objects. Format is ";file;function;line;column;;". 875 // Taken from 876 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c 877 DefaultOpenMPPSource = 878 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 879 DefaultOpenMPPSource = 880 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 881 } 882 auto DefaultOpenMPLocation = new llvm::GlobalVariable( 883 CGM.getModule(), IdentTy, /*isConstant*/ true, 884 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr); 885 DefaultOpenMPLocation->setUnnamedAddr(true); 886 DefaultOpenMPLocation->setAlignment(Align.getQuantity()); 887 888 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true); 889 llvm::Constant *Values[] = {Zero, 890 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 891 Zero, Zero, DefaultOpenMPPSource}; 892 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values); 893 DefaultOpenMPLocation->setInitializer(Init); 894 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation; 895 } 896 return Address(Entry, Align); 897 } 898 899 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 900 SourceLocation Loc, 901 unsigned Flags) { 902 Flags |= OMP_IDENT_KMPC; 903 // If no debug info is generated - return global default location. 904 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 905 Loc.isInvalid()) 906 return getOrCreateDefaultLocation(Flags).getPointer(); 907 908 assert(CGF.CurFn && "No function in current CodeGenFunction."); 909 910 Address LocValue = Address::invalid(); 911 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 912 if (I != OpenMPLocThreadIDMap.end()) 913 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM)); 914 915 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 916 // GetOpenMPThreadID was called before this routine. 917 if (!LocValue.isValid()) { 918 // Generate "ident_t .kmpc_loc.addr;" 919 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM), 920 ".kmpc_loc.addr"); 921 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 922 Elem.second.DebugLoc = AI.getPointer(); 923 LocValue = AI; 924 925 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 926 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 927 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 928 CGM.getSize(getIdentSize(CGF.CGM))); 929 } 930 931 // char **psource = &.kmpc_loc_<flags>.addr.psource; 932 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource); 933 934 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 935 if (OMPDebugLoc == nullptr) { 936 SmallString<128> Buffer2; 937 llvm::raw_svector_ostream OS2(Buffer2); 938 // Build debug location 939 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 940 OS2 << ";" << PLoc.getFilename() << ";"; 941 if (const FunctionDecl *FD = 942 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) { 943 OS2 << FD->getQualifiedNameAsString(); 944 } 945 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 946 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 947 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 948 } 949 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 950 CGF.Builder.CreateStore(OMPDebugLoc, PSource); 951 952 // Our callers always pass this to a runtime function, so for 953 // convenience, go ahead and return a naked pointer. 954 return LocValue.getPointer(); 955 } 956 957 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 958 SourceLocation Loc) { 959 assert(CGF.CurFn && "No function in current CodeGenFunction."); 960 961 llvm::Value *ThreadID = nullptr; 962 // Check whether we've already cached a load of the thread id in this 963 // function. 964 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 965 if (I != OpenMPLocThreadIDMap.end()) { 966 ThreadID = I->second.ThreadID; 967 if (ThreadID != nullptr) 968 return ThreadID; 969 } 970 if (auto *OMPRegionInfo = 971 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 972 if (OMPRegionInfo->getThreadIDVariable()) { 973 // Check if this an outlined function with thread id passed as argument. 974 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 975 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal(); 976 // If value loaded in entry block, cache it and use it everywhere in 977 // function. 978 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 979 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 980 Elem.second.ThreadID = ThreadID; 981 } 982 return ThreadID; 983 } 984 } 985 986 // This is not an outlined function region - need to call __kmpc_int32 987 // kmpc_global_thread_num(ident_t *loc). 988 // Generate thread id value and cache this value for use across the 989 // function. 990 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 991 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 992 ThreadID = 993 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 994 emitUpdateLocation(CGF, Loc)); 995 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 996 Elem.second.ThreadID = ThreadID; 997 return ThreadID; 998 } 999 1000 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1001 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1002 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) 1003 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1004 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1005 for(auto *D : FunctionUDRMap[CGF.CurFn]) { 1006 UDRMap.erase(D); 1007 } 1008 FunctionUDRMap.erase(CGF.CurFn); 1009 } 1010 } 1011 1012 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1013 if (!IdentTy) { 1014 } 1015 return llvm::PointerType::getUnqual(IdentTy); 1016 } 1017 1018 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1019 if (!Kmpc_MicroTy) { 1020 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1021 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1022 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1023 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1024 } 1025 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1026 } 1027 1028 llvm::Constant * 1029 CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1030 llvm::Constant *RTLFn = nullptr; 1031 switch (static_cast<OpenMPRTLFunction>(Function)) { 1032 case OMPRTL__kmpc_fork_call: { 1033 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1034 // microtask, ...); 1035 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1036 getKmpc_MicroPointerTy()}; 1037 llvm::FunctionType *FnTy = 1038 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1039 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1040 break; 1041 } 1042 case OMPRTL__kmpc_global_thread_num: { 1043 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1044 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1045 llvm::FunctionType *FnTy = 1046 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1047 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1048 break; 1049 } 1050 case OMPRTL__kmpc_threadprivate_cached: { 1051 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1052 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1053 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1054 CGM.VoidPtrTy, CGM.SizeTy, 1055 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1056 llvm::FunctionType *FnTy = 1057 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1058 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1059 break; 1060 } 1061 case OMPRTL__kmpc_critical: { 1062 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1063 // kmp_critical_name *crit); 1064 llvm::Type *TypeParams[] = { 1065 getIdentTyPointerTy(), CGM.Int32Ty, 1066 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1067 llvm::FunctionType *FnTy = 1068 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1069 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1070 break; 1071 } 1072 case OMPRTL__kmpc_critical_with_hint: { 1073 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1074 // kmp_critical_name *crit, uintptr_t hint); 1075 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1076 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1077 CGM.IntPtrTy}; 1078 llvm::FunctionType *FnTy = 1079 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1080 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1081 break; 1082 } 1083 case OMPRTL__kmpc_threadprivate_register: { 1084 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1085 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1086 // typedef void *(*kmpc_ctor)(void *); 1087 auto KmpcCtorTy = 1088 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1089 /*isVarArg*/ false)->getPointerTo(); 1090 // typedef void *(*kmpc_cctor)(void *, void *); 1091 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1092 auto KmpcCopyCtorTy = 1093 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1094 /*isVarArg*/ false)->getPointerTo(); 1095 // typedef void (*kmpc_dtor)(void *); 1096 auto KmpcDtorTy = 1097 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1098 ->getPointerTo(); 1099 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1100 KmpcCopyCtorTy, KmpcDtorTy}; 1101 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1102 /*isVarArg*/ false); 1103 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1104 break; 1105 } 1106 case OMPRTL__kmpc_end_critical: { 1107 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1108 // kmp_critical_name *crit); 1109 llvm::Type *TypeParams[] = { 1110 getIdentTyPointerTy(), CGM.Int32Ty, 1111 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1112 llvm::FunctionType *FnTy = 1113 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1114 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1115 break; 1116 } 1117 case OMPRTL__kmpc_cancel_barrier: { 1118 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1119 // global_tid); 1120 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1121 llvm::FunctionType *FnTy = 1122 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1123 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1124 break; 1125 } 1126 case OMPRTL__kmpc_barrier: { 1127 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1128 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1129 llvm::FunctionType *FnTy = 1130 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1131 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1132 break; 1133 } 1134 case OMPRTL__kmpc_for_static_fini: { 1135 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1136 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1137 llvm::FunctionType *FnTy = 1138 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1139 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1140 break; 1141 } 1142 case OMPRTL__kmpc_push_num_threads: { 1143 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1144 // kmp_int32 num_threads) 1145 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1146 CGM.Int32Ty}; 1147 llvm::FunctionType *FnTy = 1148 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1149 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1150 break; 1151 } 1152 case OMPRTL__kmpc_serialized_parallel: { 1153 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1154 // global_tid); 1155 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1156 llvm::FunctionType *FnTy = 1157 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1158 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1159 break; 1160 } 1161 case OMPRTL__kmpc_end_serialized_parallel: { 1162 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1163 // global_tid); 1164 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1165 llvm::FunctionType *FnTy = 1166 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1167 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1168 break; 1169 } 1170 case OMPRTL__kmpc_flush: { 1171 // Build void __kmpc_flush(ident_t *loc); 1172 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1173 llvm::FunctionType *FnTy = 1174 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1175 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1176 break; 1177 } 1178 case OMPRTL__kmpc_master: { 1179 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1180 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1181 llvm::FunctionType *FnTy = 1182 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1183 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 1184 break; 1185 } 1186 case OMPRTL__kmpc_end_master: { 1187 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 1188 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1189 llvm::FunctionType *FnTy = 1190 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1191 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 1192 break; 1193 } 1194 case OMPRTL__kmpc_omp_taskyield: { 1195 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 1196 // int end_part); 1197 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1198 llvm::FunctionType *FnTy = 1199 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1200 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 1201 break; 1202 } 1203 case OMPRTL__kmpc_single: { 1204 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 1205 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1206 llvm::FunctionType *FnTy = 1207 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1208 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 1209 break; 1210 } 1211 case OMPRTL__kmpc_end_single: { 1212 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 1213 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1214 llvm::FunctionType *FnTy = 1215 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1216 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 1217 break; 1218 } 1219 case OMPRTL__kmpc_omp_task_alloc: { 1220 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 1221 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1222 // kmp_routine_entry_t *task_entry); 1223 assert(KmpRoutineEntryPtrTy != nullptr && 1224 "Type kmp_routine_entry_t must be created."); 1225 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1226 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 1227 // Return void * and then cast to particular kmp_task_t type. 1228 llvm::FunctionType *FnTy = 1229 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 1230 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 1231 break; 1232 } 1233 case OMPRTL__kmpc_omp_task: { 1234 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 1235 // *new_task); 1236 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1237 CGM.VoidPtrTy}; 1238 llvm::FunctionType *FnTy = 1239 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1240 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 1241 break; 1242 } 1243 case OMPRTL__kmpc_copyprivate: { 1244 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 1245 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 1246 // kmp_int32 didit); 1247 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1248 auto *CpyFnTy = 1249 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 1250 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 1251 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 1252 CGM.Int32Ty}; 1253 llvm::FunctionType *FnTy = 1254 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1255 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 1256 break; 1257 } 1258 case OMPRTL__kmpc_reduce: { 1259 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 1260 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 1261 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 1262 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1263 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 1264 /*isVarArg=*/false); 1265 llvm::Type *TypeParams[] = { 1266 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 1267 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 1268 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1269 llvm::FunctionType *FnTy = 1270 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1271 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 1272 break; 1273 } 1274 case OMPRTL__kmpc_reduce_nowait: { 1275 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 1276 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 1277 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 1278 // *lck); 1279 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1280 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 1281 /*isVarArg=*/false); 1282 llvm::Type *TypeParams[] = { 1283 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 1284 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 1285 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1286 llvm::FunctionType *FnTy = 1287 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1288 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 1289 break; 1290 } 1291 case OMPRTL__kmpc_end_reduce: { 1292 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 1293 // kmp_critical_name *lck); 1294 llvm::Type *TypeParams[] = { 1295 getIdentTyPointerTy(), CGM.Int32Ty, 1296 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1297 llvm::FunctionType *FnTy = 1298 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1299 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 1300 break; 1301 } 1302 case OMPRTL__kmpc_end_reduce_nowait: { 1303 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 1304 // kmp_critical_name *lck); 1305 llvm::Type *TypeParams[] = { 1306 getIdentTyPointerTy(), CGM.Int32Ty, 1307 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1308 llvm::FunctionType *FnTy = 1309 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1310 RTLFn = 1311 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 1312 break; 1313 } 1314 case OMPRTL__kmpc_omp_task_begin_if0: { 1315 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 1316 // *new_task); 1317 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1318 CGM.VoidPtrTy}; 1319 llvm::FunctionType *FnTy = 1320 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1321 RTLFn = 1322 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 1323 break; 1324 } 1325 case OMPRTL__kmpc_omp_task_complete_if0: { 1326 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 1327 // *new_task); 1328 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1329 CGM.VoidPtrTy}; 1330 llvm::FunctionType *FnTy = 1331 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1332 RTLFn = CGM.CreateRuntimeFunction(FnTy, 1333 /*Name=*/"__kmpc_omp_task_complete_if0"); 1334 break; 1335 } 1336 case OMPRTL__kmpc_ordered: { 1337 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 1338 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1339 llvm::FunctionType *FnTy = 1340 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1341 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 1342 break; 1343 } 1344 case OMPRTL__kmpc_end_ordered: { 1345 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 1346 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1347 llvm::FunctionType *FnTy = 1348 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1349 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 1350 break; 1351 } 1352 case OMPRTL__kmpc_omp_taskwait: { 1353 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 1354 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1355 llvm::FunctionType *FnTy = 1356 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1357 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 1358 break; 1359 } 1360 case OMPRTL__kmpc_taskgroup: { 1361 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 1362 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1363 llvm::FunctionType *FnTy = 1364 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1365 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 1366 break; 1367 } 1368 case OMPRTL__kmpc_end_taskgroup: { 1369 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 1370 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1371 llvm::FunctionType *FnTy = 1372 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1373 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 1374 break; 1375 } 1376 case OMPRTL__kmpc_push_proc_bind: { 1377 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 1378 // int proc_bind) 1379 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1380 llvm::FunctionType *FnTy = 1381 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1382 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 1383 break; 1384 } 1385 case OMPRTL__kmpc_omp_task_with_deps: { 1386 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 1387 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 1388 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 1389 llvm::Type *TypeParams[] = { 1390 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 1391 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 1392 llvm::FunctionType *FnTy = 1393 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1394 RTLFn = 1395 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 1396 break; 1397 } 1398 case OMPRTL__kmpc_omp_wait_deps: { 1399 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 1400 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 1401 // kmp_depend_info_t *noalias_dep_list); 1402 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1403 CGM.Int32Ty, CGM.VoidPtrTy, 1404 CGM.Int32Ty, CGM.VoidPtrTy}; 1405 llvm::FunctionType *FnTy = 1406 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1407 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 1408 break; 1409 } 1410 case OMPRTL__kmpc_cancellationpoint: { 1411 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 1412 // global_tid, kmp_int32 cncl_kind) 1413 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1414 llvm::FunctionType *FnTy = 1415 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1416 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 1417 break; 1418 } 1419 case OMPRTL__kmpc_cancel: { 1420 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 1421 // kmp_int32 cncl_kind) 1422 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1423 llvm::FunctionType *FnTy = 1424 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1425 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 1426 break; 1427 } 1428 case OMPRTL__kmpc_push_num_teams: { 1429 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 1430 // kmp_int32 num_teams, kmp_int32 num_threads) 1431 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1432 CGM.Int32Ty}; 1433 llvm::FunctionType *FnTy = 1434 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1435 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 1436 break; 1437 } 1438 case OMPRTL__kmpc_fork_teams: { 1439 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 1440 // microtask, ...); 1441 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1442 getKmpc_MicroPointerTy()}; 1443 llvm::FunctionType *FnTy = 1444 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1445 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 1446 break; 1447 } 1448 case OMPRTL__kmpc_taskloop: { 1449 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 1450 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 1451 // sched, kmp_uint64 grainsize, void *task_dup); 1452 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 1453 CGM.IntTy, 1454 CGM.VoidPtrTy, 1455 CGM.IntTy, 1456 CGM.Int64Ty->getPointerTo(), 1457 CGM.Int64Ty->getPointerTo(), 1458 CGM.Int64Ty, 1459 CGM.IntTy, 1460 CGM.IntTy, 1461 CGM.Int64Ty, 1462 CGM.VoidPtrTy}; 1463 llvm::FunctionType *FnTy = 1464 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1465 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 1466 break; 1467 } 1468 case OMPRTL__tgt_target: { 1469 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t 1470 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t 1471 // *arg_types); 1472 llvm::Type *TypeParams[] = {CGM.Int32Ty, 1473 CGM.VoidPtrTy, 1474 CGM.Int32Ty, 1475 CGM.VoidPtrPtrTy, 1476 CGM.VoidPtrPtrTy, 1477 CGM.SizeTy->getPointerTo(), 1478 CGM.Int32Ty->getPointerTo()}; 1479 llvm::FunctionType *FnTy = 1480 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1481 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 1482 break; 1483 } 1484 case OMPRTL__tgt_target_teams: { 1485 // Build int32_t __tgt_target_teams(int32_t device_id, void *host_ptr, 1486 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, 1487 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit); 1488 llvm::Type *TypeParams[] = {CGM.Int32Ty, 1489 CGM.VoidPtrTy, 1490 CGM.Int32Ty, 1491 CGM.VoidPtrPtrTy, 1492 CGM.VoidPtrPtrTy, 1493 CGM.SizeTy->getPointerTo(), 1494 CGM.Int32Ty->getPointerTo(), 1495 CGM.Int32Ty, 1496 CGM.Int32Ty}; 1497 llvm::FunctionType *FnTy = 1498 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1499 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 1500 break; 1501 } 1502 case OMPRTL__tgt_register_lib: { 1503 // Build void __tgt_register_lib(__tgt_bin_desc *desc); 1504 QualType ParamTy = 1505 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 1506 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 1507 llvm::FunctionType *FnTy = 1508 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1509 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); 1510 break; 1511 } 1512 case OMPRTL__tgt_unregister_lib: { 1513 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); 1514 QualType ParamTy = 1515 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 1516 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 1517 llvm::FunctionType *FnTy = 1518 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1519 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); 1520 break; 1521 } 1522 } 1523 assert(RTLFn && "Unable to find OpenMP runtime function"); 1524 return RTLFn; 1525 } 1526 1527 llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, 1528 bool IVSigned) { 1529 assert((IVSize == 32 || IVSize == 64) && 1530 "IV size is not compatible with the omp runtime"); 1531 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 1532 : "__kmpc_for_static_init_4u") 1533 : (IVSigned ? "__kmpc_for_static_init_8" 1534 : "__kmpc_for_static_init_8u"); 1535 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1536 auto PtrTy = llvm::PointerType::getUnqual(ITy); 1537 llvm::Type *TypeParams[] = { 1538 getIdentTyPointerTy(), // loc 1539 CGM.Int32Ty, // tid 1540 CGM.Int32Ty, // schedtype 1541 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1542 PtrTy, // p_lower 1543 PtrTy, // p_upper 1544 PtrTy, // p_stride 1545 ITy, // incr 1546 ITy // chunk 1547 }; 1548 llvm::FunctionType *FnTy = 1549 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1550 return CGM.CreateRuntimeFunction(FnTy, Name); 1551 } 1552 1553 llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, 1554 bool IVSigned) { 1555 assert((IVSize == 32 || IVSize == 64) && 1556 "IV size is not compatible with the omp runtime"); 1557 auto Name = 1558 IVSize == 32 1559 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 1560 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 1561 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1562 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 1563 CGM.Int32Ty, // tid 1564 CGM.Int32Ty, // schedtype 1565 ITy, // lower 1566 ITy, // upper 1567 ITy, // stride 1568 ITy // chunk 1569 }; 1570 llvm::FunctionType *FnTy = 1571 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1572 return CGM.CreateRuntimeFunction(FnTy, Name); 1573 } 1574 1575 llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, 1576 bool IVSigned) { 1577 assert((IVSize == 32 || IVSize == 64) && 1578 "IV size is not compatible with the omp runtime"); 1579 auto Name = 1580 IVSize == 32 1581 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 1582 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 1583 llvm::Type *TypeParams[] = { 1584 getIdentTyPointerTy(), // loc 1585 CGM.Int32Ty, // tid 1586 }; 1587 llvm::FunctionType *FnTy = 1588 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1589 return CGM.CreateRuntimeFunction(FnTy, Name); 1590 } 1591 1592 llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, 1593 bool IVSigned) { 1594 assert((IVSize == 32 || IVSize == 64) && 1595 "IV size is not compatible with the omp runtime"); 1596 auto Name = 1597 IVSize == 32 1598 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 1599 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 1600 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1601 auto PtrTy = llvm::PointerType::getUnqual(ITy); 1602 llvm::Type *TypeParams[] = { 1603 getIdentTyPointerTy(), // loc 1604 CGM.Int32Ty, // tid 1605 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1606 PtrTy, // p_lower 1607 PtrTy, // p_upper 1608 PtrTy // p_stride 1609 }; 1610 llvm::FunctionType *FnTy = 1611 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1612 return CGM.CreateRuntimeFunction(FnTy, Name); 1613 } 1614 1615 llvm::Constant * 1616 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 1617 assert(!CGM.getLangOpts().OpenMPUseTLS || 1618 !CGM.getContext().getTargetInfo().isTLSSupported()); 1619 // Lookup the entry, lazily creating it if necessary. 1620 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy, 1621 Twine(CGM.getMangledName(VD)) + ".cache."); 1622 } 1623 1624 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 1625 const VarDecl *VD, 1626 Address VDAddr, 1627 SourceLocation Loc) { 1628 if (CGM.getLangOpts().OpenMPUseTLS && 1629 CGM.getContext().getTargetInfo().isTLSSupported()) 1630 return VDAddr; 1631 1632 auto VarTy = VDAddr.getElementType(); 1633 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1634 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1635 CGM.Int8PtrTy), 1636 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 1637 getOrCreateThreadPrivateCache(VD)}; 1638 return Address(CGF.EmitRuntimeCall( 1639 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 1640 VDAddr.getAlignment()); 1641 } 1642 1643 void CGOpenMPRuntime::emitThreadPrivateVarInit( 1644 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 1645 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 1646 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 1647 // library. 1648 auto OMPLoc = emitUpdateLocation(CGF, Loc); 1649 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1650 OMPLoc); 1651 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 1652 // to register constructor/destructor for variable. 1653 llvm::Value *Args[] = {OMPLoc, 1654 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1655 CGM.VoidPtrTy), 1656 Ctor, CopyCtor, Dtor}; 1657 CGF.EmitRuntimeCall( 1658 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 1659 } 1660 1661 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 1662 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 1663 bool PerformInit, CodeGenFunction *CGF) { 1664 if (CGM.getLangOpts().OpenMPUseTLS && 1665 CGM.getContext().getTargetInfo().isTLSSupported()) 1666 return nullptr; 1667 1668 VD = VD->getDefinition(CGM.getContext()); 1669 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) { 1670 ThreadPrivateWithDefinition.insert(VD); 1671 QualType ASTTy = VD->getType(); 1672 1673 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 1674 auto Init = VD->getAnyInitializer(); 1675 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1676 // Generate function that re-emits the declaration's initializer into the 1677 // threadprivate copy of the variable VD 1678 CodeGenFunction CtorCGF(CGM); 1679 FunctionArgList Args; 1680 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), 1681 /*Id=*/nullptr, CGM.getContext().VoidPtrTy); 1682 Args.push_back(&Dst); 1683 1684 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1685 CGM.getContext().VoidPtrTy, Args); 1686 auto FTy = CGM.getTypes().GetFunctionType(FI); 1687 auto Fn = CGM.CreateGlobalInitOrDestructFunction( 1688 FTy, ".__kmpc_global_ctor_.", FI, Loc); 1689 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 1690 Args, SourceLocation()); 1691 auto ArgVal = CtorCGF.EmitLoadOfScalar( 1692 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1693 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1694 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 1695 Arg = CtorCGF.Builder.CreateElementBitCast(Arg, 1696 CtorCGF.ConvertTypeForMem(ASTTy)); 1697 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 1698 /*IsInitializer=*/true); 1699 ArgVal = CtorCGF.EmitLoadOfScalar( 1700 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1701 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1702 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 1703 CtorCGF.FinishFunction(); 1704 Ctor = Fn; 1705 } 1706 if (VD->getType().isDestructedType() != QualType::DK_none) { 1707 // Generate function that emits destructor call for the threadprivate copy 1708 // of the variable VD 1709 CodeGenFunction DtorCGF(CGM); 1710 FunctionArgList Args; 1711 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), 1712 /*Id=*/nullptr, CGM.getContext().VoidPtrTy); 1713 Args.push_back(&Dst); 1714 1715 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1716 CGM.getContext().VoidTy, Args); 1717 auto FTy = CGM.getTypes().GetFunctionType(FI); 1718 auto Fn = CGM.CreateGlobalInitOrDestructFunction( 1719 FTy, ".__kmpc_global_dtor_.", FI, Loc); 1720 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1721 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 1722 SourceLocation()); 1723 // Create a scope with an artificial location for the body of this function. 1724 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1725 auto ArgVal = DtorCGF.EmitLoadOfScalar( 1726 DtorCGF.GetAddrOfLocalVar(&Dst), 1727 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 1728 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 1729 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1730 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1731 DtorCGF.FinishFunction(); 1732 Dtor = Fn; 1733 } 1734 // Do not emit init function if it is not required. 1735 if (!Ctor && !Dtor) 1736 return nullptr; 1737 1738 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1739 auto CopyCtorTy = 1740 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 1741 /*isVarArg=*/false)->getPointerTo(); 1742 // Copying constructor for the threadprivate variable. 1743 // Must be NULL - reserved by runtime, but currently it requires that this 1744 // parameter is always NULL. Otherwise it fires assertion. 1745 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 1746 if (Ctor == nullptr) { 1747 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1748 /*isVarArg=*/false)->getPointerTo(); 1749 Ctor = llvm::Constant::getNullValue(CtorTy); 1750 } 1751 if (Dtor == nullptr) { 1752 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 1753 /*isVarArg=*/false)->getPointerTo(); 1754 Dtor = llvm::Constant::getNullValue(DtorTy); 1755 } 1756 if (!CGF) { 1757 auto InitFunctionTy = 1758 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 1759 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction( 1760 InitFunctionTy, ".__omp_threadprivate_init_.", 1761 CGM.getTypes().arrangeNullaryFunction()); 1762 CodeGenFunction InitCGF(CGM); 1763 FunctionArgList ArgList; 1764 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 1765 CGM.getTypes().arrangeNullaryFunction(), ArgList, 1766 Loc); 1767 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1768 InitCGF.FinishFunction(); 1769 return InitFunction; 1770 } 1771 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1772 } 1773 return nullptr; 1774 } 1775 1776 /// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen 1777 /// function. Here is the logic: 1778 /// if (Cond) { 1779 /// ThenGen(); 1780 /// } else { 1781 /// ElseGen(); 1782 /// } 1783 static void emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, 1784 const RegionCodeGenTy &ThenGen, 1785 const RegionCodeGenTy &ElseGen) { 1786 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 1787 1788 // If the condition constant folds and can be elided, try to avoid emitting 1789 // the condition and the dead arm of the if/else. 1790 bool CondConstant; 1791 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 1792 if (CondConstant) 1793 ThenGen(CGF); 1794 else 1795 ElseGen(CGF); 1796 return; 1797 } 1798 1799 // Otherwise, the condition did not fold, or we couldn't elide it. Just 1800 // emit the conditional branch. 1801 auto ThenBlock = CGF.createBasicBlock("omp_if.then"); 1802 auto ElseBlock = CGF.createBasicBlock("omp_if.else"); 1803 auto ContBlock = CGF.createBasicBlock("omp_if.end"); 1804 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 1805 1806 // Emit the 'then' code. 1807 CGF.EmitBlock(ThenBlock); 1808 ThenGen(CGF); 1809 CGF.EmitBranch(ContBlock); 1810 // Emit the 'else' code if present. 1811 // There is no need to emit line number for unconditional branch. 1812 (void)ApplyDebugLocation::CreateEmpty(CGF); 1813 CGF.EmitBlock(ElseBlock); 1814 ElseGen(CGF); 1815 // There is no need to emit line number for unconditional branch. 1816 (void)ApplyDebugLocation::CreateEmpty(CGF); 1817 CGF.EmitBranch(ContBlock); 1818 // Emit the continuation block for code after the if. 1819 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 1820 } 1821 1822 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 1823 llvm::Value *OutlinedFn, 1824 ArrayRef<llvm::Value *> CapturedVars, 1825 const Expr *IfCond) { 1826 if (!CGF.HaveInsertPoint()) 1827 return; 1828 auto *RTLoc = emitUpdateLocation(CGF, Loc); 1829 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 1830 PrePostActionTy &) { 1831 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 1832 auto &RT = CGF.CGM.getOpenMPRuntime(); 1833 llvm::Value *Args[] = { 1834 RTLoc, 1835 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 1836 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 1837 llvm::SmallVector<llvm::Value *, 16> RealArgs; 1838 RealArgs.append(std::begin(Args), std::end(Args)); 1839 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 1840 1841 auto RTLFn = RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 1842 CGF.EmitRuntimeCall(RTLFn, RealArgs); 1843 }; 1844 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 1845 PrePostActionTy &) { 1846 auto &RT = CGF.CGM.getOpenMPRuntime(); 1847 auto ThreadID = RT.getThreadID(CGF, Loc); 1848 // Build calls: 1849 // __kmpc_serialized_parallel(&Loc, GTid); 1850 llvm::Value *Args[] = {RTLoc, ThreadID}; 1851 CGF.EmitRuntimeCall( 1852 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 1853 1854 // OutlinedFn(>id, &zero, CapturedStruct); 1855 auto ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 1856 Address ZeroAddr = 1857 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4), 1858 /*Name*/ ".zero.addr"); 1859 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); 1860 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 1861 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 1862 OutlinedFnArgs.push_back(ZeroAddr.getPointer()); 1863 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 1864 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs); 1865 1866 // __kmpc_end_serialized_parallel(&Loc, GTid); 1867 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 1868 CGF.EmitRuntimeCall( 1869 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 1870 EndArgs); 1871 }; 1872 if (IfCond) 1873 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 1874 else { 1875 RegionCodeGenTy ThenRCG(ThenGen); 1876 ThenRCG(CGF); 1877 } 1878 } 1879 1880 // If we're inside an (outlined) parallel region, use the region info's 1881 // thread-ID variable (it is passed in a first argument of the outlined function 1882 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 1883 // regular serial code region, get thread ID by calling kmp_int32 1884 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 1885 // return the address of that temp. 1886 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 1887 SourceLocation Loc) { 1888 if (auto *OMPRegionInfo = 1889 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 1890 if (OMPRegionInfo->getThreadIDVariable()) 1891 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); 1892 1893 auto ThreadID = getThreadID(CGF, Loc); 1894 auto Int32Ty = 1895 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 1896 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 1897 CGF.EmitStoreOfScalar(ThreadID, 1898 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 1899 1900 return ThreadIDTemp; 1901 } 1902 1903 llvm::Constant * 1904 CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty, 1905 const llvm::Twine &Name) { 1906 SmallString<256> Buffer; 1907 llvm::raw_svector_ostream Out(Buffer); 1908 Out << Name; 1909 auto RuntimeName = Out.str(); 1910 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first; 1911 if (Elem.second) { 1912 assert(Elem.second->getType()->getPointerElementType() == Ty && 1913 "OMP internal variable has different type than requested"); 1914 return &*Elem.second; 1915 } 1916 1917 return Elem.second = new llvm::GlobalVariable( 1918 CGM.getModule(), Ty, /*IsConstant*/ false, 1919 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 1920 Elem.first()); 1921 } 1922 1923 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 1924 llvm::Twine Name(".gomp_critical_user_", CriticalName); 1925 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var")); 1926 } 1927 1928 namespace { 1929 /// Common pre(post)-action for different OpenMP constructs. 1930 class CommonActionTy final : public PrePostActionTy { 1931 llvm::Value *EnterCallee; 1932 ArrayRef<llvm::Value *> EnterArgs; 1933 llvm::Value *ExitCallee; 1934 ArrayRef<llvm::Value *> ExitArgs; 1935 bool Conditional; 1936 llvm::BasicBlock *ContBlock = nullptr; 1937 1938 public: 1939 CommonActionTy(llvm::Value *EnterCallee, ArrayRef<llvm::Value *> EnterArgs, 1940 llvm::Value *ExitCallee, ArrayRef<llvm::Value *> ExitArgs, 1941 bool Conditional = false) 1942 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 1943 ExitArgs(ExitArgs), Conditional(Conditional) {} 1944 void Enter(CodeGenFunction &CGF) override { 1945 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 1946 if (Conditional) { 1947 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 1948 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 1949 ContBlock = CGF.createBasicBlock("omp_if.end"); 1950 // Generate the branch (If-stmt) 1951 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 1952 CGF.EmitBlock(ThenBlock); 1953 } 1954 } 1955 void Done(CodeGenFunction &CGF) { 1956 // Emit the rest of blocks/branches 1957 CGF.EmitBranch(ContBlock); 1958 CGF.EmitBlock(ContBlock, true); 1959 } 1960 void Exit(CodeGenFunction &CGF) override { 1961 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 1962 } 1963 }; 1964 } // anonymous namespace 1965 1966 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 1967 StringRef CriticalName, 1968 const RegionCodeGenTy &CriticalOpGen, 1969 SourceLocation Loc, const Expr *Hint) { 1970 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 1971 // CriticalOpGen(); 1972 // __kmpc_end_critical(ident_t *, gtid, Lock); 1973 // Prepare arguments and build a call to __kmpc_critical 1974 if (!CGF.HaveInsertPoint()) 1975 return; 1976 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1977 getCriticalRegionLock(CriticalName)}; 1978 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 1979 std::end(Args)); 1980 if (Hint) { 1981 EnterArgs.push_back(CGF.Builder.CreateIntCast( 1982 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 1983 } 1984 CommonActionTy Action( 1985 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 1986 : OMPRTL__kmpc_critical), 1987 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 1988 CriticalOpGen.setAction(Action); 1989 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 1990 } 1991 1992 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 1993 const RegionCodeGenTy &MasterOpGen, 1994 SourceLocation Loc) { 1995 if (!CGF.HaveInsertPoint()) 1996 return; 1997 // if(__kmpc_master(ident_t *, gtid)) { 1998 // MasterOpGen(); 1999 // __kmpc_end_master(ident_t *, gtid); 2000 // } 2001 // Prepare arguments and build a call to __kmpc_master 2002 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2003 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 2004 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 2005 /*Conditional=*/true); 2006 MasterOpGen.setAction(Action); 2007 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 2008 Action.Done(CGF); 2009 } 2010 2011 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 2012 SourceLocation Loc) { 2013 if (!CGF.HaveInsertPoint()) 2014 return; 2015 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 2016 llvm::Value *Args[] = { 2017 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2018 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 2019 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 2020 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2021 Region->emitUntiedSwitch(CGF); 2022 } 2023 2024 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 2025 const RegionCodeGenTy &TaskgroupOpGen, 2026 SourceLocation Loc) { 2027 if (!CGF.HaveInsertPoint()) 2028 return; 2029 // __kmpc_taskgroup(ident_t *, gtid); 2030 // TaskgroupOpGen(); 2031 // __kmpc_end_taskgroup(ident_t *, gtid); 2032 // Prepare arguments and build a call to __kmpc_taskgroup 2033 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2034 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 2035 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 2036 Args); 2037 TaskgroupOpGen.setAction(Action); 2038 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 2039 } 2040 2041 /// Given an array of pointers to variables, project the address of a 2042 /// given variable. 2043 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 2044 unsigned Index, const VarDecl *Var) { 2045 // Pull out the pointer to the variable. 2046 Address PtrAddr = 2047 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize()); 2048 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 2049 2050 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 2051 Addr = CGF.Builder.CreateElementBitCast( 2052 Addr, CGF.ConvertTypeForMem(Var->getType())); 2053 return Addr; 2054 } 2055 2056 static llvm::Value *emitCopyprivateCopyFunction( 2057 CodeGenModule &CGM, llvm::Type *ArgsType, 2058 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 2059 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) { 2060 auto &C = CGM.getContext(); 2061 // void copy_func(void *LHSArg, void *RHSArg); 2062 FunctionArgList Args; 2063 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 2064 C.VoidPtrTy); 2065 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 2066 C.VoidPtrTy); 2067 Args.push_back(&LHSArg); 2068 Args.push_back(&RHSArg); 2069 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 2070 auto *Fn = llvm::Function::Create( 2071 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, 2072 ".omp.copyprivate.copy_func", &CGM.getModule()); 2073 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI); 2074 CodeGenFunction CGF(CGM); 2075 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args); 2076 // Dest = (void*[n])(LHSArg); 2077 // Src = (void*[n])(RHSArg); 2078 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2079 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 2080 ArgsType), CGF.getPointerAlign()); 2081 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2082 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 2083 ArgsType), CGF.getPointerAlign()); 2084 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 2085 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 2086 // ... 2087 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 2088 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 2089 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 2090 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 2091 2092 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 2093 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 2094 2095 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 2096 QualType Type = VD->getType(); 2097 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 2098 } 2099 CGF.FinishFunction(); 2100 return Fn; 2101 } 2102 2103 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 2104 const RegionCodeGenTy &SingleOpGen, 2105 SourceLocation Loc, 2106 ArrayRef<const Expr *> CopyprivateVars, 2107 ArrayRef<const Expr *> SrcExprs, 2108 ArrayRef<const Expr *> DstExprs, 2109 ArrayRef<const Expr *> AssignmentOps) { 2110 if (!CGF.HaveInsertPoint()) 2111 return; 2112 assert(CopyprivateVars.size() == SrcExprs.size() && 2113 CopyprivateVars.size() == DstExprs.size() && 2114 CopyprivateVars.size() == AssignmentOps.size()); 2115 auto &C = CGM.getContext(); 2116 // int32 did_it = 0; 2117 // if(__kmpc_single(ident_t *, gtid)) { 2118 // SingleOpGen(); 2119 // __kmpc_end_single(ident_t *, gtid); 2120 // did_it = 1; 2121 // } 2122 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2123 // <copy_func>, did_it); 2124 2125 Address DidIt = Address::invalid(); 2126 if (!CopyprivateVars.empty()) { 2127 // int32 did_it = 0; 2128 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2129 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 2130 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 2131 } 2132 // Prepare arguments and build a call to __kmpc_single 2133 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2134 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 2135 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 2136 /*Conditional=*/true); 2137 SingleOpGen.setAction(Action); 2138 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 2139 if (DidIt.isValid()) { 2140 // did_it = 1; 2141 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 2142 } 2143 Action.Done(CGF); 2144 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2145 // <copy_func>, did_it); 2146 if (DidIt.isValid()) { 2147 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 2148 auto CopyprivateArrayTy = 2149 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 2150 /*IndexTypeQuals=*/0); 2151 // Create a list of all private variables for copyprivate. 2152 Address CopyprivateList = 2153 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 2154 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 2155 Address Elem = CGF.Builder.CreateConstArrayGEP( 2156 CopyprivateList, I, CGF.getPointerSize()); 2157 CGF.Builder.CreateStore( 2158 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2159 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy), 2160 Elem); 2161 } 2162 // Build function that copies private values from single region to all other 2163 // threads in the corresponding parallel region. 2164 auto *CpyFn = emitCopyprivateCopyFunction( 2165 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 2166 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps); 2167 auto *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 2168 Address CL = 2169 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 2170 CGF.VoidPtrTy); 2171 auto *DidItVal = CGF.Builder.CreateLoad(DidIt); 2172 llvm::Value *Args[] = { 2173 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 2174 getThreadID(CGF, Loc), // i32 <gtid> 2175 BufSize, // size_t <buf_size> 2176 CL.getPointer(), // void *<copyprivate list> 2177 CpyFn, // void (*) (void *, void *) <copy_func> 2178 DidItVal // i32 did_it 2179 }; 2180 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 2181 } 2182 } 2183 2184 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 2185 const RegionCodeGenTy &OrderedOpGen, 2186 SourceLocation Loc, bool IsThreads) { 2187 if (!CGF.HaveInsertPoint()) 2188 return; 2189 // __kmpc_ordered(ident_t *, gtid); 2190 // OrderedOpGen(); 2191 // __kmpc_end_ordered(ident_t *, gtid); 2192 // Prepare arguments and build a call to __kmpc_ordered 2193 if (IsThreads) { 2194 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2195 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 2196 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 2197 Args); 2198 OrderedOpGen.setAction(Action); 2199 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2200 return; 2201 } 2202 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2203 } 2204 2205 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 2206 OpenMPDirectiveKind Kind, bool EmitChecks, 2207 bool ForceSimpleCall) { 2208 if (!CGF.HaveInsertPoint()) 2209 return; 2210 // Build call __kmpc_cancel_barrier(loc, thread_id); 2211 // Build call __kmpc_barrier(loc, thread_id); 2212 unsigned Flags; 2213 if (Kind == OMPD_for) 2214 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 2215 else if (Kind == OMPD_sections) 2216 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 2217 else if (Kind == OMPD_single) 2218 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 2219 else if (Kind == OMPD_barrier) 2220 Flags = OMP_IDENT_BARRIER_EXPL; 2221 else 2222 Flags = OMP_IDENT_BARRIER_IMPL; 2223 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 2224 // thread_id); 2225 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 2226 getThreadID(CGF, Loc)}; 2227 if (auto *OMPRegionInfo = 2228 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 2229 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 2230 auto *Result = CGF.EmitRuntimeCall( 2231 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 2232 if (EmitChecks) { 2233 // if (__kmpc_cancel_barrier()) { 2234 // exit from construct; 2235 // } 2236 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 2237 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 2238 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 2239 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 2240 CGF.EmitBlock(ExitBB); 2241 // exit from construct; 2242 auto CancelDestination = 2243 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 2244 CGF.EmitBranchThroughCleanup(CancelDestination); 2245 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 2246 } 2247 return; 2248 } 2249 } 2250 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 2251 } 2252 2253 /// \brief Map the OpenMP loop schedule to the runtime enumeration. 2254 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 2255 bool Chunked, bool Ordered) { 2256 switch (ScheduleKind) { 2257 case OMPC_SCHEDULE_static: 2258 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 2259 : (Ordered ? OMP_ord_static : OMP_sch_static); 2260 case OMPC_SCHEDULE_dynamic: 2261 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 2262 case OMPC_SCHEDULE_guided: 2263 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 2264 case OMPC_SCHEDULE_runtime: 2265 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 2266 case OMPC_SCHEDULE_auto: 2267 return Ordered ? OMP_ord_auto : OMP_sch_auto; 2268 case OMPC_SCHEDULE_unknown: 2269 assert(!Chunked && "chunk was specified but schedule kind not known"); 2270 return Ordered ? OMP_ord_static : OMP_sch_static; 2271 } 2272 llvm_unreachable("Unexpected runtime schedule"); 2273 } 2274 2275 /// \brief Map the OpenMP distribute schedule to the runtime enumeration. 2276 static OpenMPSchedType 2277 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 2278 // only static is allowed for dist_schedule 2279 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 2280 } 2281 2282 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 2283 bool Chunked) const { 2284 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2285 return Schedule == OMP_sch_static; 2286 } 2287 2288 bool CGOpenMPRuntime::isStaticNonchunked( 2289 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2290 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2291 return Schedule == OMP_dist_sch_static; 2292 } 2293 2294 2295 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 2296 auto Schedule = 2297 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 2298 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 2299 return Schedule != OMP_sch_static; 2300 } 2301 2302 void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF, 2303 SourceLocation Loc, 2304 OpenMPScheduleClauseKind ScheduleKind, 2305 unsigned IVSize, bool IVSigned, 2306 bool Ordered, llvm::Value *UB, 2307 llvm::Value *Chunk) { 2308 if (!CGF.HaveInsertPoint()) 2309 return; 2310 OpenMPSchedType Schedule = 2311 getRuntimeSchedule(ScheduleKind, Chunk != nullptr, Ordered); 2312 assert(Ordered || 2313 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 2314 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked)); 2315 // Call __kmpc_dispatch_init( 2316 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 2317 // kmp_int[32|64] lower, kmp_int[32|64] upper, 2318 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 2319 2320 // If the Chunk was not specified in the clause - use default value 1. 2321 if (Chunk == nullptr) 2322 Chunk = CGF.Builder.getIntN(IVSize, 1); 2323 llvm::Value *Args[] = { 2324 emitUpdateLocation(CGF, Loc), 2325 getThreadID(CGF, Loc), 2326 CGF.Builder.getInt32(Schedule), // Schedule type 2327 CGF.Builder.getIntN(IVSize, 0), // Lower 2328 UB, // Upper 2329 CGF.Builder.getIntN(IVSize, 1), // Stride 2330 Chunk // Chunk 2331 }; 2332 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 2333 } 2334 2335 static void emitForStaticInitCall(CodeGenFunction &CGF, 2336 SourceLocation Loc, 2337 llvm::Value * UpdateLocation, 2338 llvm::Value * ThreadId, 2339 llvm::Constant * ForStaticInitFunction, 2340 OpenMPSchedType Schedule, 2341 unsigned IVSize, bool IVSigned, bool Ordered, 2342 Address IL, Address LB, Address UB, 2343 Address ST, llvm::Value *Chunk) { 2344 if (!CGF.HaveInsertPoint()) 2345 return; 2346 2347 assert(!Ordered); 2348 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 2349 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 2350 Schedule == OMP_dist_sch_static || 2351 Schedule == OMP_dist_sch_static_chunked); 2352 2353 // Call __kmpc_for_static_init( 2354 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 2355 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 2356 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 2357 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 2358 if (Chunk == nullptr) { 2359 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 2360 Schedule == OMP_dist_sch_static) && 2361 "expected static non-chunked schedule"); 2362 // If the Chunk was not specified in the clause - use default value 1. 2363 Chunk = CGF.Builder.getIntN(IVSize, 1); 2364 } else { 2365 assert((Schedule == OMP_sch_static_chunked || 2366 Schedule == OMP_ord_static_chunked || 2367 Schedule == OMP_dist_sch_static_chunked) && 2368 "expected static chunked schedule"); 2369 } 2370 llvm::Value *Args[] = { 2371 UpdateLocation, 2372 ThreadId, 2373 CGF.Builder.getInt32(Schedule), // Schedule type 2374 IL.getPointer(), // &isLastIter 2375 LB.getPointer(), // &LB 2376 UB.getPointer(), // &UB 2377 ST.getPointer(), // &Stride 2378 CGF.Builder.getIntN(IVSize, 1), // Incr 2379 Chunk // Chunk 2380 }; 2381 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 2382 } 2383 2384 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 2385 SourceLocation Loc, 2386 OpenMPScheduleClauseKind ScheduleKind, 2387 unsigned IVSize, bool IVSigned, 2388 bool Ordered, Address IL, Address LB, 2389 Address UB, Address ST, 2390 llvm::Value *Chunk) { 2391 OpenMPSchedType ScheduleNum = getRuntimeSchedule(ScheduleKind, Chunk != nullptr, 2392 Ordered); 2393 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc); 2394 auto *ThreadId = getThreadID(CGF, Loc); 2395 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned); 2396 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction, 2397 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk); 2398 } 2399 2400 void CGOpenMPRuntime::emitDistributeStaticInit(CodeGenFunction &CGF, 2401 SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, 2402 unsigned IVSize, bool IVSigned, 2403 bool Ordered, Address IL, Address LB, 2404 Address UB, Address ST, 2405 llvm::Value *Chunk) { 2406 OpenMPSchedType ScheduleNum = getRuntimeSchedule(SchedKind, Chunk != nullptr); 2407 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc); 2408 auto *ThreadId = getThreadID(CGF, Loc); 2409 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned); 2410 emitForStaticInitCall(CGF, Loc, UpdatedLocation, ThreadId, StaticInitFunction, 2411 ScheduleNum, IVSize, IVSigned, Ordered, IL, LB, UB, ST, Chunk); 2412 } 2413 2414 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 2415 SourceLocation Loc) { 2416 if (!CGF.HaveInsertPoint()) 2417 return; 2418 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 2419 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2420 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 2421 Args); 2422 } 2423 2424 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 2425 SourceLocation Loc, 2426 unsigned IVSize, 2427 bool IVSigned) { 2428 if (!CGF.HaveInsertPoint()) 2429 return; 2430 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 2431 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2432 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 2433 } 2434 2435 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 2436 SourceLocation Loc, unsigned IVSize, 2437 bool IVSigned, Address IL, 2438 Address LB, Address UB, 2439 Address ST) { 2440 // Call __kmpc_dispatch_next( 2441 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 2442 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 2443 // kmp_int[32|64] *p_stride); 2444 llvm::Value *Args[] = { 2445 emitUpdateLocation(CGF, Loc), 2446 getThreadID(CGF, Loc), 2447 IL.getPointer(), // &isLastIter 2448 LB.getPointer(), // &Lower 2449 UB.getPointer(), // &Upper 2450 ST.getPointer() // &Stride 2451 }; 2452 llvm::Value *Call = 2453 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 2454 return CGF.EmitScalarConversion( 2455 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true), 2456 CGF.getContext().BoolTy, Loc); 2457 } 2458 2459 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 2460 llvm::Value *NumThreads, 2461 SourceLocation Loc) { 2462 if (!CGF.HaveInsertPoint()) 2463 return; 2464 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 2465 llvm::Value *Args[] = { 2466 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2467 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 2468 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 2469 Args); 2470 } 2471 2472 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 2473 OpenMPProcBindClauseKind ProcBind, 2474 SourceLocation Loc) { 2475 if (!CGF.HaveInsertPoint()) 2476 return; 2477 // Constants for proc bind value accepted by the runtime. 2478 enum ProcBindTy { 2479 ProcBindFalse = 0, 2480 ProcBindTrue, 2481 ProcBindMaster, 2482 ProcBindClose, 2483 ProcBindSpread, 2484 ProcBindIntel, 2485 ProcBindDefault 2486 } RuntimeProcBind; 2487 switch (ProcBind) { 2488 case OMPC_PROC_BIND_master: 2489 RuntimeProcBind = ProcBindMaster; 2490 break; 2491 case OMPC_PROC_BIND_close: 2492 RuntimeProcBind = ProcBindClose; 2493 break; 2494 case OMPC_PROC_BIND_spread: 2495 RuntimeProcBind = ProcBindSpread; 2496 break; 2497 case OMPC_PROC_BIND_unknown: 2498 llvm_unreachable("Unsupported proc_bind value."); 2499 } 2500 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 2501 llvm::Value *Args[] = { 2502 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2503 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; 2504 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 2505 } 2506 2507 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 2508 SourceLocation Loc) { 2509 if (!CGF.HaveInsertPoint()) 2510 return; 2511 // Build call void __kmpc_flush(ident_t *loc) 2512 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 2513 emitUpdateLocation(CGF, Loc)); 2514 } 2515 2516 namespace { 2517 /// \brief Indexes of fields for type kmp_task_t. 2518 enum KmpTaskTFields { 2519 /// \brief List of shared variables. 2520 KmpTaskTShareds, 2521 /// \brief Task routine. 2522 KmpTaskTRoutine, 2523 /// \brief Partition id for the untied tasks. 2524 KmpTaskTPartId, 2525 /// \brief Function with call of destructors for private variables. 2526 KmpTaskTDestructors, 2527 /// (Taskloops only) Lower bound. 2528 KmpTaskTLowerBound, 2529 /// (Taskloops only) Upper bound. 2530 KmpTaskTUpperBound, 2531 /// (Taskloops only) Stride. 2532 KmpTaskTStride, 2533 /// (Taskloops only) Is last iteration flag. 2534 KmpTaskTLastIter, 2535 }; 2536 } // anonymous namespace 2537 2538 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 2539 // FIXME: Add other entries type when they become supported. 2540 return OffloadEntriesTargetRegion.empty(); 2541 } 2542 2543 /// \brief Initialize target region entry. 2544 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2545 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2546 StringRef ParentName, unsigned LineNum, 2547 unsigned Order) { 2548 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 2549 "only required for the device " 2550 "code generation."); 2551 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 2552 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr); 2553 ++OffloadingEntriesNum; 2554 } 2555 2556 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2557 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2558 StringRef ParentName, unsigned LineNum, 2559 llvm::Constant *Addr, llvm::Constant *ID) { 2560 // If we are emitting code for a target, the entry is already initialized, 2561 // only has to be registered. 2562 if (CGM.getLangOpts().OpenMPIsDevice) { 2563 assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) && 2564 "Entry must exist."); 2565 auto &Entry = 2566 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 2567 assert(Entry.isValid() && "Entry not initialized!"); 2568 Entry.setAddress(Addr); 2569 Entry.setID(ID); 2570 return; 2571 } else { 2572 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID); 2573 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 2574 } 2575 } 2576 2577 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 2578 unsigned DeviceID, unsigned FileID, StringRef ParentName, 2579 unsigned LineNum) const { 2580 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 2581 if (PerDevice == OffloadEntriesTargetRegion.end()) 2582 return false; 2583 auto PerFile = PerDevice->second.find(FileID); 2584 if (PerFile == PerDevice->second.end()) 2585 return false; 2586 auto PerParentName = PerFile->second.find(ParentName); 2587 if (PerParentName == PerFile->second.end()) 2588 return false; 2589 auto PerLine = PerParentName->second.find(LineNum); 2590 if (PerLine == PerParentName->second.end()) 2591 return false; 2592 // Fail if this entry is already registered. 2593 if (PerLine->second.getAddress() || PerLine->second.getID()) 2594 return false; 2595 return true; 2596 } 2597 2598 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 2599 const OffloadTargetRegionEntryInfoActTy &Action) { 2600 // Scan all target region entries and perform the provided action. 2601 for (auto &D : OffloadEntriesTargetRegion) 2602 for (auto &F : D.second) 2603 for (auto &P : F.second) 2604 for (auto &L : P.second) 2605 Action(D.first, F.first, P.first(), L.first, L.second); 2606 } 2607 2608 /// \brief Create a Ctor/Dtor-like function whose body is emitted through 2609 /// \a Codegen. This is used to emit the two functions that register and 2610 /// unregister the descriptor of the current compilation unit. 2611 static llvm::Function * 2612 createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name, 2613 const RegionCodeGenTy &Codegen) { 2614 auto &C = CGM.getContext(); 2615 FunctionArgList Args; 2616 ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(), 2617 /*Id=*/nullptr, C.VoidPtrTy); 2618 Args.push_back(&DummyPtr); 2619 2620 CodeGenFunction CGF(CGM); 2621 GlobalDecl(); 2622 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 2623 auto FTy = CGM.getTypes().GetFunctionType(FI); 2624 auto *Fn = 2625 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation()); 2626 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation()); 2627 Codegen(CGF); 2628 CGF.FinishFunction(); 2629 return Fn; 2630 } 2631 2632 llvm::Function * 2633 CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() { 2634 2635 // If we don't have entries or if we are emitting code for the device, we 2636 // don't need to do anything. 2637 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty()) 2638 return nullptr; 2639 2640 auto &M = CGM.getModule(); 2641 auto &C = CGM.getContext(); 2642 2643 // Get list of devices we care about 2644 auto &Devices = CGM.getLangOpts().OMPTargetTriples; 2645 2646 // We should be creating an offloading descriptor only if there are devices 2647 // specified. 2648 assert(!Devices.empty() && "No OpenMP offloading devices??"); 2649 2650 // Create the external variables that will point to the begin and end of the 2651 // host entries section. These will be defined by the linker. 2652 auto *OffloadEntryTy = 2653 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()); 2654 llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable( 2655 M, OffloadEntryTy, /*isConstant=*/true, 2656 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr, 2657 ".omp_offloading.entries_begin"); 2658 llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable( 2659 M, OffloadEntryTy, /*isConstant=*/true, 2660 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr, 2661 ".omp_offloading.entries_end"); 2662 2663 // Create all device images 2664 llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires; 2665 auto *DeviceImageTy = cast<llvm::StructType>( 2666 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy())); 2667 2668 for (unsigned i = 0; i < Devices.size(); ++i) { 2669 StringRef T = Devices[i].getTriple(); 2670 auto *ImgBegin = new llvm::GlobalVariable( 2671 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, 2672 /*Initializer=*/nullptr, 2673 Twine(".omp_offloading.img_start.") + Twine(T)); 2674 auto *ImgEnd = new llvm::GlobalVariable( 2675 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, 2676 /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T)); 2677 2678 llvm::Constant *Dev = 2679 llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd, 2680 HostEntriesBegin, HostEntriesEnd, nullptr); 2681 DeviceImagesEntires.push_back(Dev); 2682 } 2683 2684 // Create device images global array. 2685 llvm::ArrayType *DeviceImagesInitTy = 2686 llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size()); 2687 llvm::Constant *DeviceImagesInit = 2688 llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires); 2689 2690 llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable( 2691 M, DeviceImagesInitTy, /*isConstant=*/true, 2692 llvm::GlobalValue::InternalLinkage, DeviceImagesInit, 2693 ".omp_offloading.device_images"); 2694 DeviceImages->setUnnamedAddr(true); 2695 2696 // This is a Zero array to be used in the creation of the constant expressions 2697 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty), 2698 llvm::Constant::getNullValue(CGM.Int32Ty)}; 2699 2700 // Create the target region descriptor. 2701 auto *BinaryDescriptorTy = cast<llvm::StructType>( 2702 CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy())); 2703 llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get( 2704 BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()), 2705 llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages, 2706 Index), 2707 HostEntriesBegin, HostEntriesEnd, nullptr); 2708 2709 auto *Desc = new llvm::GlobalVariable( 2710 M, BinaryDescriptorTy, /*isConstant=*/true, 2711 llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit, 2712 ".omp_offloading.descriptor"); 2713 2714 // Emit code to register or unregister the descriptor at execution 2715 // startup or closing, respectively. 2716 2717 // Create a variable to drive the registration and unregistration of the 2718 // descriptor, so we can reuse the logic that emits Ctors and Dtors. 2719 auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var"); 2720 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(), 2721 IdentInfo, C.CharTy); 2722 2723 auto *UnRegFn = createOffloadingBinaryDescriptorFunction( 2724 CGM, ".omp_offloading.descriptor_unreg", 2725 [&](CodeGenFunction &CGF, PrePostActionTy &) { 2726 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib), 2727 Desc); 2728 }); 2729 auto *RegFn = createOffloadingBinaryDescriptorFunction( 2730 CGM, ".omp_offloading.descriptor_reg", 2731 [&](CodeGenFunction &CGF, PrePostActionTy &) { 2732 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib), 2733 Desc); 2734 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc); 2735 }); 2736 return RegFn; 2737 } 2738 2739 void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID, 2740 llvm::Constant *Addr, uint64_t Size) { 2741 StringRef Name = Addr->getName(); 2742 auto *TgtOffloadEntryType = cast<llvm::StructType>( 2743 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy())); 2744 llvm::LLVMContext &C = CGM.getModule().getContext(); 2745 llvm::Module &M = CGM.getModule(); 2746 2747 // Make sure the address has the right type. 2748 llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy); 2749 2750 // Create constant string with the name. 2751 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 2752 2753 llvm::GlobalVariable *Str = 2754 new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true, 2755 llvm::GlobalValue::InternalLinkage, StrPtrInit, 2756 ".omp_offloading.entry_name"); 2757 Str->setUnnamedAddr(true); 2758 llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy); 2759 2760 // Create the entry struct. 2761 llvm::Constant *EntryInit = llvm::ConstantStruct::get( 2762 TgtOffloadEntryType, AddrPtr, StrPtr, 2763 llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr); 2764 llvm::GlobalVariable *Entry = new llvm::GlobalVariable( 2765 M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage, 2766 EntryInit, ".omp_offloading.entry"); 2767 2768 // The entry has to be created in the section the linker expects it to be. 2769 Entry->setSection(".omp_offloading.entries"); 2770 // We can't have any padding between symbols, so we need to have 1-byte 2771 // alignment. 2772 Entry->setAlignment(1); 2773 } 2774 2775 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 2776 // Emit the offloading entries and metadata so that the device codegen side 2777 // can 2778 // easily figure out what to emit. The produced metadata looks like this: 2779 // 2780 // !omp_offload.info = !{!1, ...} 2781 // 2782 // Right now we only generate metadata for function that contain target 2783 // regions. 2784 2785 // If we do not have entries, we dont need to do anything. 2786 if (OffloadEntriesInfoManager.empty()) 2787 return; 2788 2789 llvm::Module &M = CGM.getModule(); 2790 llvm::LLVMContext &C = M.getContext(); 2791 SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16> 2792 OrderedEntries(OffloadEntriesInfoManager.size()); 2793 2794 // Create the offloading info metadata node. 2795 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 2796 2797 // Auxiliar methods to create metadata values and strings. 2798 auto getMDInt = [&](unsigned v) { 2799 return llvm::ConstantAsMetadata::get( 2800 llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v)); 2801 }; 2802 2803 auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); }; 2804 2805 // Create function that emits metadata for each target region entry; 2806 auto &&TargetRegionMetadataEmitter = [&]( 2807 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line, 2808 OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 2809 llvm::SmallVector<llvm::Metadata *, 32> Ops; 2810 // Generate metadata for target regions. Each entry of this metadata 2811 // contains: 2812 // - Entry 0 -> Kind of this type of metadata (0). 2813 // - Entry 1 -> Device ID of the file where the entry was identified. 2814 // - Entry 2 -> File ID of the file where the entry was identified. 2815 // - Entry 3 -> Mangled name of the function where the entry was identified. 2816 // - Entry 4 -> Line in the file where the entry was identified. 2817 // - Entry 5 -> Order the entry was created. 2818 // The first element of the metadata node is the kind. 2819 Ops.push_back(getMDInt(E.getKind())); 2820 Ops.push_back(getMDInt(DeviceID)); 2821 Ops.push_back(getMDInt(FileID)); 2822 Ops.push_back(getMDString(ParentName)); 2823 Ops.push_back(getMDInt(Line)); 2824 Ops.push_back(getMDInt(E.getOrder())); 2825 2826 // Save this entry in the right position of the ordered entries array. 2827 OrderedEntries[E.getOrder()] = &E; 2828 2829 // Add metadata to the named metadata node. 2830 MD->addOperand(llvm::MDNode::get(C, Ops)); 2831 }; 2832 2833 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 2834 TargetRegionMetadataEmitter); 2835 2836 for (auto *E : OrderedEntries) { 2837 assert(E && "All ordered entries must exist!"); 2838 if (auto *CE = 2839 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 2840 E)) { 2841 assert(CE->getID() && CE->getAddress() && 2842 "Entry ID and Addr are invalid!"); 2843 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0); 2844 } else 2845 llvm_unreachable("Unsupported entry kind."); 2846 } 2847 } 2848 2849 /// \brief Loads all the offload entries information from the host IR 2850 /// metadata. 2851 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 2852 // If we are in target mode, load the metadata from the host IR. This code has 2853 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 2854 2855 if (!CGM.getLangOpts().OpenMPIsDevice) 2856 return; 2857 2858 if (CGM.getLangOpts().OMPHostIRFile.empty()) 2859 return; 2860 2861 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 2862 if (Buf.getError()) 2863 return; 2864 2865 llvm::LLVMContext C; 2866 auto ME = llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C); 2867 2868 if (ME.getError()) 2869 return; 2870 2871 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 2872 if (!MD) 2873 return; 2874 2875 for (auto I : MD->operands()) { 2876 llvm::MDNode *MN = cast<llvm::MDNode>(I); 2877 2878 auto getMDInt = [&](unsigned Idx) { 2879 llvm::ConstantAsMetadata *V = 2880 cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 2881 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 2882 }; 2883 2884 auto getMDString = [&](unsigned Idx) { 2885 llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx)); 2886 return V->getString(); 2887 }; 2888 2889 switch (getMDInt(0)) { 2890 default: 2891 llvm_unreachable("Unexpected metadata!"); 2892 break; 2893 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 2894 OFFLOAD_ENTRY_INFO_TARGET_REGION: 2895 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 2896 /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2), 2897 /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4), 2898 /*Order=*/getMDInt(5)); 2899 break; 2900 } 2901 } 2902 } 2903 2904 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 2905 if (!KmpRoutineEntryPtrTy) { 2906 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 2907 auto &C = CGM.getContext(); 2908 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 2909 FunctionProtoType::ExtProtoInfo EPI; 2910 KmpRoutineEntryPtrQTy = C.getPointerType( 2911 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 2912 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 2913 } 2914 } 2915 2916 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 2917 QualType FieldTy) { 2918 auto *Field = FieldDecl::Create( 2919 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 2920 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 2921 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 2922 Field->setAccess(AS_public); 2923 DC->addDecl(Field); 2924 return Field; 2925 } 2926 2927 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 2928 2929 // Make sure the type of the entry is already created. This is the type we 2930 // have to create: 2931 // struct __tgt_offload_entry{ 2932 // void *addr; // Pointer to the offload entry info. 2933 // // (function or global) 2934 // char *name; // Name of the function or global. 2935 // size_t size; // Size of the entry info (0 if it a function). 2936 // }; 2937 if (TgtOffloadEntryQTy.isNull()) { 2938 ASTContext &C = CGM.getContext(); 2939 auto *RD = C.buildImplicitRecord("__tgt_offload_entry"); 2940 RD->startDefinition(); 2941 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 2942 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 2943 addFieldToRecordDecl(C, RD, C.getSizeType()); 2944 RD->completeDefinition(); 2945 TgtOffloadEntryQTy = C.getRecordType(RD); 2946 } 2947 return TgtOffloadEntryQTy; 2948 } 2949 2950 QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { 2951 // These are the types we need to build: 2952 // struct __tgt_device_image{ 2953 // void *ImageStart; // Pointer to the target code start. 2954 // void *ImageEnd; // Pointer to the target code end. 2955 // // We also add the host entries to the device image, as it may be useful 2956 // // for the target runtime to have access to that information. 2957 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all 2958 // // the entries. 2959 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 2960 // // entries (non inclusive). 2961 // }; 2962 if (TgtDeviceImageQTy.isNull()) { 2963 ASTContext &C = CGM.getContext(); 2964 auto *RD = C.buildImplicitRecord("__tgt_device_image"); 2965 RD->startDefinition(); 2966 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 2967 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 2968 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 2969 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 2970 RD->completeDefinition(); 2971 TgtDeviceImageQTy = C.getRecordType(RD); 2972 } 2973 return TgtDeviceImageQTy; 2974 } 2975 2976 QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { 2977 // struct __tgt_bin_desc{ 2978 // int32_t NumDevices; // Number of devices supported. 2979 // __tgt_device_image *DeviceImages; // Arrays of device images 2980 // // (one per device). 2981 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the 2982 // // entries. 2983 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 2984 // // entries (non inclusive). 2985 // }; 2986 if (TgtBinaryDescriptorQTy.isNull()) { 2987 ASTContext &C = CGM.getContext(); 2988 auto *RD = C.buildImplicitRecord("__tgt_bin_desc"); 2989 RD->startDefinition(); 2990 addFieldToRecordDecl( 2991 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 2992 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); 2993 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 2994 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 2995 RD->completeDefinition(); 2996 TgtBinaryDescriptorQTy = C.getRecordType(RD); 2997 } 2998 return TgtBinaryDescriptorQTy; 2999 } 3000 3001 namespace { 3002 struct PrivateHelpersTy { 3003 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 3004 const VarDecl *PrivateElemInit) 3005 : Original(Original), PrivateCopy(PrivateCopy), 3006 PrivateElemInit(PrivateElemInit) {} 3007 const VarDecl *Original; 3008 const VarDecl *PrivateCopy; 3009 const VarDecl *PrivateElemInit; 3010 }; 3011 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 3012 } // anonymous namespace 3013 3014 static RecordDecl * 3015 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 3016 if (!Privates.empty()) { 3017 auto &C = CGM.getContext(); 3018 // Build struct .kmp_privates_t. { 3019 // /* private vars */ 3020 // }; 3021 auto *RD = C.buildImplicitRecord(".kmp_privates.t"); 3022 RD->startDefinition(); 3023 for (auto &&Pair : Privates) { 3024 auto *VD = Pair.second.Original; 3025 auto Type = VD->getType(); 3026 Type = Type.getNonReferenceType(); 3027 auto *FD = addFieldToRecordDecl(C, RD, Type); 3028 if (VD->hasAttrs()) { 3029 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 3030 E(VD->getAttrs().end()); 3031 I != E; ++I) 3032 FD->addAttr(*I); 3033 } 3034 } 3035 RD->completeDefinition(); 3036 return RD; 3037 } 3038 return nullptr; 3039 } 3040 3041 static RecordDecl * 3042 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 3043 QualType KmpInt32Ty, 3044 QualType KmpRoutineEntryPointerQTy) { 3045 auto &C = CGM.getContext(); 3046 // Build struct kmp_task_t { 3047 // void * shareds; 3048 // kmp_routine_entry_t routine; 3049 // kmp_int32 part_id; 3050 // kmp_routine_entry_t destructors; 3051 // For taskloops additional fields: 3052 // kmp_uint64 lb; 3053 // kmp_uint64 ub; 3054 // kmp_int64 st; 3055 // kmp_int32 liter; 3056 // }; 3057 auto *RD = C.buildImplicitRecord("kmp_task_t"); 3058 RD->startDefinition(); 3059 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3060 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 3061 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3062 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 3063 if (isOpenMPTaskLoopDirective(Kind)) { 3064 QualType KmpUInt64Ty = 3065 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 3066 QualType KmpInt64Ty = 3067 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 3068 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3069 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3070 addFieldToRecordDecl(C, RD, KmpInt64Ty); 3071 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3072 } 3073 RD->completeDefinition(); 3074 return RD; 3075 } 3076 3077 static RecordDecl * 3078 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 3079 ArrayRef<PrivateDataTy> Privates) { 3080 auto &C = CGM.getContext(); 3081 // Build struct kmp_task_t_with_privates { 3082 // kmp_task_t task_data; 3083 // .kmp_privates_t. privates; 3084 // }; 3085 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 3086 RD->startDefinition(); 3087 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 3088 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) { 3089 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 3090 } 3091 RD->completeDefinition(); 3092 return RD; 3093 } 3094 3095 /// \brief Emit a proxy function which accepts kmp_task_t as the second 3096 /// argument. 3097 /// \code 3098 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 3099 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 3100 /// For taskloops: 3101 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3102 /// tt->shareds); 3103 /// return 0; 3104 /// } 3105 /// \endcode 3106 static llvm::Value * 3107 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 3108 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 3109 QualType KmpTaskTWithPrivatesPtrQTy, 3110 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 3111 QualType SharedsPtrTy, llvm::Value *TaskFunction, 3112 llvm::Value *TaskPrivatesMap) { 3113 auto &C = CGM.getContext(); 3114 FunctionArgList Args; 3115 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty); 3116 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, 3117 /*Id=*/nullptr, 3118 KmpTaskTWithPrivatesPtrQTy.withRestrict()); 3119 Args.push_back(&GtidArg); 3120 Args.push_back(&TaskTypeArg); 3121 auto &TaskEntryFnInfo = 3122 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3123 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 3124 auto *TaskEntry = 3125 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage, 3126 ".omp_task_entry.", &CGM.getModule()); 3127 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo); 3128 CodeGenFunction CGF(CGM); 3129 CGF.disableDebugInfo(); 3130 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args); 3131 3132 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 3133 // tt, 3134 // For taskloops: 3135 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3136 // tt->task_data.shareds); 3137 auto *GtidParam = CGF.EmitLoadOfScalar( 3138 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 3139 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3140 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3141 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3142 auto *KmpTaskTWithPrivatesQTyRD = 3143 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3144 LValue Base = 3145 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3146 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 3147 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 3148 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 3149 auto *PartidParam = PartIdLVal.getPointer(); 3150 3151 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 3152 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 3153 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3154 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(), 3155 CGF.ConvertTypeForMem(SharedsPtrTy)); 3156 3157 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 3158 llvm::Value *PrivatesParam; 3159 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 3160 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 3161 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3162 PrivatesLVal.getPointer(), CGF.VoidPtrTy); 3163 } else 3164 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3165 3166 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 3167 TaskPrivatesMap, 3168 CGF.Builder 3169 .CreatePointerBitCastOrAddrSpaceCast( 3170 TDBase.getAddress(), CGF.VoidPtrTy) 3171 .getPointer()}; 3172 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 3173 std::end(CommonArgs)); 3174 if (isOpenMPTaskLoopDirective(Kind)) { 3175 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 3176 auto LBLVal = CGF.EmitLValueForField(Base, *LBFI); 3177 auto *LBParam = CGF.EmitLoadOfLValue(LBLVal, Loc).getScalarVal(); 3178 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 3179 auto UBLVal = CGF.EmitLValueForField(Base, *UBFI); 3180 auto *UBParam = CGF.EmitLoadOfLValue(UBLVal, Loc).getScalarVal(); 3181 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 3182 auto StLVal = CGF.EmitLValueForField(Base, *StFI); 3183 auto *StParam = CGF.EmitLoadOfLValue(StLVal, Loc).getScalarVal(); 3184 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3185 auto LILVal = CGF.EmitLValueForField(Base, *LIFI); 3186 auto *LIParam = CGF.EmitLoadOfLValue(LILVal, Loc).getScalarVal(); 3187 CallArgs.push_back(LBParam); 3188 CallArgs.push_back(UBParam); 3189 CallArgs.push_back(StParam); 3190 CallArgs.push_back(LIParam); 3191 } 3192 CallArgs.push_back(SharedsParam); 3193 3194 CGF.EmitCallOrInvoke(TaskFunction, CallArgs); 3195 CGF.EmitStoreThroughLValue( 3196 RValue::get(CGF.Builder.getInt32(/*C=*/0)), 3197 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 3198 CGF.FinishFunction(); 3199 return TaskEntry; 3200 } 3201 3202 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 3203 SourceLocation Loc, 3204 QualType KmpInt32Ty, 3205 QualType KmpTaskTWithPrivatesPtrQTy, 3206 QualType KmpTaskTWithPrivatesQTy) { 3207 auto &C = CGM.getContext(); 3208 FunctionArgList Args; 3209 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty); 3210 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, 3211 /*Id=*/nullptr, 3212 KmpTaskTWithPrivatesPtrQTy.withRestrict()); 3213 Args.push_back(&GtidArg); 3214 Args.push_back(&TaskTypeArg); 3215 FunctionType::ExtInfo Info; 3216 auto &DestructorFnInfo = 3217 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3218 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo); 3219 auto *DestructorFn = 3220 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 3221 ".omp_task_destructor.", &CGM.getModule()); 3222 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn, 3223 DestructorFnInfo); 3224 CodeGenFunction CGF(CGM); 3225 CGF.disableDebugInfo(); 3226 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 3227 Args); 3228 3229 LValue Base = CGF.EmitLoadOfPointerLValue( 3230 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3231 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3232 auto *KmpTaskTWithPrivatesQTyRD = 3233 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3234 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3235 Base = CGF.EmitLValueForField(Base, *FI); 3236 for (auto *Field : 3237 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 3238 if (auto DtorKind = Field->getType().isDestructedType()) { 3239 auto FieldLValue = CGF.EmitLValueForField(Base, Field); 3240 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType()); 3241 } 3242 } 3243 CGF.FinishFunction(); 3244 return DestructorFn; 3245 } 3246 3247 /// \brief Emit a privates mapping function for correct handling of private and 3248 /// firstprivate variables. 3249 /// \code 3250 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 3251 /// **noalias priv1,..., <tyn> **noalias privn) { 3252 /// *priv1 = &.privates.priv1; 3253 /// ...; 3254 /// *privn = &.privates.privn; 3255 /// } 3256 /// \endcode 3257 static llvm::Value * 3258 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 3259 ArrayRef<const Expr *> PrivateVars, 3260 ArrayRef<const Expr *> FirstprivateVars, 3261 QualType PrivatesQTy, 3262 ArrayRef<PrivateDataTy> Privates) { 3263 auto &C = CGM.getContext(); 3264 FunctionArgList Args; 3265 ImplicitParamDecl TaskPrivatesArg( 3266 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3267 C.getPointerType(PrivatesQTy).withConst().withRestrict()); 3268 Args.push_back(&TaskPrivatesArg); 3269 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 3270 unsigned Counter = 1; 3271 for (auto *E: PrivateVars) { 3272 Args.push_back(ImplicitParamDecl::Create( 3273 C, /*DC=*/nullptr, Loc, 3274 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) 3275 .withConst() 3276 .withRestrict())); 3277 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3278 PrivateVarsPos[VD] = Counter; 3279 ++Counter; 3280 } 3281 for (auto *E : FirstprivateVars) { 3282 Args.push_back(ImplicitParamDecl::Create( 3283 C, /*DC=*/nullptr, Loc, 3284 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) 3285 .withConst() 3286 .withRestrict())); 3287 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3288 PrivateVarsPos[VD] = Counter; 3289 ++Counter; 3290 } 3291 auto &TaskPrivatesMapFnInfo = 3292 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3293 auto *TaskPrivatesMapTy = 3294 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 3295 auto *TaskPrivatesMap = llvm::Function::Create( 3296 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, 3297 ".omp_task_privates_map.", &CGM.getModule()); 3298 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap, 3299 TaskPrivatesMapFnInfo); 3300 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 3301 CodeGenFunction CGF(CGM); 3302 CGF.disableDebugInfo(); 3303 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 3304 TaskPrivatesMapFnInfo, Args); 3305 3306 // *privi = &.privates.privi; 3307 LValue Base = CGF.EmitLoadOfPointerLValue( 3308 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 3309 TaskPrivatesArg.getType()->castAs<PointerType>()); 3310 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 3311 Counter = 0; 3312 for (auto *Field : PrivatesQTyRD->fields()) { 3313 auto FieldLVal = CGF.EmitLValueForField(Base, Field); 3314 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 3315 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 3316 auto RefLoadLVal = CGF.EmitLoadOfPointerLValue( 3317 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>()); 3318 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal); 3319 ++Counter; 3320 } 3321 CGF.FinishFunction(); 3322 return TaskPrivatesMap; 3323 } 3324 3325 static int array_pod_sort_comparator(const PrivateDataTy *P1, 3326 const PrivateDataTy *P2) { 3327 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0); 3328 } 3329 3330 CGOpenMPRuntime::TaskDataTy CGOpenMPRuntime::emitTaskInit( 3331 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, 3332 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, 3333 unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy, 3334 Address Shareds, ArrayRef<const Expr *> PrivateVars, 3335 ArrayRef<const Expr *> PrivateCopies, 3336 ArrayRef<const Expr *> FirstprivateVars, 3337 ArrayRef<const Expr *> FirstprivateCopies, 3338 ArrayRef<const Expr *> FirstprivateInits) { 3339 auto &C = CGM.getContext(); 3340 llvm::SmallVector<PrivateDataTy, 4> Privates; 3341 // Aggregate privates and sort them by the alignment. 3342 auto I = PrivateCopies.begin(); 3343 for (auto *E : PrivateVars) { 3344 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3345 Privates.push_back(std::make_pair( 3346 C.getDeclAlign(VD), 3347 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 3348 /*PrivateElemInit=*/nullptr))); 3349 ++I; 3350 } 3351 I = FirstprivateCopies.begin(); 3352 auto IElemInitRef = FirstprivateInits.begin(); 3353 for (auto *E : FirstprivateVars) { 3354 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3355 Privates.push_back(std::make_pair( 3356 C.getDeclAlign(VD), 3357 PrivateHelpersTy( 3358 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 3359 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())))); 3360 ++I; 3361 ++IElemInitRef; 3362 } 3363 llvm::array_pod_sort(Privates.begin(), Privates.end(), 3364 array_pod_sort_comparator); 3365 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3366 // Build type kmp_routine_entry_t (if not built yet). 3367 emitKmpRoutineEntryT(KmpInt32Ty); 3368 // Build type kmp_task_t (if not built yet). 3369 if (KmpTaskTQTy.isNull()) { 3370 KmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 3371 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 3372 } 3373 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 3374 // Build particular struct kmp_task_t for the given task. 3375 auto *KmpTaskTWithPrivatesQTyRD = 3376 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 3377 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 3378 QualType KmpTaskTWithPrivatesPtrQTy = 3379 C.getPointerType(KmpTaskTWithPrivatesQTy); 3380 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 3381 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo(); 3382 auto *KmpTaskTWithPrivatesTySize = CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 3383 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 3384 3385 // Emit initial values for private copies (if any). 3386 llvm::Value *TaskPrivatesMap = nullptr; 3387 auto *TaskPrivatesMapTy = 3388 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(), 3389 3) 3390 ->getType(); 3391 if (!Privates.empty()) { 3392 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3393 TaskPrivatesMap = emitTaskPrivateMappingFunction( 3394 CGM, Loc, PrivateVars, FirstprivateVars, FI->getType(), Privates); 3395 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3396 TaskPrivatesMap, TaskPrivatesMapTy); 3397 } else { 3398 TaskPrivatesMap = llvm::ConstantPointerNull::get( 3399 cast<llvm::PointerType>(TaskPrivatesMapTy)); 3400 } 3401 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 3402 // kmp_task_t *tt); 3403 auto *TaskEntry = emitProxyTaskFunction( 3404 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 3405 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 3406 TaskPrivatesMap); 3407 3408 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 3409 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 3410 // kmp_routine_entry_t *task_entry); 3411 // Task flags. Format is taken from 3412 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h, 3413 // description of kmp_tasking_flags struct. 3414 const unsigned TiedFlag = 0x1; 3415 const unsigned FinalFlag = 0x2; 3416 unsigned Flags = Tied ? TiedFlag : 0; 3417 auto *TaskFlags = 3418 Final.getPointer() 3419 ? CGF.Builder.CreateSelect(Final.getPointer(), 3420 CGF.Builder.getInt32(FinalFlag), 3421 CGF.Builder.getInt32(/*C=*/0)) 3422 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0); 3423 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 3424 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 3425 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc), 3426 getThreadID(CGF, Loc), TaskFlags, 3427 KmpTaskTWithPrivatesTySize, SharedsSize, 3428 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3429 TaskEntry, KmpRoutineEntryPtrTy)}; 3430 auto *NewTask = CGF.EmitRuntimeCall( 3431 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 3432 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3433 NewTask, KmpTaskTWithPrivatesPtrTy); 3434 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 3435 KmpTaskTWithPrivatesQTy); 3436 LValue TDBase = 3437 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3438 // Fill the data in the resulting kmp_task_t record. 3439 // Copy shareds if there are any. 3440 Address KmpTaskSharedsPtr = Address::invalid(); 3441 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 3442 KmpTaskSharedsPtr = 3443 Address(CGF.EmitLoadOfScalar( 3444 CGF.EmitLValueForField( 3445 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 3446 KmpTaskTShareds)), 3447 Loc), 3448 CGF.getNaturalTypeAlignment(SharedsTy)); 3449 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy); 3450 } 3451 // Emit initial values for private copies (if any). 3452 bool NeedsCleanup = false; 3453 if (!Privates.empty()) { 3454 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3455 auto PrivatesBase = CGF.EmitLValueForField(Base, *FI); 3456 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 3457 LValue SharedsBase; 3458 if (!FirstprivateVars.empty()) { 3459 SharedsBase = CGF.MakeAddrLValue( 3460 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3461 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 3462 SharedsTy); 3463 } 3464 CodeGenFunction::CGCapturedStmtInfo CapturesInfo( 3465 cast<CapturedStmt>(*D.getAssociatedStmt())); 3466 for (auto &&Pair : Privates) { 3467 auto *VD = Pair.second.PrivateCopy; 3468 auto *Init = VD->getAnyInitializer(); 3469 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 3470 if (Init) { 3471 if (auto *Elem = Pair.second.PrivateElemInit) { 3472 auto *OriginalVD = Pair.second.Original; 3473 auto *SharedField = CapturesInfo.lookup(OriginalVD); 3474 auto SharedRefLValue = 3475 CGF.EmitLValueForField(SharedsBase, SharedField); 3476 SharedRefLValue = CGF.MakeAddrLValue( 3477 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)), 3478 SharedRefLValue.getType(), AlignmentSource::Decl); 3479 QualType Type = OriginalVD->getType(); 3480 if (Type->isArrayType()) { 3481 // Initialize firstprivate array. 3482 if (!isa<CXXConstructExpr>(Init) || 3483 CGF.isTrivialInitializer(Init)) { 3484 // Perform simple memcpy. 3485 CGF.EmitAggregateAssign(PrivateLValue.getAddress(), 3486 SharedRefLValue.getAddress(), Type); 3487 } else { 3488 // Initialize firstprivate array using element-by-element 3489 // intialization. 3490 CGF.EmitOMPAggregateAssign( 3491 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), 3492 Type, [&CGF, Elem, Init, &CapturesInfo]( 3493 Address DestElement, Address SrcElement) { 3494 // Clean up any temporaries needed by the initialization. 3495 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3496 InitScope.addPrivate(Elem, [SrcElement]() -> Address { 3497 return SrcElement; 3498 }); 3499 (void)InitScope.Privatize(); 3500 // Emit initialization for single element. 3501 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 3502 CGF, &CapturesInfo); 3503 CGF.EmitAnyExprToMem(Init, DestElement, 3504 Init->getType().getQualifiers(), 3505 /*IsInitializer=*/false); 3506 }); 3507 } 3508 } else { 3509 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3510 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address { 3511 return SharedRefLValue.getAddress(); 3512 }); 3513 (void)InitScope.Privatize(); 3514 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 3515 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 3516 /*capturedByInit=*/false); 3517 } 3518 } else { 3519 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 3520 } 3521 } 3522 NeedsCleanup = NeedsCleanup || FI->getType().isDestructedType(); 3523 ++FI; 3524 } 3525 } 3526 // Provide pointer to function with destructors for privates. 3527 llvm::Value *DestructorFn = 3528 NeedsCleanup ? emitDestructorsFunction(CGM, Loc, KmpInt32Ty, 3529 KmpTaskTWithPrivatesPtrQTy, 3530 KmpTaskTWithPrivatesQTy) 3531 : llvm::ConstantPointerNull::get( 3532 cast<llvm::PointerType>(KmpRoutineEntryPtrTy)); 3533 LValue Destructor = CGF.EmitLValueForField( 3534 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTDestructors)); 3535 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3536 DestructorFn, KmpRoutineEntryPtrTy), 3537 Destructor); 3538 TaskDataTy Data; 3539 Data.NewTask = NewTask; 3540 Data.TaskEntry = TaskEntry; 3541 Data.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 3542 Data.TDBase = TDBase; 3543 Data.KmpTaskTQTyRD = KmpTaskTQTyRD; 3544 return Data; 3545 } 3546 3547 void CGOpenMPRuntime::emitTaskCall( 3548 CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, 3549 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, 3550 unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy, 3551 Address Shareds, const Expr *IfCond, ArrayRef<const Expr *> PrivateVars, 3552 ArrayRef<const Expr *> PrivateCopies, 3553 ArrayRef<const Expr *> FirstprivateVars, 3554 ArrayRef<const Expr *> FirstprivateCopies, 3555 ArrayRef<const Expr *> FirstprivateInits, 3556 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependences) { 3557 if (!CGF.HaveInsertPoint()) 3558 return; 3559 3560 TaskDataTy Data = 3561 emitTaskInit(CGF, Loc, D, Tied, Final, NumberOfParts, TaskFunction, 3562 SharedsTy, Shareds, PrivateVars, PrivateCopies, 3563 FirstprivateVars, FirstprivateCopies, FirstprivateInits); 3564 llvm::Value *NewTask = Data.NewTask; 3565 llvm::Value *TaskEntry = Data.TaskEntry; 3566 llvm::Value *NewTaskNewTaskTTy = Data.NewTaskNewTaskTTy; 3567 LValue TDBase = Data.TDBase; 3568 RecordDecl *KmpTaskTQTyRD = Data.KmpTaskTQTyRD; 3569 auto &C = CGM.getContext(); 3570 // Process list of dependences. 3571 Address DependenciesArray = Address::invalid(); 3572 unsigned NumDependencies = Dependences.size(); 3573 if (NumDependencies) { 3574 // Dependence kind for RTL. 3575 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 }; 3576 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 3577 RecordDecl *KmpDependInfoRD; 3578 QualType FlagsTy = 3579 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 3580 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 3581 if (KmpDependInfoTy.isNull()) { 3582 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 3583 KmpDependInfoRD->startDefinition(); 3584 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 3585 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 3586 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 3587 KmpDependInfoRD->completeDefinition(); 3588 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 3589 } else { 3590 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 3591 } 3592 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy); 3593 // Define type kmp_depend_info[<Dependences.size()>]; 3594 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 3595 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 3596 ArrayType::Normal, /*IndexTypeQuals=*/0); 3597 // kmp_depend_info[<Dependences.size()>] deps; 3598 DependenciesArray = 3599 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 3600 for (unsigned i = 0; i < NumDependencies; ++i) { 3601 const Expr *E = Dependences[i].second; 3602 auto Addr = CGF.EmitLValue(E); 3603 llvm::Value *Size; 3604 QualType Ty = E->getType(); 3605 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 3606 LValue UpAddrLVal = 3607 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false); 3608 llvm::Value *UpAddr = 3609 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1); 3610 llvm::Value *LowIntPtr = 3611 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy); 3612 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 3613 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 3614 } else 3615 Size = CGF.getTypeSize(Ty); 3616 auto Base = CGF.MakeAddrLValue( 3617 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize), 3618 KmpDependInfoTy); 3619 // deps[i].base_addr = &<Dependences[i].second>; 3620 auto BaseAddrLVal = CGF.EmitLValueForField( 3621 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 3622 CGF.EmitStoreOfScalar( 3623 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy), 3624 BaseAddrLVal); 3625 // deps[i].len = sizeof(<Dependences[i].second>); 3626 auto LenLVal = CGF.EmitLValueForField( 3627 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 3628 CGF.EmitStoreOfScalar(Size, LenLVal); 3629 // deps[i].flags = <Dependences[i].first>; 3630 RTLDependenceKindTy DepKind; 3631 switch (Dependences[i].first) { 3632 case OMPC_DEPEND_in: 3633 DepKind = DepIn; 3634 break; 3635 // Out and InOut dependencies must use the same code. 3636 case OMPC_DEPEND_out: 3637 case OMPC_DEPEND_inout: 3638 DepKind = DepInOut; 3639 break; 3640 case OMPC_DEPEND_source: 3641 case OMPC_DEPEND_sink: 3642 case OMPC_DEPEND_unknown: 3643 llvm_unreachable("Unknown task dependence type"); 3644 } 3645 auto FlagsLVal = CGF.EmitLValueForField( 3646 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 3647 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 3648 FlagsLVal); 3649 } 3650 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3651 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()), 3652 CGF.VoidPtrTy); 3653 } 3654 3655 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc() 3656 // libcall. 3657 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 3658 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 3659 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 3660 // list is not empty 3661 auto *ThreadID = getThreadID(CGF, Loc); 3662 auto *UpLoc = emitUpdateLocation(CGF, Loc); 3663 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 3664 llvm::Value *DepTaskArgs[7]; 3665 if (NumDependencies) { 3666 DepTaskArgs[0] = UpLoc; 3667 DepTaskArgs[1] = ThreadID; 3668 DepTaskArgs[2] = NewTask; 3669 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 3670 DepTaskArgs[4] = DependenciesArray.getPointer(); 3671 DepTaskArgs[5] = CGF.Builder.getInt32(0); 3672 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3673 } 3674 auto &&ThenCodeGen = [this, Tied, Loc, NumberOfParts, TDBase, KmpTaskTQTyRD, 3675 NumDependencies, &TaskArgs, 3676 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 3677 if (!Tied) { 3678 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 3679 auto PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 3680 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 3681 } 3682 if (NumDependencies) { 3683 CGF.EmitRuntimeCall( 3684 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 3685 } else { 3686 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 3687 TaskArgs); 3688 } 3689 // Check if parent region is untied and build return for untied task; 3690 if (auto *Region = 3691 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3692 Region->emitUntiedSwitch(CGF); 3693 }; 3694 3695 llvm::Value *DepWaitTaskArgs[6]; 3696 if (NumDependencies) { 3697 DepWaitTaskArgs[0] = UpLoc; 3698 DepWaitTaskArgs[1] = ThreadID; 3699 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 3700 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 3701 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 3702 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3703 } 3704 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 3705 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF, 3706 PrePostActionTy &) { 3707 auto &RT = CGF.CGM.getOpenMPRuntime(); 3708 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 3709 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 3710 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 3711 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 3712 // is specified. 3713 if (NumDependencies) 3714 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 3715 DepWaitTaskArgs); 3716 // Call proxy_task_entry(gtid, new_task); 3717 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy]( 3718 CodeGenFunction &CGF, PrePostActionTy &Action) { 3719 Action.Enter(CGF); 3720 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 3721 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs); 3722 }; 3723 3724 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 3725 // kmp_task_t *new_task); 3726 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 3727 // kmp_task_t *new_task); 3728 RegionCodeGenTy RCG(CodeGen); 3729 CommonActionTy Action( 3730 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 3731 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 3732 RCG.setAction(Action); 3733 RCG(CGF); 3734 }; 3735 3736 if (IfCond) 3737 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 3738 else { 3739 RegionCodeGenTy ThenRCG(ThenCodeGen); 3740 ThenRCG(CGF); 3741 } 3742 } 3743 3744 void CGOpenMPRuntime::emitTaskLoopCall( 3745 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 3746 bool Tied, llvm::PointerIntPair<llvm::Value *, 1, bool> Final, bool Nogroup, 3747 unsigned NumberOfParts, llvm::Value *TaskFunction, QualType SharedsTy, 3748 Address Shareds, const Expr *IfCond, ArrayRef<const Expr *> PrivateVars, 3749 ArrayRef<const Expr *> PrivateCopies, 3750 ArrayRef<const Expr *> FirstprivateVars, 3751 ArrayRef<const Expr *> FirstprivateCopies, 3752 ArrayRef<const Expr *> FirstprivateInits) { 3753 if (!CGF.HaveInsertPoint()) 3754 return; 3755 TaskDataTy Data = 3756 emitTaskInit(CGF, Loc, D, Tied, Final, NumberOfParts, TaskFunction, 3757 SharedsTy, Shareds, PrivateVars, PrivateCopies, 3758 FirstprivateVars, FirstprivateCopies, FirstprivateInits); 3759 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc() 3760 // libcall. 3761 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 3762 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 3763 // sched, kmp_uint64 grainsize, void *task_dup); 3764 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3765 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 3766 llvm::Value *IfVal; 3767 if (IfCond) { 3768 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 3769 /*isSigned=*/true); 3770 } else 3771 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 3772 3773 LValue LBLVal = CGF.EmitLValueForField( 3774 Data.TDBase, 3775 *std::next(Data.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 3776 auto *LBVar = 3777 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 3778 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(), 3779 /*IsInitializer=*/true); 3780 LValue UBLVal = CGF.EmitLValueForField( 3781 Data.TDBase, 3782 *std::next(Data.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 3783 auto *UBVar = 3784 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 3785 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(), 3786 /*IsInitializer=*/true); 3787 LValue StLVal = CGF.EmitLValueForField( 3788 Data.TDBase, 3789 *std::next(Data.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 3790 auto *StVar = 3791 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 3792 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(), 3793 /*IsInitializer=*/true); 3794 llvm::Value *TaskArgs[] = { 3795 UpLoc, 3796 ThreadID, 3797 Data.NewTask, 3798 IfVal, 3799 LBLVal.getPointer(), 3800 UBLVal.getPointer(), 3801 CGF.EmitLoadOfScalar(StLVal, SourceLocation()), 3802 llvm::ConstantInt::getSigned(CGF.IntTy, Nogroup ? 1 : 0), 3803 llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/0), 3804 llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 3805 llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 3806 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 3807 } 3808 3809 /// \brief Emit reduction operation for each element of array (required for 3810 /// array sections) LHS op = RHS. 3811 /// \param Type Type of array. 3812 /// \param LHSVar Variable on the left side of the reduction operation 3813 /// (references element of array in original variable). 3814 /// \param RHSVar Variable on the right side of the reduction operation 3815 /// (references element of array in original variable). 3816 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 3817 /// RHSVar. 3818 static void EmitOMPAggregateReduction( 3819 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 3820 const VarDecl *RHSVar, 3821 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 3822 const Expr *, const Expr *)> &RedOpGen, 3823 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 3824 const Expr *UpExpr = nullptr) { 3825 // Perform element-by-element initialization. 3826 QualType ElementTy; 3827 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 3828 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 3829 3830 // Drill down to the base element type on both arrays. 3831 auto ArrayTy = Type->getAsArrayTypeUnsafe(); 3832 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 3833 3834 auto RHSBegin = RHSAddr.getPointer(); 3835 auto LHSBegin = LHSAddr.getPointer(); 3836 // Cast from pointer to array type to pointer to single element. 3837 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 3838 // The basic structure here is a while-do loop. 3839 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 3840 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 3841 auto IsEmpty = 3842 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 3843 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 3844 3845 // Enter the loop body, making that address the current address. 3846 auto EntryBB = CGF.Builder.GetInsertBlock(); 3847 CGF.EmitBlock(BodyBB); 3848 3849 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 3850 3851 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 3852 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 3853 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 3854 Address RHSElementCurrent = 3855 Address(RHSElementPHI, 3856 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 3857 3858 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 3859 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 3860 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 3861 Address LHSElementCurrent = 3862 Address(LHSElementPHI, 3863 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 3864 3865 // Emit copy. 3866 CodeGenFunction::OMPPrivateScope Scope(CGF); 3867 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; }); 3868 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; }); 3869 Scope.Privatize(); 3870 RedOpGen(CGF, XExpr, EExpr, UpExpr); 3871 Scope.ForceCleanup(); 3872 3873 // Shift the address forward by one element. 3874 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32( 3875 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 3876 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32( 3877 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 3878 // Check whether we've reached the end. 3879 auto Done = 3880 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 3881 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 3882 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 3883 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 3884 3885 // Done. 3886 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 3887 } 3888 3889 /// Emit reduction combiner. If the combiner is a simple expression emit it as 3890 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 3891 /// UDR combiner function. 3892 static void emitReductionCombiner(CodeGenFunction &CGF, 3893 const Expr *ReductionOp) { 3894 if (auto *CE = dyn_cast<CallExpr>(ReductionOp)) 3895 if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 3896 if (auto *DRE = 3897 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 3898 if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 3899 std::pair<llvm::Function *, llvm::Function *> Reduction = 3900 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 3901 RValue Func = RValue::get(Reduction.first); 3902 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 3903 CGF.EmitIgnoredExpr(ReductionOp); 3904 return; 3905 } 3906 CGF.EmitIgnoredExpr(ReductionOp); 3907 } 3908 3909 static llvm::Value *emitReductionFunction(CodeGenModule &CGM, 3910 llvm::Type *ArgsType, 3911 ArrayRef<const Expr *> Privates, 3912 ArrayRef<const Expr *> LHSExprs, 3913 ArrayRef<const Expr *> RHSExprs, 3914 ArrayRef<const Expr *> ReductionOps) { 3915 auto &C = CGM.getContext(); 3916 3917 // void reduction_func(void *LHSArg, void *RHSArg); 3918 FunctionArgList Args; 3919 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 3920 C.VoidPtrTy); 3921 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 3922 C.VoidPtrTy); 3923 Args.push_back(&LHSArg); 3924 Args.push_back(&RHSArg); 3925 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3926 auto *Fn = llvm::Function::Create( 3927 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, 3928 ".omp.reduction.reduction_func", &CGM.getModule()); 3929 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI); 3930 CodeGenFunction CGF(CGM); 3931 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args); 3932 3933 // Dst = (void*[n])(LHSArg); 3934 // Src = (void*[n])(RHSArg); 3935 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3936 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3937 ArgsType), CGF.getPointerAlign()); 3938 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3939 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3940 ArgsType), CGF.getPointerAlign()); 3941 3942 // ... 3943 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 3944 // ... 3945 CodeGenFunction::OMPPrivateScope Scope(CGF); 3946 auto IPriv = Privates.begin(); 3947 unsigned Idx = 0; 3948 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 3949 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 3950 Scope.addPrivate(RHSVar, [&]() -> Address { 3951 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 3952 }); 3953 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 3954 Scope.addPrivate(LHSVar, [&]() -> Address { 3955 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 3956 }); 3957 QualType PrivTy = (*IPriv)->getType(); 3958 if (PrivTy->isVariablyModifiedType()) { 3959 // Get array size and emit VLA type. 3960 ++Idx; 3961 Address Elem = 3962 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize()); 3963 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 3964 auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy); 3965 auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 3966 CodeGenFunction::OpaqueValueMapping OpaqueMap( 3967 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 3968 CGF.EmitVariablyModifiedType(PrivTy); 3969 } 3970 } 3971 Scope.Privatize(); 3972 IPriv = Privates.begin(); 3973 auto ILHS = LHSExprs.begin(); 3974 auto IRHS = RHSExprs.begin(); 3975 for (auto *E : ReductionOps) { 3976 if ((*IPriv)->getType()->isArrayType()) { 3977 // Emit reduction for array section. 3978 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 3979 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 3980 EmitOMPAggregateReduction( 3981 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 3982 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 3983 emitReductionCombiner(CGF, E); 3984 }); 3985 } else 3986 // Emit reduction for array subscript or single variable. 3987 emitReductionCombiner(CGF, E); 3988 ++IPriv; 3989 ++ILHS; 3990 ++IRHS; 3991 } 3992 Scope.ForceCleanup(); 3993 CGF.FinishFunction(); 3994 return Fn; 3995 } 3996 3997 static void emitSingleReductionCombiner(CodeGenFunction &CGF, 3998 const Expr *ReductionOp, 3999 const Expr *PrivateRef, 4000 const DeclRefExpr *LHS, 4001 const DeclRefExpr *RHS) { 4002 if (PrivateRef->getType()->isArrayType()) { 4003 // Emit reduction for array section. 4004 auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 4005 auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 4006 EmitOMPAggregateReduction( 4007 CGF, PrivateRef->getType(), LHSVar, RHSVar, 4008 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 4009 emitReductionCombiner(CGF, ReductionOp); 4010 }); 4011 } else 4012 // Emit reduction for array subscript or single variable. 4013 emitReductionCombiner(CGF, ReductionOp); 4014 } 4015 4016 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 4017 ArrayRef<const Expr *> Privates, 4018 ArrayRef<const Expr *> LHSExprs, 4019 ArrayRef<const Expr *> RHSExprs, 4020 ArrayRef<const Expr *> ReductionOps, 4021 bool WithNowait, bool SimpleReduction) { 4022 if (!CGF.HaveInsertPoint()) 4023 return; 4024 // Next code should be emitted for reduction: 4025 // 4026 // static kmp_critical_name lock = { 0 }; 4027 // 4028 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 4029 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 4030 // ... 4031 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 4032 // *(Type<n>-1*)rhs[<n>-1]); 4033 // } 4034 // 4035 // ... 4036 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 4037 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 4038 // RedList, reduce_func, &<lock>)) { 4039 // case 1: 4040 // ... 4041 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 4042 // ... 4043 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 4044 // break; 4045 // case 2: 4046 // ... 4047 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 4048 // ... 4049 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 4050 // break; 4051 // default:; 4052 // } 4053 // 4054 // if SimpleReduction is true, only the next code is generated: 4055 // ... 4056 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 4057 // ... 4058 4059 auto &C = CGM.getContext(); 4060 4061 if (SimpleReduction) { 4062 CodeGenFunction::RunCleanupsScope Scope(CGF); 4063 auto IPriv = Privates.begin(); 4064 auto ILHS = LHSExprs.begin(); 4065 auto IRHS = RHSExprs.begin(); 4066 for (auto *E : ReductionOps) { 4067 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 4068 cast<DeclRefExpr>(*IRHS)); 4069 ++IPriv; 4070 ++ILHS; 4071 ++IRHS; 4072 } 4073 return; 4074 } 4075 4076 // 1. Build a list of reduction variables. 4077 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 4078 auto Size = RHSExprs.size(); 4079 for (auto *E : Privates) { 4080 if (E->getType()->isVariablyModifiedType()) 4081 // Reserve place for array size. 4082 ++Size; 4083 } 4084 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 4085 QualType ReductionArrayTy = 4086 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 4087 /*IndexTypeQuals=*/0); 4088 Address ReductionList = 4089 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 4090 auto IPriv = Privates.begin(); 4091 unsigned Idx = 0; 4092 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 4093 Address Elem = 4094 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize()); 4095 CGF.Builder.CreateStore( 4096 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4097 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy), 4098 Elem); 4099 if ((*IPriv)->getType()->isVariablyModifiedType()) { 4100 // Store array size. 4101 ++Idx; 4102 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, 4103 CGF.getPointerSize()); 4104 llvm::Value *Size = CGF.Builder.CreateIntCast( 4105 CGF.getVLASize( 4106 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 4107 .first, 4108 CGF.SizeTy, /*isSigned=*/false); 4109 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 4110 Elem); 4111 } 4112 } 4113 4114 // 2. Emit reduce_func(). 4115 auto *ReductionFn = emitReductionFunction( 4116 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 4117 LHSExprs, RHSExprs, ReductionOps); 4118 4119 // 3. Create static kmp_critical_name lock = { 0 }; 4120 auto *Lock = getCriticalRegionLock(".reduction"); 4121 4122 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 4123 // RedList, reduce_func, &<lock>); 4124 auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 4125 auto *ThreadId = getThreadID(CGF, Loc); 4126 auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 4127 auto *RL = 4128 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList.getPointer(), 4129 CGF.VoidPtrTy); 4130 llvm::Value *Args[] = { 4131 IdentTLoc, // ident_t *<loc> 4132 ThreadId, // i32 <gtid> 4133 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 4134 ReductionArrayTySize, // size_type sizeof(RedList) 4135 RL, // void *RedList 4136 ReductionFn, // void (*) (void *, void *) <reduce_func> 4137 Lock // kmp_critical_name *&<lock> 4138 }; 4139 auto Res = CGF.EmitRuntimeCall( 4140 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 4141 : OMPRTL__kmpc_reduce), 4142 Args); 4143 4144 // 5. Build switch(res) 4145 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 4146 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 4147 4148 // 6. Build case 1: 4149 // ... 4150 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 4151 // ... 4152 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 4153 // break; 4154 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 4155 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 4156 CGF.EmitBlock(Case1BB); 4157 4158 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 4159 llvm::Value *EndArgs[] = { 4160 IdentTLoc, // ident_t *<loc> 4161 ThreadId, // i32 <gtid> 4162 Lock // kmp_critical_name *&<lock> 4163 }; 4164 auto &&CodeGen = [&Privates, &LHSExprs, &RHSExprs, &ReductionOps]( 4165 CodeGenFunction &CGF, PrePostActionTy &Action) { 4166 auto IPriv = Privates.begin(); 4167 auto ILHS = LHSExprs.begin(); 4168 auto IRHS = RHSExprs.begin(); 4169 for (auto *E : ReductionOps) { 4170 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 4171 cast<DeclRefExpr>(*IRHS)); 4172 ++IPriv; 4173 ++ILHS; 4174 ++IRHS; 4175 } 4176 }; 4177 RegionCodeGenTy RCG(CodeGen); 4178 CommonActionTy Action( 4179 nullptr, llvm::None, 4180 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 4181 : OMPRTL__kmpc_end_reduce), 4182 EndArgs); 4183 RCG.setAction(Action); 4184 RCG(CGF); 4185 4186 CGF.EmitBranch(DefaultBB); 4187 4188 // 7. Build case 2: 4189 // ... 4190 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 4191 // ... 4192 // break; 4193 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 4194 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 4195 CGF.EmitBlock(Case2BB); 4196 4197 auto &&AtomicCodeGen = [Loc, &Privates, &LHSExprs, &RHSExprs, &ReductionOps]( 4198 CodeGenFunction &CGF, PrePostActionTy &Action) { 4199 auto ILHS = LHSExprs.begin(); 4200 auto IRHS = RHSExprs.begin(); 4201 auto IPriv = Privates.begin(); 4202 for (auto *E : ReductionOps) { 4203 const Expr *XExpr = nullptr; 4204 const Expr *EExpr = nullptr; 4205 const Expr *UpExpr = nullptr; 4206 BinaryOperatorKind BO = BO_Comma; 4207 if (auto *BO = dyn_cast<BinaryOperator>(E)) { 4208 if (BO->getOpcode() == BO_Assign) { 4209 XExpr = BO->getLHS(); 4210 UpExpr = BO->getRHS(); 4211 } 4212 } 4213 // Try to emit update expression as a simple atomic. 4214 auto *RHSExpr = UpExpr; 4215 if (RHSExpr) { 4216 // Analyze RHS part of the whole expression. 4217 if (auto *ACO = dyn_cast<AbstractConditionalOperator>( 4218 RHSExpr->IgnoreParenImpCasts())) { 4219 // If this is a conditional operator, analyze its condition for 4220 // min/max reduction operator. 4221 RHSExpr = ACO->getCond(); 4222 } 4223 if (auto *BORHS = 4224 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 4225 EExpr = BORHS->getRHS(); 4226 BO = BORHS->getOpcode(); 4227 } 4228 } 4229 if (XExpr) { 4230 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 4231 auto &&AtomicRedGen = [BO, VD, IPriv, 4232 Loc](CodeGenFunction &CGF, const Expr *XExpr, 4233 const Expr *EExpr, const Expr *UpExpr) { 4234 LValue X = CGF.EmitLValue(XExpr); 4235 RValue E; 4236 if (EExpr) 4237 E = CGF.EmitAnyExpr(EExpr); 4238 CGF.EmitOMPAtomicSimpleUpdateExpr( 4239 X, E, BO, /*IsXLHSInRHSPart=*/true, 4240 llvm::AtomicOrdering::Monotonic, Loc, 4241 [&CGF, UpExpr, VD, IPriv, Loc](RValue XRValue) { 4242 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 4243 PrivateScope.addPrivate( 4244 VD, [&CGF, VD, XRValue, Loc]() -> Address { 4245 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 4246 CGF.emitOMPSimpleStore( 4247 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 4248 VD->getType().getNonReferenceType(), Loc); 4249 return LHSTemp; 4250 }); 4251 (void)PrivateScope.Privatize(); 4252 return CGF.EmitAnyExpr(UpExpr); 4253 }); 4254 }; 4255 if ((*IPriv)->getType()->isArrayType()) { 4256 // Emit atomic reduction for array section. 4257 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 4258 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 4259 AtomicRedGen, XExpr, EExpr, UpExpr); 4260 } else 4261 // Emit atomic reduction for array subscript or single variable. 4262 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 4263 } else { 4264 // Emit as a critical region. 4265 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 4266 const Expr *, const Expr *) { 4267 auto &RT = CGF.CGM.getOpenMPRuntime(); 4268 RT.emitCriticalRegion( 4269 CGF, ".atomic_reduction", 4270 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 4271 Action.Enter(CGF); 4272 emitReductionCombiner(CGF, E); 4273 }, 4274 Loc); 4275 }; 4276 if ((*IPriv)->getType()->isArrayType()) { 4277 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 4278 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 4279 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 4280 CritRedGen); 4281 } else 4282 CritRedGen(CGF, nullptr, nullptr, nullptr); 4283 } 4284 ++ILHS; 4285 ++IRHS; 4286 ++IPriv; 4287 } 4288 }; 4289 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 4290 if (!WithNowait) { 4291 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 4292 llvm::Value *EndArgs[] = { 4293 IdentTLoc, // ident_t *<loc> 4294 ThreadId, // i32 <gtid> 4295 Lock // kmp_critical_name *&<lock> 4296 }; 4297 CommonActionTy Action(nullptr, llvm::None, 4298 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 4299 EndArgs); 4300 AtomicRCG.setAction(Action); 4301 AtomicRCG(CGF); 4302 } else 4303 AtomicRCG(CGF); 4304 4305 CGF.EmitBranch(DefaultBB); 4306 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 4307 } 4308 4309 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 4310 SourceLocation Loc) { 4311 if (!CGF.HaveInsertPoint()) 4312 return; 4313 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 4314 // global_tid); 4315 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 4316 // Ignore return result until untied tasks are supported. 4317 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 4318 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 4319 Region->emitUntiedSwitch(CGF); 4320 } 4321 4322 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 4323 OpenMPDirectiveKind InnerKind, 4324 const RegionCodeGenTy &CodeGen, 4325 bool HasCancel) { 4326 if (!CGF.HaveInsertPoint()) 4327 return; 4328 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 4329 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 4330 } 4331 4332 namespace { 4333 enum RTCancelKind { 4334 CancelNoreq = 0, 4335 CancelParallel = 1, 4336 CancelLoop = 2, 4337 CancelSections = 3, 4338 CancelTaskgroup = 4 4339 }; 4340 } // anonymous namespace 4341 4342 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 4343 RTCancelKind CancelKind = CancelNoreq; 4344 if (CancelRegion == OMPD_parallel) 4345 CancelKind = CancelParallel; 4346 else if (CancelRegion == OMPD_for) 4347 CancelKind = CancelLoop; 4348 else if (CancelRegion == OMPD_sections) 4349 CancelKind = CancelSections; 4350 else { 4351 assert(CancelRegion == OMPD_taskgroup); 4352 CancelKind = CancelTaskgroup; 4353 } 4354 return CancelKind; 4355 } 4356 4357 void CGOpenMPRuntime::emitCancellationPointCall( 4358 CodeGenFunction &CGF, SourceLocation Loc, 4359 OpenMPDirectiveKind CancelRegion) { 4360 if (!CGF.HaveInsertPoint()) 4361 return; 4362 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 4363 // global_tid, kmp_int32 cncl_kind); 4364 if (auto *OMPRegionInfo = 4365 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 4366 if (OMPRegionInfo->hasCancel()) { 4367 llvm::Value *Args[] = { 4368 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 4369 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 4370 // Ignore return result until untied tasks are supported. 4371 auto *Result = CGF.EmitRuntimeCall( 4372 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 4373 // if (__kmpc_cancellationpoint()) { 4374 // __kmpc_cancel_barrier(); 4375 // exit from construct; 4376 // } 4377 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 4378 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 4379 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 4380 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 4381 CGF.EmitBlock(ExitBB); 4382 // __kmpc_cancel_barrier(); 4383 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 4384 // exit from construct; 4385 auto CancelDest = 4386 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 4387 CGF.EmitBranchThroughCleanup(CancelDest); 4388 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 4389 } 4390 } 4391 } 4392 4393 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 4394 const Expr *IfCond, 4395 OpenMPDirectiveKind CancelRegion) { 4396 if (!CGF.HaveInsertPoint()) 4397 return; 4398 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 4399 // kmp_int32 cncl_kind); 4400 if (auto *OMPRegionInfo = 4401 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 4402 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 4403 PrePostActionTy &) { 4404 auto &RT = CGF.CGM.getOpenMPRuntime(); 4405 llvm::Value *Args[] = { 4406 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 4407 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 4408 // Ignore return result until untied tasks are supported. 4409 auto *Result = CGF.EmitRuntimeCall( 4410 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 4411 // if (__kmpc_cancel()) { 4412 // __kmpc_cancel_barrier(); 4413 // exit from construct; 4414 // } 4415 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 4416 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 4417 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 4418 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 4419 CGF.EmitBlock(ExitBB); 4420 // __kmpc_cancel_barrier(); 4421 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 4422 // exit from construct; 4423 auto CancelDest = 4424 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 4425 CGF.EmitBranchThroughCleanup(CancelDest); 4426 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 4427 }; 4428 if (IfCond) 4429 emitOMPIfClause(CGF, IfCond, ThenGen, 4430 [](CodeGenFunction &, PrePostActionTy &) {}); 4431 else { 4432 RegionCodeGenTy ThenRCG(ThenGen); 4433 ThenRCG(CGF); 4434 } 4435 } 4436 } 4437 4438 /// \brief Obtain information that uniquely identifies a target entry. This 4439 /// consists of the file and device IDs as well as line number associated with 4440 /// the relevant entry source location. 4441 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 4442 unsigned &DeviceID, unsigned &FileID, 4443 unsigned &LineNum) { 4444 4445 auto &SM = C.getSourceManager(); 4446 4447 // The loc should be always valid and have a file ID (the user cannot use 4448 // #pragma directives in macros) 4449 4450 assert(Loc.isValid() && "Source location is expected to be always valid."); 4451 assert(Loc.isFileID() && "Source location is expected to refer to a file."); 4452 4453 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 4454 assert(PLoc.isValid() && "Source location is expected to be always valid."); 4455 4456 llvm::sys::fs::UniqueID ID; 4457 if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 4458 llvm_unreachable("Source file with target region no longer exists!"); 4459 4460 DeviceID = ID.getDevice(); 4461 FileID = ID.getFile(); 4462 LineNum = PLoc.getLine(); 4463 } 4464 4465 void CGOpenMPRuntime::emitTargetOutlinedFunction( 4466 const OMPExecutableDirective &D, StringRef ParentName, 4467 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 4468 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 4469 assert(!ParentName.empty() && "Invalid target region parent name!"); 4470 4471 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 4472 IsOffloadEntry, CodeGen); 4473 } 4474 4475 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 4476 const OMPExecutableDirective &D, StringRef ParentName, 4477 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 4478 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 4479 // Create a unique name for the entry function using the source location 4480 // information of the current target region. The name will be something like: 4481 // 4482 // __omp_offloading_DD_FFFF_PP_lBB 4483 // 4484 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 4485 // mangled name of the function that encloses the target region and BB is the 4486 // line number of the target region. 4487 4488 unsigned DeviceID; 4489 unsigned FileID; 4490 unsigned Line; 4491 getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID, 4492 Line); 4493 SmallString<64> EntryFnName; 4494 { 4495 llvm::raw_svector_ostream OS(EntryFnName); 4496 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 4497 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 4498 } 4499 4500 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 4501 4502 CodeGenFunction CGF(CGM, true); 4503 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 4504 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 4505 4506 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 4507 4508 // If this target outline function is not an offload entry, we don't need to 4509 // register it. 4510 if (!IsOffloadEntry) 4511 return; 4512 4513 // The target region ID is used by the runtime library to identify the current 4514 // target region, so it only has to be unique and not necessarily point to 4515 // anything. It could be the pointer to the outlined function that implements 4516 // the target region, but we aren't using that so that the compiler doesn't 4517 // need to keep that, and could therefore inline the host function if proven 4518 // worthwhile during optimization. In the other hand, if emitting code for the 4519 // device, the ID has to be the function address so that it can retrieved from 4520 // the offloading entry and launched by the runtime library. We also mark the 4521 // outlined function to have external linkage in case we are emitting code for 4522 // the device, because these functions will be entry points to the device. 4523 4524 if (CGM.getLangOpts().OpenMPIsDevice) { 4525 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 4526 OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage); 4527 } else 4528 OutlinedFnID = new llvm::GlobalVariable( 4529 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 4530 llvm::GlobalValue::PrivateLinkage, 4531 llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id"); 4532 4533 // Register the information for the entry associated with this target region. 4534 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 4535 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID); 4536 } 4537 4538 /// \brief Emit the num_teams clause of an enclosed teams directive at the 4539 /// target region scope. If there is no teams directive associated with the 4540 /// target directive, or if there is no num_teams clause associated with the 4541 /// enclosed teams directive, return nullptr. 4542 static llvm::Value * 4543 emitNumTeamsClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime, 4544 CodeGenFunction &CGF, 4545 const OMPExecutableDirective &D) { 4546 4547 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the " 4548 "teams directive expected to be " 4549 "emitted only for the host!"); 4550 4551 // FIXME: For the moment we do not support combined directives with target and 4552 // teams, so we do not expect to get any num_teams clause in the provided 4553 // directive. Once we support that, this assertion can be replaced by the 4554 // actual emission of the clause expression. 4555 assert(D.getSingleClause<OMPNumTeamsClause>() == nullptr && 4556 "Not expecting clause in directive."); 4557 4558 // If the current target region has a teams region enclosed, we need to get 4559 // the number of teams to pass to the runtime function call. This is done 4560 // by generating the expression in a inlined region. This is required because 4561 // the expression is captured in the enclosing target environment when the 4562 // teams directive is not combined with target. 4563 4564 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 4565 4566 // FIXME: Accommodate other combined directives with teams when they become 4567 // available. 4568 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) { 4569 if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) { 4570 CGOpenMPInnerExprInfo CGInfo(CGF, CS); 4571 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 4572 llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams()); 4573 return CGF.Builder.CreateIntCast(NumTeams, CGF.Int32Ty, 4574 /*IsSigned=*/true); 4575 } 4576 4577 // If we have an enclosed teams directive but no num_teams clause we use 4578 // the default value 0. 4579 return CGF.Builder.getInt32(0); 4580 } 4581 4582 // No teams associated with the directive. 4583 return nullptr; 4584 } 4585 4586 /// \brief Emit the thread_limit clause of an enclosed teams directive at the 4587 /// target region scope. If there is no teams directive associated with the 4588 /// target directive, or if there is no thread_limit clause associated with the 4589 /// enclosed teams directive, return nullptr. 4590 static llvm::Value * 4591 emitThreadLimitClauseForTargetDirective(CGOpenMPRuntime &OMPRuntime, 4592 CodeGenFunction &CGF, 4593 const OMPExecutableDirective &D) { 4594 4595 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the " 4596 "teams directive expected to be " 4597 "emitted only for the host!"); 4598 4599 // FIXME: For the moment we do not support combined directives with target and 4600 // teams, so we do not expect to get any thread_limit clause in the provided 4601 // directive. Once we support that, this assertion can be replaced by the 4602 // actual emission of the clause expression. 4603 assert(D.getSingleClause<OMPThreadLimitClause>() == nullptr && 4604 "Not expecting clause in directive."); 4605 4606 // If the current target region has a teams region enclosed, we need to get 4607 // the thread limit to pass to the runtime function call. This is done 4608 // by generating the expression in a inlined region. This is required because 4609 // the expression is captured in the enclosing target environment when the 4610 // teams directive is not combined with target. 4611 4612 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 4613 4614 // FIXME: Accommodate other combined directives with teams when they become 4615 // available. 4616 if (auto *TeamsDir = dyn_cast<OMPTeamsDirective>(CS.getCapturedStmt())) { 4617 if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) { 4618 CGOpenMPInnerExprInfo CGInfo(CGF, CS); 4619 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 4620 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit()); 4621 return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty, 4622 /*IsSigned=*/true); 4623 } 4624 4625 // If we have an enclosed teams directive but no thread_limit clause we use 4626 // the default value 0. 4627 return CGF.Builder.getInt32(0); 4628 } 4629 4630 // No teams associated with the directive. 4631 return nullptr; 4632 } 4633 4634 void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, 4635 const OMPExecutableDirective &D, 4636 llvm::Value *OutlinedFn, 4637 llvm::Value *OutlinedFnID, 4638 const Expr *IfCond, const Expr *Device, 4639 ArrayRef<llvm::Value *> CapturedVars) { 4640 if (!CGF.HaveInsertPoint()) 4641 return; 4642 /// \brief Values for bit flags used to specify the mapping type for 4643 /// offloading. 4644 enum OpenMPOffloadMappingFlags { 4645 /// \brief Allocate memory on the device and move data from host to device. 4646 OMP_MAP_TO = 0x01, 4647 /// \brief Allocate memory on the device and move data from device to host. 4648 OMP_MAP_FROM = 0x02, 4649 /// \brief The element passed to the device is a pointer. 4650 OMP_MAP_PTR = 0x20, 4651 /// \brief Pass the element to the device by value. 4652 OMP_MAP_BYCOPY = 0x80, 4653 }; 4654 4655 enum OpenMPOffloadingReservedDeviceIDs { 4656 /// \brief Device ID if the device was not defined, runtime should get it 4657 /// from environment variables in the spec. 4658 OMP_DEVICEID_UNDEF = -1, 4659 }; 4660 4661 assert(OutlinedFn && "Invalid outlined function!"); 4662 4663 auto &Ctx = CGF.getContext(); 4664 4665 // Fill up the arrays with the all the captured variables. 4666 SmallVector<llvm::Value *, 16> BasePointers; 4667 SmallVector<llvm::Value *, 16> Pointers; 4668 SmallVector<llvm::Value *, 16> Sizes; 4669 SmallVector<unsigned, 16> MapTypes; 4670 4671 bool hasVLACaptures = false; 4672 4673 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 4674 auto RI = CS.getCapturedRecordDecl()->field_begin(); 4675 // auto II = CS.capture_init_begin(); 4676 auto CV = CapturedVars.begin(); 4677 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 4678 CE = CS.capture_end(); 4679 CI != CE; ++CI, ++RI, ++CV) { 4680 StringRef Name; 4681 QualType Ty; 4682 llvm::Value *BasePointer; 4683 llvm::Value *Pointer; 4684 llvm::Value *Size; 4685 unsigned MapType; 4686 4687 // VLA sizes are passed to the outlined region by copy. 4688 if (CI->capturesVariableArrayType()) { 4689 BasePointer = Pointer = *CV; 4690 Size = CGF.getTypeSize(RI->getType()); 4691 // Copy to the device as an argument. No need to retrieve it. 4692 MapType = OMP_MAP_BYCOPY; 4693 hasVLACaptures = true; 4694 } else if (CI->capturesThis()) { 4695 BasePointer = Pointer = *CV; 4696 const PointerType *PtrTy = cast<PointerType>(RI->getType().getTypePtr()); 4697 Size = CGF.getTypeSize(PtrTy->getPointeeType()); 4698 // Default map type. 4699 MapType = OMP_MAP_TO | OMP_MAP_FROM; 4700 } else if (CI->capturesVariableByCopy()) { 4701 MapType = OMP_MAP_BYCOPY; 4702 if (!RI->getType()->isAnyPointerType()) { 4703 // If the field is not a pointer, we need to save the actual value and 4704 // load it as a void pointer. 4705 auto DstAddr = CGF.CreateMemTemp( 4706 Ctx.getUIntPtrType(), 4707 Twine(CI->getCapturedVar()->getName()) + ".casted"); 4708 LValue DstLV = CGF.MakeAddrLValue(DstAddr, Ctx.getUIntPtrType()); 4709 4710 auto *SrcAddrVal = CGF.EmitScalarConversion( 4711 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()), 4712 Ctx.getPointerType(RI->getType()), SourceLocation()); 4713 LValue SrcLV = 4714 CGF.MakeNaturalAlignAddrLValue(SrcAddrVal, RI->getType()); 4715 4716 // Store the value using the source type pointer. 4717 CGF.EmitStoreThroughLValue(RValue::get(*CV), SrcLV); 4718 4719 // Load the value using the destination type pointer. 4720 BasePointer = Pointer = 4721 CGF.EmitLoadOfLValue(DstLV, SourceLocation()).getScalarVal(); 4722 } else { 4723 MapType |= OMP_MAP_PTR; 4724 BasePointer = Pointer = *CV; 4725 } 4726 Size = CGF.getTypeSize(RI->getType()); 4727 } else { 4728 assert(CI->capturesVariable() && "Expected captured reference."); 4729 BasePointer = Pointer = *CV; 4730 4731 const ReferenceType *PtrTy = 4732 cast<ReferenceType>(RI->getType().getTypePtr()); 4733 QualType ElementType = PtrTy->getPointeeType(); 4734 Size = CGF.getTypeSize(ElementType); 4735 // The default map type for a scalar/complex type is 'to' because by 4736 // default the value doesn't have to be retrieved. For an aggregate type, 4737 // the default is 'tofrom'. 4738 MapType = ElementType->isAggregateType() ? (OMP_MAP_TO | OMP_MAP_FROM) 4739 : OMP_MAP_TO; 4740 if (ElementType->isAnyPointerType()) 4741 MapType |= OMP_MAP_PTR; 4742 } 4743 4744 BasePointers.push_back(BasePointer); 4745 Pointers.push_back(Pointer); 4746 Sizes.push_back(Size); 4747 MapTypes.push_back(MapType); 4748 } 4749 4750 // Keep track on whether the host function has to be executed. 4751 auto OffloadErrorQType = 4752 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true); 4753 auto OffloadError = CGF.MakeAddrLValue( 4754 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"), 4755 OffloadErrorQType); 4756 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty), 4757 OffloadError); 4758 4759 // Fill up the pointer arrays and transfer execution to the device. 4760 auto &&ThenGen = [&Ctx, &BasePointers, &Pointers, &Sizes, &MapTypes, 4761 hasVLACaptures, Device, OutlinedFnID, OffloadError, 4762 OffloadErrorQType, 4763 &D](CodeGenFunction &CGF, PrePostActionTy &) { 4764 auto &RT = CGF.CGM.getOpenMPRuntime(); 4765 unsigned PointerNumVal = BasePointers.size(); 4766 llvm::Value *PointerNum = CGF.Builder.getInt32(PointerNumVal); 4767 llvm::Value *BasePointersArray; 4768 llvm::Value *PointersArray; 4769 llvm::Value *SizesArray; 4770 llvm::Value *MapTypesArray; 4771 4772 if (PointerNumVal) { 4773 llvm::APInt PointerNumAP(32, PointerNumVal, /*isSigned=*/true); 4774 QualType PointerArrayType = Ctx.getConstantArrayType( 4775 Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal, 4776 /*IndexTypeQuals=*/0); 4777 4778 BasePointersArray = 4779 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 4780 PointersArray = 4781 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 4782 4783 // If we don't have any VLA types, we can use a constant array for the map 4784 // sizes, otherwise we need to fill up the arrays as we do for the 4785 // pointers. 4786 if (hasVLACaptures) { 4787 QualType SizeArrayType = Ctx.getConstantArrayType( 4788 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal, 4789 /*IndexTypeQuals=*/0); 4790 SizesArray = 4791 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 4792 } else { 4793 // We expect all the sizes to be constant, so we collect them to create 4794 // a constant array. 4795 SmallVector<llvm::Constant *, 16> ConstSizes; 4796 for (auto S : Sizes) 4797 ConstSizes.push_back(cast<llvm::Constant>(S)); 4798 4799 auto *SizesArrayInit = llvm::ConstantArray::get( 4800 llvm::ArrayType::get(CGF.CGM.SizeTy, ConstSizes.size()), 4801 ConstSizes); 4802 auto *SizesArrayGbl = new llvm::GlobalVariable( 4803 CGF.CGM.getModule(), SizesArrayInit->getType(), 4804 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 4805 SizesArrayInit, ".offload_sizes"); 4806 SizesArrayGbl->setUnnamedAddr(true); 4807 SizesArray = SizesArrayGbl; 4808 } 4809 4810 // The map types are always constant so we don't need to generate code to 4811 // fill arrays. Instead, we create an array constant. 4812 llvm::Constant *MapTypesArrayInit = 4813 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes); 4814 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 4815 CGF.CGM.getModule(), MapTypesArrayInit->getType(), 4816 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 4817 MapTypesArrayInit, ".offload_maptypes"); 4818 MapTypesArrayGbl->setUnnamedAddr(true); 4819 MapTypesArray = MapTypesArrayGbl; 4820 4821 for (unsigned i = 0; i < PointerNumVal; ++i) { 4822 llvm::Value *BPVal = BasePointers[i]; 4823 if (BPVal->getType()->isPointerTy()) 4824 BPVal = CGF.Builder.CreateBitCast(BPVal, CGF.VoidPtrTy); 4825 else { 4826 assert(BPVal->getType()->isIntegerTy() && 4827 "If not a pointer, the value type must be an integer."); 4828 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGF.VoidPtrTy); 4829 } 4830 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 4831 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), 4832 BasePointersArray, 0, i); 4833 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 4834 CGF.Builder.CreateStore(BPVal, BPAddr); 4835 4836 llvm::Value *PVal = Pointers[i]; 4837 if (PVal->getType()->isPointerTy()) 4838 PVal = CGF.Builder.CreateBitCast(PVal, CGF.VoidPtrTy); 4839 else { 4840 assert(PVal->getType()->isIntegerTy() && 4841 "If not a pointer, the value type must be an integer."); 4842 PVal = CGF.Builder.CreateIntToPtr(PVal, CGF.VoidPtrTy); 4843 } 4844 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 4845 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), PointersArray, 4846 0, i); 4847 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 4848 CGF.Builder.CreateStore(PVal, PAddr); 4849 4850 if (hasVLACaptures) { 4851 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 4852 llvm::ArrayType::get(CGF.SizeTy, PointerNumVal), SizesArray, 4853 /*Idx0=*/0, 4854 /*Idx1=*/i); 4855 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType())); 4856 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast( 4857 Sizes[i], CGF.SizeTy, /*isSigned=*/true), 4858 SAddr); 4859 } 4860 } 4861 4862 BasePointersArray = CGF.Builder.CreateConstInBoundsGEP2_32( 4863 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), BasePointersArray, 4864 /*Idx0=*/0, /*Idx1=*/0); 4865 PointersArray = CGF.Builder.CreateConstInBoundsGEP2_32( 4866 llvm::ArrayType::get(CGF.VoidPtrTy, PointerNumVal), PointersArray, 4867 /*Idx0=*/0, 4868 /*Idx1=*/0); 4869 SizesArray = CGF.Builder.CreateConstInBoundsGEP2_32( 4870 llvm::ArrayType::get(CGF.SizeTy, PointerNumVal), SizesArray, 4871 /*Idx0=*/0, /*Idx1=*/0); 4872 MapTypesArray = CGF.Builder.CreateConstInBoundsGEP2_32( 4873 llvm::ArrayType::get(CGF.Int32Ty, PointerNumVal), MapTypesArray, 4874 /*Idx0=*/0, 4875 /*Idx1=*/0); 4876 4877 } else { 4878 BasePointersArray = llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy); 4879 PointersArray = llvm::ConstantPointerNull::get(CGF.VoidPtrPtrTy); 4880 SizesArray = llvm::ConstantPointerNull::get(CGF.SizeTy->getPointerTo()); 4881 MapTypesArray = 4882 llvm::ConstantPointerNull::get(CGF.Int32Ty->getPointerTo()); 4883 } 4884 4885 // On top of the arrays that were filled up, the target offloading call 4886 // takes as arguments the device id as well as the host pointer. The host 4887 // pointer is used by the runtime library to identify the current target 4888 // region, so it only has to be unique and not necessarily point to 4889 // anything. It could be the pointer to the outlined function that 4890 // implements the target region, but we aren't using that so that the 4891 // compiler doesn't need to keep that, and could therefore inline the host 4892 // function if proven worthwhile during optimization. 4893 4894 // From this point on, we need to have an ID of the target region defined. 4895 assert(OutlinedFnID && "Invalid outlined function ID!"); 4896 4897 // Emit device ID if any. 4898 llvm::Value *DeviceID; 4899 if (Device) 4900 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 4901 CGF.Int32Ty, /*isSigned=*/true); 4902 else 4903 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF); 4904 4905 // Return value of the runtime offloading call. 4906 llvm::Value *Return; 4907 4908 auto *NumTeams = emitNumTeamsClauseForTargetDirective(RT, CGF, D); 4909 auto *ThreadLimit = emitThreadLimitClauseForTargetDirective(RT, CGF, D); 4910 4911 // If we have NumTeams defined this means that we have an enclosed teams 4912 // region. Therefore we also expect to have ThreadLimit defined. These two 4913 // values should be defined in the presence of a teams directive, regardless 4914 // of having any clauses associated. If the user is using teams but no 4915 // clauses, these two values will be the default that should be passed to 4916 // the runtime library - a 32-bit integer with the value zero. 4917 if (NumTeams) { 4918 assert(ThreadLimit && "Thread limit expression should be available along " 4919 "with number of teams."); 4920 llvm::Value *OffloadingArgs[] = { 4921 DeviceID, OutlinedFnID, PointerNum, 4922 BasePointersArray, PointersArray, SizesArray, 4923 MapTypesArray, NumTeams, ThreadLimit}; 4924 Return = CGF.EmitRuntimeCall( 4925 RT.createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs); 4926 } else { 4927 llvm::Value *OffloadingArgs[] = { 4928 DeviceID, OutlinedFnID, PointerNum, BasePointersArray, 4929 PointersArray, SizesArray, MapTypesArray}; 4930 Return = CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target), 4931 OffloadingArgs); 4932 } 4933 4934 CGF.EmitStoreOfScalar(Return, OffloadError); 4935 }; 4936 4937 // Notify that the host version must be executed. 4938 auto &&ElseGen = [OffloadError](CodeGenFunction &CGF, PrePostActionTy &) { 4939 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/-1u), 4940 OffloadError); 4941 }; 4942 4943 // If we have a target function ID it means that we need to support 4944 // offloading, otherwise, just execute on the host. We need to execute on host 4945 // regardless of the conditional in the if clause if, e.g., the user do not 4946 // specify target triples. 4947 if (OutlinedFnID) { 4948 if (IfCond) 4949 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 4950 else { 4951 RegionCodeGenTy ThenRCG(ThenGen); 4952 ThenRCG(CGF); 4953 } 4954 } else { 4955 RegionCodeGenTy ElseRCG(ElseGen); 4956 ElseRCG(CGF); 4957 } 4958 4959 // Check the error code and execute the host version if required. 4960 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed"); 4961 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont"); 4962 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation()); 4963 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal); 4964 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 4965 4966 CGF.EmitBlock(OffloadFailedBlock); 4967 CGF.Builder.CreateCall(OutlinedFn, BasePointers); 4968 CGF.EmitBranch(OffloadContBlock); 4969 4970 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 4971 } 4972 4973 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 4974 StringRef ParentName) { 4975 if (!S) 4976 return; 4977 4978 // If we find a OMP target directive, codegen the outline function and 4979 // register the result. 4980 // FIXME: Add other directives with target when they become supported. 4981 bool isTargetDirective = isa<OMPTargetDirective>(S); 4982 4983 if (isTargetDirective) { 4984 auto *E = cast<OMPExecutableDirective>(S); 4985 unsigned DeviceID; 4986 unsigned FileID; 4987 unsigned Line; 4988 getTargetEntryUniqueInfo(CGM.getContext(), E->getLocStart(), DeviceID, 4989 FileID, Line); 4990 4991 // Is this a target region that should not be emitted as an entry point? If 4992 // so just signal we are done with this target region. 4993 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 4994 ParentName, Line)) 4995 return; 4996 4997 llvm::Function *Fn; 4998 llvm::Constant *Addr; 4999 std::tie(Fn, Addr) = 5000 CodeGenFunction::EmitOMPTargetDirectiveOutlinedFunction( 5001 CGM, cast<OMPTargetDirective>(*E), ParentName, 5002 /*isOffloadEntry=*/true); 5003 assert(Fn && Addr && "Target region emission failed."); 5004 return; 5005 } 5006 5007 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) { 5008 if (!E->getAssociatedStmt()) 5009 return; 5010 5011 scanForTargetRegionsFunctions( 5012 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(), 5013 ParentName); 5014 return; 5015 } 5016 5017 // If this is a lambda function, look into its body. 5018 if (auto *L = dyn_cast<LambdaExpr>(S)) 5019 S = L->getBody(); 5020 5021 // Keep looking for target regions recursively. 5022 for (auto *II : S->children()) 5023 scanForTargetRegionsFunctions(II, ParentName); 5024 } 5025 5026 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 5027 auto &FD = *cast<FunctionDecl>(GD.getDecl()); 5028 5029 // If emitting code for the host, we do not process FD here. Instead we do 5030 // the normal code generation. 5031 if (!CGM.getLangOpts().OpenMPIsDevice) 5032 return false; 5033 5034 // Try to detect target regions in the function. 5035 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD)); 5036 5037 // We should not emit any function othen that the ones created during the 5038 // scanning. Therefore, we signal that this function is completely dealt 5039 // with. 5040 return true; 5041 } 5042 5043 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 5044 if (!CGM.getLangOpts().OpenMPIsDevice) 5045 return false; 5046 5047 // Check if there are Ctors/Dtors in this declaration and look for target 5048 // regions in it. We use the complete variant to produce the kernel name 5049 // mangling. 5050 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 5051 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 5052 for (auto *Ctor : RD->ctors()) { 5053 StringRef ParentName = 5054 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 5055 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 5056 } 5057 auto *Dtor = RD->getDestructor(); 5058 if (Dtor) { 5059 StringRef ParentName = 5060 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 5061 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 5062 } 5063 } 5064 5065 // If we are in target mode we do not emit any global (declare target is not 5066 // implemented yet). Therefore we signal that GD was processed in this case. 5067 return true; 5068 } 5069 5070 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 5071 auto *VD = GD.getDecl(); 5072 if (isa<FunctionDecl>(VD)) 5073 return emitTargetFunctions(GD); 5074 5075 return emitTargetGlobalVariable(GD); 5076 } 5077 5078 llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() { 5079 // If we have offloading in the current module, we need to emit the entries 5080 // now and register the offloading descriptor. 5081 createOffloadEntriesAndInfoMetadata(); 5082 5083 // Create and register the offloading binary descriptors. This is the main 5084 // entity that captures all the information about offloading in the current 5085 // compilation unit. 5086 return createOffloadingBinaryDescriptorRegistration(); 5087 } 5088 5089 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 5090 const OMPExecutableDirective &D, 5091 SourceLocation Loc, 5092 llvm::Value *OutlinedFn, 5093 ArrayRef<llvm::Value *> CapturedVars) { 5094 if (!CGF.HaveInsertPoint()) 5095 return; 5096 5097 auto *RTLoc = emitUpdateLocation(CGF, Loc); 5098 CodeGenFunction::RunCleanupsScope Scope(CGF); 5099 5100 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 5101 llvm::Value *Args[] = { 5102 RTLoc, 5103 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 5104 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 5105 llvm::SmallVector<llvm::Value *, 16> RealArgs; 5106 RealArgs.append(std::begin(Args), std::end(Args)); 5107 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 5108 5109 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 5110 CGF.EmitRuntimeCall(RTLFn, RealArgs); 5111 } 5112 5113 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 5114 const Expr *NumTeams, 5115 const Expr *ThreadLimit, 5116 SourceLocation Loc) { 5117 if (!CGF.HaveInsertPoint()) 5118 return; 5119 5120 auto *RTLoc = emitUpdateLocation(CGF, Loc); 5121 5122 llvm::Value *NumTeamsVal = 5123 (NumTeams) 5124 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 5125 CGF.CGM.Int32Ty, /* isSigned = */ true) 5126 : CGF.Builder.getInt32(0); 5127 5128 llvm::Value *ThreadLimitVal = 5129 (ThreadLimit) 5130 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 5131 CGF.CGM.Int32Ty, /* isSigned = */ true) 5132 : CGF.Builder.getInt32(0); 5133 5134 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 5135 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 5136 ThreadLimitVal}; 5137 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 5138 PushNumTeamsArgs); 5139 } 5140