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