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 "ConstantBuilder.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/StmtOpenMP.h" 21 #include "llvm/ADT/ArrayRef.h" 22 #include "llvm/Bitcode/BitcodeReader.h" 23 #include "llvm/IR/CallSite.h" 24 #include "llvm/IR/DerivedTypes.h" 25 #include "llvm/IR/GlobalValue.h" 26 #include "llvm/IR/Value.h" 27 #include "llvm/Support/Format.h" 28 #include "llvm/Support/raw_ostream.h" 29 #include <cassert> 30 31 using namespace clang; 32 using namespace CodeGen; 33 34 namespace { 35 /// \brief Base class for handling code generation inside OpenMP regions. 36 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 37 public: 38 /// \brief Kinds of OpenMP regions used in codegen. 39 enum CGOpenMPRegionKind { 40 /// \brief Region with outlined function for standalone 'parallel' 41 /// directive. 42 ParallelOutlinedRegion, 43 /// \brief Region with outlined function for standalone 'task' directive. 44 TaskOutlinedRegion, 45 /// \brief Region for constructs that do not require function outlining, 46 /// like 'for', 'sections', 'atomic' etc. directives. 47 InlinedRegion, 48 /// \brief Region with outlined function for standalone 'target' directive. 49 TargetRegion, 50 }; 51 52 CGOpenMPRegionInfo(const CapturedStmt &CS, 53 const CGOpenMPRegionKind RegionKind, 54 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 55 bool HasCancel) 56 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 57 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 58 59 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 60 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 61 bool HasCancel) 62 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 63 Kind(Kind), HasCancel(HasCancel) {} 64 65 /// \brief Get a variable or parameter for storing global thread id 66 /// inside OpenMP construct. 67 virtual const VarDecl *getThreadIDVariable() const = 0; 68 69 /// \brief Emit the captured statement body. 70 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 71 72 /// \brief Get an LValue for the current ThreadID variable. 73 /// \return LValue for thread id variable. This LValue always has type int32*. 74 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 75 76 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 77 78 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 79 80 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 81 82 bool hasCancel() const { return HasCancel; } 83 84 static bool classof(const CGCapturedStmtInfo *Info) { 85 return Info->getKind() == CR_OpenMP; 86 } 87 88 ~CGOpenMPRegionInfo() override = default; 89 90 protected: 91 CGOpenMPRegionKind RegionKind; 92 RegionCodeGenTy CodeGen; 93 OpenMPDirectiveKind Kind; 94 bool HasCancel; 95 }; 96 97 /// \brief API for captured statement code generation in OpenMP constructs. 98 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 99 public: 100 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 101 const RegionCodeGenTy &CodeGen, 102 OpenMPDirectiveKind Kind, bool HasCancel, 103 StringRef HelperName) 104 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 105 HasCancel), 106 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 107 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 108 } 109 110 /// \brief Get a variable or parameter for storing global thread id 111 /// inside OpenMP construct. 112 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 113 114 /// \brief Get the name of the capture helper. 115 StringRef getHelperName() const override { return HelperName; } 116 117 static bool classof(const CGCapturedStmtInfo *Info) { 118 return CGOpenMPRegionInfo::classof(Info) && 119 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 120 ParallelOutlinedRegion; 121 } 122 123 private: 124 /// \brief A variable or parameter storing global thread id for OpenMP 125 /// constructs. 126 const VarDecl *ThreadIDVar; 127 StringRef HelperName; 128 }; 129 130 /// \brief API for captured statement code generation in OpenMP constructs. 131 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 132 public: 133 class UntiedTaskActionTy final : public PrePostActionTy { 134 bool Untied; 135 const VarDecl *PartIDVar; 136 const RegionCodeGenTy UntiedCodeGen; 137 llvm::SwitchInst *UntiedSwitch = nullptr; 138 139 public: 140 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 141 const RegionCodeGenTy &UntiedCodeGen) 142 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 143 void Enter(CodeGenFunction &CGF) override { 144 if (Untied) { 145 // Emit task switching point. 146 auto PartIdLVal = CGF.EmitLoadOfPointerLValue( 147 CGF.GetAddrOfLocalVar(PartIDVar), 148 PartIDVar->getType()->castAs<PointerType>()); 149 auto *Res = CGF.EmitLoadOfScalar(PartIdLVal, SourceLocation()); 150 auto *DoneBB = CGF.createBasicBlock(".untied.done."); 151 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 152 CGF.EmitBlock(DoneBB); 153 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 154 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 155 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 156 CGF.Builder.GetInsertBlock()); 157 emitUntiedSwitch(CGF); 158 } 159 } 160 void emitUntiedSwitch(CodeGenFunction &CGF) const { 161 if (Untied) { 162 auto PartIdLVal = CGF.EmitLoadOfPointerLValue( 163 CGF.GetAddrOfLocalVar(PartIDVar), 164 PartIDVar->getType()->castAs<PointerType>()); 165 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 166 PartIdLVal); 167 UntiedCodeGen(CGF); 168 CodeGenFunction::JumpDest CurPoint = 169 CGF.getJumpDestInCurrentScope(".untied.next."); 170 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 171 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 172 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 173 CGF.Builder.GetInsertBlock()); 174 CGF.EmitBranchThroughCleanup(CurPoint); 175 CGF.EmitBlock(CurPoint.getBlock()); 176 } 177 } 178 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 179 }; 180 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 181 const VarDecl *ThreadIDVar, 182 const RegionCodeGenTy &CodeGen, 183 OpenMPDirectiveKind Kind, bool HasCancel, 184 const UntiedTaskActionTy &Action) 185 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 186 ThreadIDVar(ThreadIDVar), Action(Action) { 187 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 188 } 189 190 /// \brief Get a variable or parameter for storing global thread id 191 /// inside OpenMP construct. 192 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 193 194 /// \brief Get an LValue for the current ThreadID variable. 195 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 196 197 /// \brief Get the name of the capture helper. 198 StringRef getHelperName() const override { return ".omp_outlined."; } 199 200 void emitUntiedSwitch(CodeGenFunction &CGF) override { 201 Action.emitUntiedSwitch(CGF); 202 } 203 204 static bool classof(const CGCapturedStmtInfo *Info) { 205 return CGOpenMPRegionInfo::classof(Info) && 206 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 207 TaskOutlinedRegion; 208 } 209 210 private: 211 /// \brief A variable or parameter storing global thread id for OpenMP 212 /// constructs. 213 const VarDecl *ThreadIDVar; 214 /// Action for emitting code for untied tasks. 215 const UntiedTaskActionTy &Action; 216 }; 217 218 /// \brief API for inlined captured statement code generation in OpenMP 219 /// constructs. 220 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 221 public: 222 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 223 const RegionCodeGenTy &CodeGen, 224 OpenMPDirectiveKind Kind, bool HasCancel) 225 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 226 OldCSI(OldCSI), 227 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 228 229 // \brief Retrieve the value of the context parameter. 230 llvm::Value *getContextValue() const override { 231 if (OuterRegionInfo) 232 return OuterRegionInfo->getContextValue(); 233 llvm_unreachable("No context value for inlined OpenMP region"); 234 } 235 236 void setContextValue(llvm::Value *V) override { 237 if (OuterRegionInfo) { 238 OuterRegionInfo->setContextValue(V); 239 return; 240 } 241 llvm_unreachable("No context value for inlined OpenMP region"); 242 } 243 244 /// \brief Lookup the captured field decl for a variable. 245 const FieldDecl *lookup(const VarDecl *VD) const override { 246 if (OuterRegionInfo) 247 return OuterRegionInfo->lookup(VD); 248 // If there is no outer outlined region,no need to lookup in a list of 249 // captured variables, we can use the original one. 250 return nullptr; 251 } 252 253 FieldDecl *getThisFieldDecl() const override { 254 if (OuterRegionInfo) 255 return OuterRegionInfo->getThisFieldDecl(); 256 return nullptr; 257 } 258 259 /// \brief Get a variable or parameter for storing global thread id 260 /// inside OpenMP construct. 261 const VarDecl *getThreadIDVariable() const override { 262 if (OuterRegionInfo) 263 return OuterRegionInfo->getThreadIDVariable(); 264 return nullptr; 265 } 266 267 /// \brief Get the name of the capture helper. 268 StringRef getHelperName() const override { 269 if (auto *OuterRegionInfo = getOldCSI()) 270 return OuterRegionInfo->getHelperName(); 271 llvm_unreachable("No helper name for inlined OpenMP construct"); 272 } 273 274 void emitUntiedSwitch(CodeGenFunction &CGF) override { 275 if (OuterRegionInfo) 276 OuterRegionInfo->emitUntiedSwitch(CGF); 277 } 278 279 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 280 281 static bool classof(const CGCapturedStmtInfo *Info) { 282 return CGOpenMPRegionInfo::classof(Info) && 283 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 284 } 285 286 ~CGOpenMPInlinedRegionInfo() override = default; 287 288 private: 289 /// \brief CodeGen info about outer OpenMP region. 290 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 291 CGOpenMPRegionInfo *OuterRegionInfo; 292 }; 293 294 /// \brief API for captured statement code generation in OpenMP target 295 /// constructs. For this captures, implicit parameters are used instead of the 296 /// captured fields. The name of the target region has to be unique in a given 297 /// application so it is provided by the client, because only the client has 298 /// the information to generate that. 299 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 300 public: 301 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 302 const RegionCodeGenTy &CodeGen, StringRef HelperName) 303 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 304 /*HasCancel=*/false), 305 HelperName(HelperName) {} 306 307 /// \brief This is unused for target regions because each starts executing 308 /// with a single thread. 309 const VarDecl *getThreadIDVariable() const override { return nullptr; } 310 311 /// \brief Get the name of the capture helper. 312 StringRef getHelperName() const override { return HelperName; } 313 314 static bool classof(const CGCapturedStmtInfo *Info) { 315 return CGOpenMPRegionInfo::classof(Info) && 316 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 317 } 318 319 private: 320 StringRef HelperName; 321 }; 322 323 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 324 llvm_unreachable("No codegen for expressions"); 325 } 326 /// \brief API for generation of expressions captured in a innermost OpenMP 327 /// region. 328 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 329 public: 330 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 331 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 332 OMPD_unknown, 333 /*HasCancel=*/false), 334 PrivScope(CGF) { 335 // Make sure the globals captured in the provided statement are local by 336 // using the privatization logic. We assume the same variable is not 337 // captured more than once. 338 for (auto &C : CS.captures()) { 339 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 340 continue; 341 342 const VarDecl *VD = C.getCapturedVar(); 343 if (VD->isLocalVarDeclOrParm()) 344 continue; 345 346 DeclRefExpr DRE(const_cast<VarDecl *>(VD), 347 /*RefersToEnclosingVariableOrCapture=*/false, 348 VD->getType().getNonReferenceType(), VK_LValue, 349 SourceLocation()); 350 PrivScope.addPrivate(VD, [&CGF, &DRE]() -> Address { 351 return CGF.EmitLValue(&DRE).getAddress(); 352 }); 353 } 354 (void)PrivScope.Privatize(); 355 } 356 357 /// \brief Lookup the captured field decl for a variable. 358 const FieldDecl *lookup(const VarDecl *VD) const override { 359 if (auto *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 360 return FD; 361 return nullptr; 362 } 363 364 /// \brief Emit the captured statement body. 365 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 366 llvm_unreachable("No body for expressions"); 367 } 368 369 /// \brief Get a variable or parameter for storing global thread id 370 /// inside OpenMP construct. 371 const VarDecl *getThreadIDVariable() const override { 372 llvm_unreachable("No thread id for expressions"); 373 } 374 375 /// \brief Get the name of the capture helper. 376 StringRef getHelperName() const override { 377 llvm_unreachable("No helper name for expressions"); 378 } 379 380 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 381 382 private: 383 /// Private scope to capture global variables. 384 CodeGenFunction::OMPPrivateScope PrivScope; 385 }; 386 387 /// \brief RAII for emitting code of OpenMP constructs. 388 class InlinedOpenMPRegionRAII { 389 CodeGenFunction &CGF; 390 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 391 FieldDecl *LambdaThisCaptureField = nullptr; 392 393 public: 394 /// \brief Constructs region for combined constructs. 395 /// \param CodeGen Code generation sequence for combined directives. Includes 396 /// a list of functions used for code generation of implicitly inlined 397 /// regions. 398 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 399 OpenMPDirectiveKind Kind, bool HasCancel) 400 : CGF(CGF) { 401 // Start emission for the construct. 402 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 403 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 404 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 405 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 406 CGF.LambdaThisCaptureField = nullptr; 407 } 408 409 ~InlinedOpenMPRegionRAII() { 410 // Restore original CapturedStmtInfo only if we're done with code emission. 411 auto *OldCSI = 412 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 413 delete CGF.CapturedStmtInfo; 414 CGF.CapturedStmtInfo = OldCSI; 415 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 416 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 417 } 418 }; 419 420 /// \brief Values for bit flags used in the ident_t to describe the fields. 421 /// All enumeric elements are named and described in accordance with the code 422 /// from http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h 423 enum OpenMPLocationFlags { 424 /// \brief Use trampoline for internal microtask. 425 OMP_IDENT_IMD = 0x01, 426 /// \brief Use c-style ident structure. 427 OMP_IDENT_KMPC = 0x02, 428 /// \brief Atomic reduction option for kmpc_reduce. 429 OMP_ATOMIC_REDUCE = 0x10, 430 /// \brief Explicit 'barrier' directive. 431 OMP_IDENT_BARRIER_EXPL = 0x20, 432 /// \brief Implicit barrier in code. 433 OMP_IDENT_BARRIER_IMPL = 0x40, 434 /// \brief Implicit barrier in 'for' directive. 435 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 436 /// \brief Implicit barrier in 'sections' directive. 437 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 438 /// \brief Implicit barrier in 'single' directive. 439 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140 440 }; 441 442 /// \brief Describes ident structure that describes a source location. 443 /// All descriptions are taken from 444 /// http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h 445 /// Original structure: 446 /// typedef struct ident { 447 /// kmp_int32 reserved_1; /**< might be used in Fortran; 448 /// see above */ 449 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 450 /// KMP_IDENT_KMPC identifies this union 451 /// member */ 452 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 453 /// see above */ 454 ///#if USE_ITT_BUILD 455 /// /* but currently used for storing 456 /// region-specific ITT */ 457 /// /* contextual information. */ 458 ///#endif /* USE_ITT_BUILD */ 459 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 460 /// C++ */ 461 /// char const *psource; /**< String describing the source location. 462 /// The string is composed of semi-colon separated 463 // fields which describe the source file, 464 /// the function and a pair of line numbers that 465 /// delimit the construct. 466 /// */ 467 /// } ident_t; 468 enum IdentFieldIndex { 469 /// \brief might be used in Fortran 470 IdentField_Reserved_1, 471 /// \brief OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 472 IdentField_Flags, 473 /// \brief Not really used in Fortran any more 474 IdentField_Reserved_2, 475 /// \brief Source[4] in Fortran, do not use for C++ 476 IdentField_Reserved_3, 477 /// \brief String describing the source location. The string is composed of 478 /// semi-colon separated fields which describe the source file, the function 479 /// and a pair of line numbers that delimit the construct. 480 IdentField_PSource 481 }; 482 483 /// \brief Schedule types for 'omp for' loops (these enumerators are taken from 484 /// the enum sched_type in kmp.h). 485 enum OpenMPSchedType { 486 /// \brief Lower bound for default (unordered) versions. 487 OMP_sch_lower = 32, 488 OMP_sch_static_chunked = 33, 489 OMP_sch_static = 34, 490 OMP_sch_dynamic_chunked = 35, 491 OMP_sch_guided_chunked = 36, 492 OMP_sch_runtime = 37, 493 OMP_sch_auto = 38, 494 /// static with chunk adjustment (e.g., simd) 495 OMP_sch_static_balanced_chunked = 45, 496 /// \brief Lower bound for 'ordered' versions. 497 OMP_ord_lower = 64, 498 OMP_ord_static_chunked = 65, 499 OMP_ord_static = 66, 500 OMP_ord_dynamic_chunked = 67, 501 OMP_ord_guided_chunked = 68, 502 OMP_ord_runtime = 69, 503 OMP_ord_auto = 70, 504 OMP_sch_default = OMP_sch_static, 505 /// \brief dist_schedule types 506 OMP_dist_sch_static_chunked = 91, 507 OMP_dist_sch_static = 92, 508 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 509 /// Set if the monotonic schedule modifier was present. 510 OMP_sch_modifier_monotonic = (1 << 29), 511 /// Set if the nonmonotonic schedule modifier was present. 512 OMP_sch_modifier_nonmonotonic = (1 << 30), 513 }; 514 515 enum OpenMPRTLFunction { 516 /// \brief Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 517 /// kmpc_micro microtask, ...); 518 OMPRTL__kmpc_fork_call, 519 /// \brief Call to void *__kmpc_threadprivate_cached(ident_t *loc, 520 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 521 OMPRTL__kmpc_threadprivate_cached, 522 /// \brief Call to void __kmpc_threadprivate_register( ident_t *, 523 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 524 OMPRTL__kmpc_threadprivate_register, 525 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 526 OMPRTL__kmpc_global_thread_num, 527 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 528 // kmp_critical_name *crit); 529 OMPRTL__kmpc_critical, 530 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 531 // global_tid, kmp_critical_name *crit, uintptr_t hint); 532 OMPRTL__kmpc_critical_with_hint, 533 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 534 // kmp_critical_name *crit); 535 OMPRTL__kmpc_end_critical, 536 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 537 // global_tid); 538 OMPRTL__kmpc_cancel_barrier, 539 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 540 OMPRTL__kmpc_barrier, 541 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 542 OMPRTL__kmpc_for_static_fini, 543 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 544 // global_tid); 545 OMPRTL__kmpc_serialized_parallel, 546 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 547 // global_tid); 548 OMPRTL__kmpc_end_serialized_parallel, 549 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 550 // kmp_int32 num_threads); 551 OMPRTL__kmpc_push_num_threads, 552 // Call to void __kmpc_flush(ident_t *loc); 553 OMPRTL__kmpc_flush, 554 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 555 OMPRTL__kmpc_master, 556 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 557 OMPRTL__kmpc_end_master, 558 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 559 // int end_part); 560 OMPRTL__kmpc_omp_taskyield, 561 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 562 OMPRTL__kmpc_single, 563 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 564 OMPRTL__kmpc_end_single, 565 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 566 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 567 // kmp_routine_entry_t *task_entry); 568 OMPRTL__kmpc_omp_task_alloc, 569 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 570 // new_task); 571 OMPRTL__kmpc_omp_task, 572 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 573 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 574 // kmp_int32 didit); 575 OMPRTL__kmpc_copyprivate, 576 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 577 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 578 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 579 OMPRTL__kmpc_reduce, 580 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 581 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 582 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 583 // *lck); 584 OMPRTL__kmpc_reduce_nowait, 585 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 586 // kmp_critical_name *lck); 587 OMPRTL__kmpc_end_reduce, 588 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 589 // kmp_critical_name *lck); 590 OMPRTL__kmpc_end_reduce_nowait, 591 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 592 // kmp_task_t * new_task); 593 OMPRTL__kmpc_omp_task_begin_if0, 594 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 595 // kmp_task_t * new_task); 596 OMPRTL__kmpc_omp_task_complete_if0, 597 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 598 OMPRTL__kmpc_ordered, 599 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 600 OMPRTL__kmpc_end_ordered, 601 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 602 // global_tid); 603 OMPRTL__kmpc_omp_taskwait, 604 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 605 OMPRTL__kmpc_taskgroup, 606 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 607 OMPRTL__kmpc_end_taskgroup, 608 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 609 // int proc_bind); 610 OMPRTL__kmpc_push_proc_bind, 611 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 612 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 613 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 614 OMPRTL__kmpc_omp_task_with_deps, 615 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 616 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 617 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 618 OMPRTL__kmpc_omp_wait_deps, 619 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 620 // global_tid, kmp_int32 cncl_kind); 621 OMPRTL__kmpc_cancellationpoint, 622 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 623 // kmp_int32 cncl_kind); 624 OMPRTL__kmpc_cancel, 625 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 626 // kmp_int32 num_teams, kmp_int32 thread_limit); 627 OMPRTL__kmpc_push_num_teams, 628 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 629 // microtask, ...); 630 OMPRTL__kmpc_fork_teams, 631 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 632 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 633 // sched, kmp_uint64 grainsize, void *task_dup); 634 OMPRTL__kmpc_taskloop, 635 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 636 // num_dims, struct kmp_dim *dims); 637 OMPRTL__kmpc_doacross_init, 638 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 639 OMPRTL__kmpc_doacross_fini, 640 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 641 // *vec); 642 OMPRTL__kmpc_doacross_post, 643 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 644 // *vec); 645 OMPRTL__kmpc_doacross_wait, 646 647 // 648 // Offloading related calls 649 // 650 // Call to int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t 651 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t 652 // *arg_types); 653 OMPRTL__tgt_target, 654 // Call to int32_t __tgt_target_teams(int32_t device_id, void *host_ptr, 655 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, 656 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit); 657 OMPRTL__tgt_target_teams, 658 // Call to void __tgt_register_lib(__tgt_bin_desc *desc); 659 OMPRTL__tgt_register_lib, 660 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); 661 OMPRTL__tgt_unregister_lib, 662 // Call to void __tgt_target_data_begin(int32_t device_id, int32_t arg_num, 663 // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types); 664 OMPRTL__tgt_target_data_begin, 665 // Call to void __tgt_target_data_end(int32_t device_id, int32_t arg_num, 666 // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types); 667 OMPRTL__tgt_target_data_end, 668 // Call to void __tgt_target_data_update(int32_t device_id, int32_t arg_num, 669 // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types); 670 OMPRTL__tgt_target_data_update, 671 }; 672 673 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 674 /// region. 675 class CleanupTy final : public EHScopeStack::Cleanup { 676 PrePostActionTy *Action; 677 678 public: 679 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 680 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 681 if (!CGF.HaveInsertPoint()) 682 return; 683 Action->Exit(CGF); 684 } 685 }; 686 687 } // anonymous namespace 688 689 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 690 CodeGenFunction::RunCleanupsScope Scope(CGF); 691 if (PrePostAction) { 692 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 693 Callback(CodeGen, CGF, *PrePostAction); 694 } else { 695 PrePostActionTy Action; 696 Callback(CodeGen, CGF, Action); 697 } 698 } 699 700 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 701 return CGF.EmitLoadOfPointerLValue( 702 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 703 getThreadIDVariable()->getType()->castAs<PointerType>()); 704 } 705 706 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 707 if (!CGF.HaveInsertPoint()) 708 return; 709 // 1.2.2 OpenMP Language Terminology 710 // Structured block - An executable statement with a single entry at the 711 // top and a single exit at the bottom. 712 // The point of exit cannot be a branch out of the structured block. 713 // longjmp() and throw() must not violate the entry/exit criteria. 714 CGF.EHStack.pushTerminate(); 715 CodeGen(CGF); 716 CGF.EHStack.popTerminate(); 717 } 718 719 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 720 CodeGenFunction &CGF) { 721 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 722 getThreadIDVariable()->getType(), 723 AlignmentSource::Decl); 724 } 725 726 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) 727 : CGM(CGM), OffloadEntriesInfoManager(CGM) { 728 IdentTy = llvm::StructType::create( 729 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */, 730 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */, 731 CGM.Int8PtrTy /* psource */, nullptr); 732 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 733 734 loadOffloadInfoMetadata(); 735 } 736 737 void CGOpenMPRuntime::clear() { 738 InternalVars.clear(); 739 } 740 741 static llvm::Function * 742 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 743 const Expr *CombinerInitializer, const VarDecl *In, 744 const VarDecl *Out, bool IsCombiner) { 745 // void .omp_combiner.(Ty *in, Ty *out); 746 auto &C = CGM.getContext(); 747 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 748 FunctionArgList Args; 749 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 750 /*Id=*/nullptr, PtrTy); 751 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 752 /*Id=*/nullptr, PtrTy); 753 Args.push_back(&OmpOutParm); 754 Args.push_back(&OmpInParm); 755 auto &FnInfo = 756 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 757 auto *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 758 auto *Fn = llvm::Function::Create( 759 FnTy, llvm::GlobalValue::InternalLinkage, 760 IsCombiner ? ".omp_combiner." : ".omp_initializer.", &CGM.getModule()); 761 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, FnInfo); 762 Fn->removeFnAttr(llvm::Attribute::NoInline); 763 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 764 CodeGenFunction CGF(CGM); 765 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 766 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 767 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args); 768 CodeGenFunction::OMPPrivateScope Scope(CGF); 769 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 770 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() -> Address { 771 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 772 .getAddress(); 773 }); 774 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 775 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() -> Address { 776 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 777 .getAddress(); 778 }); 779 (void)Scope.Privatize(); 780 CGF.EmitIgnoredExpr(CombinerInitializer); 781 Scope.ForceCleanup(); 782 CGF.FinishFunction(); 783 return Fn; 784 } 785 786 void CGOpenMPRuntime::emitUserDefinedReduction( 787 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 788 if (UDRMap.count(D) > 0) 789 return; 790 auto &C = CGM.getContext(); 791 if (!In || !Out) { 792 In = &C.Idents.get("omp_in"); 793 Out = &C.Idents.get("omp_out"); 794 } 795 llvm::Function *Combiner = emitCombinerOrInitializer( 796 CGM, D->getType(), D->getCombiner(), cast<VarDecl>(D->lookup(In).front()), 797 cast<VarDecl>(D->lookup(Out).front()), 798 /*IsCombiner=*/true); 799 llvm::Function *Initializer = nullptr; 800 if (auto *Init = D->getInitializer()) { 801 if (!Priv || !Orig) { 802 Priv = &C.Idents.get("omp_priv"); 803 Orig = &C.Idents.get("omp_orig"); 804 } 805 Initializer = emitCombinerOrInitializer( 806 CGM, D->getType(), Init, cast<VarDecl>(D->lookup(Orig).front()), 807 cast<VarDecl>(D->lookup(Priv).front()), 808 /*IsCombiner=*/false); 809 } 810 UDRMap.insert(std::make_pair(D, std::make_pair(Combiner, Initializer))); 811 if (CGF) { 812 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 813 Decls.second.push_back(D); 814 } 815 } 816 817 std::pair<llvm::Function *, llvm::Function *> 818 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 819 auto I = UDRMap.find(D); 820 if (I != UDRMap.end()) 821 return I->second; 822 emitUserDefinedReduction(/*CGF=*/nullptr, D); 823 return UDRMap.lookup(D); 824 } 825 826 // Layout information for ident_t. 827 static CharUnits getIdentAlign(CodeGenModule &CGM) { 828 return CGM.getPointerAlign(); 829 } 830 static CharUnits getIdentSize(CodeGenModule &CGM) { 831 assert((4 * CGM.getPointerSize()).isMultipleOf(CGM.getPointerAlign())); 832 return CharUnits::fromQuantity(16) + CGM.getPointerSize(); 833 } 834 static CharUnits getOffsetOfIdentField(IdentFieldIndex Field) { 835 // All the fields except the last are i32, so this works beautifully. 836 return unsigned(Field) * CharUnits::fromQuantity(4); 837 } 838 static Address createIdentFieldGEP(CodeGenFunction &CGF, Address Addr, 839 IdentFieldIndex Field, 840 const llvm::Twine &Name = "") { 841 auto Offset = getOffsetOfIdentField(Field); 842 return CGF.Builder.CreateStructGEP(Addr, Field, Offset, Name); 843 } 844 845 static llvm::Value *emitParallelOrTeamsOutlinedFunction( 846 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 847 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 848 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 849 assert(ThreadIDVar->getType()->isPointerType() && 850 "thread id variable must be of type kmp_int32 *"); 851 CodeGenFunction CGF(CGM, true); 852 bool HasCancel = false; 853 if (auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 854 HasCancel = OPD->hasCancel(); 855 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 856 HasCancel = OPSD->hasCancel(); 857 else if (auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 858 HasCancel = OPFD->hasCancel(); 859 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 860 HasCancel, OutlinedHelperName); 861 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 862 return CGF.GenerateOpenMPCapturedStmtFunction(*CS); 863 } 864 865 llvm::Value *CGOpenMPRuntime::emitParallelOutlinedFunction( 866 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 867 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 868 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 869 return emitParallelOrTeamsOutlinedFunction( 870 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 871 } 872 873 llvm::Value *CGOpenMPRuntime::emitTeamsOutlinedFunction( 874 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 875 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 876 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 877 return emitParallelOrTeamsOutlinedFunction( 878 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 879 } 880 881 llvm::Value *CGOpenMPRuntime::emitTaskOutlinedFunction( 882 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 883 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 884 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 885 bool Tied, unsigned &NumberOfParts) { 886 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 887 PrePostActionTy &) { 888 auto *ThreadID = getThreadID(CGF, D.getLocStart()); 889 auto *UpLoc = emitUpdateLocation(CGF, D.getLocStart()); 890 llvm::Value *TaskArgs[] = { 891 UpLoc, ThreadID, 892 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 893 TaskTVar->getType()->castAs<PointerType>()) 894 .getPointer()}; 895 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 896 }; 897 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 898 UntiedCodeGen); 899 CodeGen.setAction(Action); 900 assert(!ThreadIDVar->getType()->isPointerType() && 901 "thread id variable must be of type kmp_int32 for tasks"); 902 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt()); 903 auto *TD = dyn_cast<OMPTaskDirective>(&D); 904 CodeGenFunction CGF(CGM, true); 905 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 906 InnermostKind, 907 TD ? TD->hasCancel() : false, Action); 908 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 909 auto *Res = CGF.GenerateCapturedStmtFunction(*CS); 910 if (!Tied) 911 NumberOfParts = Action.getNumberOfParts(); 912 return Res; 913 } 914 915 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 916 CharUnits Align = getIdentAlign(CGM); 917 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags); 918 if (!Entry) { 919 if (!DefaultOpenMPPSource) { 920 // Initialize default location for psource field of ident_t structure of 921 // all ident_t objects. Format is ";file;function;line;column;;". 922 // Taken from 923 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c 924 DefaultOpenMPPSource = 925 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 926 DefaultOpenMPPSource = 927 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 928 } 929 930 ConstantInitBuilder builder(CGM); 931 auto fields = builder.beginStruct(IdentTy); 932 fields.addInt(CGM.Int32Ty, 0); 933 fields.addInt(CGM.Int32Ty, Flags); 934 fields.addInt(CGM.Int32Ty, 0); 935 fields.addInt(CGM.Int32Ty, 0); 936 fields.add(DefaultOpenMPPSource); 937 auto DefaultOpenMPLocation = 938 fields.finishAndCreateGlobal("", Align, /*isConstant*/ true, 939 llvm::GlobalValue::PrivateLinkage); 940 DefaultOpenMPLocation->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 941 942 OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation; 943 } 944 return Address(Entry, Align); 945 } 946 947 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 948 SourceLocation Loc, 949 unsigned Flags) { 950 Flags |= OMP_IDENT_KMPC; 951 // If no debug info is generated - return global default location. 952 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 953 Loc.isInvalid()) 954 return getOrCreateDefaultLocation(Flags).getPointer(); 955 956 assert(CGF.CurFn && "No function in current CodeGenFunction."); 957 958 Address LocValue = Address::invalid(); 959 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 960 if (I != OpenMPLocThreadIDMap.end()) 961 LocValue = Address(I->second.DebugLoc, getIdentAlign(CGF.CGM)); 962 963 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 964 // GetOpenMPThreadID was called before this routine. 965 if (!LocValue.isValid()) { 966 // Generate "ident_t .kmpc_loc.addr;" 967 Address AI = CGF.CreateTempAlloca(IdentTy, getIdentAlign(CGF.CGM), 968 ".kmpc_loc.addr"); 969 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 970 Elem.second.DebugLoc = AI.getPointer(); 971 LocValue = AI; 972 973 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 974 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 975 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 976 CGM.getSize(getIdentSize(CGF.CGM))); 977 } 978 979 // char **psource = &.kmpc_loc_<flags>.addr.psource; 980 Address PSource = createIdentFieldGEP(CGF, LocValue, IdentField_PSource); 981 982 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 983 if (OMPDebugLoc == nullptr) { 984 SmallString<128> Buffer2; 985 llvm::raw_svector_ostream OS2(Buffer2); 986 // Build debug location 987 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 988 OS2 << ";" << PLoc.getFilename() << ";"; 989 if (const FunctionDecl *FD = 990 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) { 991 OS2 << FD->getQualifiedNameAsString(); 992 } 993 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 994 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 995 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 996 } 997 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 998 CGF.Builder.CreateStore(OMPDebugLoc, PSource); 999 1000 // Our callers always pass this to a runtime function, so for 1001 // convenience, go ahead and return a naked pointer. 1002 return LocValue.getPointer(); 1003 } 1004 1005 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1006 SourceLocation Loc) { 1007 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1008 1009 llvm::Value *ThreadID = nullptr; 1010 // Check whether we've already cached a load of the thread id in this 1011 // function. 1012 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1013 if (I != OpenMPLocThreadIDMap.end()) { 1014 ThreadID = I->second.ThreadID; 1015 if (ThreadID != nullptr) 1016 return ThreadID; 1017 } 1018 if (auto *OMPRegionInfo = 1019 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1020 if (OMPRegionInfo->getThreadIDVariable()) { 1021 // Check if this an outlined function with thread id passed as argument. 1022 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1023 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal(); 1024 // If value loaded in entry block, cache it and use it everywhere in 1025 // function. 1026 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 1027 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1028 Elem.second.ThreadID = ThreadID; 1029 } 1030 return ThreadID; 1031 } 1032 } 1033 1034 // This is not an outlined function region - need to call __kmpc_int32 1035 // kmpc_global_thread_num(ident_t *loc). 1036 // Generate thread id value and cache this value for use across the 1037 // function. 1038 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1039 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 1040 ThreadID = 1041 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1042 emitUpdateLocation(CGF, Loc)); 1043 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1044 Elem.second.ThreadID = ThreadID; 1045 return ThreadID; 1046 } 1047 1048 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1049 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1050 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) 1051 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1052 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1053 for(auto *D : FunctionUDRMap[CGF.CurFn]) { 1054 UDRMap.erase(D); 1055 } 1056 FunctionUDRMap.erase(CGF.CurFn); 1057 } 1058 } 1059 1060 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1061 if (!IdentTy) { 1062 } 1063 return llvm::PointerType::getUnqual(IdentTy); 1064 } 1065 1066 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1067 if (!Kmpc_MicroTy) { 1068 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1069 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1070 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1071 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1072 } 1073 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1074 } 1075 1076 llvm::Constant * 1077 CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1078 llvm::Constant *RTLFn = nullptr; 1079 switch (static_cast<OpenMPRTLFunction>(Function)) { 1080 case OMPRTL__kmpc_fork_call: { 1081 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1082 // microtask, ...); 1083 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1084 getKmpc_MicroPointerTy()}; 1085 llvm::FunctionType *FnTy = 1086 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1087 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1088 break; 1089 } 1090 case OMPRTL__kmpc_global_thread_num: { 1091 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1092 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1093 llvm::FunctionType *FnTy = 1094 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1095 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1096 break; 1097 } 1098 case OMPRTL__kmpc_threadprivate_cached: { 1099 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1100 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1101 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1102 CGM.VoidPtrTy, CGM.SizeTy, 1103 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1104 llvm::FunctionType *FnTy = 1105 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1106 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1107 break; 1108 } 1109 case OMPRTL__kmpc_critical: { 1110 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1111 // kmp_critical_name *crit); 1112 llvm::Type *TypeParams[] = { 1113 getIdentTyPointerTy(), CGM.Int32Ty, 1114 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1115 llvm::FunctionType *FnTy = 1116 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1117 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1118 break; 1119 } 1120 case OMPRTL__kmpc_critical_with_hint: { 1121 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1122 // kmp_critical_name *crit, uintptr_t hint); 1123 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1124 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1125 CGM.IntPtrTy}; 1126 llvm::FunctionType *FnTy = 1127 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1128 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1129 break; 1130 } 1131 case OMPRTL__kmpc_threadprivate_register: { 1132 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1133 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1134 // typedef void *(*kmpc_ctor)(void *); 1135 auto KmpcCtorTy = 1136 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1137 /*isVarArg*/ false)->getPointerTo(); 1138 // typedef void *(*kmpc_cctor)(void *, void *); 1139 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1140 auto KmpcCopyCtorTy = 1141 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1142 /*isVarArg*/ false)->getPointerTo(); 1143 // typedef void (*kmpc_dtor)(void *); 1144 auto KmpcDtorTy = 1145 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1146 ->getPointerTo(); 1147 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1148 KmpcCopyCtorTy, KmpcDtorTy}; 1149 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1150 /*isVarArg*/ false); 1151 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1152 break; 1153 } 1154 case OMPRTL__kmpc_end_critical: { 1155 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1156 // kmp_critical_name *crit); 1157 llvm::Type *TypeParams[] = { 1158 getIdentTyPointerTy(), CGM.Int32Ty, 1159 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1160 llvm::FunctionType *FnTy = 1161 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1162 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1163 break; 1164 } 1165 case OMPRTL__kmpc_cancel_barrier: { 1166 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1167 // global_tid); 1168 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1169 llvm::FunctionType *FnTy = 1170 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1171 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1172 break; 1173 } 1174 case OMPRTL__kmpc_barrier: { 1175 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1176 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1177 llvm::FunctionType *FnTy = 1178 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1179 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1180 break; 1181 } 1182 case OMPRTL__kmpc_for_static_fini: { 1183 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1184 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1185 llvm::FunctionType *FnTy = 1186 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1187 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1188 break; 1189 } 1190 case OMPRTL__kmpc_push_num_threads: { 1191 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1192 // kmp_int32 num_threads) 1193 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1194 CGM.Int32Ty}; 1195 llvm::FunctionType *FnTy = 1196 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1197 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1198 break; 1199 } 1200 case OMPRTL__kmpc_serialized_parallel: { 1201 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1202 // global_tid); 1203 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1204 llvm::FunctionType *FnTy = 1205 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1206 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1207 break; 1208 } 1209 case OMPRTL__kmpc_end_serialized_parallel: { 1210 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1211 // global_tid); 1212 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1213 llvm::FunctionType *FnTy = 1214 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1215 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1216 break; 1217 } 1218 case OMPRTL__kmpc_flush: { 1219 // Build void __kmpc_flush(ident_t *loc); 1220 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1221 llvm::FunctionType *FnTy = 1222 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1223 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1224 break; 1225 } 1226 case OMPRTL__kmpc_master: { 1227 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1228 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1229 llvm::FunctionType *FnTy = 1230 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1231 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 1232 break; 1233 } 1234 case OMPRTL__kmpc_end_master: { 1235 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 1236 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1237 llvm::FunctionType *FnTy = 1238 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1239 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 1240 break; 1241 } 1242 case OMPRTL__kmpc_omp_taskyield: { 1243 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 1244 // int end_part); 1245 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1246 llvm::FunctionType *FnTy = 1247 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1248 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 1249 break; 1250 } 1251 case OMPRTL__kmpc_single: { 1252 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 1253 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1254 llvm::FunctionType *FnTy = 1255 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1256 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 1257 break; 1258 } 1259 case OMPRTL__kmpc_end_single: { 1260 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 1261 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1262 llvm::FunctionType *FnTy = 1263 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1264 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 1265 break; 1266 } 1267 case OMPRTL__kmpc_omp_task_alloc: { 1268 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 1269 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1270 // kmp_routine_entry_t *task_entry); 1271 assert(KmpRoutineEntryPtrTy != nullptr && 1272 "Type kmp_routine_entry_t must be created."); 1273 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1274 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 1275 // Return void * and then cast to particular kmp_task_t type. 1276 llvm::FunctionType *FnTy = 1277 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 1278 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 1279 break; 1280 } 1281 case OMPRTL__kmpc_omp_task: { 1282 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 1283 // *new_task); 1284 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1285 CGM.VoidPtrTy}; 1286 llvm::FunctionType *FnTy = 1287 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1288 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 1289 break; 1290 } 1291 case OMPRTL__kmpc_copyprivate: { 1292 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 1293 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 1294 // kmp_int32 didit); 1295 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1296 auto *CpyFnTy = 1297 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 1298 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 1299 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 1300 CGM.Int32Ty}; 1301 llvm::FunctionType *FnTy = 1302 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1303 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 1304 break; 1305 } 1306 case OMPRTL__kmpc_reduce: { 1307 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 1308 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 1309 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 1310 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1311 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 1312 /*isVarArg=*/false); 1313 llvm::Type *TypeParams[] = { 1314 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 1315 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 1316 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1317 llvm::FunctionType *FnTy = 1318 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1319 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 1320 break; 1321 } 1322 case OMPRTL__kmpc_reduce_nowait: { 1323 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 1324 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 1325 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 1326 // *lck); 1327 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1328 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 1329 /*isVarArg=*/false); 1330 llvm::Type *TypeParams[] = { 1331 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 1332 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 1333 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1334 llvm::FunctionType *FnTy = 1335 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1336 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 1337 break; 1338 } 1339 case OMPRTL__kmpc_end_reduce: { 1340 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 1341 // kmp_critical_name *lck); 1342 llvm::Type *TypeParams[] = { 1343 getIdentTyPointerTy(), CGM.Int32Ty, 1344 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1345 llvm::FunctionType *FnTy = 1346 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1347 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 1348 break; 1349 } 1350 case OMPRTL__kmpc_end_reduce_nowait: { 1351 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 1352 // kmp_critical_name *lck); 1353 llvm::Type *TypeParams[] = { 1354 getIdentTyPointerTy(), CGM.Int32Ty, 1355 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1356 llvm::FunctionType *FnTy = 1357 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1358 RTLFn = 1359 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 1360 break; 1361 } 1362 case OMPRTL__kmpc_omp_task_begin_if0: { 1363 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 1364 // *new_task); 1365 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1366 CGM.VoidPtrTy}; 1367 llvm::FunctionType *FnTy = 1368 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1369 RTLFn = 1370 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 1371 break; 1372 } 1373 case OMPRTL__kmpc_omp_task_complete_if0: { 1374 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 1375 // *new_task); 1376 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1377 CGM.VoidPtrTy}; 1378 llvm::FunctionType *FnTy = 1379 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1380 RTLFn = CGM.CreateRuntimeFunction(FnTy, 1381 /*Name=*/"__kmpc_omp_task_complete_if0"); 1382 break; 1383 } 1384 case OMPRTL__kmpc_ordered: { 1385 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 1386 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1387 llvm::FunctionType *FnTy = 1388 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1389 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 1390 break; 1391 } 1392 case OMPRTL__kmpc_end_ordered: { 1393 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 1394 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1395 llvm::FunctionType *FnTy = 1396 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1397 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 1398 break; 1399 } 1400 case OMPRTL__kmpc_omp_taskwait: { 1401 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 1402 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1403 llvm::FunctionType *FnTy = 1404 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1405 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 1406 break; 1407 } 1408 case OMPRTL__kmpc_taskgroup: { 1409 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 1410 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1411 llvm::FunctionType *FnTy = 1412 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1413 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 1414 break; 1415 } 1416 case OMPRTL__kmpc_end_taskgroup: { 1417 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 1418 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1419 llvm::FunctionType *FnTy = 1420 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1421 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 1422 break; 1423 } 1424 case OMPRTL__kmpc_push_proc_bind: { 1425 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 1426 // int proc_bind) 1427 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1428 llvm::FunctionType *FnTy = 1429 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1430 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 1431 break; 1432 } 1433 case OMPRTL__kmpc_omp_task_with_deps: { 1434 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 1435 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 1436 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 1437 llvm::Type *TypeParams[] = { 1438 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 1439 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 1440 llvm::FunctionType *FnTy = 1441 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1442 RTLFn = 1443 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 1444 break; 1445 } 1446 case OMPRTL__kmpc_omp_wait_deps: { 1447 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 1448 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 1449 // kmp_depend_info_t *noalias_dep_list); 1450 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1451 CGM.Int32Ty, CGM.VoidPtrTy, 1452 CGM.Int32Ty, CGM.VoidPtrTy}; 1453 llvm::FunctionType *FnTy = 1454 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1455 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 1456 break; 1457 } 1458 case OMPRTL__kmpc_cancellationpoint: { 1459 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 1460 // global_tid, kmp_int32 cncl_kind) 1461 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1462 llvm::FunctionType *FnTy = 1463 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1464 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 1465 break; 1466 } 1467 case OMPRTL__kmpc_cancel: { 1468 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 1469 // kmp_int32 cncl_kind) 1470 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1471 llvm::FunctionType *FnTy = 1472 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1473 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 1474 break; 1475 } 1476 case OMPRTL__kmpc_push_num_teams: { 1477 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 1478 // kmp_int32 num_teams, kmp_int32 num_threads) 1479 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1480 CGM.Int32Ty}; 1481 llvm::FunctionType *FnTy = 1482 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1483 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 1484 break; 1485 } 1486 case OMPRTL__kmpc_fork_teams: { 1487 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 1488 // microtask, ...); 1489 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1490 getKmpc_MicroPointerTy()}; 1491 llvm::FunctionType *FnTy = 1492 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1493 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 1494 break; 1495 } 1496 case OMPRTL__kmpc_taskloop: { 1497 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 1498 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 1499 // sched, kmp_uint64 grainsize, void *task_dup); 1500 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 1501 CGM.IntTy, 1502 CGM.VoidPtrTy, 1503 CGM.IntTy, 1504 CGM.Int64Ty->getPointerTo(), 1505 CGM.Int64Ty->getPointerTo(), 1506 CGM.Int64Ty, 1507 CGM.IntTy, 1508 CGM.IntTy, 1509 CGM.Int64Ty, 1510 CGM.VoidPtrTy}; 1511 llvm::FunctionType *FnTy = 1512 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1513 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 1514 break; 1515 } 1516 case OMPRTL__kmpc_doacross_init: { 1517 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 1518 // num_dims, struct kmp_dim *dims); 1519 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 1520 CGM.Int32Ty, 1521 CGM.Int32Ty, 1522 CGM.VoidPtrTy}; 1523 llvm::FunctionType *FnTy = 1524 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1525 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 1526 break; 1527 } 1528 case OMPRTL__kmpc_doacross_fini: { 1529 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 1530 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1531 llvm::FunctionType *FnTy = 1532 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1533 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 1534 break; 1535 } 1536 case OMPRTL__kmpc_doacross_post: { 1537 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 1538 // *vec); 1539 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1540 CGM.Int64Ty->getPointerTo()}; 1541 llvm::FunctionType *FnTy = 1542 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1543 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 1544 break; 1545 } 1546 case OMPRTL__kmpc_doacross_wait: { 1547 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 1548 // *vec); 1549 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1550 CGM.Int64Ty->getPointerTo()}; 1551 llvm::FunctionType *FnTy = 1552 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1553 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 1554 break; 1555 } 1556 case OMPRTL__tgt_target: { 1557 // Build int32_t __tgt_target(int32_t device_id, void *host_ptr, int32_t 1558 // arg_num, void** args_base, void **args, size_t *arg_sizes, int32_t 1559 // *arg_types); 1560 llvm::Type *TypeParams[] = {CGM.Int32Ty, 1561 CGM.VoidPtrTy, 1562 CGM.Int32Ty, 1563 CGM.VoidPtrPtrTy, 1564 CGM.VoidPtrPtrTy, 1565 CGM.SizeTy->getPointerTo(), 1566 CGM.Int32Ty->getPointerTo()}; 1567 llvm::FunctionType *FnTy = 1568 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1569 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 1570 break; 1571 } 1572 case OMPRTL__tgt_target_teams: { 1573 // Build int32_t __tgt_target_teams(int32_t device_id, void *host_ptr, 1574 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, 1575 // int32_t *arg_types, int32_t num_teams, int32_t thread_limit); 1576 llvm::Type *TypeParams[] = {CGM.Int32Ty, 1577 CGM.VoidPtrTy, 1578 CGM.Int32Ty, 1579 CGM.VoidPtrPtrTy, 1580 CGM.VoidPtrPtrTy, 1581 CGM.SizeTy->getPointerTo(), 1582 CGM.Int32Ty->getPointerTo(), 1583 CGM.Int32Ty, 1584 CGM.Int32Ty}; 1585 llvm::FunctionType *FnTy = 1586 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1587 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 1588 break; 1589 } 1590 case OMPRTL__tgt_register_lib: { 1591 // Build void __tgt_register_lib(__tgt_bin_desc *desc); 1592 QualType ParamTy = 1593 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 1594 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 1595 llvm::FunctionType *FnTy = 1596 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1597 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); 1598 break; 1599 } 1600 case OMPRTL__tgt_unregister_lib: { 1601 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); 1602 QualType ParamTy = 1603 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 1604 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 1605 llvm::FunctionType *FnTy = 1606 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1607 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); 1608 break; 1609 } 1610 case OMPRTL__tgt_target_data_begin: { 1611 // Build void __tgt_target_data_begin(int32_t device_id, int32_t arg_num, 1612 // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types); 1613 llvm::Type *TypeParams[] = {CGM.Int32Ty, 1614 CGM.Int32Ty, 1615 CGM.VoidPtrPtrTy, 1616 CGM.VoidPtrPtrTy, 1617 CGM.SizeTy->getPointerTo(), 1618 CGM.Int32Ty->getPointerTo()}; 1619 llvm::FunctionType *FnTy = 1620 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1621 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 1622 break; 1623 } 1624 case OMPRTL__tgt_target_data_end: { 1625 // Build void __tgt_target_data_end(int32_t device_id, int32_t arg_num, 1626 // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types); 1627 llvm::Type *TypeParams[] = {CGM.Int32Ty, 1628 CGM.Int32Ty, 1629 CGM.VoidPtrPtrTy, 1630 CGM.VoidPtrPtrTy, 1631 CGM.SizeTy->getPointerTo(), 1632 CGM.Int32Ty->getPointerTo()}; 1633 llvm::FunctionType *FnTy = 1634 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1635 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 1636 break; 1637 } 1638 case OMPRTL__tgt_target_data_update: { 1639 // Build void __tgt_target_data_update(int32_t device_id, int32_t arg_num, 1640 // void** args_base, void **args, size_t *arg_sizes, int32_t *arg_types); 1641 llvm::Type *TypeParams[] = {CGM.Int32Ty, 1642 CGM.Int32Ty, 1643 CGM.VoidPtrPtrTy, 1644 CGM.VoidPtrPtrTy, 1645 CGM.SizeTy->getPointerTo(), 1646 CGM.Int32Ty->getPointerTo()}; 1647 llvm::FunctionType *FnTy = 1648 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1649 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 1650 break; 1651 } 1652 } 1653 assert(RTLFn && "Unable to find OpenMP runtime function"); 1654 return RTLFn; 1655 } 1656 1657 llvm::Constant *CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, 1658 bool IVSigned) { 1659 assert((IVSize == 32 || IVSize == 64) && 1660 "IV size is not compatible with the omp runtime"); 1661 auto Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 1662 : "__kmpc_for_static_init_4u") 1663 : (IVSigned ? "__kmpc_for_static_init_8" 1664 : "__kmpc_for_static_init_8u"); 1665 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1666 auto PtrTy = llvm::PointerType::getUnqual(ITy); 1667 llvm::Type *TypeParams[] = { 1668 getIdentTyPointerTy(), // loc 1669 CGM.Int32Ty, // tid 1670 CGM.Int32Ty, // schedtype 1671 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1672 PtrTy, // p_lower 1673 PtrTy, // p_upper 1674 PtrTy, // p_stride 1675 ITy, // incr 1676 ITy // chunk 1677 }; 1678 llvm::FunctionType *FnTy = 1679 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1680 return CGM.CreateRuntimeFunction(FnTy, Name); 1681 } 1682 1683 llvm::Constant *CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, 1684 bool IVSigned) { 1685 assert((IVSize == 32 || IVSize == 64) && 1686 "IV size is not compatible with the omp runtime"); 1687 auto Name = 1688 IVSize == 32 1689 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 1690 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 1691 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1692 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 1693 CGM.Int32Ty, // tid 1694 CGM.Int32Ty, // schedtype 1695 ITy, // lower 1696 ITy, // upper 1697 ITy, // stride 1698 ITy // chunk 1699 }; 1700 llvm::FunctionType *FnTy = 1701 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1702 return CGM.CreateRuntimeFunction(FnTy, Name); 1703 } 1704 1705 llvm::Constant *CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, 1706 bool IVSigned) { 1707 assert((IVSize == 32 || IVSize == 64) && 1708 "IV size is not compatible with the omp runtime"); 1709 auto Name = 1710 IVSize == 32 1711 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 1712 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 1713 llvm::Type *TypeParams[] = { 1714 getIdentTyPointerTy(), // loc 1715 CGM.Int32Ty, // tid 1716 }; 1717 llvm::FunctionType *FnTy = 1718 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1719 return CGM.CreateRuntimeFunction(FnTy, Name); 1720 } 1721 1722 llvm::Constant *CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, 1723 bool IVSigned) { 1724 assert((IVSize == 32 || IVSize == 64) && 1725 "IV size is not compatible with the omp runtime"); 1726 auto Name = 1727 IVSize == 32 1728 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 1729 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 1730 auto ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1731 auto PtrTy = llvm::PointerType::getUnqual(ITy); 1732 llvm::Type *TypeParams[] = { 1733 getIdentTyPointerTy(), // loc 1734 CGM.Int32Ty, // tid 1735 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1736 PtrTy, // p_lower 1737 PtrTy, // p_upper 1738 PtrTy // p_stride 1739 }; 1740 llvm::FunctionType *FnTy = 1741 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1742 return CGM.CreateRuntimeFunction(FnTy, Name); 1743 } 1744 1745 llvm::Constant * 1746 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 1747 assert(!CGM.getLangOpts().OpenMPUseTLS || 1748 !CGM.getContext().getTargetInfo().isTLSSupported()); 1749 // Lookup the entry, lazily creating it if necessary. 1750 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy, 1751 Twine(CGM.getMangledName(VD)) + ".cache."); 1752 } 1753 1754 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 1755 const VarDecl *VD, 1756 Address VDAddr, 1757 SourceLocation Loc) { 1758 if (CGM.getLangOpts().OpenMPUseTLS && 1759 CGM.getContext().getTargetInfo().isTLSSupported()) 1760 return VDAddr; 1761 1762 auto VarTy = VDAddr.getElementType(); 1763 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1764 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1765 CGM.Int8PtrTy), 1766 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 1767 getOrCreateThreadPrivateCache(VD)}; 1768 return Address(CGF.EmitRuntimeCall( 1769 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 1770 VDAddr.getAlignment()); 1771 } 1772 1773 void CGOpenMPRuntime::emitThreadPrivateVarInit( 1774 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 1775 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 1776 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 1777 // library. 1778 auto OMPLoc = emitUpdateLocation(CGF, Loc); 1779 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1780 OMPLoc); 1781 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 1782 // to register constructor/destructor for variable. 1783 llvm::Value *Args[] = {OMPLoc, 1784 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1785 CGM.VoidPtrTy), 1786 Ctor, CopyCtor, Dtor}; 1787 CGF.EmitRuntimeCall( 1788 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 1789 } 1790 1791 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 1792 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 1793 bool PerformInit, CodeGenFunction *CGF) { 1794 if (CGM.getLangOpts().OpenMPUseTLS && 1795 CGM.getContext().getTargetInfo().isTLSSupported()) 1796 return nullptr; 1797 1798 VD = VD->getDefinition(CGM.getContext()); 1799 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) { 1800 ThreadPrivateWithDefinition.insert(VD); 1801 QualType ASTTy = VD->getType(); 1802 1803 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 1804 auto Init = VD->getAnyInitializer(); 1805 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1806 // Generate function that re-emits the declaration's initializer into the 1807 // threadprivate copy of the variable VD 1808 CodeGenFunction CtorCGF(CGM); 1809 FunctionArgList Args; 1810 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), 1811 /*Id=*/nullptr, CGM.getContext().VoidPtrTy); 1812 Args.push_back(&Dst); 1813 1814 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1815 CGM.getContext().VoidPtrTy, Args); 1816 auto FTy = CGM.getTypes().GetFunctionType(FI); 1817 auto Fn = CGM.CreateGlobalInitOrDestructFunction( 1818 FTy, ".__kmpc_global_ctor_.", FI, Loc); 1819 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 1820 Args, SourceLocation()); 1821 auto ArgVal = CtorCGF.EmitLoadOfScalar( 1822 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1823 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1824 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 1825 Arg = CtorCGF.Builder.CreateElementBitCast(Arg, 1826 CtorCGF.ConvertTypeForMem(ASTTy)); 1827 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 1828 /*IsInitializer=*/true); 1829 ArgVal = CtorCGF.EmitLoadOfScalar( 1830 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1831 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1832 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 1833 CtorCGF.FinishFunction(); 1834 Ctor = Fn; 1835 } 1836 if (VD->getType().isDestructedType() != QualType::DK_none) { 1837 // Generate function that emits destructor call for the threadprivate copy 1838 // of the variable VD 1839 CodeGenFunction DtorCGF(CGM); 1840 FunctionArgList Args; 1841 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), 1842 /*Id=*/nullptr, CGM.getContext().VoidPtrTy); 1843 Args.push_back(&Dst); 1844 1845 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1846 CGM.getContext().VoidTy, Args); 1847 auto FTy = CGM.getTypes().GetFunctionType(FI); 1848 auto Fn = CGM.CreateGlobalInitOrDestructFunction( 1849 FTy, ".__kmpc_global_dtor_.", FI, Loc); 1850 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1851 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 1852 SourceLocation()); 1853 // Create a scope with an artificial location for the body of this function. 1854 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1855 auto ArgVal = DtorCGF.EmitLoadOfScalar( 1856 DtorCGF.GetAddrOfLocalVar(&Dst), 1857 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 1858 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 1859 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1860 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1861 DtorCGF.FinishFunction(); 1862 Dtor = Fn; 1863 } 1864 // Do not emit init function if it is not required. 1865 if (!Ctor && !Dtor) 1866 return nullptr; 1867 1868 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1869 auto CopyCtorTy = 1870 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 1871 /*isVarArg=*/false)->getPointerTo(); 1872 // Copying constructor for the threadprivate variable. 1873 // Must be NULL - reserved by runtime, but currently it requires that this 1874 // parameter is always NULL. Otherwise it fires assertion. 1875 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 1876 if (Ctor == nullptr) { 1877 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1878 /*isVarArg=*/false)->getPointerTo(); 1879 Ctor = llvm::Constant::getNullValue(CtorTy); 1880 } 1881 if (Dtor == nullptr) { 1882 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 1883 /*isVarArg=*/false)->getPointerTo(); 1884 Dtor = llvm::Constant::getNullValue(DtorTy); 1885 } 1886 if (!CGF) { 1887 auto InitFunctionTy = 1888 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 1889 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction( 1890 InitFunctionTy, ".__omp_threadprivate_init_.", 1891 CGM.getTypes().arrangeNullaryFunction()); 1892 CodeGenFunction InitCGF(CGM); 1893 FunctionArgList ArgList; 1894 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 1895 CGM.getTypes().arrangeNullaryFunction(), ArgList, 1896 Loc); 1897 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1898 InitCGF.FinishFunction(); 1899 return InitFunction; 1900 } 1901 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1902 } 1903 return nullptr; 1904 } 1905 1906 /// \brief Emits code for OpenMP 'if' clause using specified \a CodeGen 1907 /// function. Here is the logic: 1908 /// if (Cond) { 1909 /// ThenGen(); 1910 /// } else { 1911 /// ElseGen(); 1912 /// } 1913 void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, 1914 const RegionCodeGenTy &ThenGen, 1915 const RegionCodeGenTy &ElseGen) { 1916 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 1917 1918 // If the condition constant folds and can be elided, try to avoid emitting 1919 // the condition and the dead arm of the if/else. 1920 bool CondConstant; 1921 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 1922 if (CondConstant) 1923 ThenGen(CGF); 1924 else 1925 ElseGen(CGF); 1926 return; 1927 } 1928 1929 // Otherwise, the condition did not fold, or we couldn't elide it. Just 1930 // emit the conditional branch. 1931 auto ThenBlock = CGF.createBasicBlock("omp_if.then"); 1932 auto ElseBlock = CGF.createBasicBlock("omp_if.else"); 1933 auto ContBlock = CGF.createBasicBlock("omp_if.end"); 1934 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 1935 1936 // Emit the 'then' code. 1937 CGF.EmitBlock(ThenBlock); 1938 ThenGen(CGF); 1939 CGF.EmitBranch(ContBlock); 1940 // Emit the 'else' code if present. 1941 // There is no need to emit line number for unconditional branch. 1942 (void)ApplyDebugLocation::CreateEmpty(CGF); 1943 CGF.EmitBlock(ElseBlock); 1944 ElseGen(CGF); 1945 // There is no need to emit line number for unconditional branch. 1946 (void)ApplyDebugLocation::CreateEmpty(CGF); 1947 CGF.EmitBranch(ContBlock); 1948 // Emit the continuation block for code after the if. 1949 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 1950 } 1951 1952 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 1953 llvm::Value *OutlinedFn, 1954 ArrayRef<llvm::Value *> CapturedVars, 1955 const Expr *IfCond) { 1956 if (!CGF.HaveInsertPoint()) 1957 return; 1958 auto *RTLoc = emitUpdateLocation(CGF, Loc); 1959 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 1960 PrePostActionTy &) { 1961 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 1962 auto &RT = CGF.CGM.getOpenMPRuntime(); 1963 llvm::Value *Args[] = { 1964 RTLoc, 1965 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 1966 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 1967 llvm::SmallVector<llvm::Value *, 16> RealArgs; 1968 RealArgs.append(std::begin(Args), std::end(Args)); 1969 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 1970 1971 auto RTLFn = RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 1972 CGF.EmitRuntimeCall(RTLFn, RealArgs); 1973 }; 1974 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 1975 PrePostActionTy &) { 1976 auto &RT = CGF.CGM.getOpenMPRuntime(); 1977 auto ThreadID = RT.getThreadID(CGF, Loc); 1978 // Build calls: 1979 // __kmpc_serialized_parallel(&Loc, GTid); 1980 llvm::Value *Args[] = {RTLoc, ThreadID}; 1981 CGF.EmitRuntimeCall( 1982 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 1983 1984 // OutlinedFn(>id, &zero, CapturedStruct); 1985 auto ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 1986 Address ZeroAddr = 1987 CGF.CreateTempAlloca(CGF.Int32Ty, CharUnits::fromQuantity(4), 1988 /*Name*/ ".zero.addr"); 1989 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); 1990 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 1991 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 1992 OutlinedFnArgs.push_back(ZeroAddr.getPointer()); 1993 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 1994 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs); 1995 1996 // __kmpc_end_serialized_parallel(&Loc, GTid); 1997 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 1998 CGF.EmitRuntimeCall( 1999 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 2000 EndArgs); 2001 }; 2002 if (IfCond) 2003 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 2004 else { 2005 RegionCodeGenTy ThenRCG(ThenGen); 2006 ThenRCG(CGF); 2007 } 2008 } 2009 2010 // If we're inside an (outlined) parallel region, use the region info's 2011 // thread-ID variable (it is passed in a first argument of the outlined function 2012 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 2013 // regular serial code region, get thread ID by calling kmp_int32 2014 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 2015 // return the address of that temp. 2016 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 2017 SourceLocation Loc) { 2018 if (auto *OMPRegionInfo = 2019 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2020 if (OMPRegionInfo->getThreadIDVariable()) 2021 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); 2022 2023 auto ThreadID = getThreadID(CGF, Loc); 2024 auto Int32Ty = 2025 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 2026 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 2027 CGF.EmitStoreOfScalar(ThreadID, 2028 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 2029 2030 return ThreadIDTemp; 2031 } 2032 2033 llvm::Constant * 2034 CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty, 2035 const llvm::Twine &Name) { 2036 SmallString<256> Buffer; 2037 llvm::raw_svector_ostream Out(Buffer); 2038 Out << Name; 2039 auto RuntimeName = Out.str(); 2040 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first; 2041 if (Elem.second) { 2042 assert(Elem.second->getType()->getPointerElementType() == Ty && 2043 "OMP internal variable has different type than requested"); 2044 return &*Elem.second; 2045 } 2046 2047 return Elem.second = new llvm::GlobalVariable( 2048 CGM.getModule(), Ty, /*IsConstant*/ false, 2049 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 2050 Elem.first()); 2051 } 2052 2053 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 2054 llvm::Twine Name(".gomp_critical_user_", CriticalName); 2055 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var")); 2056 } 2057 2058 namespace { 2059 /// Common pre(post)-action for different OpenMP constructs. 2060 class CommonActionTy final : public PrePostActionTy { 2061 llvm::Value *EnterCallee; 2062 ArrayRef<llvm::Value *> EnterArgs; 2063 llvm::Value *ExitCallee; 2064 ArrayRef<llvm::Value *> ExitArgs; 2065 bool Conditional; 2066 llvm::BasicBlock *ContBlock = nullptr; 2067 2068 public: 2069 CommonActionTy(llvm::Value *EnterCallee, ArrayRef<llvm::Value *> EnterArgs, 2070 llvm::Value *ExitCallee, ArrayRef<llvm::Value *> ExitArgs, 2071 bool Conditional = false) 2072 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 2073 ExitArgs(ExitArgs), Conditional(Conditional) {} 2074 void Enter(CodeGenFunction &CGF) override { 2075 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 2076 if (Conditional) { 2077 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 2078 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2079 ContBlock = CGF.createBasicBlock("omp_if.end"); 2080 // Generate the branch (If-stmt) 2081 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 2082 CGF.EmitBlock(ThenBlock); 2083 } 2084 } 2085 void Done(CodeGenFunction &CGF) { 2086 // Emit the rest of blocks/branches 2087 CGF.EmitBranch(ContBlock); 2088 CGF.EmitBlock(ContBlock, true); 2089 } 2090 void Exit(CodeGenFunction &CGF) override { 2091 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 2092 } 2093 }; 2094 } // anonymous namespace 2095 2096 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 2097 StringRef CriticalName, 2098 const RegionCodeGenTy &CriticalOpGen, 2099 SourceLocation Loc, const Expr *Hint) { 2100 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 2101 // CriticalOpGen(); 2102 // __kmpc_end_critical(ident_t *, gtid, Lock); 2103 // Prepare arguments and build a call to __kmpc_critical 2104 if (!CGF.HaveInsertPoint()) 2105 return; 2106 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2107 getCriticalRegionLock(CriticalName)}; 2108 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 2109 std::end(Args)); 2110 if (Hint) { 2111 EnterArgs.push_back(CGF.Builder.CreateIntCast( 2112 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 2113 } 2114 CommonActionTy Action( 2115 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 2116 : OMPRTL__kmpc_critical), 2117 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 2118 CriticalOpGen.setAction(Action); 2119 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 2120 } 2121 2122 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 2123 const RegionCodeGenTy &MasterOpGen, 2124 SourceLocation Loc) { 2125 if (!CGF.HaveInsertPoint()) 2126 return; 2127 // if(__kmpc_master(ident_t *, gtid)) { 2128 // MasterOpGen(); 2129 // __kmpc_end_master(ident_t *, gtid); 2130 // } 2131 // Prepare arguments and build a call to __kmpc_master 2132 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2133 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 2134 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 2135 /*Conditional=*/true); 2136 MasterOpGen.setAction(Action); 2137 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 2138 Action.Done(CGF); 2139 } 2140 2141 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 2142 SourceLocation Loc) { 2143 if (!CGF.HaveInsertPoint()) 2144 return; 2145 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 2146 llvm::Value *Args[] = { 2147 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2148 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 2149 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 2150 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2151 Region->emitUntiedSwitch(CGF); 2152 } 2153 2154 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 2155 const RegionCodeGenTy &TaskgroupOpGen, 2156 SourceLocation Loc) { 2157 if (!CGF.HaveInsertPoint()) 2158 return; 2159 // __kmpc_taskgroup(ident_t *, gtid); 2160 // TaskgroupOpGen(); 2161 // __kmpc_end_taskgroup(ident_t *, gtid); 2162 // Prepare arguments and build a call to __kmpc_taskgroup 2163 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2164 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 2165 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 2166 Args); 2167 TaskgroupOpGen.setAction(Action); 2168 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 2169 } 2170 2171 /// Given an array of pointers to variables, project the address of a 2172 /// given variable. 2173 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 2174 unsigned Index, const VarDecl *Var) { 2175 // Pull out the pointer to the variable. 2176 Address PtrAddr = 2177 CGF.Builder.CreateConstArrayGEP(Array, Index, CGF.getPointerSize()); 2178 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 2179 2180 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 2181 Addr = CGF.Builder.CreateElementBitCast( 2182 Addr, CGF.ConvertTypeForMem(Var->getType())); 2183 return Addr; 2184 } 2185 2186 static llvm::Value *emitCopyprivateCopyFunction( 2187 CodeGenModule &CGM, llvm::Type *ArgsType, 2188 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 2189 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps) { 2190 auto &C = CGM.getContext(); 2191 // void copy_func(void *LHSArg, void *RHSArg); 2192 FunctionArgList Args; 2193 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 2194 C.VoidPtrTy); 2195 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 2196 C.VoidPtrTy); 2197 Args.push_back(&LHSArg); 2198 Args.push_back(&RHSArg); 2199 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 2200 auto *Fn = llvm::Function::Create( 2201 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, 2202 ".omp.copyprivate.copy_func", &CGM.getModule()); 2203 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI); 2204 CodeGenFunction CGF(CGM); 2205 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args); 2206 // Dest = (void*[n])(LHSArg); 2207 // Src = (void*[n])(RHSArg); 2208 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2209 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 2210 ArgsType), CGF.getPointerAlign()); 2211 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2212 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 2213 ArgsType), CGF.getPointerAlign()); 2214 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 2215 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 2216 // ... 2217 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 2218 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 2219 auto DestVar = cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 2220 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 2221 2222 auto SrcVar = cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 2223 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 2224 2225 auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 2226 QualType Type = VD->getType(); 2227 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 2228 } 2229 CGF.FinishFunction(); 2230 return Fn; 2231 } 2232 2233 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 2234 const RegionCodeGenTy &SingleOpGen, 2235 SourceLocation Loc, 2236 ArrayRef<const Expr *> CopyprivateVars, 2237 ArrayRef<const Expr *> SrcExprs, 2238 ArrayRef<const Expr *> DstExprs, 2239 ArrayRef<const Expr *> AssignmentOps) { 2240 if (!CGF.HaveInsertPoint()) 2241 return; 2242 assert(CopyprivateVars.size() == SrcExprs.size() && 2243 CopyprivateVars.size() == DstExprs.size() && 2244 CopyprivateVars.size() == AssignmentOps.size()); 2245 auto &C = CGM.getContext(); 2246 // int32 did_it = 0; 2247 // if(__kmpc_single(ident_t *, gtid)) { 2248 // SingleOpGen(); 2249 // __kmpc_end_single(ident_t *, gtid); 2250 // did_it = 1; 2251 // } 2252 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2253 // <copy_func>, did_it); 2254 2255 Address DidIt = Address::invalid(); 2256 if (!CopyprivateVars.empty()) { 2257 // int32 did_it = 0; 2258 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2259 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 2260 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 2261 } 2262 // Prepare arguments and build a call to __kmpc_single 2263 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2264 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 2265 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 2266 /*Conditional=*/true); 2267 SingleOpGen.setAction(Action); 2268 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 2269 if (DidIt.isValid()) { 2270 // did_it = 1; 2271 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 2272 } 2273 Action.Done(CGF); 2274 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2275 // <copy_func>, did_it); 2276 if (DidIt.isValid()) { 2277 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 2278 auto CopyprivateArrayTy = 2279 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 2280 /*IndexTypeQuals=*/0); 2281 // Create a list of all private variables for copyprivate. 2282 Address CopyprivateList = 2283 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 2284 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 2285 Address Elem = CGF.Builder.CreateConstArrayGEP( 2286 CopyprivateList, I, CGF.getPointerSize()); 2287 CGF.Builder.CreateStore( 2288 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2289 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy), 2290 Elem); 2291 } 2292 // Build function that copies private values from single region to all other 2293 // threads in the corresponding parallel region. 2294 auto *CpyFn = emitCopyprivateCopyFunction( 2295 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 2296 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps); 2297 auto *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 2298 Address CL = 2299 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 2300 CGF.VoidPtrTy); 2301 auto *DidItVal = CGF.Builder.CreateLoad(DidIt); 2302 llvm::Value *Args[] = { 2303 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 2304 getThreadID(CGF, Loc), // i32 <gtid> 2305 BufSize, // size_t <buf_size> 2306 CL.getPointer(), // void *<copyprivate list> 2307 CpyFn, // void (*) (void *, void *) <copy_func> 2308 DidItVal // i32 did_it 2309 }; 2310 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 2311 } 2312 } 2313 2314 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 2315 const RegionCodeGenTy &OrderedOpGen, 2316 SourceLocation Loc, bool IsThreads) { 2317 if (!CGF.HaveInsertPoint()) 2318 return; 2319 // __kmpc_ordered(ident_t *, gtid); 2320 // OrderedOpGen(); 2321 // __kmpc_end_ordered(ident_t *, gtid); 2322 // Prepare arguments and build a call to __kmpc_ordered 2323 if (IsThreads) { 2324 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2325 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 2326 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 2327 Args); 2328 OrderedOpGen.setAction(Action); 2329 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2330 return; 2331 } 2332 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2333 } 2334 2335 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 2336 OpenMPDirectiveKind Kind, bool EmitChecks, 2337 bool ForceSimpleCall) { 2338 if (!CGF.HaveInsertPoint()) 2339 return; 2340 // Build call __kmpc_cancel_barrier(loc, thread_id); 2341 // Build call __kmpc_barrier(loc, thread_id); 2342 unsigned Flags; 2343 if (Kind == OMPD_for) 2344 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 2345 else if (Kind == OMPD_sections) 2346 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 2347 else if (Kind == OMPD_single) 2348 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 2349 else if (Kind == OMPD_barrier) 2350 Flags = OMP_IDENT_BARRIER_EXPL; 2351 else 2352 Flags = OMP_IDENT_BARRIER_IMPL; 2353 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 2354 // thread_id); 2355 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 2356 getThreadID(CGF, Loc)}; 2357 if (auto *OMPRegionInfo = 2358 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 2359 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 2360 auto *Result = CGF.EmitRuntimeCall( 2361 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 2362 if (EmitChecks) { 2363 // if (__kmpc_cancel_barrier()) { 2364 // exit from construct; 2365 // } 2366 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 2367 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 2368 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 2369 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 2370 CGF.EmitBlock(ExitBB); 2371 // exit from construct; 2372 auto CancelDestination = 2373 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 2374 CGF.EmitBranchThroughCleanup(CancelDestination); 2375 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 2376 } 2377 return; 2378 } 2379 } 2380 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 2381 } 2382 2383 /// \brief Map the OpenMP loop schedule to the runtime enumeration. 2384 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 2385 bool Chunked, bool Ordered) { 2386 switch (ScheduleKind) { 2387 case OMPC_SCHEDULE_static: 2388 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 2389 : (Ordered ? OMP_ord_static : OMP_sch_static); 2390 case OMPC_SCHEDULE_dynamic: 2391 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 2392 case OMPC_SCHEDULE_guided: 2393 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 2394 case OMPC_SCHEDULE_runtime: 2395 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 2396 case OMPC_SCHEDULE_auto: 2397 return Ordered ? OMP_ord_auto : OMP_sch_auto; 2398 case OMPC_SCHEDULE_unknown: 2399 assert(!Chunked && "chunk was specified but schedule kind not known"); 2400 return Ordered ? OMP_ord_static : OMP_sch_static; 2401 } 2402 llvm_unreachable("Unexpected runtime schedule"); 2403 } 2404 2405 /// \brief Map the OpenMP distribute schedule to the runtime enumeration. 2406 static OpenMPSchedType 2407 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 2408 // only static is allowed for dist_schedule 2409 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 2410 } 2411 2412 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 2413 bool Chunked) const { 2414 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2415 return Schedule == OMP_sch_static; 2416 } 2417 2418 bool CGOpenMPRuntime::isStaticNonchunked( 2419 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2420 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2421 return Schedule == OMP_dist_sch_static; 2422 } 2423 2424 2425 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 2426 auto Schedule = 2427 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 2428 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 2429 return Schedule != OMP_sch_static; 2430 } 2431 2432 static int addMonoNonMonoModifier(OpenMPSchedType Schedule, 2433 OpenMPScheduleClauseModifier M1, 2434 OpenMPScheduleClauseModifier M2) { 2435 int Modifier = 0; 2436 switch (M1) { 2437 case OMPC_SCHEDULE_MODIFIER_monotonic: 2438 Modifier = OMP_sch_modifier_monotonic; 2439 break; 2440 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2441 Modifier = OMP_sch_modifier_nonmonotonic; 2442 break; 2443 case OMPC_SCHEDULE_MODIFIER_simd: 2444 if (Schedule == OMP_sch_static_chunked) 2445 Schedule = OMP_sch_static_balanced_chunked; 2446 break; 2447 case OMPC_SCHEDULE_MODIFIER_last: 2448 case OMPC_SCHEDULE_MODIFIER_unknown: 2449 break; 2450 } 2451 switch (M2) { 2452 case OMPC_SCHEDULE_MODIFIER_monotonic: 2453 Modifier = OMP_sch_modifier_monotonic; 2454 break; 2455 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2456 Modifier = OMP_sch_modifier_nonmonotonic; 2457 break; 2458 case OMPC_SCHEDULE_MODIFIER_simd: 2459 if (Schedule == OMP_sch_static_chunked) 2460 Schedule = OMP_sch_static_balanced_chunked; 2461 break; 2462 case OMPC_SCHEDULE_MODIFIER_last: 2463 case OMPC_SCHEDULE_MODIFIER_unknown: 2464 break; 2465 } 2466 return Schedule | Modifier; 2467 } 2468 2469 void CGOpenMPRuntime::emitForDispatchInit(CodeGenFunction &CGF, 2470 SourceLocation Loc, 2471 const OpenMPScheduleTy &ScheduleKind, 2472 unsigned IVSize, bool IVSigned, 2473 bool Ordered, llvm::Value *UB, 2474 llvm::Value *Chunk) { 2475 if (!CGF.HaveInsertPoint()) 2476 return; 2477 OpenMPSchedType Schedule = 2478 getRuntimeSchedule(ScheduleKind.Schedule, Chunk != nullptr, Ordered); 2479 assert(Ordered || 2480 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 2481 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 2482 Schedule != OMP_sch_static_balanced_chunked)); 2483 // Call __kmpc_dispatch_init( 2484 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 2485 // kmp_int[32|64] lower, kmp_int[32|64] upper, 2486 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 2487 2488 // If the Chunk was not specified in the clause - use default value 1. 2489 if (Chunk == nullptr) 2490 Chunk = CGF.Builder.getIntN(IVSize, 1); 2491 llvm::Value *Args[] = { 2492 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2493 CGF.Builder.getInt32(addMonoNonMonoModifier( 2494 Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 2495 CGF.Builder.getIntN(IVSize, 0), // Lower 2496 UB, // Upper 2497 CGF.Builder.getIntN(IVSize, 1), // Stride 2498 Chunk // Chunk 2499 }; 2500 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 2501 } 2502 2503 static void emitForStaticInitCall( 2504 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 2505 llvm::Constant *ForStaticInitFunction, OpenMPSchedType Schedule, 2506 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 2507 unsigned IVSize, bool Ordered, Address IL, Address LB, Address UB, 2508 Address ST, llvm::Value *Chunk) { 2509 if (!CGF.HaveInsertPoint()) 2510 return; 2511 2512 assert(!Ordered); 2513 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 2514 Schedule == OMP_sch_static_balanced_chunked || 2515 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 2516 Schedule == OMP_dist_sch_static || 2517 Schedule == OMP_dist_sch_static_chunked); 2518 2519 // Call __kmpc_for_static_init( 2520 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 2521 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 2522 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 2523 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 2524 if (Chunk == nullptr) { 2525 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 2526 Schedule == OMP_dist_sch_static) && 2527 "expected static non-chunked schedule"); 2528 // If the Chunk was not specified in the clause - use default value 1. 2529 Chunk = CGF.Builder.getIntN(IVSize, 1); 2530 } else { 2531 assert((Schedule == OMP_sch_static_chunked || 2532 Schedule == OMP_sch_static_balanced_chunked || 2533 Schedule == OMP_ord_static_chunked || 2534 Schedule == OMP_dist_sch_static_chunked) && 2535 "expected static chunked schedule"); 2536 } 2537 llvm::Value *Args[] = { 2538 UpdateLocation, ThreadId, CGF.Builder.getInt32(addMonoNonMonoModifier( 2539 Schedule, M1, M2)), // Schedule type 2540 IL.getPointer(), // &isLastIter 2541 LB.getPointer(), // &LB 2542 UB.getPointer(), // &UB 2543 ST.getPointer(), // &Stride 2544 CGF.Builder.getIntN(IVSize, 1), // Incr 2545 Chunk // Chunk 2546 }; 2547 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 2548 } 2549 2550 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 2551 SourceLocation Loc, 2552 const OpenMPScheduleTy &ScheduleKind, 2553 unsigned IVSize, bool IVSigned, 2554 bool Ordered, Address IL, Address LB, 2555 Address UB, Address ST, 2556 llvm::Value *Chunk) { 2557 OpenMPSchedType ScheduleNum = 2558 getRuntimeSchedule(ScheduleKind.Schedule, Chunk != nullptr, Ordered); 2559 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc); 2560 auto *ThreadId = getThreadID(CGF, Loc); 2561 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned); 2562 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2563 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, IVSize, 2564 Ordered, IL, LB, UB, ST, Chunk); 2565 } 2566 2567 void CGOpenMPRuntime::emitDistributeStaticInit( 2568 CodeGenFunction &CGF, SourceLocation Loc, 2569 OpenMPDistScheduleClauseKind SchedKind, unsigned IVSize, bool IVSigned, 2570 bool Ordered, Address IL, Address LB, Address UB, Address ST, 2571 llvm::Value *Chunk) { 2572 OpenMPSchedType ScheduleNum = getRuntimeSchedule(SchedKind, Chunk != nullptr); 2573 auto *UpdatedLocation = emitUpdateLocation(CGF, Loc); 2574 auto *ThreadId = getThreadID(CGF, Loc); 2575 auto *StaticInitFunction = createForStaticInitFunction(IVSize, IVSigned); 2576 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2577 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 2578 OMPC_SCHEDULE_MODIFIER_unknown, IVSize, Ordered, IL, LB, 2579 UB, ST, Chunk); 2580 } 2581 2582 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 2583 SourceLocation Loc) { 2584 if (!CGF.HaveInsertPoint()) 2585 return; 2586 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 2587 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2588 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 2589 Args); 2590 } 2591 2592 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 2593 SourceLocation Loc, 2594 unsigned IVSize, 2595 bool IVSigned) { 2596 if (!CGF.HaveInsertPoint()) 2597 return; 2598 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 2599 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2600 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 2601 } 2602 2603 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 2604 SourceLocation Loc, unsigned IVSize, 2605 bool IVSigned, Address IL, 2606 Address LB, Address UB, 2607 Address ST) { 2608 // Call __kmpc_dispatch_next( 2609 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 2610 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 2611 // kmp_int[32|64] *p_stride); 2612 llvm::Value *Args[] = { 2613 emitUpdateLocation(CGF, Loc), 2614 getThreadID(CGF, Loc), 2615 IL.getPointer(), // &isLastIter 2616 LB.getPointer(), // &Lower 2617 UB.getPointer(), // &Upper 2618 ST.getPointer() // &Stride 2619 }; 2620 llvm::Value *Call = 2621 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 2622 return CGF.EmitScalarConversion( 2623 Call, CGF.getContext().getIntTypeForBitwidth(32, /* Signed */ true), 2624 CGF.getContext().BoolTy, Loc); 2625 } 2626 2627 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 2628 llvm::Value *NumThreads, 2629 SourceLocation Loc) { 2630 if (!CGF.HaveInsertPoint()) 2631 return; 2632 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 2633 llvm::Value *Args[] = { 2634 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2635 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 2636 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 2637 Args); 2638 } 2639 2640 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 2641 OpenMPProcBindClauseKind ProcBind, 2642 SourceLocation Loc) { 2643 if (!CGF.HaveInsertPoint()) 2644 return; 2645 // Constants for proc bind value accepted by the runtime. 2646 enum ProcBindTy { 2647 ProcBindFalse = 0, 2648 ProcBindTrue, 2649 ProcBindMaster, 2650 ProcBindClose, 2651 ProcBindSpread, 2652 ProcBindIntel, 2653 ProcBindDefault 2654 } RuntimeProcBind; 2655 switch (ProcBind) { 2656 case OMPC_PROC_BIND_master: 2657 RuntimeProcBind = ProcBindMaster; 2658 break; 2659 case OMPC_PROC_BIND_close: 2660 RuntimeProcBind = ProcBindClose; 2661 break; 2662 case OMPC_PROC_BIND_spread: 2663 RuntimeProcBind = ProcBindSpread; 2664 break; 2665 case OMPC_PROC_BIND_unknown: 2666 llvm_unreachable("Unsupported proc_bind value."); 2667 } 2668 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 2669 llvm::Value *Args[] = { 2670 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2671 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; 2672 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 2673 } 2674 2675 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 2676 SourceLocation Loc) { 2677 if (!CGF.HaveInsertPoint()) 2678 return; 2679 // Build call void __kmpc_flush(ident_t *loc) 2680 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 2681 emitUpdateLocation(CGF, Loc)); 2682 } 2683 2684 namespace { 2685 /// \brief Indexes of fields for type kmp_task_t. 2686 enum KmpTaskTFields { 2687 /// \brief List of shared variables. 2688 KmpTaskTShareds, 2689 /// \brief Task routine. 2690 KmpTaskTRoutine, 2691 /// \brief Partition id for the untied tasks. 2692 KmpTaskTPartId, 2693 /// Function with call of destructors for private variables. 2694 Data1, 2695 /// Task priority. 2696 Data2, 2697 /// (Taskloops only) Lower bound. 2698 KmpTaskTLowerBound, 2699 /// (Taskloops only) Upper bound. 2700 KmpTaskTUpperBound, 2701 /// (Taskloops only) Stride. 2702 KmpTaskTStride, 2703 /// (Taskloops only) Is last iteration flag. 2704 KmpTaskTLastIter, 2705 }; 2706 } // anonymous namespace 2707 2708 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 2709 // FIXME: Add other entries type when they become supported. 2710 return OffloadEntriesTargetRegion.empty(); 2711 } 2712 2713 /// \brief Initialize target region entry. 2714 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2715 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2716 StringRef ParentName, unsigned LineNum, 2717 unsigned Order) { 2718 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 2719 "only required for the device " 2720 "code generation."); 2721 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 2722 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 2723 /*Flags=*/0); 2724 ++OffloadingEntriesNum; 2725 } 2726 2727 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2728 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2729 StringRef ParentName, unsigned LineNum, 2730 llvm::Constant *Addr, llvm::Constant *ID, 2731 int32_t Flags) { 2732 // If we are emitting code for a target, the entry is already initialized, 2733 // only has to be registered. 2734 if (CGM.getLangOpts().OpenMPIsDevice) { 2735 assert(hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) && 2736 "Entry must exist."); 2737 auto &Entry = 2738 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 2739 assert(Entry.isValid() && "Entry not initialized!"); 2740 Entry.setAddress(Addr); 2741 Entry.setID(ID); 2742 Entry.setFlags(Flags); 2743 return; 2744 } else { 2745 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum++, Addr, ID, Flags); 2746 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 2747 } 2748 } 2749 2750 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 2751 unsigned DeviceID, unsigned FileID, StringRef ParentName, 2752 unsigned LineNum) const { 2753 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 2754 if (PerDevice == OffloadEntriesTargetRegion.end()) 2755 return false; 2756 auto PerFile = PerDevice->second.find(FileID); 2757 if (PerFile == PerDevice->second.end()) 2758 return false; 2759 auto PerParentName = PerFile->second.find(ParentName); 2760 if (PerParentName == PerFile->second.end()) 2761 return false; 2762 auto PerLine = PerParentName->second.find(LineNum); 2763 if (PerLine == PerParentName->second.end()) 2764 return false; 2765 // Fail if this entry is already registered. 2766 if (PerLine->second.getAddress() || PerLine->second.getID()) 2767 return false; 2768 return true; 2769 } 2770 2771 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 2772 const OffloadTargetRegionEntryInfoActTy &Action) { 2773 // Scan all target region entries and perform the provided action. 2774 for (auto &D : OffloadEntriesTargetRegion) 2775 for (auto &F : D.second) 2776 for (auto &P : F.second) 2777 for (auto &L : P.second) 2778 Action(D.first, F.first, P.first(), L.first, L.second); 2779 } 2780 2781 /// \brief Create a Ctor/Dtor-like function whose body is emitted through 2782 /// \a Codegen. This is used to emit the two functions that register and 2783 /// unregister the descriptor of the current compilation unit. 2784 static llvm::Function * 2785 createOffloadingBinaryDescriptorFunction(CodeGenModule &CGM, StringRef Name, 2786 const RegionCodeGenTy &Codegen) { 2787 auto &C = CGM.getContext(); 2788 FunctionArgList Args; 2789 ImplicitParamDecl DummyPtr(C, /*DC=*/nullptr, SourceLocation(), 2790 /*Id=*/nullptr, C.VoidPtrTy); 2791 Args.push_back(&DummyPtr); 2792 2793 CodeGenFunction CGF(CGM); 2794 auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 2795 auto FTy = CGM.getTypes().GetFunctionType(FI); 2796 auto *Fn = 2797 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, SourceLocation()); 2798 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FI, Args, SourceLocation()); 2799 Codegen(CGF); 2800 CGF.FinishFunction(); 2801 return Fn; 2802 } 2803 2804 llvm::Function * 2805 CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() { 2806 2807 // If we don't have entries or if we are emitting code for the device, we 2808 // don't need to do anything. 2809 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty()) 2810 return nullptr; 2811 2812 auto &M = CGM.getModule(); 2813 auto &C = CGM.getContext(); 2814 2815 // Get list of devices we care about 2816 auto &Devices = CGM.getLangOpts().OMPTargetTriples; 2817 2818 // We should be creating an offloading descriptor only if there are devices 2819 // specified. 2820 assert(!Devices.empty() && "No OpenMP offloading devices??"); 2821 2822 // Create the external variables that will point to the begin and end of the 2823 // host entries section. These will be defined by the linker. 2824 auto *OffloadEntryTy = 2825 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()); 2826 llvm::GlobalVariable *HostEntriesBegin = new llvm::GlobalVariable( 2827 M, OffloadEntryTy, /*isConstant=*/true, 2828 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr, 2829 ".omp_offloading.entries_begin"); 2830 llvm::GlobalVariable *HostEntriesEnd = new llvm::GlobalVariable( 2831 M, OffloadEntryTy, /*isConstant=*/true, 2832 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr, 2833 ".omp_offloading.entries_end"); 2834 2835 // Create all device images 2836 auto *DeviceImageTy = cast<llvm::StructType>( 2837 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy())); 2838 ConstantInitBuilder DeviceImagesBuilder(CGM); 2839 auto DeviceImagesEntries = DeviceImagesBuilder.beginArray(DeviceImageTy); 2840 2841 for (unsigned i = 0; i < Devices.size(); ++i) { 2842 StringRef T = Devices[i].getTriple(); 2843 auto *ImgBegin = new llvm::GlobalVariable( 2844 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, 2845 /*Initializer=*/nullptr, 2846 Twine(".omp_offloading.img_start.") + Twine(T)); 2847 auto *ImgEnd = new llvm::GlobalVariable( 2848 M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, 2849 /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T)); 2850 2851 auto Dev = DeviceImagesEntries.beginStruct(DeviceImageTy); 2852 Dev.add(ImgBegin); 2853 Dev.add(ImgEnd); 2854 Dev.add(HostEntriesBegin); 2855 Dev.add(HostEntriesEnd); 2856 Dev.finishAndAddTo(DeviceImagesEntries); 2857 } 2858 2859 // Create device images global array. 2860 llvm::GlobalVariable *DeviceImages = 2861 DeviceImagesEntries.finishAndCreateGlobal(".omp_offloading.device_images", 2862 CGM.getPointerAlign(), 2863 /*isConstant=*/true); 2864 DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 2865 2866 // This is a Zero array to be used in the creation of the constant expressions 2867 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty), 2868 llvm::Constant::getNullValue(CGM.Int32Ty)}; 2869 2870 // Create the target region descriptor. 2871 auto *BinaryDescriptorTy = cast<llvm::StructType>( 2872 CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy())); 2873 ConstantInitBuilder DescBuilder(CGM); 2874 auto DescInit = DescBuilder.beginStruct(BinaryDescriptorTy); 2875 DescInit.addInt(CGM.Int32Ty, Devices.size()); 2876 DescInit.add(llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(), 2877 DeviceImages, 2878 Index)); 2879 DescInit.add(HostEntriesBegin); 2880 DescInit.add(HostEntriesEnd); 2881 2882 auto *Desc = DescInit.finishAndCreateGlobal(".omp_offloading.descriptor", 2883 CGM.getPointerAlign(), 2884 /*isConstant=*/true); 2885 2886 // Emit code to register or unregister the descriptor at execution 2887 // startup or closing, respectively. 2888 2889 // Create a variable to drive the registration and unregistration of the 2890 // descriptor, so we can reuse the logic that emits Ctors and Dtors. 2891 auto *IdentInfo = &C.Idents.get(".omp_offloading.reg_unreg_var"); 2892 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), SourceLocation(), 2893 IdentInfo, C.CharTy); 2894 2895 auto *UnRegFn = createOffloadingBinaryDescriptorFunction( 2896 CGM, ".omp_offloading.descriptor_unreg", 2897 [&](CodeGenFunction &CGF, PrePostActionTy &) { 2898 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_unregister_lib), 2899 Desc); 2900 }); 2901 auto *RegFn = createOffloadingBinaryDescriptorFunction( 2902 CGM, ".omp_offloading.descriptor_reg", 2903 [&](CodeGenFunction &CGF, PrePostActionTy &) { 2904 CGF.EmitCallOrInvoke(createRuntimeFunction(OMPRTL__tgt_register_lib), 2905 Desc); 2906 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc); 2907 }); 2908 return RegFn; 2909 } 2910 2911 void CGOpenMPRuntime::createOffloadEntry(llvm::Constant *ID, 2912 llvm::Constant *Addr, uint64_t Size, 2913 int32_t Flags) { 2914 StringRef Name = Addr->getName(); 2915 auto *TgtOffloadEntryType = cast<llvm::StructType>( 2916 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy())); 2917 llvm::LLVMContext &C = CGM.getModule().getContext(); 2918 llvm::Module &M = CGM.getModule(); 2919 2920 // Make sure the address has the right type. 2921 llvm::Constant *AddrPtr = llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy); 2922 2923 // Create constant string with the name. 2924 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 2925 2926 llvm::GlobalVariable *Str = 2927 new llvm::GlobalVariable(M, StrPtrInit->getType(), /*isConstant=*/true, 2928 llvm::GlobalValue::InternalLinkage, StrPtrInit, 2929 ".omp_offloading.entry_name"); 2930 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 2931 llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy); 2932 2933 // We can't have any padding between symbols, so we need to have 1-byte 2934 // alignment. 2935 auto Align = CharUnits::fromQuantity(1); 2936 2937 // Create the entry struct. 2938 ConstantInitBuilder EntryBuilder(CGM); 2939 auto EntryInit = EntryBuilder.beginStruct(TgtOffloadEntryType); 2940 EntryInit.add(AddrPtr); 2941 EntryInit.add(StrPtr); 2942 EntryInit.addInt(CGM.SizeTy, Size); 2943 EntryInit.addInt(CGM.Int32Ty, Flags); 2944 EntryInit.addInt(CGM.Int32Ty, 0); 2945 llvm::GlobalVariable *Entry = 2946 EntryInit.finishAndCreateGlobal(".omp_offloading.entry", 2947 Align, 2948 /*constant*/ true, 2949 llvm::GlobalValue::ExternalLinkage); 2950 2951 // The entry has to be created in the section the linker expects it to be. 2952 Entry->setSection(".omp_offloading.entries"); 2953 } 2954 2955 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 2956 // Emit the offloading entries and metadata so that the device codegen side 2957 // can easily figure out what to emit. The produced metadata looks like 2958 // this: 2959 // 2960 // !omp_offload.info = !{!1, ...} 2961 // 2962 // Right now we only generate metadata for function that contain target 2963 // regions. 2964 2965 // If we do not have entries, we dont need to do anything. 2966 if (OffloadEntriesInfoManager.empty()) 2967 return; 2968 2969 llvm::Module &M = CGM.getModule(); 2970 llvm::LLVMContext &C = M.getContext(); 2971 SmallVector<OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16> 2972 OrderedEntries(OffloadEntriesInfoManager.size()); 2973 2974 // Create the offloading info metadata node. 2975 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 2976 2977 // Auxiliar methods to create metadata values and strings. 2978 auto getMDInt = [&](unsigned v) { 2979 return llvm::ConstantAsMetadata::get( 2980 llvm::ConstantInt::get(llvm::Type::getInt32Ty(C), v)); 2981 }; 2982 2983 auto getMDString = [&](StringRef v) { return llvm::MDString::get(C, v); }; 2984 2985 // Create function that emits metadata for each target region entry; 2986 auto &&TargetRegionMetadataEmitter = [&]( 2987 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line, 2988 OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 2989 llvm::SmallVector<llvm::Metadata *, 32> Ops; 2990 // Generate metadata for target regions. Each entry of this metadata 2991 // contains: 2992 // - Entry 0 -> Kind of this type of metadata (0). 2993 // - Entry 1 -> Device ID of the file where the entry was identified. 2994 // - Entry 2 -> File ID of the file where the entry was identified. 2995 // - Entry 3 -> Mangled name of the function where the entry was identified. 2996 // - Entry 4 -> Line in the file where the entry was identified. 2997 // - Entry 5 -> Order the entry was created. 2998 // The first element of the metadata node is the kind. 2999 Ops.push_back(getMDInt(E.getKind())); 3000 Ops.push_back(getMDInt(DeviceID)); 3001 Ops.push_back(getMDInt(FileID)); 3002 Ops.push_back(getMDString(ParentName)); 3003 Ops.push_back(getMDInt(Line)); 3004 Ops.push_back(getMDInt(E.getOrder())); 3005 3006 // Save this entry in the right position of the ordered entries array. 3007 OrderedEntries[E.getOrder()] = &E; 3008 3009 // Add metadata to the named metadata node. 3010 MD->addOperand(llvm::MDNode::get(C, Ops)); 3011 }; 3012 3013 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 3014 TargetRegionMetadataEmitter); 3015 3016 for (auto *E : OrderedEntries) { 3017 assert(E && "All ordered entries must exist!"); 3018 if (auto *CE = 3019 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 3020 E)) { 3021 assert(CE->getID() && CE->getAddress() && 3022 "Entry ID and Addr are invalid!"); 3023 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0); 3024 } else 3025 llvm_unreachable("Unsupported entry kind."); 3026 } 3027 } 3028 3029 /// \brief Loads all the offload entries information from the host IR 3030 /// metadata. 3031 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 3032 // If we are in target mode, load the metadata from the host IR. This code has 3033 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 3034 3035 if (!CGM.getLangOpts().OpenMPIsDevice) 3036 return; 3037 3038 if (CGM.getLangOpts().OMPHostIRFile.empty()) 3039 return; 3040 3041 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 3042 if (Buf.getError()) 3043 return; 3044 3045 llvm::LLVMContext C; 3046 auto ME = expectedToErrorOrAndEmitErrors( 3047 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 3048 3049 if (ME.getError()) 3050 return; 3051 3052 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 3053 if (!MD) 3054 return; 3055 3056 for (auto I : MD->operands()) { 3057 llvm::MDNode *MN = cast<llvm::MDNode>(I); 3058 3059 auto getMDInt = [&](unsigned Idx) { 3060 llvm::ConstantAsMetadata *V = 3061 cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 3062 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 3063 }; 3064 3065 auto getMDString = [&](unsigned Idx) { 3066 llvm::MDString *V = cast<llvm::MDString>(MN->getOperand(Idx)); 3067 return V->getString(); 3068 }; 3069 3070 switch (getMDInt(0)) { 3071 default: 3072 llvm_unreachable("Unexpected metadata!"); 3073 break; 3074 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3075 OFFLOAD_ENTRY_INFO_TARGET_REGION: 3076 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 3077 /*DeviceID=*/getMDInt(1), /*FileID=*/getMDInt(2), 3078 /*ParentName=*/getMDString(3), /*Line=*/getMDInt(4), 3079 /*Order=*/getMDInt(5)); 3080 break; 3081 } 3082 } 3083 } 3084 3085 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 3086 if (!KmpRoutineEntryPtrTy) { 3087 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 3088 auto &C = CGM.getContext(); 3089 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 3090 FunctionProtoType::ExtProtoInfo EPI; 3091 KmpRoutineEntryPtrQTy = C.getPointerType( 3092 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 3093 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 3094 } 3095 } 3096 3097 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 3098 QualType FieldTy) { 3099 auto *Field = FieldDecl::Create( 3100 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 3101 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 3102 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 3103 Field->setAccess(AS_public); 3104 DC->addDecl(Field); 3105 return Field; 3106 } 3107 3108 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 3109 3110 // Make sure the type of the entry is already created. This is the type we 3111 // have to create: 3112 // struct __tgt_offload_entry{ 3113 // void *addr; // Pointer to the offload entry info. 3114 // // (function or global) 3115 // char *name; // Name of the function or global. 3116 // size_t size; // Size of the entry info (0 if it a function). 3117 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 3118 // int32_t reserved; // Reserved, to use by the runtime library. 3119 // }; 3120 if (TgtOffloadEntryQTy.isNull()) { 3121 ASTContext &C = CGM.getContext(); 3122 auto *RD = C.buildImplicitRecord("__tgt_offload_entry"); 3123 RD->startDefinition(); 3124 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3125 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 3126 addFieldToRecordDecl(C, RD, C.getSizeType()); 3127 addFieldToRecordDecl( 3128 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3129 addFieldToRecordDecl( 3130 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3131 RD->completeDefinition(); 3132 TgtOffloadEntryQTy = C.getRecordType(RD); 3133 } 3134 return TgtOffloadEntryQTy; 3135 } 3136 3137 QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { 3138 // These are the types we need to build: 3139 // struct __tgt_device_image{ 3140 // void *ImageStart; // Pointer to the target code start. 3141 // void *ImageEnd; // Pointer to the target code end. 3142 // // We also add the host entries to the device image, as it may be useful 3143 // // for the target runtime to have access to that information. 3144 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all 3145 // // the entries. 3146 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 3147 // // entries (non inclusive). 3148 // }; 3149 if (TgtDeviceImageQTy.isNull()) { 3150 ASTContext &C = CGM.getContext(); 3151 auto *RD = C.buildImplicitRecord("__tgt_device_image"); 3152 RD->startDefinition(); 3153 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3154 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3155 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 3156 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 3157 RD->completeDefinition(); 3158 TgtDeviceImageQTy = C.getRecordType(RD); 3159 } 3160 return TgtDeviceImageQTy; 3161 } 3162 3163 QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { 3164 // struct __tgt_bin_desc{ 3165 // int32_t NumDevices; // Number of devices supported. 3166 // __tgt_device_image *DeviceImages; // Arrays of device images 3167 // // (one per device). 3168 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the 3169 // // entries. 3170 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 3171 // // entries (non inclusive). 3172 // }; 3173 if (TgtBinaryDescriptorQTy.isNull()) { 3174 ASTContext &C = CGM.getContext(); 3175 auto *RD = C.buildImplicitRecord("__tgt_bin_desc"); 3176 RD->startDefinition(); 3177 addFieldToRecordDecl( 3178 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3179 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); 3180 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 3181 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 3182 RD->completeDefinition(); 3183 TgtBinaryDescriptorQTy = C.getRecordType(RD); 3184 } 3185 return TgtBinaryDescriptorQTy; 3186 } 3187 3188 namespace { 3189 struct PrivateHelpersTy { 3190 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 3191 const VarDecl *PrivateElemInit) 3192 : Original(Original), PrivateCopy(PrivateCopy), 3193 PrivateElemInit(PrivateElemInit) {} 3194 const VarDecl *Original; 3195 const VarDecl *PrivateCopy; 3196 const VarDecl *PrivateElemInit; 3197 }; 3198 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 3199 } // anonymous namespace 3200 3201 static RecordDecl * 3202 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 3203 if (!Privates.empty()) { 3204 auto &C = CGM.getContext(); 3205 // Build struct .kmp_privates_t. { 3206 // /* private vars */ 3207 // }; 3208 auto *RD = C.buildImplicitRecord(".kmp_privates.t"); 3209 RD->startDefinition(); 3210 for (auto &&Pair : Privates) { 3211 auto *VD = Pair.second.Original; 3212 auto Type = VD->getType(); 3213 Type = Type.getNonReferenceType(); 3214 auto *FD = addFieldToRecordDecl(C, RD, Type); 3215 if (VD->hasAttrs()) { 3216 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 3217 E(VD->getAttrs().end()); 3218 I != E; ++I) 3219 FD->addAttr(*I); 3220 } 3221 } 3222 RD->completeDefinition(); 3223 return RD; 3224 } 3225 return nullptr; 3226 } 3227 3228 static RecordDecl * 3229 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 3230 QualType KmpInt32Ty, 3231 QualType KmpRoutineEntryPointerQTy) { 3232 auto &C = CGM.getContext(); 3233 // Build struct kmp_task_t { 3234 // void * shareds; 3235 // kmp_routine_entry_t routine; 3236 // kmp_int32 part_id; 3237 // kmp_cmplrdata_t data1; 3238 // kmp_cmplrdata_t data2; 3239 // For taskloops additional fields: 3240 // kmp_uint64 lb; 3241 // kmp_uint64 ub; 3242 // kmp_int64 st; 3243 // kmp_int32 liter; 3244 // }; 3245 auto *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 3246 UD->startDefinition(); 3247 addFieldToRecordDecl(C, UD, KmpInt32Ty); 3248 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 3249 UD->completeDefinition(); 3250 QualType KmpCmplrdataTy = C.getRecordType(UD); 3251 auto *RD = C.buildImplicitRecord("kmp_task_t"); 3252 RD->startDefinition(); 3253 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3254 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 3255 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3256 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3257 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3258 if (isOpenMPTaskLoopDirective(Kind)) { 3259 QualType KmpUInt64Ty = 3260 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 3261 QualType KmpInt64Ty = 3262 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 3263 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3264 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3265 addFieldToRecordDecl(C, RD, KmpInt64Ty); 3266 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3267 } 3268 RD->completeDefinition(); 3269 return RD; 3270 } 3271 3272 static RecordDecl * 3273 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 3274 ArrayRef<PrivateDataTy> Privates) { 3275 auto &C = CGM.getContext(); 3276 // Build struct kmp_task_t_with_privates { 3277 // kmp_task_t task_data; 3278 // .kmp_privates_t. privates; 3279 // }; 3280 auto *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 3281 RD->startDefinition(); 3282 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 3283 if (auto *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) { 3284 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 3285 } 3286 RD->completeDefinition(); 3287 return RD; 3288 } 3289 3290 /// \brief Emit a proxy function which accepts kmp_task_t as the second 3291 /// argument. 3292 /// \code 3293 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 3294 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 3295 /// For taskloops: 3296 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3297 /// tt->shareds); 3298 /// return 0; 3299 /// } 3300 /// \endcode 3301 static llvm::Value * 3302 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 3303 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 3304 QualType KmpTaskTWithPrivatesPtrQTy, 3305 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 3306 QualType SharedsPtrTy, llvm::Value *TaskFunction, 3307 llvm::Value *TaskPrivatesMap) { 3308 auto &C = CGM.getContext(); 3309 FunctionArgList Args; 3310 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty); 3311 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, 3312 /*Id=*/nullptr, 3313 KmpTaskTWithPrivatesPtrQTy.withRestrict()); 3314 Args.push_back(&GtidArg); 3315 Args.push_back(&TaskTypeArg); 3316 auto &TaskEntryFnInfo = 3317 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3318 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 3319 auto *TaskEntry = 3320 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage, 3321 ".omp_task_entry.", &CGM.getModule()); 3322 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskEntry, TaskEntryFnInfo); 3323 CodeGenFunction CGF(CGM); 3324 CGF.disableDebugInfo(); 3325 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args); 3326 3327 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 3328 // tt, 3329 // For taskloops: 3330 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3331 // tt->task_data.shareds); 3332 auto *GtidParam = CGF.EmitLoadOfScalar( 3333 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 3334 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3335 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3336 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3337 auto *KmpTaskTWithPrivatesQTyRD = 3338 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3339 LValue Base = 3340 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3341 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 3342 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 3343 auto PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 3344 auto *PartidParam = PartIdLVal.getPointer(); 3345 3346 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 3347 auto SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 3348 auto *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3349 CGF.EmitLoadOfLValue(SharedsLVal, Loc).getScalarVal(), 3350 CGF.ConvertTypeForMem(SharedsPtrTy)); 3351 3352 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 3353 llvm::Value *PrivatesParam; 3354 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 3355 auto PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 3356 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3357 PrivatesLVal.getPointer(), CGF.VoidPtrTy); 3358 } else 3359 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3360 3361 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 3362 TaskPrivatesMap, 3363 CGF.Builder 3364 .CreatePointerBitCastOrAddrSpaceCast( 3365 TDBase.getAddress(), CGF.VoidPtrTy) 3366 .getPointer()}; 3367 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 3368 std::end(CommonArgs)); 3369 if (isOpenMPTaskLoopDirective(Kind)) { 3370 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 3371 auto LBLVal = CGF.EmitLValueForField(Base, *LBFI); 3372 auto *LBParam = CGF.EmitLoadOfLValue(LBLVal, Loc).getScalarVal(); 3373 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 3374 auto UBLVal = CGF.EmitLValueForField(Base, *UBFI); 3375 auto *UBParam = CGF.EmitLoadOfLValue(UBLVal, Loc).getScalarVal(); 3376 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 3377 auto StLVal = CGF.EmitLValueForField(Base, *StFI); 3378 auto *StParam = CGF.EmitLoadOfLValue(StLVal, Loc).getScalarVal(); 3379 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3380 auto LILVal = CGF.EmitLValueForField(Base, *LIFI); 3381 auto *LIParam = CGF.EmitLoadOfLValue(LILVal, Loc).getScalarVal(); 3382 CallArgs.push_back(LBParam); 3383 CallArgs.push_back(UBParam); 3384 CallArgs.push_back(StParam); 3385 CallArgs.push_back(LIParam); 3386 } 3387 CallArgs.push_back(SharedsParam); 3388 3389 CGF.EmitCallOrInvoke(TaskFunction, CallArgs); 3390 CGF.EmitStoreThroughLValue( 3391 RValue::get(CGF.Builder.getInt32(/*C=*/0)), 3392 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 3393 CGF.FinishFunction(); 3394 return TaskEntry; 3395 } 3396 3397 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 3398 SourceLocation Loc, 3399 QualType KmpInt32Ty, 3400 QualType KmpTaskTWithPrivatesPtrQTy, 3401 QualType KmpTaskTWithPrivatesQTy) { 3402 auto &C = CGM.getContext(); 3403 FunctionArgList Args; 3404 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty); 3405 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, 3406 /*Id=*/nullptr, 3407 KmpTaskTWithPrivatesPtrQTy.withRestrict()); 3408 Args.push_back(&GtidArg); 3409 Args.push_back(&TaskTypeArg); 3410 FunctionType::ExtInfo Info; 3411 auto &DestructorFnInfo = 3412 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3413 auto *DestructorFnTy = CGM.getTypes().GetFunctionType(DestructorFnInfo); 3414 auto *DestructorFn = 3415 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 3416 ".omp_task_destructor.", &CGM.getModule()); 3417 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, DestructorFn, 3418 DestructorFnInfo); 3419 CodeGenFunction CGF(CGM); 3420 CGF.disableDebugInfo(); 3421 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 3422 Args); 3423 3424 LValue Base = CGF.EmitLoadOfPointerLValue( 3425 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3426 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3427 auto *KmpTaskTWithPrivatesQTyRD = 3428 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3429 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3430 Base = CGF.EmitLValueForField(Base, *FI); 3431 for (auto *Field : 3432 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 3433 if (auto DtorKind = Field->getType().isDestructedType()) { 3434 auto FieldLValue = CGF.EmitLValueForField(Base, Field); 3435 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType()); 3436 } 3437 } 3438 CGF.FinishFunction(); 3439 return DestructorFn; 3440 } 3441 3442 /// \brief Emit a privates mapping function for correct handling of private and 3443 /// firstprivate variables. 3444 /// \code 3445 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 3446 /// **noalias priv1,..., <tyn> **noalias privn) { 3447 /// *priv1 = &.privates.priv1; 3448 /// ...; 3449 /// *privn = &.privates.privn; 3450 /// } 3451 /// \endcode 3452 static llvm::Value * 3453 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 3454 ArrayRef<const Expr *> PrivateVars, 3455 ArrayRef<const Expr *> FirstprivateVars, 3456 ArrayRef<const Expr *> LastprivateVars, 3457 QualType PrivatesQTy, 3458 ArrayRef<PrivateDataTy> Privates) { 3459 auto &C = CGM.getContext(); 3460 FunctionArgList Args; 3461 ImplicitParamDecl TaskPrivatesArg( 3462 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3463 C.getPointerType(PrivatesQTy).withConst().withRestrict()); 3464 Args.push_back(&TaskPrivatesArg); 3465 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 3466 unsigned Counter = 1; 3467 for (auto *E: PrivateVars) { 3468 Args.push_back(ImplicitParamDecl::Create( 3469 C, /*DC=*/nullptr, Loc, 3470 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) 3471 .withConst() 3472 .withRestrict())); 3473 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3474 PrivateVarsPos[VD] = Counter; 3475 ++Counter; 3476 } 3477 for (auto *E : FirstprivateVars) { 3478 Args.push_back(ImplicitParamDecl::Create( 3479 C, /*DC=*/nullptr, Loc, 3480 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) 3481 .withConst() 3482 .withRestrict())); 3483 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3484 PrivateVarsPos[VD] = Counter; 3485 ++Counter; 3486 } 3487 for (auto *E: LastprivateVars) { 3488 Args.push_back(ImplicitParamDecl::Create( 3489 C, /*DC=*/nullptr, Loc, 3490 /*Id=*/nullptr, C.getPointerType(C.getPointerType(E->getType())) 3491 .withConst() 3492 .withRestrict())); 3493 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3494 PrivateVarsPos[VD] = Counter; 3495 ++Counter; 3496 } 3497 auto &TaskPrivatesMapFnInfo = 3498 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3499 auto *TaskPrivatesMapTy = 3500 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 3501 auto *TaskPrivatesMap = llvm::Function::Create( 3502 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, 3503 ".omp_task_privates_map.", &CGM.getModule()); 3504 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskPrivatesMap, 3505 TaskPrivatesMapFnInfo); 3506 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 3507 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 3508 CodeGenFunction CGF(CGM); 3509 CGF.disableDebugInfo(); 3510 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 3511 TaskPrivatesMapFnInfo, Args); 3512 3513 // *privi = &.privates.privi; 3514 LValue Base = CGF.EmitLoadOfPointerLValue( 3515 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 3516 TaskPrivatesArg.getType()->castAs<PointerType>()); 3517 auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 3518 Counter = 0; 3519 for (auto *Field : PrivatesQTyRD->fields()) { 3520 auto FieldLVal = CGF.EmitLValueForField(Base, Field); 3521 auto *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 3522 auto RefLVal = CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 3523 auto RefLoadLVal = CGF.EmitLoadOfPointerLValue( 3524 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>()); 3525 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal); 3526 ++Counter; 3527 } 3528 CGF.FinishFunction(); 3529 return TaskPrivatesMap; 3530 } 3531 3532 static int array_pod_sort_comparator(const PrivateDataTy *P1, 3533 const PrivateDataTy *P2) { 3534 return P1->first < P2->first ? 1 : (P2->first < P1->first ? -1 : 0); 3535 } 3536 3537 /// Emit initialization for private variables in task-based directives. 3538 static void emitPrivatesInit(CodeGenFunction &CGF, 3539 const OMPExecutableDirective &D, 3540 Address KmpTaskSharedsPtr, LValue TDBase, 3541 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3542 QualType SharedsTy, QualType SharedsPtrTy, 3543 const OMPTaskDataTy &Data, 3544 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 3545 auto &C = CGF.getContext(); 3546 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3547 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 3548 LValue SrcBase; 3549 if (!Data.FirstprivateVars.empty()) { 3550 SrcBase = CGF.MakeAddrLValue( 3551 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3552 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 3553 SharedsTy); 3554 } 3555 CodeGenFunction::CGCapturedStmtInfo CapturesInfo( 3556 cast<CapturedStmt>(*D.getAssociatedStmt())); 3557 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 3558 for (auto &&Pair : Privates) { 3559 auto *VD = Pair.second.PrivateCopy; 3560 auto *Init = VD->getAnyInitializer(); 3561 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 3562 !CGF.isTrivialInitializer(Init)))) { 3563 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 3564 if (auto *Elem = Pair.second.PrivateElemInit) { 3565 auto *OriginalVD = Pair.second.Original; 3566 auto *SharedField = CapturesInfo.lookup(OriginalVD); 3567 auto SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 3568 SharedRefLValue = CGF.MakeAddrLValue( 3569 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)), 3570 SharedRefLValue.getType(), AlignmentSource::Decl); 3571 QualType Type = OriginalVD->getType(); 3572 if (Type->isArrayType()) { 3573 // Initialize firstprivate array. 3574 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 3575 // Perform simple memcpy. 3576 CGF.EmitAggregateAssign(PrivateLValue.getAddress(), 3577 SharedRefLValue.getAddress(), Type); 3578 } else { 3579 // Initialize firstprivate array using element-by-element 3580 // intialization. 3581 CGF.EmitOMPAggregateAssign( 3582 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type, 3583 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 3584 Address SrcElement) { 3585 // Clean up any temporaries needed by the initialization. 3586 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3587 InitScope.addPrivate( 3588 Elem, [SrcElement]() -> Address { return SrcElement; }); 3589 (void)InitScope.Privatize(); 3590 // Emit initialization for single element. 3591 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 3592 CGF, &CapturesInfo); 3593 CGF.EmitAnyExprToMem(Init, DestElement, 3594 Init->getType().getQualifiers(), 3595 /*IsInitializer=*/false); 3596 }); 3597 } 3598 } else { 3599 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3600 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address { 3601 return SharedRefLValue.getAddress(); 3602 }); 3603 (void)InitScope.Privatize(); 3604 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 3605 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 3606 /*capturedByInit=*/false); 3607 } 3608 } else 3609 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 3610 } 3611 ++FI; 3612 } 3613 } 3614 3615 /// Check if duplication function is required for taskloops. 3616 static bool checkInitIsRequired(CodeGenFunction &CGF, 3617 ArrayRef<PrivateDataTy> Privates) { 3618 bool InitRequired = false; 3619 for (auto &&Pair : Privates) { 3620 auto *VD = Pair.second.PrivateCopy; 3621 auto *Init = VD->getAnyInitializer(); 3622 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 3623 !CGF.isTrivialInitializer(Init)); 3624 } 3625 return InitRequired; 3626 } 3627 3628 3629 /// Emit task_dup function (for initialization of 3630 /// private/firstprivate/lastprivate vars and last_iter flag) 3631 /// \code 3632 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 3633 /// lastpriv) { 3634 /// // setup lastprivate flag 3635 /// task_dst->last = lastpriv; 3636 /// // could be constructor calls here... 3637 /// } 3638 /// \endcode 3639 static llvm::Value * 3640 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 3641 const OMPExecutableDirective &D, 3642 QualType KmpTaskTWithPrivatesPtrQTy, 3643 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3644 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 3645 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 3646 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 3647 auto &C = CGM.getContext(); 3648 FunctionArgList Args; 3649 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, 3650 /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy); 3651 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, 3652 /*Id=*/nullptr, KmpTaskTWithPrivatesPtrQTy); 3653 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, 3654 /*Id=*/nullptr, C.IntTy); 3655 Args.push_back(&DstArg); 3656 Args.push_back(&SrcArg); 3657 Args.push_back(&LastprivArg); 3658 auto &TaskDupFnInfo = 3659 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3660 auto *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 3661 auto *TaskDup = 3662 llvm::Function::Create(TaskDupTy, llvm::GlobalValue::InternalLinkage, 3663 ".omp_task_dup.", &CGM.getModule()); 3664 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, TaskDup, TaskDupFnInfo); 3665 CodeGenFunction CGF(CGM); 3666 CGF.disableDebugInfo(); 3667 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args); 3668 3669 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3670 CGF.GetAddrOfLocalVar(&DstArg), 3671 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3672 // task_dst->liter = lastpriv; 3673 if (WithLastIter) { 3674 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3675 LValue Base = CGF.EmitLValueForField( 3676 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3677 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 3678 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 3679 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 3680 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 3681 } 3682 3683 // Emit initial values for private copies (if any). 3684 assert(!Privates.empty()); 3685 Address KmpTaskSharedsPtr = Address::invalid(); 3686 if (!Data.FirstprivateVars.empty()) { 3687 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3688 CGF.GetAddrOfLocalVar(&SrcArg), 3689 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3690 LValue Base = CGF.EmitLValueForField( 3691 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3692 KmpTaskSharedsPtr = Address( 3693 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 3694 Base, *std::next(KmpTaskTQTyRD->field_begin(), 3695 KmpTaskTShareds)), 3696 Loc), 3697 CGF.getNaturalTypeAlignment(SharedsTy)); 3698 } 3699 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 3700 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 3701 CGF.FinishFunction(); 3702 return TaskDup; 3703 } 3704 3705 /// Checks if destructor function is required to be generated. 3706 /// \return true if cleanups are required, false otherwise. 3707 static bool 3708 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 3709 bool NeedsCleanup = false; 3710 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3711 auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 3712 for (auto *FD : PrivateRD->fields()) { 3713 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 3714 if (NeedsCleanup) 3715 break; 3716 } 3717 return NeedsCleanup; 3718 } 3719 3720 CGOpenMPRuntime::TaskResultTy 3721 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 3722 const OMPExecutableDirective &D, 3723 llvm::Value *TaskFunction, QualType SharedsTy, 3724 Address Shareds, const OMPTaskDataTy &Data) { 3725 auto &C = CGM.getContext(); 3726 llvm::SmallVector<PrivateDataTy, 4> Privates; 3727 // Aggregate privates and sort them by the alignment. 3728 auto I = Data.PrivateCopies.begin(); 3729 for (auto *E : Data.PrivateVars) { 3730 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3731 Privates.push_back(std::make_pair( 3732 C.getDeclAlign(VD), 3733 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 3734 /*PrivateElemInit=*/nullptr))); 3735 ++I; 3736 } 3737 I = Data.FirstprivateCopies.begin(); 3738 auto IElemInitRef = Data.FirstprivateInits.begin(); 3739 for (auto *E : Data.FirstprivateVars) { 3740 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3741 Privates.push_back(std::make_pair( 3742 C.getDeclAlign(VD), 3743 PrivateHelpersTy( 3744 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 3745 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())))); 3746 ++I; 3747 ++IElemInitRef; 3748 } 3749 I = Data.LastprivateCopies.begin(); 3750 for (auto *E : Data.LastprivateVars) { 3751 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3752 Privates.push_back(std::make_pair( 3753 C.getDeclAlign(VD), 3754 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 3755 /*PrivateElemInit=*/nullptr))); 3756 ++I; 3757 } 3758 llvm::array_pod_sort(Privates.begin(), Privates.end(), 3759 array_pod_sort_comparator); 3760 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3761 // Build type kmp_routine_entry_t (if not built yet). 3762 emitKmpRoutineEntryT(KmpInt32Ty); 3763 // Build type kmp_task_t (if not built yet). 3764 if (KmpTaskTQTy.isNull()) { 3765 KmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 3766 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 3767 } 3768 auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 3769 // Build particular struct kmp_task_t for the given task. 3770 auto *KmpTaskTWithPrivatesQTyRD = 3771 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 3772 auto KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 3773 QualType KmpTaskTWithPrivatesPtrQTy = 3774 C.getPointerType(KmpTaskTWithPrivatesQTy); 3775 auto *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 3776 auto *KmpTaskTWithPrivatesPtrTy = KmpTaskTWithPrivatesTy->getPointerTo(); 3777 auto *KmpTaskTWithPrivatesTySize = CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 3778 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 3779 3780 // Emit initial values for private copies (if any). 3781 llvm::Value *TaskPrivatesMap = nullptr; 3782 auto *TaskPrivatesMapTy = 3783 std::next(cast<llvm::Function>(TaskFunction)->getArgumentList().begin(), 3784 3) 3785 ->getType(); 3786 if (!Privates.empty()) { 3787 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3788 TaskPrivatesMap = emitTaskPrivateMappingFunction( 3789 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 3790 FI->getType(), Privates); 3791 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3792 TaskPrivatesMap, TaskPrivatesMapTy); 3793 } else { 3794 TaskPrivatesMap = llvm::ConstantPointerNull::get( 3795 cast<llvm::PointerType>(TaskPrivatesMapTy)); 3796 } 3797 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 3798 // kmp_task_t *tt); 3799 auto *TaskEntry = emitProxyTaskFunction( 3800 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 3801 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 3802 TaskPrivatesMap); 3803 3804 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 3805 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 3806 // kmp_routine_entry_t *task_entry); 3807 // Task flags. Format is taken from 3808 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h, 3809 // description of kmp_tasking_flags struct. 3810 enum { 3811 TiedFlag = 0x1, 3812 FinalFlag = 0x2, 3813 DestructorsFlag = 0x8, 3814 PriorityFlag = 0x20 3815 }; 3816 unsigned Flags = Data.Tied ? TiedFlag : 0; 3817 bool NeedsCleanup = false; 3818 if (!Privates.empty()) { 3819 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 3820 if (NeedsCleanup) 3821 Flags = Flags | DestructorsFlag; 3822 } 3823 if (Data.Priority.getInt()) 3824 Flags = Flags | PriorityFlag; 3825 auto *TaskFlags = 3826 Data.Final.getPointer() 3827 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 3828 CGF.Builder.getInt32(FinalFlag), 3829 CGF.Builder.getInt32(/*C=*/0)) 3830 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 3831 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 3832 auto *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 3833 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc), 3834 getThreadID(CGF, Loc), TaskFlags, 3835 KmpTaskTWithPrivatesTySize, SharedsSize, 3836 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3837 TaskEntry, KmpRoutineEntryPtrTy)}; 3838 auto *NewTask = CGF.EmitRuntimeCall( 3839 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 3840 auto *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3841 NewTask, KmpTaskTWithPrivatesPtrTy); 3842 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 3843 KmpTaskTWithPrivatesQTy); 3844 LValue TDBase = 3845 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3846 // Fill the data in the resulting kmp_task_t record. 3847 // Copy shareds if there are any. 3848 Address KmpTaskSharedsPtr = Address::invalid(); 3849 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 3850 KmpTaskSharedsPtr = 3851 Address(CGF.EmitLoadOfScalar( 3852 CGF.EmitLValueForField( 3853 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 3854 KmpTaskTShareds)), 3855 Loc), 3856 CGF.getNaturalTypeAlignment(SharedsTy)); 3857 CGF.EmitAggregateCopy(KmpTaskSharedsPtr, Shareds, SharedsTy); 3858 } 3859 // Emit initial values for private copies (if any). 3860 TaskResultTy Result; 3861 if (!Privates.empty()) { 3862 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 3863 SharedsTy, SharedsPtrTy, Data, Privates, 3864 /*ForDup=*/false); 3865 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 3866 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 3867 Result.TaskDupFn = emitTaskDupFunction( 3868 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 3869 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 3870 /*WithLastIter=*/!Data.LastprivateVars.empty()); 3871 } 3872 } 3873 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 3874 enum { Priority = 0, Destructors = 1 }; 3875 // Provide pointer to function with destructors for privates. 3876 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 3877 auto *KmpCmplrdataUD = (*FI)->getType()->getAsUnionType()->getDecl(); 3878 if (NeedsCleanup) { 3879 llvm::Value *DestructorFn = emitDestructorsFunction( 3880 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 3881 KmpTaskTWithPrivatesQTy); 3882 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 3883 LValue DestructorsLV = CGF.EmitLValueForField( 3884 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 3885 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3886 DestructorFn, KmpRoutineEntryPtrTy), 3887 DestructorsLV); 3888 } 3889 // Set priority. 3890 if (Data.Priority.getInt()) { 3891 LValue Data2LV = CGF.EmitLValueForField( 3892 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 3893 LValue PriorityLV = CGF.EmitLValueForField( 3894 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 3895 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 3896 } 3897 Result.NewTask = NewTask; 3898 Result.TaskEntry = TaskEntry; 3899 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 3900 Result.TDBase = TDBase; 3901 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 3902 return Result; 3903 } 3904 3905 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 3906 const OMPExecutableDirective &D, 3907 llvm::Value *TaskFunction, 3908 QualType SharedsTy, Address Shareds, 3909 const Expr *IfCond, 3910 const OMPTaskDataTy &Data) { 3911 if (!CGF.HaveInsertPoint()) 3912 return; 3913 3914 TaskResultTy Result = 3915 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 3916 llvm::Value *NewTask = Result.NewTask; 3917 llvm::Value *TaskEntry = Result.TaskEntry; 3918 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 3919 LValue TDBase = Result.TDBase; 3920 RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 3921 auto &C = CGM.getContext(); 3922 // Process list of dependences. 3923 Address DependenciesArray = Address::invalid(); 3924 unsigned NumDependencies = Data.Dependences.size(); 3925 if (NumDependencies) { 3926 // Dependence kind for RTL. 3927 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3 }; 3928 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 3929 RecordDecl *KmpDependInfoRD; 3930 QualType FlagsTy = 3931 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 3932 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 3933 if (KmpDependInfoTy.isNull()) { 3934 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 3935 KmpDependInfoRD->startDefinition(); 3936 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 3937 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 3938 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 3939 KmpDependInfoRD->completeDefinition(); 3940 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 3941 } else 3942 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 3943 CharUnits DependencySize = C.getTypeSizeInChars(KmpDependInfoTy); 3944 // Define type kmp_depend_info[<Dependences.size()>]; 3945 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 3946 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 3947 ArrayType::Normal, /*IndexTypeQuals=*/0); 3948 // kmp_depend_info[<Dependences.size()>] deps; 3949 DependenciesArray = 3950 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 3951 for (unsigned i = 0; i < NumDependencies; ++i) { 3952 const Expr *E = Data.Dependences[i].second; 3953 auto Addr = CGF.EmitLValue(E); 3954 llvm::Value *Size; 3955 QualType Ty = E->getType(); 3956 if (auto *ASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 3957 LValue UpAddrLVal = 3958 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false); 3959 llvm::Value *UpAddr = 3960 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1); 3961 llvm::Value *LowIntPtr = 3962 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy); 3963 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 3964 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 3965 } else 3966 Size = CGF.getTypeSize(Ty); 3967 auto Base = CGF.MakeAddrLValue( 3968 CGF.Builder.CreateConstArrayGEP(DependenciesArray, i, DependencySize), 3969 KmpDependInfoTy); 3970 // deps[i].base_addr = &<Dependences[i].second>; 3971 auto BaseAddrLVal = CGF.EmitLValueForField( 3972 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 3973 CGF.EmitStoreOfScalar( 3974 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy), 3975 BaseAddrLVal); 3976 // deps[i].len = sizeof(<Dependences[i].second>); 3977 auto LenLVal = CGF.EmitLValueForField( 3978 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 3979 CGF.EmitStoreOfScalar(Size, LenLVal); 3980 // deps[i].flags = <Dependences[i].first>; 3981 RTLDependenceKindTy DepKind; 3982 switch (Data.Dependences[i].first) { 3983 case OMPC_DEPEND_in: 3984 DepKind = DepIn; 3985 break; 3986 // Out and InOut dependencies must use the same code. 3987 case OMPC_DEPEND_out: 3988 case OMPC_DEPEND_inout: 3989 DepKind = DepInOut; 3990 break; 3991 case OMPC_DEPEND_source: 3992 case OMPC_DEPEND_sink: 3993 case OMPC_DEPEND_unknown: 3994 llvm_unreachable("Unknown task dependence type"); 3995 } 3996 auto FlagsLVal = CGF.EmitLValueForField( 3997 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 3998 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 3999 FlagsLVal); 4000 } 4001 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4002 CGF.Builder.CreateStructGEP(DependenciesArray, 0, CharUnits::Zero()), 4003 CGF.VoidPtrTy); 4004 } 4005 4006 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc() 4007 // libcall. 4008 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 4009 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 4010 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 4011 // list is not empty 4012 auto *ThreadID = getThreadID(CGF, Loc); 4013 auto *UpLoc = emitUpdateLocation(CGF, Loc); 4014 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 4015 llvm::Value *DepTaskArgs[7]; 4016 if (NumDependencies) { 4017 DepTaskArgs[0] = UpLoc; 4018 DepTaskArgs[1] = ThreadID; 4019 DepTaskArgs[2] = NewTask; 4020 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 4021 DepTaskArgs[4] = DependenciesArray.getPointer(); 4022 DepTaskArgs[5] = CGF.Builder.getInt32(0); 4023 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4024 } 4025 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 4026 &TaskArgs, 4027 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 4028 if (!Data.Tied) { 4029 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4030 auto PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 4031 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 4032 } 4033 if (NumDependencies) { 4034 CGF.EmitRuntimeCall( 4035 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 4036 } else { 4037 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 4038 TaskArgs); 4039 } 4040 // Check if parent region is untied and build return for untied task; 4041 if (auto *Region = 4042 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 4043 Region->emitUntiedSwitch(CGF); 4044 }; 4045 4046 llvm::Value *DepWaitTaskArgs[6]; 4047 if (NumDependencies) { 4048 DepWaitTaskArgs[0] = UpLoc; 4049 DepWaitTaskArgs[1] = ThreadID; 4050 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 4051 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 4052 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 4053 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4054 } 4055 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 4056 NumDependencies, &DepWaitTaskArgs](CodeGenFunction &CGF, 4057 PrePostActionTy &) { 4058 auto &RT = CGF.CGM.getOpenMPRuntime(); 4059 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 4060 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 4061 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 4062 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 4063 // is specified. 4064 if (NumDependencies) 4065 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 4066 DepWaitTaskArgs); 4067 // Call proxy_task_entry(gtid, new_task); 4068 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy]( 4069 CodeGenFunction &CGF, PrePostActionTy &Action) { 4070 Action.Enter(CGF); 4071 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 4072 CGF.EmitCallOrInvoke(TaskEntry, OutlinedFnArgs); 4073 }; 4074 4075 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 4076 // kmp_task_t *new_task); 4077 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 4078 // kmp_task_t *new_task); 4079 RegionCodeGenTy RCG(CodeGen); 4080 CommonActionTy Action( 4081 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 4082 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 4083 RCG.setAction(Action); 4084 RCG(CGF); 4085 }; 4086 4087 if (IfCond) 4088 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 4089 else { 4090 RegionCodeGenTy ThenRCG(ThenCodeGen); 4091 ThenRCG(CGF); 4092 } 4093 } 4094 4095 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 4096 const OMPLoopDirective &D, 4097 llvm::Value *TaskFunction, 4098 QualType SharedsTy, Address Shareds, 4099 const Expr *IfCond, 4100 const OMPTaskDataTy &Data) { 4101 if (!CGF.HaveInsertPoint()) 4102 return; 4103 TaskResultTy Result = 4104 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 4105 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc() 4106 // libcall. 4107 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 4108 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 4109 // sched, kmp_uint64 grainsize, void *task_dup); 4110 llvm::Value *ThreadID = getThreadID(CGF, Loc); 4111 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 4112 llvm::Value *IfVal; 4113 if (IfCond) { 4114 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 4115 /*isSigned=*/true); 4116 } else 4117 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 4118 4119 LValue LBLVal = CGF.EmitLValueForField( 4120 Result.TDBase, 4121 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 4122 auto *LBVar = 4123 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 4124 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(), 4125 /*IsInitializer=*/true); 4126 LValue UBLVal = CGF.EmitLValueForField( 4127 Result.TDBase, 4128 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 4129 auto *UBVar = 4130 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 4131 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(), 4132 /*IsInitializer=*/true); 4133 LValue StLVal = CGF.EmitLValueForField( 4134 Result.TDBase, 4135 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 4136 auto *StVar = 4137 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 4138 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(), 4139 /*IsInitializer=*/true); 4140 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 4141 llvm::Value *TaskArgs[] = { 4142 UpLoc, ThreadID, Result.NewTask, IfVal, LBLVal.getPointer(), 4143 UBLVal.getPointer(), CGF.EmitLoadOfScalar(StLVal, SourceLocation()), 4144 llvm::ConstantInt::getSigned(CGF.IntTy, Data.Nogroup ? 1 : 0), 4145 llvm::ConstantInt::getSigned( 4146 CGF.IntTy, Data.Schedule.getPointer() 4147 ? Data.Schedule.getInt() ? NumTasks : Grainsize 4148 : NoSchedule), 4149 Data.Schedule.getPointer() 4150 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 4151 /*isSigned=*/false) 4152 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 4153 Result.TaskDupFn 4154 ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Result.TaskDupFn, 4155 CGF.VoidPtrTy) 4156 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 4157 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 4158 } 4159 4160 /// \brief Emit reduction operation for each element of array (required for 4161 /// array sections) LHS op = RHS. 4162 /// \param Type Type of array. 4163 /// \param LHSVar Variable on the left side of the reduction operation 4164 /// (references element of array in original variable). 4165 /// \param RHSVar Variable on the right side of the reduction operation 4166 /// (references element of array in original variable). 4167 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 4168 /// RHSVar. 4169 static void EmitOMPAggregateReduction( 4170 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 4171 const VarDecl *RHSVar, 4172 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 4173 const Expr *, const Expr *)> &RedOpGen, 4174 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 4175 const Expr *UpExpr = nullptr) { 4176 // Perform element-by-element initialization. 4177 QualType ElementTy; 4178 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 4179 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 4180 4181 // Drill down to the base element type on both arrays. 4182 auto ArrayTy = Type->getAsArrayTypeUnsafe(); 4183 auto NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 4184 4185 auto RHSBegin = RHSAddr.getPointer(); 4186 auto LHSBegin = LHSAddr.getPointer(); 4187 // Cast from pointer to array type to pointer to single element. 4188 auto LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 4189 // The basic structure here is a while-do loop. 4190 auto BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 4191 auto DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 4192 auto IsEmpty = 4193 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 4194 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 4195 4196 // Enter the loop body, making that address the current address. 4197 auto EntryBB = CGF.Builder.GetInsertBlock(); 4198 CGF.EmitBlock(BodyBB); 4199 4200 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 4201 4202 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 4203 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 4204 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 4205 Address RHSElementCurrent = 4206 Address(RHSElementPHI, 4207 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 4208 4209 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 4210 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 4211 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 4212 Address LHSElementCurrent = 4213 Address(LHSElementPHI, 4214 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 4215 4216 // Emit copy. 4217 CodeGenFunction::OMPPrivateScope Scope(CGF); 4218 Scope.addPrivate(LHSVar, [=]() -> Address { return LHSElementCurrent; }); 4219 Scope.addPrivate(RHSVar, [=]() -> Address { return RHSElementCurrent; }); 4220 Scope.Privatize(); 4221 RedOpGen(CGF, XExpr, EExpr, UpExpr); 4222 Scope.ForceCleanup(); 4223 4224 // Shift the address forward by one element. 4225 auto LHSElementNext = CGF.Builder.CreateConstGEP1_32( 4226 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 4227 auto RHSElementNext = CGF.Builder.CreateConstGEP1_32( 4228 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 4229 // Check whether we've reached the end. 4230 auto Done = 4231 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 4232 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 4233 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 4234 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 4235 4236 // Done. 4237 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 4238 } 4239 4240 /// Emit reduction combiner. If the combiner is a simple expression emit it as 4241 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 4242 /// UDR combiner function. 4243 static void emitReductionCombiner(CodeGenFunction &CGF, 4244 const Expr *ReductionOp) { 4245 if (auto *CE = dyn_cast<CallExpr>(ReductionOp)) 4246 if (auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 4247 if (auto *DRE = 4248 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 4249 if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 4250 std::pair<llvm::Function *, llvm::Function *> Reduction = 4251 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 4252 RValue Func = RValue::get(Reduction.first); 4253 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 4254 CGF.EmitIgnoredExpr(ReductionOp); 4255 return; 4256 } 4257 CGF.EmitIgnoredExpr(ReductionOp); 4258 } 4259 4260 static llvm::Value *emitReductionFunction(CodeGenModule &CGM, 4261 llvm::Type *ArgsType, 4262 ArrayRef<const Expr *> Privates, 4263 ArrayRef<const Expr *> LHSExprs, 4264 ArrayRef<const Expr *> RHSExprs, 4265 ArrayRef<const Expr *> ReductionOps) { 4266 auto &C = CGM.getContext(); 4267 4268 // void reduction_func(void *LHSArg, void *RHSArg); 4269 FunctionArgList Args; 4270 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 4271 C.VoidPtrTy); 4272 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 4273 C.VoidPtrTy); 4274 Args.push_back(&LHSArg); 4275 Args.push_back(&RHSArg); 4276 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4277 auto *Fn = llvm::Function::Create( 4278 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, 4279 ".omp.reduction.reduction_func", &CGM.getModule()); 4280 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI); 4281 CodeGenFunction CGF(CGM); 4282 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args); 4283 4284 // Dst = (void*[n])(LHSArg); 4285 // Src = (void*[n])(RHSArg); 4286 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4287 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 4288 ArgsType), CGF.getPointerAlign()); 4289 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4290 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 4291 ArgsType), CGF.getPointerAlign()); 4292 4293 // ... 4294 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 4295 // ... 4296 CodeGenFunction::OMPPrivateScope Scope(CGF); 4297 auto IPriv = Privates.begin(); 4298 unsigned Idx = 0; 4299 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 4300 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 4301 Scope.addPrivate(RHSVar, [&]() -> Address { 4302 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 4303 }); 4304 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 4305 Scope.addPrivate(LHSVar, [&]() -> Address { 4306 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 4307 }); 4308 QualType PrivTy = (*IPriv)->getType(); 4309 if (PrivTy->isVariablyModifiedType()) { 4310 // Get array size and emit VLA type. 4311 ++Idx; 4312 Address Elem = 4313 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize()); 4314 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 4315 auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy); 4316 auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 4317 CodeGenFunction::OpaqueValueMapping OpaqueMap( 4318 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 4319 CGF.EmitVariablyModifiedType(PrivTy); 4320 } 4321 } 4322 Scope.Privatize(); 4323 IPriv = Privates.begin(); 4324 auto ILHS = LHSExprs.begin(); 4325 auto IRHS = RHSExprs.begin(); 4326 for (auto *E : ReductionOps) { 4327 if ((*IPriv)->getType()->isArrayType()) { 4328 // Emit reduction for array section. 4329 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 4330 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 4331 EmitOMPAggregateReduction( 4332 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 4333 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 4334 emitReductionCombiner(CGF, E); 4335 }); 4336 } else 4337 // Emit reduction for array subscript or single variable. 4338 emitReductionCombiner(CGF, E); 4339 ++IPriv; 4340 ++ILHS; 4341 ++IRHS; 4342 } 4343 Scope.ForceCleanup(); 4344 CGF.FinishFunction(); 4345 return Fn; 4346 } 4347 4348 static void emitSingleReductionCombiner(CodeGenFunction &CGF, 4349 const Expr *ReductionOp, 4350 const Expr *PrivateRef, 4351 const DeclRefExpr *LHS, 4352 const DeclRefExpr *RHS) { 4353 if (PrivateRef->getType()->isArrayType()) { 4354 // Emit reduction for array section. 4355 auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 4356 auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 4357 EmitOMPAggregateReduction( 4358 CGF, PrivateRef->getType(), LHSVar, RHSVar, 4359 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 4360 emitReductionCombiner(CGF, ReductionOp); 4361 }); 4362 } else 4363 // Emit reduction for array subscript or single variable. 4364 emitReductionCombiner(CGF, ReductionOp); 4365 } 4366 4367 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 4368 ArrayRef<const Expr *> Privates, 4369 ArrayRef<const Expr *> LHSExprs, 4370 ArrayRef<const Expr *> RHSExprs, 4371 ArrayRef<const Expr *> ReductionOps, 4372 bool WithNowait, bool SimpleReduction) { 4373 if (!CGF.HaveInsertPoint()) 4374 return; 4375 // Next code should be emitted for reduction: 4376 // 4377 // static kmp_critical_name lock = { 0 }; 4378 // 4379 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 4380 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 4381 // ... 4382 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 4383 // *(Type<n>-1*)rhs[<n>-1]); 4384 // } 4385 // 4386 // ... 4387 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 4388 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 4389 // RedList, reduce_func, &<lock>)) { 4390 // case 1: 4391 // ... 4392 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 4393 // ... 4394 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 4395 // break; 4396 // case 2: 4397 // ... 4398 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 4399 // ... 4400 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 4401 // break; 4402 // default:; 4403 // } 4404 // 4405 // if SimpleReduction is true, only the next code is generated: 4406 // ... 4407 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 4408 // ... 4409 4410 auto &C = CGM.getContext(); 4411 4412 if (SimpleReduction) { 4413 CodeGenFunction::RunCleanupsScope Scope(CGF); 4414 auto IPriv = Privates.begin(); 4415 auto ILHS = LHSExprs.begin(); 4416 auto IRHS = RHSExprs.begin(); 4417 for (auto *E : ReductionOps) { 4418 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 4419 cast<DeclRefExpr>(*IRHS)); 4420 ++IPriv; 4421 ++ILHS; 4422 ++IRHS; 4423 } 4424 return; 4425 } 4426 4427 // 1. Build a list of reduction variables. 4428 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 4429 auto Size = RHSExprs.size(); 4430 for (auto *E : Privates) { 4431 if (E->getType()->isVariablyModifiedType()) 4432 // Reserve place for array size. 4433 ++Size; 4434 } 4435 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 4436 QualType ReductionArrayTy = 4437 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 4438 /*IndexTypeQuals=*/0); 4439 Address ReductionList = 4440 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 4441 auto IPriv = Privates.begin(); 4442 unsigned Idx = 0; 4443 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 4444 Address Elem = 4445 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize()); 4446 CGF.Builder.CreateStore( 4447 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4448 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy), 4449 Elem); 4450 if ((*IPriv)->getType()->isVariablyModifiedType()) { 4451 // Store array size. 4452 ++Idx; 4453 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, 4454 CGF.getPointerSize()); 4455 llvm::Value *Size = CGF.Builder.CreateIntCast( 4456 CGF.getVLASize( 4457 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 4458 .first, 4459 CGF.SizeTy, /*isSigned=*/false); 4460 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 4461 Elem); 4462 } 4463 } 4464 4465 // 2. Emit reduce_func(). 4466 auto *ReductionFn = emitReductionFunction( 4467 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 4468 LHSExprs, RHSExprs, ReductionOps); 4469 4470 // 3. Create static kmp_critical_name lock = { 0 }; 4471 auto *Lock = getCriticalRegionLock(".reduction"); 4472 4473 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 4474 // RedList, reduce_func, &<lock>); 4475 auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 4476 auto *ThreadId = getThreadID(CGF, Loc); 4477 auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 4478 auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4479 ReductionList.getPointer(), CGF.VoidPtrTy); 4480 llvm::Value *Args[] = { 4481 IdentTLoc, // ident_t *<loc> 4482 ThreadId, // i32 <gtid> 4483 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 4484 ReductionArrayTySize, // size_type sizeof(RedList) 4485 RL, // void *RedList 4486 ReductionFn, // void (*) (void *, void *) <reduce_func> 4487 Lock // kmp_critical_name *&<lock> 4488 }; 4489 auto Res = CGF.EmitRuntimeCall( 4490 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 4491 : OMPRTL__kmpc_reduce), 4492 Args); 4493 4494 // 5. Build switch(res) 4495 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 4496 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 4497 4498 // 6. Build case 1: 4499 // ... 4500 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 4501 // ... 4502 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 4503 // break; 4504 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 4505 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 4506 CGF.EmitBlock(Case1BB); 4507 4508 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 4509 llvm::Value *EndArgs[] = { 4510 IdentTLoc, // ident_t *<loc> 4511 ThreadId, // i32 <gtid> 4512 Lock // kmp_critical_name *&<lock> 4513 }; 4514 auto &&CodeGen = [&Privates, &LHSExprs, &RHSExprs, &ReductionOps]( 4515 CodeGenFunction &CGF, PrePostActionTy &Action) { 4516 auto IPriv = Privates.begin(); 4517 auto ILHS = LHSExprs.begin(); 4518 auto IRHS = RHSExprs.begin(); 4519 for (auto *E : ReductionOps) { 4520 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 4521 cast<DeclRefExpr>(*IRHS)); 4522 ++IPriv; 4523 ++ILHS; 4524 ++IRHS; 4525 } 4526 }; 4527 RegionCodeGenTy RCG(CodeGen); 4528 CommonActionTy Action( 4529 nullptr, llvm::None, 4530 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 4531 : OMPRTL__kmpc_end_reduce), 4532 EndArgs); 4533 RCG.setAction(Action); 4534 RCG(CGF); 4535 4536 CGF.EmitBranch(DefaultBB); 4537 4538 // 7. Build case 2: 4539 // ... 4540 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 4541 // ... 4542 // break; 4543 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 4544 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 4545 CGF.EmitBlock(Case2BB); 4546 4547 auto &&AtomicCodeGen = [Loc, &Privates, &LHSExprs, &RHSExprs, &ReductionOps]( 4548 CodeGenFunction &CGF, PrePostActionTy &Action) { 4549 auto ILHS = LHSExprs.begin(); 4550 auto IRHS = RHSExprs.begin(); 4551 auto IPriv = Privates.begin(); 4552 for (auto *E : ReductionOps) { 4553 const Expr *XExpr = nullptr; 4554 const Expr *EExpr = nullptr; 4555 const Expr *UpExpr = nullptr; 4556 BinaryOperatorKind BO = BO_Comma; 4557 if (auto *BO = dyn_cast<BinaryOperator>(E)) { 4558 if (BO->getOpcode() == BO_Assign) { 4559 XExpr = BO->getLHS(); 4560 UpExpr = BO->getRHS(); 4561 } 4562 } 4563 // Try to emit update expression as a simple atomic. 4564 auto *RHSExpr = UpExpr; 4565 if (RHSExpr) { 4566 // Analyze RHS part of the whole expression. 4567 if (auto *ACO = dyn_cast<AbstractConditionalOperator>( 4568 RHSExpr->IgnoreParenImpCasts())) { 4569 // If this is a conditional operator, analyze its condition for 4570 // min/max reduction operator. 4571 RHSExpr = ACO->getCond(); 4572 } 4573 if (auto *BORHS = 4574 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 4575 EExpr = BORHS->getRHS(); 4576 BO = BORHS->getOpcode(); 4577 } 4578 } 4579 if (XExpr) { 4580 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 4581 auto &&AtomicRedGen = [BO, VD, 4582 Loc](CodeGenFunction &CGF, const Expr *XExpr, 4583 const Expr *EExpr, const Expr *UpExpr) { 4584 LValue X = CGF.EmitLValue(XExpr); 4585 RValue E; 4586 if (EExpr) 4587 E = CGF.EmitAnyExpr(EExpr); 4588 CGF.EmitOMPAtomicSimpleUpdateExpr( 4589 X, E, BO, /*IsXLHSInRHSPart=*/true, 4590 llvm::AtomicOrdering::Monotonic, Loc, 4591 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 4592 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 4593 PrivateScope.addPrivate( 4594 VD, [&CGF, VD, XRValue, Loc]() -> Address { 4595 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 4596 CGF.emitOMPSimpleStore( 4597 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 4598 VD->getType().getNonReferenceType(), Loc); 4599 return LHSTemp; 4600 }); 4601 (void)PrivateScope.Privatize(); 4602 return CGF.EmitAnyExpr(UpExpr); 4603 }); 4604 }; 4605 if ((*IPriv)->getType()->isArrayType()) { 4606 // Emit atomic reduction for array section. 4607 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 4608 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 4609 AtomicRedGen, XExpr, EExpr, UpExpr); 4610 } else 4611 // Emit atomic reduction for array subscript or single variable. 4612 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 4613 } else { 4614 // Emit as a critical region. 4615 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 4616 const Expr *, const Expr *) { 4617 auto &RT = CGF.CGM.getOpenMPRuntime(); 4618 RT.emitCriticalRegion( 4619 CGF, ".atomic_reduction", 4620 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 4621 Action.Enter(CGF); 4622 emitReductionCombiner(CGF, E); 4623 }, 4624 Loc); 4625 }; 4626 if ((*IPriv)->getType()->isArrayType()) { 4627 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 4628 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 4629 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 4630 CritRedGen); 4631 } else 4632 CritRedGen(CGF, nullptr, nullptr, nullptr); 4633 } 4634 ++ILHS; 4635 ++IRHS; 4636 ++IPriv; 4637 } 4638 }; 4639 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 4640 if (!WithNowait) { 4641 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 4642 llvm::Value *EndArgs[] = { 4643 IdentTLoc, // ident_t *<loc> 4644 ThreadId, // i32 <gtid> 4645 Lock // kmp_critical_name *&<lock> 4646 }; 4647 CommonActionTy Action(nullptr, llvm::None, 4648 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 4649 EndArgs); 4650 AtomicRCG.setAction(Action); 4651 AtomicRCG(CGF); 4652 } else 4653 AtomicRCG(CGF); 4654 4655 CGF.EmitBranch(DefaultBB); 4656 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 4657 } 4658 4659 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 4660 SourceLocation Loc) { 4661 if (!CGF.HaveInsertPoint()) 4662 return; 4663 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 4664 // global_tid); 4665 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 4666 // Ignore return result until untied tasks are supported. 4667 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 4668 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 4669 Region->emitUntiedSwitch(CGF); 4670 } 4671 4672 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 4673 OpenMPDirectiveKind InnerKind, 4674 const RegionCodeGenTy &CodeGen, 4675 bool HasCancel) { 4676 if (!CGF.HaveInsertPoint()) 4677 return; 4678 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 4679 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 4680 } 4681 4682 namespace { 4683 enum RTCancelKind { 4684 CancelNoreq = 0, 4685 CancelParallel = 1, 4686 CancelLoop = 2, 4687 CancelSections = 3, 4688 CancelTaskgroup = 4 4689 }; 4690 } // anonymous namespace 4691 4692 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 4693 RTCancelKind CancelKind = CancelNoreq; 4694 if (CancelRegion == OMPD_parallel) 4695 CancelKind = CancelParallel; 4696 else if (CancelRegion == OMPD_for) 4697 CancelKind = CancelLoop; 4698 else if (CancelRegion == OMPD_sections) 4699 CancelKind = CancelSections; 4700 else { 4701 assert(CancelRegion == OMPD_taskgroup); 4702 CancelKind = CancelTaskgroup; 4703 } 4704 return CancelKind; 4705 } 4706 4707 void CGOpenMPRuntime::emitCancellationPointCall( 4708 CodeGenFunction &CGF, SourceLocation Loc, 4709 OpenMPDirectiveKind CancelRegion) { 4710 if (!CGF.HaveInsertPoint()) 4711 return; 4712 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 4713 // global_tid, kmp_int32 cncl_kind); 4714 if (auto *OMPRegionInfo = 4715 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 4716 if (OMPRegionInfo->hasCancel()) { 4717 llvm::Value *Args[] = { 4718 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 4719 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 4720 // Ignore return result until untied tasks are supported. 4721 auto *Result = CGF.EmitRuntimeCall( 4722 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 4723 // if (__kmpc_cancellationpoint()) { 4724 // __kmpc_cancel_barrier(); 4725 // exit from construct; 4726 // } 4727 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 4728 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 4729 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 4730 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 4731 CGF.EmitBlock(ExitBB); 4732 // __kmpc_cancel_barrier(); 4733 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 4734 // exit from construct; 4735 auto CancelDest = 4736 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 4737 CGF.EmitBranchThroughCleanup(CancelDest); 4738 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 4739 } 4740 } 4741 } 4742 4743 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 4744 const Expr *IfCond, 4745 OpenMPDirectiveKind CancelRegion) { 4746 if (!CGF.HaveInsertPoint()) 4747 return; 4748 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 4749 // kmp_int32 cncl_kind); 4750 if (auto *OMPRegionInfo = 4751 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 4752 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 4753 PrePostActionTy &) { 4754 auto &RT = CGF.CGM.getOpenMPRuntime(); 4755 llvm::Value *Args[] = { 4756 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 4757 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 4758 // Ignore return result until untied tasks are supported. 4759 auto *Result = CGF.EmitRuntimeCall( 4760 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 4761 // if (__kmpc_cancel()) { 4762 // __kmpc_cancel_barrier(); 4763 // exit from construct; 4764 // } 4765 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 4766 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 4767 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 4768 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 4769 CGF.EmitBlock(ExitBB); 4770 // __kmpc_cancel_barrier(); 4771 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 4772 // exit from construct; 4773 auto CancelDest = 4774 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 4775 CGF.EmitBranchThroughCleanup(CancelDest); 4776 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 4777 }; 4778 if (IfCond) 4779 emitOMPIfClause(CGF, IfCond, ThenGen, 4780 [](CodeGenFunction &, PrePostActionTy &) {}); 4781 else { 4782 RegionCodeGenTy ThenRCG(ThenGen); 4783 ThenRCG(CGF); 4784 } 4785 } 4786 } 4787 4788 /// \brief Obtain information that uniquely identifies a target entry. This 4789 /// consists of the file and device IDs as well as line number associated with 4790 /// the relevant entry source location. 4791 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 4792 unsigned &DeviceID, unsigned &FileID, 4793 unsigned &LineNum) { 4794 4795 auto &SM = C.getSourceManager(); 4796 4797 // The loc should be always valid and have a file ID (the user cannot use 4798 // #pragma directives in macros) 4799 4800 assert(Loc.isValid() && "Source location is expected to be always valid."); 4801 assert(Loc.isFileID() && "Source location is expected to refer to a file."); 4802 4803 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 4804 assert(PLoc.isValid() && "Source location is expected to be always valid."); 4805 4806 llvm::sys::fs::UniqueID ID; 4807 if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 4808 llvm_unreachable("Source file with target region no longer exists!"); 4809 4810 DeviceID = ID.getDevice(); 4811 FileID = ID.getFile(); 4812 LineNum = PLoc.getLine(); 4813 } 4814 4815 void CGOpenMPRuntime::emitTargetOutlinedFunction( 4816 const OMPExecutableDirective &D, StringRef ParentName, 4817 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 4818 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 4819 assert(!ParentName.empty() && "Invalid target region parent name!"); 4820 4821 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 4822 IsOffloadEntry, CodeGen); 4823 } 4824 4825 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 4826 const OMPExecutableDirective &D, StringRef ParentName, 4827 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 4828 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 4829 // Create a unique name for the entry function using the source location 4830 // information of the current target region. The name will be something like: 4831 // 4832 // __omp_offloading_DD_FFFF_PP_lBB 4833 // 4834 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 4835 // mangled name of the function that encloses the target region and BB is the 4836 // line number of the target region. 4837 4838 unsigned DeviceID; 4839 unsigned FileID; 4840 unsigned Line; 4841 getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID, 4842 Line); 4843 SmallString<64> EntryFnName; 4844 { 4845 llvm::raw_svector_ostream OS(EntryFnName); 4846 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 4847 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 4848 } 4849 4850 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 4851 4852 CodeGenFunction CGF(CGM, true); 4853 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 4854 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 4855 4856 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 4857 4858 // If this target outline function is not an offload entry, we don't need to 4859 // register it. 4860 if (!IsOffloadEntry) 4861 return; 4862 4863 // The target region ID is used by the runtime library to identify the current 4864 // target region, so it only has to be unique and not necessarily point to 4865 // anything. It could be the pointer to the outlined function that implements 4866 // the target region, but we aren't using that so that the compiler doesn't 4867 // need to keep that, and could therefore inline the host function if proven 4868 // worthwhile during optimization. In the other hand, if emitting code for the 4869 // device, the ID has to be the function address so that it can retrieved from 4870 // the offloading entry and launched by the runtime library. We also mark the 4871 // outlined function to have external linkage in case we are emitting code for 4872 // the device, because these functions will be entry points to the device. 4873 4874 if (CGM.getLangOpts().OpenMPIsDevice) { 4875 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 4876 OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage); 4877 } else 4878 OutlinedFnID = new llvm::GlobalVariable( 4879 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 4880 llvm::GlobalValue::PrivateLinkage, 4881 llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id"); 4882 4883 // Register the information for the entry associated with this target region. 4884 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 4885 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 4886 /*Flags=*/0); 4887 } 4888 4889 /// discard all CompoundStmts intervening between two constructs 4890 static const Stmt *ignoreCompoundStmts(const Stmt *Body) { 4891 while (auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) 4892 Body = CS->body_front(); 4893 4894 return Body; 4895 } 4896 4897 /// Emit the number of teams for a target directive. Inspect the num_teams 4898 /// clause associated with a teams construct combined or closely nested 4899 /// with the target directive. 4900 /// 4901 /// Emit a team of size one for directives such as 'target parallel' that 4902 /// have no associated teams construct. 4903 /// 4904 /// Otherwise, return nullptr. 4905 static llvm::Value * 4906 emitNumTeamsForTargetDirective(CGOpenMPRuntime &OMPRuntime, 4907 CodeGenFunction &CGF, 4908 const OMPExecutableDirective &D) { 4909 4910 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the " 4911 "teams directive expected to be " 4912 "emitted only for the host!"); 4913 4914 auto &Bld = CGF.Builder; 4915 4916 // If the target directive is combined with a teams directive: 4917 // Return the value in the num_teams clause, if any. 4918 // Otherwise, return 0 to denote the runtime default. 4919 if (isOpenMPTeamsDirective(D.getDirectiveKind())) { 4920 if (const auto *NumTeamsClause = D.getSingleClause<OMPNumTeamsClause>()) { 4921 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 4922 auto NumTeams = CGF.EmitScalarExpr(NumTeamsClause->getNumTeams(), 4923 /*IgnoreResultAssign*/ true); 4924 return Bld.CreateIntCast(NumTeams, CGF.Int32Ty, 4925 /*IsSigned=*/true); 4926 } 4927 4928 // The default value is 0. 4929 return Bld.getInt32(0); 4930 } 4931 4932 // If the target directive is combined with a parallel directive but not a 4933 // teams directive, start one team. 4934 if (isOpenMPParallelDirective(D.getDirectiveKind())) 4935 return Bld.getInt32(1); 4936 4937 // If the current target region has a teams region enclosed, we need to get 4938 // the number of teams to pass to the runtime function call. This is done 4939 // by generating the expression in a inlined region. This is required because 4940 // the expression is captured in the enclosing target environment when the 4941 // teams directive is not combined with target. 4942 4943 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 4944 4945 // FIXME: Accommodate other combined directives with teams when they become 4946 // available. 4947 if (auto *TeamsDir = dyn_cast_or_null<OMPTeamsDirective>( 4948 ignoreCompoundStmts(CS.getCapturedStmt()))) { 4949 if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) { 4950 CGOpenMPInnerExprInfo CGInfo(CGF, CS); 4951 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 4952 llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams()); 4953 return Bld.CreateIntCast(NumTeams, CGF.Int32Ty, 4954 /*IsSigned=*/true); 4955 } 4956 4957 // If we have an enclosed teams directive but no num_teams clause we use 4958 // the default value 0. 4959 return Bld.getInt32(0); 4960 } 4961 4962 // No teams associated with the directive. 4963 return nullptr; 4964 } 4965 4966 /// Emit the number of threads for a target directive. Inspect the 4967 /// thread_limit clause associated with a teams construct combined or closely 4968 /// nested with the target directive. 4969 /// 4970 /// Emit the num_threads clause for directives such as 'target parallel' that 4971 /// have no associated teams construct. 4972 /// 4973 /// Otherwise, return nullptr. 4974 static llvm::Value * 4975 emitNumThreadsForTargetDirective(CGOpenMPRuntime &OMPRuntime, 4976 CodeGenFunction &CGF, 4977 const OMPExecutableDirective &D) { 4978 4979 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the " 4980 "teams directive expected to be " 4981 "emitted only for the host!"); 4982 4983 auto &Bld = CGF.Builder; 4984 4985 // 4986 // If the target directive is combined with a teams directive: 4987 // Return the value in the thread_limit clause, if any. 4988 // 4989 // If the target directive is combined with a parallel directive: 4990 // Return the value in the num_threads clause, if any. 4991 // 4992 // If both clauses are set, select the minimum of the two. 4993 // 4994 // If neither teams or parallel combined directives set the number of threads 4995 // in a team, return 0 to denote the runtime default. 4996 // 4997 // If this is not a teams directive return nullptr. 4998 4999 if (isOpenMPTeamsDirective(D.getDirectiveKind()) || 5000 isOpenMPParallelDirective(D.getDirectiveKind())) { 5001 llvm::Value *DefaultThreadLimitVal = Bld.getInt32(0); 5002 llvm::Value *NumThreadsVal = nullptr; 5003 llvm::Value *ThreadLimitVal = nullptr; 5004 5005 if (const auto *ThreadLimitClause = 5006 D.getSingleClause<OMPThreadLimitClause>()) { 5007 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 5008 auto ThreadLimit = CGF.EmitScalarExpr(ThreadLimitClause->getThreadLimit(), 5009 /*IgnoreResultAssign*/ true); 5010 ThreadLimitVal = Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, 5011 /*IsSigned=*/true); 5012 } 5013 5014 if (const auto *NumThreadsClause = 5015 D.getSingleClause<OMPNumThreadsClause>()) { 5016 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 5017 llvm::Value *NumThreads = 5018 CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(), 5019 /*IgnoreResultAssign*/ true); 5020 NumThreadsVal = 5021 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*IsSigned=*/true); 5022 } 5023 5024 // Select the lesser of thread_limit and num_threads. 5025 if (NumThreadsVal) 5026 ThreadLimitVal = ThreadLimitVal 5027 ? Bld.CreateSelect(Bld.CreateICmpSLT(NumThreadsVal, 5028 ThreadLimitVal), 5029 NumThreadsVal, ThreadLimitVal) 5030 : NumThreadsVal; 5031 5032 // Set default value passed to the runtime if either teams or a target 5033 // parallel type directive is found but no clause is specified. 5034 if (!ThreadLimitVal) 5035 ThreadLimitVal = DefaultThreadLimitVal; 5036 5037 return ThreadLimitVal; 5038 } 5039 5040 // If the current target region has a teams region enclosed, we need to get 5041 // the thread limit to pass to the runtime function call. This is done 5042 // by generating the expression in a inlined region. This is required because 5043 // the expression is captured in the enclosing target environment when the 5044 // teams directive is not combined with target. 5045 5046 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 5047 5048 // FIXME: Accommodate other combined directives with teams when they become 5049 // available. 5050 if (auto *TeamsDir = dyn_cast_or_null<OMPTeamsDirective>( 5051 ignoreCompoundStmts(CS.getCapturedStmt()))) { 5052 if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) { 5053 CGOpenMPInnerExprInfo CGInfo(CGF, CS); 5054 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 5055 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit()); 5056 return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty, 5057 /*IsSigned=*/true); 5058 } 5059 5060 // If we have an enclosed teams directive but no thread_limit clause we use 5061 // the default value 0. 5062 return CGF.Builder.getInt32(0); 5063 } 5064 5065 // No teams associated with the directive. 5066 return nullptr; 5067 } 5068 5069 namespace { 5070 // \brief Utility to handle information from clauses associated with a given 5071 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 5072 // It provides a convenient interface to obtain the information and generate 5073 // code for that information. 5074 class MappableExprsHandler { 5075 public: 5076 /// \brief Values for bit flags used to specify the mapping type for 5077 /// offloading. 5078 enum OpenMPOffloadMappingFlags { 5079 /// \brief Allocate memory on the device and move data from host to device. 5080 OMP_MAP_TO = 0x01, 5081 /// \brief Allocate memory on the device and move data from device to host. 5082 OMP_MAP_FROM = 0x02, 5083 /// \brief Always perform the requested mapping action on the element, even 5084 /// if it was already mapped before. 5085 OMP_MAP_ALWAYS = 0x04, 5086 /// \brief Delete the element from the device environment, ignoring the 5087 /// current reference count associated with the element. 5088 OMP_MAP_DELETE = 0x08, 5089 /// \brief The element being mapped is a pointer, therefore the pointee 5090 /// should be mapped as well. 5091 OMP_MAP_IS_PTR = 0x10, 5092 /// \brief This flags signals that an argument is the first one relating to 5093 /// a map/private clause expression. For some cases a single 5094 /// map/privatization results in multiple arguments passed to the runtime 5095 /// library. 5096 OMP_MAP_FIRST_REF = 0x20, 5097 /// \brief Signal that the runtime library has to return the device pointer 5098 /// in the current position for the data being mapped. 5099 OMP_MAP_RETURN_PTR = 0x40, 5100 /// \brief This flag signals that the reference being passed is a pointer to 5101 /// private data. 5102 OMP_MAP_PRIVATE_PTR = 0x80, 5103 /// \brief Pass the element to the device by value. 5104 OMP_MAP_PRIVATE_VAL = 0x100, 5105 }; 5106 5107 /// Class that associates information with a base pointer to be passed to the 5108 /// runtime library. 5109 class BasePointerInfo { 5110 /// The base pointer. 5111 llvm::Value *Ptr = nullptr; 5112 /// The base declaration that refers to this device pointer, or null if 5113 /// there is none. 5114 const ValueDecl *DevPtrDecl = nullptr; 5115 5116 public: 5117 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 5118 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 5119 llvm::Value *operator*() const { return Ptr; } 5120 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 5121 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 5122 }; 5123 5124 typedef SmallVector<BasePointerInfo, 16> MapBaseValuesArrayTy; 5125 typedef SmallVector<llvm::Value *, 16> MapValuesArrayTy; 5126 typedef SmallVector<unsigned, 16> MapFlagsArrayTy; 5127 5128 private: 5129 /// \brief Directive from where the map clauses were extracted. 5130 const OMPExecutableDirective &CurDir; 5131 5132 /// \brief Function the directive is being generated for. 5133 CodeGenFunction &CGF; 5134 5135 /// \brief Set of all first private variables in the current directive. 5136 llvm::SmallPtrSet<const VarDecl *, 8> FirstPrivateDecls; 5137 5138 /// Map between device pointer declarations and their expression components. 5139 /// The key value for declarations in 'this' is null. 5140 llvm::DenseMap< 5141 const ValueDecl *, 5142 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 5143 DevPointersMap; 5144 5145 llvm::Value *getExprTypeSize(const Expr *E) const { 5146 auto ExprTy = E->getType().getCanonicalType(); 5147 5148 // Reference types are ignored for mapping purposes. 5149 if (auto *RefTy = ExprTy->getAs<ReferenceType>()) 5150 ExprTy = RefTy->getPointeeType().getCanonicalType(); 5151 5152 // Given that an array section is considered a built-in type, we need to 5153 // do the calculation based on the length of the section instead of relying 5154 // on CGF.getTypeSize(E->getType()). 5155 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 5156 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 5157 OAE->getBase()->IgnoreParenImpCasts()) 5158 .getCanonicalType(); 5159 5160 // If there is no length associated with the expression, that means we 5161 // are using the whole length of the base. 5162 if (!OAE->getLength() && OAE->getColonLoc().isValid()) 5163 return CGF.getTypeSize(BaseTy); 5164 5165 llvm::Value *ElemSize; 5166 if (auto *PTy = BaseTy->getAs<PointerType>()) 5167 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 5168 else { 5169 auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 5170 assert(ATy && "Expecting array type if not a pointer type."); 5171 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 5172 } 5173 5174 // If we don't have a length at this point, that is because we have an 5175 // array section with a single element. 5176 if (!OAE->getLength()) 5177 return ElemSize; 5178 5179 auto *LengthVal = CGF.EmitScalarExpr(OAE->getLength()); 5180 LengthVal = 5181 CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false); 5182 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 5183 } 5184 return CGF.getTypeSize(ExprTy); 5185 } 5186 5187 /// \brief Return the corresponding bits for a given map clause modifier. Add 5188 /// a flag marking the map as a pointer if requested. Add a flag marking the 5189 /// map as the first one of a series of maps that relate to the same map 5190 /// expression. 5191 unsigned getMapTypeBits(OpenMPMapClauseKind MapType, 5192 OpenMPMapClauseKind MapTypeModifier, bool AddPtrFlag, 5193 bool AddIsFirstFlag) const { 5194 unsigned Bits = 0u; 5195 switch (MapType) { 5196 case OMPC_MAP_alloc: 5197 case OMPC_MAP_release: 5198 // alloc and release is the default behavior in the runtime library, i.e. 5199 // if we don't pass any bits alloc/release that is what the runtime is 5200 // going to do. Therefore, we don't need to signal anything for these two 5201 // type modifiers. 5202 break; 5203 case OMPC_MAP_to: 5204 Bits = OMP_MAP_TO; 5205 break; 5206 case OMPC_MAP_from: 5207 Bits = OMP_MAP_FROM; 5208 break; 5209 case OMPC_MAP_tofrom: 5210 Bits = OMP_MAP_TO | OMP_MAP_FROM; 5211 break; 5212 case OMPC_MAP_delete: 5213 Bits = OMP_MAP_DELETE; 5214 break; 5215 default: 5216 llvm_unreachable("Unexpected map type!"); 5217 break; 5218 } 5219 if (AddPtrFlag) 5220 Bits |= OMP_MAP_IS_PTR; 5221 if (AddIsFirstFlag) 5222 Bits |= OMP_MAP_FIRST_REF; 5223 if (MapTypeModifier == OMPC_MAP_always) 5224 Bits |= OMP_MAP_ALWAYS; 5225 return Bits; 5226 } 5227 5228 /// \brief Return true if the provided expression is a final array section. A 5229 /// final array section, is one whose length can't be proved to be one. 5230 bool isFinalArraySectionExpression(const Expr *E) const { 5231 auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 5232 5233 // It is not an array section and therefore not a unity-size one. 5234 if (!OASE) 5235 return false; 5236 5237 // An array section with no colon always refer to a single element. 5238 if (OASE->getColonLoc().isInvalid()) 5239 return false; 5240 5241 auto *Length = OASE->getLength(); 5242 5243 // If we don't have a length we have to check if the array has size 1 5244 // for this dimension. Also, we should always expect a length if the 5245 // base type is pointer. 5246 if (!Length) { 5247 auto BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 5248 OASE->getBase()->IgnoreParenImpCasts()) 5249 .getCanonicalType(); 5250 if (auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 5251 return ATy->getSize().getSExtValue() != 1; 5252 // If we don't have a constant dimension length, we have to consider 5253 // the current section as having any size, so it is not necessarily 5254 // unitary. If it happen to be unity size, that's user fault. 5255 return true; 5256 } 5257 5258 // Check if the length evaluates to 1. 5259 llvm::APSInt ConstLength; 5260 if (!Length->EvaluateAsInt(ConstLength, CGF.getContext())) 5261 return true; // Can have more that size 1. 5262 5263 return ConstLength.getSExtValue() != 1; 5264 } 5265 5266 /// \brief Generate the base pointers, section pointers, sizes and map type 5267 /// bits for the provided map type, map modifier, and expression components. 5268 /// \a IsFirstComponent should be set to true if the provided set of 5269 /// components is the first associated with a capture. 5270 void generateInfoForComponentList( 5271 OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier, 5272 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 5273 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 5274 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 5275 bool IsFirstComponentList) const { 5276 5277 // The following summarizes what has to be generated for each map and the 5278 // types bellow. The generated information is expressed in this order: 5279 // base pointer, section pointer, size, flags 5280 // (to add to the ones that come from the map type and modifier). 5281 // 5282 // double d; 5283 // int i[100]; 5284 // float *p; 5285 // 5286 // struct S1 { 5287 // int i; 5288 // float f[50]; 5289 // } 5290 // struct S2 { 5291 // int i; 5292 // float f[50]; 5293 // S1 s; 5294 // double *p; 5295 // struct S2 *ps; 5296 // } 5297 // S2 s; 5298 // S2 *ps; 5299 // 5300 // map(d) 5301 // &d, &d, sizeof(double), noflags 5302 // 5303 // map(i) 5304 // &i, &i, 100*sizeof(int), noflags 5305 // 5306 // map(i[1:23]) 5307 // &i(=&i[0]), &i[1], 23*sizeof(int), noflags 5308 // 5309 // map(p) 5310 // &p, &p, sizeof(float*), noflags 5311 // 5312 // map(p[1:24]) 5313 // p, &p[1], 24*sizeof(float), noflags 5314 // 5315 // map(s) 5316 // &s, &s, sizeof(S2), noflags 5317 // 5318 // map(s.i) 5319 // &s, &(s.i), sizeof(int), noflags 5320 // 5321 // map(s.s.f) 5322 // &s, &(s.i.f), 50*sizeof(int), noflags 5323 // 5324 // map(s.p) 5325 // &s, &(s.p), sizeof(double*), noflags 5326 // 5327 // map(s.p[:22], s.a s.b) 5328 // &s, &(s.p), sizeof(double*), noflags 5329 // &(s.p), &(s.p[0]), 22*sizeof(double), ptr_flag + extra_flag 5330 // 5331 // map(s.ps) 5332 // &s, &(s.ps), sizeof(S2*), noflags 5333 // 5334 // map(s.ps->s.i) 5335 // &s, &(s.ps), sizeof(S2*), noflags 5336 // &(s.ps), &(s.ps->s.i), sizeof(int), ptr_flag + extra_flag 5337 // 5338 // map(s.ps->ps) 5339 // &s, &(s.ps), sizeof(S2*), noflags 5340 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag 5341 // 5342 // map(s.ps->ps->ps) 5343 // &s, &(s.ps), sizeof(S2*), noflags 5344 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag 5345 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag 5346 // 5347 // map(s.ps->ps->s.f[:22]) 5348 // &s, &(s.ps), sizeof(S2*), noflags 5349 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag 5350 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), ptr_flag + extra_flag 5351 // 5352 // map(ps) 5353 // &ps, &ps, sizeof(S2*), noflags 5354 // 5355 // map(ps->i) 5356 // ps, &(ps->i), sizeof(int), noflags 5357 // 5358 // map(ps->s.f) 5359 // ps, &(ps->s.f[0]), 50*sizeof(float), noflags 5360 // 5361 // map(ps->p) 5362 // ps, &(ps->p), sizeof(double*), noflags 5363 // 5364 // map(ps->p[:22]) 5365 // ps, &(ps->p), sizeof(double*), noflags 5366 // &(ps->p), &(ps->p[0]), 22*sizeof(double), ptr_flag + extra_flag 5367 // 5368 // map(ps->ps) 5369 // ps, &(ps->ps), sizeof(S2*), noflags 5370 // 5371 // map(ps->ps->s.i) 5372 // ps, &(ps->ps), sizeof(S2*), noflags 5373 // &(ps->ps), &(ps->ps->s.i), sizeof(int), ptr_flag + extra_flag 5374 // 5375 // map(ps->ps->ps) 5376 // ps, &(ps->ps), sizeof(S2*), noflags 5377 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag 5378 // 5379 // map(ps->ps->ps->ps) 5380 // ps, &(ps->ps), sizeof(S2*), noflags 5381 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag 5382 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag 5383 // 5384 // map(ps->ps->ps->s.f[:22]) 5385 // ps, &(ps->ps), sizeof(S2*), noflags 5386 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag 5387 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), ptr_flag + 5388 // extra_flag 5389 5390 // Track if the map information being generated is the first for a capture. 5391 bool IsCaptureFirstInfo = IsFirstComponentList; 5392 5393 // Scan the components from the base to the complete expression. 5394 auto CI = Components.rbegin(); 5395 auto CE = Components.rend(); 5396 auto I = CI; 5397 5398 // Track if the map information being generated is the first for a list of 5399 // components. 5400 bool IsExpressionFirstInfo = true; 5401 llvm::Value *BP = nullptr; 5402 5403 if (auto *ME = dyn_cast<MemberExpr>(I->getAssociatedExpression())) { 5404 // The base is the 'this' pointer. The content of the pointer is going 5405 // to be the base of the field being mapped. 5406 BP = CGF.EmitScalarExpr(ME->getBase()); 5407 } else { 5408 // The base is the reference to the variable. 5409 // BP = &Var. 5410 BP = CGF.EmitLValue(cast<DeclRefExpr>(I->getAssociatedExpression())) 5411 .getPointer(); 5412 5413 // If the variable is a pointer and is being dereferenced (i.e. is not 5414 // the last component), the base has to be the pointer itself, not its 5415 // reference. References are ignored for mapping purposes. 5416 QualType Ty = 5417 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 5418 if (Ty->isAnyPointerType() && std::next(I) != CE) { 5419 auto PtrAddr = CGF.MakeNaturalAlignAddrLValue(BP, Ty); 5420 BP = CGF.EmitLoadOfPointerLValue(PtrAddr.getAddress(), 5421 Ty->castAs<PointerType>()) 5422 .getPointer(); 5423 5424 // We do not need to generate individual map information for the 5425 // pointer, it can be associated with the combined storage. 5426 ++I; 5427 } 5428 } 5429 5430 for (; I != CE; ++I) { 5431 auto Next = std::next(I); 5432 5433 // We need to generate the addresses and sizes if this is the last 5434 // component, if the component is a pointer or if it is an array section 5435 // whose length can't be proved to be one. If this is a pointer, it 5436 // becomes the base address for the following components. 5437 5438 // A final array section, is one whose length can't be proved to be one. 5439 bool IsFinalArraySection = 5440 isFinalArraySectionExpression(I->getAssociatedExpression()); 5441 5442 // Get information on whether the element is a pointer. Have to do a 5443 // special treatment for array sections given that they are built-in 5444 // types. 5445 const auto *OASE = 5446 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 5447 bool IsPointer = 5448 (OASE && 5449 OMPArraySectionExpr::getBaseOriginalType(OASE) 5450 .getCanonicalType() 5451 ->isAnyPointerType()) || 5452 I->getAssociatedExpression()->getType()->isAnyPointerType(); 5453 5454 if (Next == CE || IsPointer || IsFinalArraySection) { 5455 5456 // If this is not the last component, we expect the pointer to be 5457 // associated with an array expression or member expression. 5458 assert((Next == CE || 5459 isa<MemberExpr>(Next->getAssociatedExpression()) || 5460 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 5461 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 5462 "Unexpected expression"); 5463 5464 auto *LB = CGF.EmitLValue(I->getAssociatedExpression()).getPointer(); 5465 auto *Size = getExprTypeSize(I->getAssociatedExpression()); 5466 5467 // If we have a member expression and the current component is a 5468 // reference, we have to map the reference too. Whenever we have a 5469 // reference, the section that reference refers to is going to be a 5470 // load instruction from the storage assigned to the reference. 5471 if (isa<MemberExpr>(I->getAssociatedExpression()) && 5472 I->getAssociatedDeclaration()->getType()->isReferenceType()) { 5473 auto *LI = cast<llvm::LoadInst>(LB); 5474 auto *RefAddr = LI->getPointerOperand(); 5475 5476 BasePointers.push_back(BP); 5477 Pointers.push_back(RefAddr); 5478 Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy)); 5479 Types.push_back(getMapTypeBits( 5480 /*MapType*/ OMPC_MAP_alloc, /*MapTypeModifier=*/OMPC_MAP_unknown, 5481 !IsExpressionFirstInfo, IsCaptureFirstInfo)); 5482 IsExpressionFirstInfo = false; 5483 IsCaptureFirstInfo = false; 5484 // The reference will be the next base address. 5485 BP = RefAddr; 5486 } 5487 5488 BasePointers.push_back(BP); 5489 Pointers.push_back(LB); 5490 Sizes.push_back(Size); 5491 5492 // We need to add a pointer flag for each map that comes from the 5493 // same expression except for the first one. We also need to signal 5494 // this map is the first one that relates with the current capture 5495 // (there is a set of entries for each capture). 5496 Types.push_back(getMapTypeBits(MapType, MapTypeModifier, 5497 !IsExpressionFirstInfo, 5498 IsCaptureFirstInfo)); 5499 5500 // If we have a final array section, we are done with this expression. 5501 if (IsFinalArraySection) 5502 break; 5503 5504 // The pointer becomes the base for the next element. 5505 if (Next != CE) 5506 BP = LB; 5507 5508 IsExpressionFirstInfo = false; 5509 IsCaptureFirstInfo = false; 5510 continue; 5511 } 5512 } 5513 } 5514 5515 /// \brief Return the adjusted map modifiers if the declaration a capture 5516 /// refers to appears in a first-private clause. This is expected to be used 5517 /// only with directives that start with 'target'. 5518 unsigned adjustMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap, 5519 unsigned CurrentModifiers) { 5520 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 5521 5522 // A first private variable captured by reference will use only the 5523 // 'private ptr' and 'map to' flag. Return the right flags if the captured 5524 // declaration is known as first-private in this handler. 5525 if (FirstPrivateDecls.count(Cap.getCapturedVar())) 5526 return MappableExprsHandler::OMP_MAP_PRIVATE_PTR | 5527 MappableExprsHandler::OMP_MAP_TO; 5528 5529 // We didn't modify anything. 5530 return CurrentModifiers; 5531 } 5532 5533 public: 5534 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 5535 : CurDir(Dir), CGF(CGF) { 5536 // Extract firstprivate clause information. 5537 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 5538 for (const auto *D : C->varlists()) 5539 FirstPrivateDecls.insert( 5540 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl()); 5541 // Extract device pointer clause information. 5542 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 5543 for (auto L : C->component_lists()) 5544 DevPointersMap[L.first].push_back(L.second); 5545 } 5546 5547 /// \brief Generate all the base pointers, section pointers, sizes and map 5548 /// types for the extracted mappable expressions. Also, for each item that 5549 /// relates with a device pointer, a pair of the relevant declaration and 5550 /// index where it occurs is appended to the device pointers info array. 5551 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 5552 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 5553 MapFlagsArrayTy &Types) const { 5554 BasePointers.clear(); 5555 Pointers.clear(); 5556 Sizes.clear(); 5557 Types.clear(); 5558 5559 struct MapInfo { 5560 /// Kind that defines how a device pointer has to be returned. 5561 enum ReturnPointerKind { 5562 // Don't have to return any pointer. 5563 RPK_None, 5564 // Pointer is the base of the declaration. 5565 RPK_Base, 5566 // Pointer is a member of the base declaration - 'this' 5567 RPK_Member, 5568 // Pointer is a reference and a member of the base declaration - 'this' 5569 RPK_MemberReference, 5570 }; 5571 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 5572 OpenMPMapClauseKind MapType; 5573 OpenMPMapClauseKind MapTypeModifier; 5574 ReturnPointerKind ReturnDevicePointer; 5575 5576 MapInfo() 5577 : MapType(OMPC_MAP_unknown), MapTypeModifier(OMPC_MAP_unknown), 5578 ReturnDevicePointer(RPK_None) {} 5579 MapInfo( 5580 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 5581 OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier, 5582 ReturnPointerKind ReturnDevicePointer) 5583 : Components(Components), MapType(MapType), 5584 MapTypeModifier(MapTypeModifier), 5585 ReturnDevicePointer(ReturnDevicePointer) {} 5586 }; 5587 5588 // We have to process the component lists that relate with the same 5589 // declaration in a single chunk so that we can generate the map flags 5590 // correctly. Therefore, we organize all lists in a map. 5591 llvm::DenseMap<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 5592 5593 // Helper function to fill the information map for the different supported 5594 // clauses. 5595 auto &&InfoGen = [&Info]( 5596 const ValueDecl *D, 5597 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 5598 OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapModifier, 5599 MapInfo::ReturnPointerKind ReturnDevicePointer) { 5600 const ValueDecl *VD = 5601 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 5602 Info[VD].push_back({L, MapType, MapModifier, ReturnDevicePointer}); 5603 }; 5604 5605 // FIXME: MSVC 2013 seems to require this-> to find member CurDir. 5606 for (auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) 5607 for (auto L : C->component_lists()) 5608 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifier(), 5609 MapInfo::RPK_None); 5610 for (auto *C : this->CurDir.getClausesOfKind<OMPToClause>()) 5611 for (auto L : C->component_lists()) 5612 InfoGen(L.first, L.second, OMPC_MAP_to, OMPC_MAP_unknown, 5613 MapInfo::RPK_None); 5614 for (auto *C : this->CurDir.getClausesOfKind<OMPFromClause>()) 5615 for (auto L : C->component_lists()) 5616 InfoGen(L.first, L.second, OMPC_MAP_from, OMPC_MAP_unknown, 5617 MapInfo::RPK_None); 5618 5619 // Look at the use_device_ptr clause information and mark the existing map 5620 // entries as such. If there is no map information for an entry in the 5621 // use_device_ptr list, we create one with map type 'alloc' and zero size 5622 // section. It is the user fault if that was not mapped before. 5623 // FIXME: MSVC 2013 seems to require this-> to find member CurDir. 5624 for (auto *C : this->CurDir.getClausesOfKind<OMPUseDevicePtrClause>()) 5625 for (auto L : C->component_lists()) { 5626 assert(!L.second.empty() && "Not expecting empty list of components!"); 5627 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 5628 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 5629 auto *IE = L.second.back().getAssociatedExpression(); 5630 // If the first component is a member expression, we have to look into 5631 // 'this', which maps to null in the map of map information. Otherwise 5632 // look directly for the information. 5633 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 5634 5635 // We potentially have map information for this declaration already. 5636 // Look for the first set of components that refer to it. 5637 if (It != Info.end()) { 5638 auto CI = std::find_if( 5639 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 5640 return MI.Components.back().getAssociatedDeclaration() == VD; 5641 }); 5642 // If we found a map entry, signal that the pointer has to be returned 5643 // and move on to the next declaration. 5644 if (CI != It->second.end()) { 5645 CI->ReturnDevicePointer = isa<MemberExpr>(IE) 5646 ? (VD->getType()->isReferenceType() 5647 ? MapInfo::RPK_MemberReference 5648 : MapInfo::RPK_Member) 5649 : MapInfo::RPK_Base; 5650 continue; 5651 } 5652 } 5653 5654 // We didn't find any match in our map information - generate a zero 5655 // size array section. 5656 // FIXME: MSVC 2013 seems to require this-> to find member CGF. 5657 llvm::Value *Ptr = 5658 this->CGF 5659 .EmitLoadOfLValue(this->CGF.EmitLValue(IE), SourceLocation()) 5660 .getScalarVal(); 5661 BasePointers.push_back({Ptr, VD}); 5662 Pointers.push_back(Ptr); 5663 Sizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy)); 5664 Types.push_back(OMP_MAP_RETURN_PTR | OMP_MAP_FIRST_REF); 5665 } 5666 5667 for (auto &M : Info) { 5668 // We need to know when we generate information for the first component 5669 // associated with a capture, because the mapping flags depend on it. 5670 bool IsFirstComponentList = true; 5671 for (MapInfo &L : M.second) { 5672 assert(!L.Components.empty() && 5673 "Not expecting declaration with no component lists."); 5674 5675 // Remember the current base pointer index. 5676 unsigned CurrentBasePointersIdx = BasePointers.size(); 5677 // FIXME: MSVC 2013 seems to require this-> to find the member method. 5678 this->generateInfoForComponentList(L.MapType, L.MapTypeModifier, 5679 L.Components, BasePointers, Pointers, 5680 Sizes, Types, IsFirstComponentList); 5681 5682 // If this entry relates with a device pointer, set the relevant 5683 // declaration and add the 'return pointer' flag. 5684 if (IsFirstComponentList && 5685 L.ReturnDevicePointer != MapInfo::RPK_None) { 5686 // If the pointer is not the base of the map, we need to skip the 5687 // base. If it is a reference in a member field, we also need to skip 5688 // the map of the reference. 5689 if (L.ReturnDevicePointer != MapInfo::RPK_Base) { 5690 ++CurrentBasePointersIdx; 5691 if (L.ReturnDevicePointer == MapInfo::RPK_MemberReference) 5692 ++CurrentBasePointersIdx; 5693 } 5694 assert(BasePointers.size() > CurrentBasePointersIdx && 5695 "Unexpected number of mapped base pointers."); 5696 5697 auto *RelevantVD = L.Components.back().getAssociatedDeclaration(); 5698 assert(RelevantVD && 5699 "No relevant declaration related with device pointer??"); 5700 5701 BasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 5702 Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PTR; 5703 } 5704 IsFirstComponentList = false; 5705 } 5706 } 5707 } 5708 5709 /// \brief Generate the base pointers, section pointers, sizes and map types 5710 /// associated to a given capture. 5711 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 5712 llvm::Value *Arg, 5713 MapBaseValuesArrayTy &BasePointers, 5714 MapValuesArrayTy &Pointers, 5715 MapValuesArrayTy &Sizes, 5716 MapFlagsArrayTy &Types) const { 5717 assert(!Cap->capturesVariableArrayType() && 5718 "Not expecting to generate map info for a variable array type!"); 5719 5720 BasePointers.clear(); 5721 Pointers.clear(); 5722 Sizes.clear(); 5723 Types.clear(); 5724 5725 // We need to know when we generating information for the first component 5726 // associated with a capture, because the mapping flags depend on it. 5727 bool IsFirstComponentList = true; 5728 5729 const ValueDecl *VD = 5730 Cap->capturesThis() 5731 ? nullptr 5732 : cast<ValueDecl>(Cap->getCapturedVar()->getCanonicalDecl()); 5733 5734 // If this declaration appears in a is_device_ptr clause we just have to 5735 // pass the pointer by value. If it is a reference to a declaration, we just 5736 // pass its value, otherwise, if it is a member expression, we need to map 5737 // 'to' the field. 5738 if (!VD) { 5739 auto It = DevPointersMap.find(VD); 5740 if (It != DevPointersMap.end()) { 5741 for (auto L : It->second) { 5742 generateInfoForComponentList( 5743 /*MapType=*/OMPC_MAP_to, /*MapTypeModifier=*/OMPC_MAP_unknown, L, 5744 BasePointers, Pointers, Sizes, Types, IsFirstComponentList); 5745 IsFirstComponentList = false; 5746 } 5747 return; 5748 } 5749 } else if (DevPointersMap.count(VD)) { 5750 BasePointers.push_back({Arg, VD}); 5751 Pointers.push_back(Arg); 5752 Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy)); 5753 Types.push_back(OMP_MAP_PRIVATE_VAL | OMP_MAP_FIRST_REF); 5754 return; 5755 } 5756 5757 // FIXME: MSVC 2013 seems to require this-> to find member CurDir. 5758 for (auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) 5759 for (auto L : C->decl_component_lists(VD)) { 5760 assert(L.first == VD && 5761 "We got information for the wrong declaration??"); 5762 assert(!L.second.empty() && 5763 "Not expecting declaration with no component lists."); 5764 generateInfoForComponentList(C->getMapType(), C->getMapTypeModifier(), 5765 L.second, BasePointers, Pointers, Sizes, 5766 Types, IsFirstComponentList); 5767 IsFirstComponentList = false; 5768 } 5769 5770 return; 5771 } 5772 5773 /// \brief Generate the default map information for a given capture \a CI, 5774 /// record field declaration \a RI and captured value \a CV. 5775 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 5776 const FieldDecl &RI, llvm::Value *CV, 5777 MapBaseValuesArrayTy &CurBasePointers, 5778 MapValuesArrayTy &CurPointers, 5779 MapValuesArrayTy &CurSizes, 5780 MapFlagsArrayTy &CurMapTypes) { 5781 5782 // Do the default mapping. 5783 if (CI.capturesThis()) { 5784 CurBasePointers.push_back(CV); 5785 CurPointers.push_back(CV); 5786 const PointerType *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 5787 CurSizes.push_back(CGF.getTypeSize(PtrTy->getPointeeType())); 5788 // Default map type. 5789 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 5790 } else if (CI.capturesVariableByCopy()) { 5791 CurBasePointers.push_back(CV); 5792 CurPointers.push_back(CV); 5793 if (!RI.getType()->isAnyPointerType()) { 5794 // We have to signal to the runtime captures passed by value that are 5795 // not pointers. 5796 CurMapTypes.push_back(OMP_MAP_PRIVATE_VAL); 5797 CurSizes.push_back(CGF.getTypeSize(RI.getType())); 5798 } else { 5799 // Pointers are implicitly mapped with a zero size and no flags 5800 // (other than first map that is added for all implicit maps). 5801 CurMapTypes.push_back(0u); 5802 CurSizes.push_back(llvm::Constant::getNullValue(CGF.SizeTy)); 5803 } 5804 } else { 5805 assert(CI.capturesVariable() && "Expected captured reference."); 5806 CurBasePointers.push_back(CV); 5807 CurPointers.push_back(CV); 5808 5809 const ReferenceType *PtrTy = 5810 cast<ReferenceType>(RI.getType().getTypePtr()); 5811 QualType ElementType = PtrTy->getPointeeType(); 5812 CurSizes.push_back(CGF.getTypeSize(ElementType)); 5813 // The default map type for a scalar/complex type is 'to' because by 5814 // default the value doesn't have to be retrieved. For an aggregate 5815 // type, the default is 'tofrom'. 5816 CurMapTypes.push_back(ElementType->isAggregateType() 5817 ? (OMP_MAP_TO | OMP_MAP_FROM) 5818 : OMP_MAP_TO); 5819 5820 // If we have a capture by reference we may need to add the private 5821 // pointer flag if the base declaration shows in some first-private 5822 // clause. 5823 CurMapTypes.back() = 5824 adjustMapModifiersForPrivateClauses(CI, CurMapTypes.back()); 5825 } 5826 // Every default map produces a single argument, so, it is always the 5827 // first one. 5828 CurMapTypes.back() |= OMP_MAP_FIRST_REF; 5829 } 5830 }; 5831 5832 enum OpenMPOffloadingReservedDeviceIDs { 5833 /// \brief Device ID if the device was not defined, runtime should get it 5834 /// from environment variables in the spec. 5835 OMP_DEVICEID_UNDEF = -1, 5836 }; 5837 } // anonymous namespace 5838 5839 /// \brief Emit the arrays used to pass the captures and map information to the 5840 /// offloading runtime library. If there is no map or capture information, 5841 /// return nullptr by reference. 5842 static void 5843 emitOffloadingArrays(CodeGenFunction &CGF, 5844 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 5845 MappableExprsHandler::MapValuesArrayTy &Pointers, 5846 MappableExprsHandler::MapValuesArrayTy &Sizes, 5847 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 5848 CGOpenMPRuntime::TargetDataInfo &Info) { 5849 auto &CGM = CGF.CGM; 5850 auto &Ctx = CGF.getContext(); 5851 5852 // Reset the array information. 5853 Info.clearArrayInfo(); 5854 Info.NumberOfPtrs = BasePointers.size(); 5855 5856 if (Info.NumberOfPtrs) { 5857 // Detect if we have any capture size requiring runtime evaluation of the 5858 // size so that a constant array could be eventually used. 5859 bool hasRuntimeEvaluationCaptureSize = false; 5860 for (auto *S : Sizes) 5861 if (!isa<llvm::Constant>(S)) { 5862 hasRuntimeEvaluationCaptureSize = true; 5863 break; 5864 } 5865 5866 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 5867 QualType PointerArrayType = 5868 Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal, 5869 /*IndexTypeQuals=*/0); 5870 5871 Info.BasePointersArray = 5872 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 5873 Info.PointersArray = 5874 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 5875 5876 // If we don't have any VLA types or other types that require runtime 5877 // evaluation, we can use a constant array for the map sizes, otherwise we 5878 // need to fill up the arrays as we do for the pointers. 5879 if (hasRuntimeEvaluationCaptureSize) { 5880 QualType SizeArrayType = Ctx.getConstantArrayType( 5881 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal, 5882 /*IndexTypeQuals=*/0); 5883 Info.SizesArray = 5884 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 5885 } else { 5886 // We expect all the sizes to be constant, so we collect them to create 5887 // a constant array. 5888 SmallVector<llvm::Constant *, 16> ConstSizes; 5889 for (auto S : Sizes) 5890 ConstSizes.push_back(cast<llvm::Constant>(S)); 5891 5892 auto *SizesArrayInit = llvm::ConstantArray::get( 5893 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes); 5894 auto *SizesArrayGbl = new llvm::GlobalVariable( 5895 CGM.getModule(), SizesArrayInit->getType(), 5896 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 5897 SizesArrayInit, ".offload_sizes"); 5898 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 5899 Info.SizesArray = SizesArrayGbl; 5900 } 5901 5902 // The map types are always constant so we don't need to generate code to 5903 // fill arrays. Instead, we create an array constant. 5904 llvm::Constant *MapTypesArrayInit = 5905 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes); 5906 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 5907 CGM.getModule(), MapTypesArrayInit->getType(), 5908 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 5909 MapTypesArrayInit, ".offload_maptypes"); 5910 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 5911 Info.MapTypesArray = MapTypesArrayGbl; 5912 5913 for (unsigned i = 0; i < Info.NumberOfPtrs; ++i) { 5914 llvm::Value *BPVal = *BasePointers[i]; 5915 if (BPVal->getType()->isPointerTy()) 5916 BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy); 5917 else { 5918 assert(BPVal->getType()->isIntegerTy() && 5919 "If not a pointer, the value type must be an integer."); 5920 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy); 5921 } 5922 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 5923 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 5924 Info.BasePointersArray, 0, i); 5925 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 5926 CGF.Builder.CreateStore(BPVal, BPAddr); 5927 5928 if (Info.requiresDevicePointerInfo()) 5929 if (auto *DevVD = BasePointers[i].getDevicePtrDecl()) 5930 Info.CaptureDeviceAddrMap.insert(std::make_pair(DevVD, BPAddr)); 5931 5932 llvm::Value *PVal = Pointers[i]; 5933 if (PVal->getType()->isPointerTy()) 5934 PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy); 5935 else { 5936 assert(PVal->getType()->isIntegerTy() && 5937 "If not a pointer, the value type must be an integer."); 5938 PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy); 5939 } 5940 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 5941 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 5942 Info.PointersArray, 0, i); 5943 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 5944 CGF.Builder.CreateStore(PVal, PAddr); 5945 5946 if (hasRuntimeEvaluationCaptureSize) { 5947 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 5948 llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), 5949 Info.SizesArray, 5950 /*Idx0=*/0, 5951 /*Idx1=*/i); 5952 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType())); 5953 CGF.Builder.CreateStore( 5954 CGF.Builder.CreateIntCast(Sizes[i], CGM.SizeTy, /*isSigned=*/true), 5955 SAddr); 5956 } 5957 } 5958 } 5959 } 5960 /// \brief Emit the arguments to be passed to the runtime library based on the 5961 /// arrays of pointers, sizes and map types. 5962 static void emitOffloadingArraysArgument( 5963 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 5964 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 5965 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 5966 auto &CGM = CGF.CGM; 5967 if (Info.NumberOfPtrs) { 5968 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 5969 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 5970 Info.BasePointersArray, 5971 /*Idx0=*/0, /*Idx1=*/0); 5972 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 5973 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 5974 Info.PointersArray, 5975 /*Idx0=*/0, 5976 /*Idx1=*/0); 5977 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 5978 llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), Info.SizesArray, 5979 /*Idx0=*/0, /*Idx1=*/0); 5980 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 5981 llvm::ArrayType::get(CGM.Int32Ty, Info.NumberOfPtrs), 5982 Info.MapTypesArray, 5983 /*Idx0=*/0, 5984 /*Idx1=*/0); 5985 } else { 5986 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 5987 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 5988 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo()); 5989 MapTypesArrayArg = 5990 llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo()); 5991 } 5992 } 5993 5994 void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, 5995 const OMPExecutableDirective &D, 5996 llvm::Value *OutlinedFn, 5997 llvm::Value *OutlinedFnID, 5998 const Expr *IfCond, const Expr *Device, 5999 ArrayRef<llvm::Value *> CapturedVars) { 6000 if (!CGF.HaveInsertPoint()) 6001 return; 6002 6003 assert(OutlinedFn && "Invalid outlined function!"); 6004 6005 auto &Ctx = CGF.getContext(); 6006 6007 // Fill up the arrays with all the captured variables. 6008 MappableExprsHandler::MapValuesArrayTy KernelArgs; 6009 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 6010 MappableExprsHandler::MapValuesArrayTy Pointers; 6011 MappableExprsHandler::MapValuesArrayTy Sizes; 6012 MappableExprsHandler::MapFlagsArrayTy MapTypes; 6013 6014 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 6015 MappableExprsHandler::MapValuesArrayTy CurPointers; 6016 MappableExprsHandler::MapValuesArrayTy CurSizes; 6017 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 6018 6019 // Get mappable expression information. 6020 MappableExprsHandler MEHandler(D, CGF); 6021 6022 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 6023 auto RI = CS.getCapturedRecordDecl()->field_begin(); 6024 auto CV = CapturedVars.begin(); 6025 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 6026 CE = CS.capture_end(); 6027 CI != CE; ++CI, ++RI, ++CV) { 6028 StringRef Name; 6029 QualType Ty; 6030 6031 CurBasePointers.clear(); 6032 CurPointers.clear(); 6033 CurSizes.clear(); 6034 CurMapTypes.clear(); 6035 6036 // VLA sizes are passed to the outlined region by copy and do not have map 6037 // information associated. 6038 if (CI->capturesVariableArrayType()) { 6039 CurBasePointers.push_back(*CV); 6040 CurPointers.push_back(*CV); 6041 CurSizes.push_back(CGF.getTypeSize(RI->getType())); 6042 // Copy to the device as an argument. No need to retrieve it. 6043 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_PRIVATE_VAL | 6044 MappableExprsHandler::OMP_MAP_FIRST_REF); 6045 } else { 6046 // If we have any information in the map clause, we use it, otherwise we 6047 // just do a default mapping. 6048 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 6049 CurSizes, CurMapTypes); 6050 if (CurBasePointers.empty()) 6051 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 6052 CurPointers, CurSizes, CurMapTypes); 6053 } 6054 // We expect to have at least an element of information for this capture. 6055 assert(!CurBasePointers.empty() && "Non-existing map pointer for capture!"); 6056 assert(CurBasePointers.size() == CurPointers.size() && 6057 CurBasePointers.size() == CurSizes.size() && 6058 CurBasePointers.size() == CurMapTypes.size() && 6059 "Inconsistent map information sizes!"); 6060 6061 // The kernel args are always the first elements of the base pointers 6062 // associated with a capture. 6063 KernelArgs.push_back(*CurBasePointers.front()); 6064 // We need to append the results of this capture to what we already have. 6065 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 6066 Pointers.append(CurPointers.begin(), CurPointers.end()); 6067 Sizes.append(CurSizes.begin(), CurSizes.end()); 6068 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 6069 } 6070 6071 // Keep track on whether the host function has to be executed. 6072 auto OffloadErrorQType = 6073 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true); 6074 auto OffloadError = CGF.MakeAddrLValue( 6075 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"), 6076 OffloadErrorQType); 6077 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty), 6078 OffloadError); 6079 6080 // Fill up the pointer arrays and transfer execution to the device. 6081 auto &&ThenGen = [&BasePointers, &Pointers, &Sizes, &MapTypes, Device, 6082 OutlinedFnID, OffloadError, 6083 &D](CodeGenFunction &CGF, PrePostActionTy &) { 6084 auto &RT = CGF.CGM.getOpenMPRuntime(); 6085 // Emit the offloading arrays. 6086 TargetDataInfo Info; 6087 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 6088 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 6089 Info.PointersArray, Info.SizesArray, 6090 Info.MapTypesArray, Info); 6091 6092 // On top of the arrays that were filled up, the target offloading call 6093 // takes as arguments the device id as well as the host pointer. The host 6094 // pointer is used by the runtime library to identify the current target 6095 // region, so it only has to be unique and not necessarily point to 6096 // anything. It could be the pointer to the outlined function that 6097 // implements the target region, but we aren't using that so that the 6098 // compiler doesn't need to keep that, and could therefore inline the host 6099 // function if proven worthwhile during optimization. 6100 6101 // From this point on, we need to have an ID of the target region defined. 6102 assert(OutlinedFnID && "Invalid outlined function ID!"); 6103 6104 // Emit device ID if any. 6105 llvm::Value *DeviceID; 6106 if (Device) 6107 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 6108 CGF.Int32Ty, /*isSigned=*/true); 6109 else 6110 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF); 6111 6112 // Emit the number of elements in the offloading arrays. 6113 llvm::Value *PointerNum = CGF.Builder.getInt32(BasePointers.size()); 6114 6115 // Return value of the runtime offloading call. 6116 llvm::Value *Return; 6117 6118 auto *NumTeams = emitNumTeamsForTargetDirective(RT, CGF, D); 6119 auto *NumThreads = emitNumThreadsForTargetDirective(RT, CGF, D); 6120 6121 // The target region is an outlined function launched by the runtime 6122 // via calls __tgt_target() or __tgt_target_teams(). 6123 // 6124 // __tgt_target() launches a target region with one team and one thread, 6125 // executing a serial region. This master thread may in turn launch 6126 // more threads within its team upon encountering a parallel region, 6127 // however, no additional teams can be launched on the device. 6128 // 6129 // __tgt_target_teams() launches a target region with one or more teams, 6130 // each with one or more threads. This call is required for target 6131 // constructs such as: 6132 // 'target teams' 6133 // 'target' / 'teams' 6134 // 'target teams distribute parallel for' 6135 // 'target parallel' 6136 // and so on. 6137 // 6138 // Note that on the host and CPU targets, the runtime implementation of 6139 // these calls simply call the outlined function without forking threads. 6140 // The outlined functions themselves have runtime calls to 6141 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 6142 // the compiler in emitTeamsCall() and emitParallelCall(). 6143 // 6144 // In contrast, on the NVPTX target, the implementation of 6145 // __tgt_target_teams() launches a GPU kernel with the requested number 6146 // of teams and threads so no additional calls to the runtime are required. 6147 if (NumTeams) { 6148 // If we have NumTeams defined this means that we have an enclosed teams 6149 // region. Therefore we also expect to have NumThreads defined. These two 6150 // values should be defined in the presence of a teams directive, 6151 // regardless of having any clauses associated. If the user is using teams 6152 // but no clauses, these two values will be the default that should be 6153 // passed to the runtime library - a 32-bit integer with the value zero. 6154 assert(NumThreads && "Thread limit expression should be available along " 6155 "with number of teams."); 6156 llvm::Value *OffloadingArgs[] = { 6157 DeviceID, OutlinedFnID, 6158 PointerNum, Info.BasePointersArray, 6159 Info.PointersArray, Info.SizesArray, 6160 Info.MapTypesArray, NumTeams, 6161 NumThreads}; 6162 Return = CGF.EmitRuntimeCall( 6163 RT.createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs); 6164 } else { 6165 llvm::Value *OffloadingArgs[] = { 6166 DeviceID, OutlinedFnID, 6167 PointerNum, Info.BasePointersArray, 6168 Info.PointersArray, Info.SizesArray, 6169 Info.MapTypesArray}; 6170 Return = CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target), 6171 OffloadingArgs); 6172 } 6173 6174 CGF.EmitStoreOfScalar(Return, OffloadError); 6175 }; 6176 6177 // Notify that the host version must be executed. 6178 auto &&ElseGen = [OffloadError](CodeGenFunction &CGF, PrePostActionTy &) { 6179 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/-1u), 6180 OffloadError); 6181 }; 6182 6183 // If we have a target function ID it means that we need to support 6184 // offloading, otherwise, just execute on the host. We need to execute on host 6185 // regardless of the conditional in the if clause if, e.g., the user do not 6186 // specify target triples. 6187 if (OutlinedFnID) { 6188 if (IfCond) 6189 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 6190 else { 6191 RegionCodeGenTy ThenRCG(ThenGen); 6192 ThenRCG(CGF); 6193 } 6194 } else { 6195 RegionCodeGenTy ElseRCG(ElseGen); 6196 ElseRCG(CGF); 6197 } 6198 6199 // Check the error code and execute the host version if required. 6200 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed"); 6201 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont"); 6202 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation()); 6203 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal); 6204 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 6205 6206 CGF.EmitBlock(OffloadFailedBlock); 6207 CGF.Builder.CreateCall(OutlinedFn, KernelArgs); 6208 CGF.EmitBranch(OffloadContBlock); 6209 6210 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 6211 } 6212 6213 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 6214 StringRef ParentName) { 6215 if (!S) 6216 return; 6217 6218 // Codegen OMP target directives that offload compute to the device. 6219 bool requiresDeviceCodegen = 6220 isa<OMPExecutableDirective>(S) && 6221 isOpenMPTargetExecutionDirective( 6222 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 6223 6224 if (requiresDeviceCodegen) { 6225 auto &E = *cast<OMPExecutableDirective>(S); 6226 unsigned DeviceID; 6227 unsigned FileID; 6228 unsigned Line; 6229 getTargetEntryUniqueInfo(CGM.getContext(), E.getLocStart(), DeviceID, 6230 FileID, Line); 6231 6232 // Is this a target region that should not be emitted as an entry point? If 6233 // so just signal we are done with this target region. 6234 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 6235 ParentName, Line)) 6236 return; 6237 6238 switch (S->getStmtClass()) { 6239 case Stmt::OMPTargetDirectiveClass: 6240 CodeGenFunction::EmitOMPTargetDeviceFunction( 6241 CGM, ParentName, cast<OMPTargetDirective>(*S)); 6242 break; 6243 case Stmt::OMPTargetParallelDirectiveClass: 6244 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 6245 CGM, ParentName, cast<OMPTargetParallelDirective>(*S)); 6246 break; 6247 case Stmt::OMPTargetTeamsDirectiveClass: 6248 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 6249 CGM, ParentName, cast<OMPTargetTeamsDirective>(*S)); 6250 break; 6251 default: 6252 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 6253 } 6254 return; 6255 } 6256 6257 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) { 6258 if (!E->hasAssociatedStmt()) 6259 return; 6260 6261 scanForTargetRegionsFunctions( 6262 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(), 6263 ParentName); 6264 return; 6265 } 6266 6267 // If this is a lambda function, look into its body. 6268 if (auto *L = dyn_cast<LambdaExpr>(S)) 6269 S = L->getBody(); 6270 6271 // Keep looking for target regions recursively. 6272 for (auto *II : S->children()) 6273 scanForTargetRegionsFunctions(II, ParentName); 6274 } 6275 6276 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 6277 auto &FD = *cast<FunctionDecl>(GD.getDecl()); 6278 6279 // If emitting code for the host, we do not process FD here. Instead we do 6280 // the normal code generation. 6281 if (!CGM.getLangOpts().OpenMPIsDevice) 6282 return false; 6283 6284 // Try to detect target regions in the function. 6285 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD)); 6286 6287 // We should not emit any function other that the ones created during the 6288 // scanning. Therefore, we signal that this function is completely dealt 6289 // with. 6290 return true; 6291 } 6292 6293 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 6294 if (!CGM.getLangOpts().OpenMPIsDevice) 6295 return false; 6296 6297 // Check if there are Ctors/Dtors in this declaration and look for target 6298 // regions in it. We use the complete variant to produce the kernel name 6299 // mangling. 6300 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 6301 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 6302 for (auto *Ctor : RD->ctors()) { 6303 StringRef ParentName = 6304 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 6305 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 6306 } 6307 auto *Dtor = RD->getDestructor(); 6308 if (Dtor) { 6309 StringRef ParentName = 6310 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 6311 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 6312 } 6313 } 6314 6315 // If we are in target mode we do not emit any global (declare target is not 6316 // implemented yet). Therefore we signal that GD was processed in this case. 6317 return true; 6318 } 6319 6320 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 6321 auto *VD = GD.getDecl(); 6322 if (isa<FunctionDecl>(VD)) 6323 return emitTargetFunctions(GD); 6324 6325 return emitTargetGlobalVariable(GD); 6326 } 6327 6328 llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() { 6329 // If we have offloading in the current module, we need to emit the entries 6330 // now and register the offloading descriptor. 6331 createOffloadEntriesAndInfoMetadata(); 6332 6333 // Create and register the offloading binary descriptors. This is the main 6334 // entity that captures all the information about offloading in the current 6335 // compilation unit. 6336 return createOffloadingBinaryDescriptorRegistration(); 6337 } 6338 6339 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 6340 const OMPExecutableDirective &D, 6341 SourceLocation Loc, 6342 llvm::Value *OutlinedFn, 6343 ArrayRef<llvm::Value *> CapturedVars) { 6344 if (!CGF.HaveInsertPoint()) 6345 return; 6346 6347 auto *RTLoc = emitUpdateLocation(CGF, Loc); 6348 CodeGenFunction::RunCleanupsScope Scope(CGF); 6349 6350 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 6351 llvm::Value *Args[] = { 6352 RTLoc, 6353 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 6354 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 6355 llvm::SmallVector<llvm::Value *, 16> RealArgs; 6356 RealArgs.append(std::begin(Args), std::end(Args)); 6357 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 6358 6359 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 6360 CGF.EmitRuntimeCall(RTLFn, RealArgs); 6361 } 6362 6363 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 6364 const Expr *NumTeams, 6365 const Expr *ThreadLimit, 6366 SourceLocation Loc) { 6367 if (!CGF.HaveInsertPoint()) 6368 return; 6369 6370 auto *RTLoc = emitUpdateLocation(CGF, Loc); 6371 6372 llvm::Value *NumTeamsVal = 6373 (NumTeams) 6374 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 6375 CGF.CGM.Int32Ty, /* isSigned = */ true) 6376 : CGF.Builder.getInt32(0); 6377 6378 llvm::Value *ThreadLimitVal = 6379 (ThreadLimit) 6380 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 6381 CGF.CGM.Int32Ty, /* isSigned = */ true) 6382 : CGF.Builder.getInt32(0); 6383 6384 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 6385 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 6386 ThreadLimitVal}; 6387 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 6388 PushNumTeamsArgs); 6389 } 6390 6391 void CGOpenMPRuntime::emitTargetDataCalls( 6392 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 6393 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 6394 if (!CGF.HaveInsertPoint()) 6395 return; 6396 6397 // Action used to replace the default codegen action and turn privatization 6398 // off. 6399 PrePostActionTy NoPrivAction; 6400 6401 // Generate the code for the opening of the data environment. Capture all the 6402 // arguments of the runtime call by reference because they are used in the 6403 // closing of the region. 6404 auto &&BeginThenGen = [&D, Device, &Info, &CodeGen](CodeGenFunction &CGF, 6405 PrePostActionTy &) { 6406 // Fill up the arrays with all the mapped variables. 6407 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 6408 MappableExprsHandler::MapValuesArrayTy Pointers; 6409 MappableExprsHandler::MapValuesArrayTy Sizes; 6410 MappableExprsHandler::MapFlagsArrayTy MapTypes; 6411 6412 // Get map clause information. 6413 MappableExprsHandler MCHandler(D, CGF); 6414 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 6415 6416 // Fill up the arrays and create the arguments. 6417 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 6418 6419 llvm::Value *BasePointersArrayArg = nullptr; 6420 llvm::Value *PointersArrayArg = nullptr; 6421 llvm::Value *SizesArrayArg = nullptr; 6422 llvm::Value *MapTypesArrayArg = nullptr; 6423 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 6424 SizesArrayArg, MapTypesArrayArg, Info); 6425 6426 // Emit device ID if any. 6427 llvm::Value *DeviceID = nullptr; 6428 if (Device) 6429 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 6430 CGF.Int32Ty, /*isSigned=*/true); 6431 else 6432 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF); 6433 6434 // Emit the number of elements in the offloading arrays. 6435 auto *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 6436 6437 llvm::Value *OffloadingArgs[] = { 6438 DeviceID, PointerNum, BasePointersArrayArg, 6439 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 6440 auto &RT = CGF.CGM.getOpenMPRuntime(); 6441 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target_data_begin), 6442 OffloadingArgs); 6443 6444 // If device pointer privatization is required, emit the body of the region 6445 // here. It will have to be duplicated: with and without privatization. 6446 if (!Info.CaptureDeviceAddrMap.empty()) 6447 CodeGen(CGF); 6448 }; 6449 6450 // Generate code for the closing of the data region. 6451 auto &&EndThenGen = [Device, &Info](CodeGenFunction &CGF, PrePostActionTy &) { 6452 assert(Info.isValid() && "Invalid data environment closing arguments."); 6453 6454 llvm::Value *BasePointersArrayArg = nullptr; 6455 llvm::Value *PointersArrayArg = nullptr; 6456 llvm::Value *SizesArrayArg = nullptr; 6457 llvm::Value *MapTypesArrayArg = nullptr; 6458 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 6459 SizesArrayArg, MapTypesArrayArg, Info); 6460 6461 // Emit device ID if any. 6462 llvm::Value *DeviceID = nullptr; 6463 if (Device) 6464 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 6465 CGF.Int32Ty, /*isSigned=*/true); 6466 else 6467 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF); 6468 6469 // Emit the number of elements in the offloading arrays. 6470 auto *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 6471 6472 llvm::Value *OffloadingArgs[] = { 6473 DeviceID, PointerNum, BasePointersArrayArg, 6474 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 6475 auto &RT = CGF.CGM.getOpenMPRuntime(); 6476 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target_data_end), 6477 OffloadingArgs); 6478 }; 6479 6480 // If we need device pointer privatization, we need to emit the body of the 6481 // region with no privatization in the 'else' branch of the conditional. 6482 // Otherwise, we don't have to do anything. 6483 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 6484 PrePostActionTy &) { 6485 if (!Info.CaptureDeviceAddrMap.empty()) { 6486 CodeGen.setAction(NoPrivAction); 6487 CodeGen(CGF); 6488 } 6489 }; 6490 6491 // We don't have to do anything to close the region if the if clause evaluates 6492 // to false. 6493 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 6494 6495 if (IfCond) { 6496 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 6497 } else { 6498 RegionCodeGenTy RCG(BeginThenGen); 6499 RCG(CGF); 6500 } 6501 6502 // If we don't require privatization of device pointers, we emit the body in 6503 // between the runtime calls. This avoids duplicating the body code. 6504 if (Info.CaptureDeviceAddrMap.empty()) { 6505 CodeGen.setAction(NoPrivAction); 6506 CodeGen(CGF); 6507 } 6508 6509 if (IfCond) { 6510 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen); 6511 } else { 6512 RegionCodeGenTy RCG(EndThenGen); 6513 RCG(CGF); 6514 } 6515 } 6516 6517 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 6518 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 6519 const Expr *Device) { 6520 if (!CGF.HaveInsertPoint()) 6521 return; 6522 6523 assert((isa<OMPTargetEnterDataDirective>(D) || 6524 isa<OMPTargetExitDataDirective>(D) || 6525 isa<OMPTargetUpdateDirective>(D)) && 6526 "Expecting either target enter, exit data, or update directives."); 6527 6528 // Generate the code for the opening of the data environment. 6529 auto &&ThenGen = [&D, Device](CodeGenFunction &CGF, PrePostActionTy &) { 6530 // Fill up the arrays with all the mapped variables. 6531 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 6532 MappableExprsHandler::MapValuesArrayTy Pointers; 6533 MappableExprsHandler::MapValuesArrayTy Sizes; 6534 MappableExprsHandler::MapFlagsArrayTy MapTypes; 6535 6536 // Get map clause information. 6537 MappableExprsHandler MEHandler(D, CGF); 6538 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 6539 6540 // Fill up the arrays and create the arguments. 6541 TargetDataInfo Info; 6542 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 6543 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 6544 Info.PointersArray, Info.SizesArray, 6545 Info.MapTypesArray, Info); 6546 6547 // Emit device ID if any. 6548 llvm::Value *DeviceID = nullptr; 6549 if (Device) 6550 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 6551 CGF.Int32Ty, /*isSigned=*/true); 6552 else 6553 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF); 6554 6555 // Emit the number of elements in the offloading arrays. 6556 auto *PointerNum = CGF.Builder.getInt32(BasePointers.size()); 6557 6558 llvm::Value *OffloadingArgs[] = { 6559 DeviceID, PointerNum, Info.BasePointersArray, 6560 Info.PointersArray, Info.SizesArray, Info.MapTypesArray}; 6561 6562 auto &RT = CGF.CGM.getOpenMPRuntime(); 6563 // Select the right runtime function call for each expected standalone 6564 // directive. 6565 OpenMPRTLFunction RTLFn; 6566 switch (D.getDirectiveKind()) { 6567 default: 6568 llvm_unreachable("Unexpected standalone target data directive."); 6569 break; 6570 case OMPD_target_enter_data: 6571 RTLFn = OMPRTL__tgt_target_data_begin; 6572 break; 6573 case OMPD_target_exit_data: 6574 RTLFn = OMPRTL__tgt_target_data_end; 6575 break; 6576 case OMPD_target_update: 6577 RTLFn = OMPRTL__tgt_target_data_update; 6578 break; 6579 } 6580 CGF.EmitRuntimeCall(RT.createRuntimeFunction(RTLFn), OffloadingArgs); 6581 }; 6582 6583 // In the event we get an if clause, we don't have to take any action on the 6584 // else side. 6585 auto &&ElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 6586 6587 if (IfCond) { 6588 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 6589 } else { 6590 RegionCodeGenTy ThenGenRCG(ThenGen); 6591 ThenGenRCG(CGF); 6592 } 6593 } 6594 6595 namespace { 6596 /// Kind of parameter in a function with 'declare simd' directive. 6597 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 6598 /// Attribute set of the parameter. 6599 struct ParamAttrTy { 6600 ParamKindTy Kind = Vector; 6601 llvm::APSInt StrideOrArg; 6602 llvm::APSInt Alignment; 6603 }; 6604 } // namespace 6605 6606 static unsigned evaluateCDTSize(const FunctionDecl *FD, 6607 ArrayRef<ParamAttrTy> ParamAttrs) { 6608 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 6609 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 6610 // of that clause. The VLEN value must be power of 2. 6611 // In other case the notion of the function`s "characteristic data type" (CDT) 6612 // is used to compute the vector length. 6613 // CDT is defined in the following order: 6614 // a) For non-void function, the CDT is the return type. 6615 // b) If the function has any non-uniform, non-linear parameters, then the 6616 // CDT is the type of the first such parameter. 6617 // c) If the CDT determined by a) or b) above is struct, union, or class 6618 // type which is pass-by-value (except for the type that maps to the 6619 // built-in complex data type), the characteristic data type is int. 6620 // d) If none of the above three cases is applicable, the CDT is int. 6621 // The VLEN is then determined based on the CDT and the size of vector 6622 // register of that ISA for which current vector version is generated. The 6623 // VLEN is computed using the formula below: 6624 // VLEN = sizeof(vector_register) / sizeof(CDT), 6625 // where vector register size specified in section 3.2.1 Registers and the 6626 // Stack Frame of original AMD64 ABI document. 6627 QualType RetType = FD->getReturnType(); 6628 if (RetType.isNull()) 6629 return 0; 6630 ASTContext &C = FD->getASTContext(); 6631 QualType CDT; 6632 if (!RetType.isNull() && !RetType->isVoidType()) 6633 CDT = RetType; 6634 else { 6635 unsigned Offset = 0; 6636 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 6637 if (ParamAttrs[Offset].Kind == Vector) 6638 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 6639 ++Offset; 6640 } 6641 if (CDT.isNull()) { 6642 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 6643 if (ParamAttrs[I + Offset].Kind == Vector) { 6644 CDT = FD->getParamDecl(I)->getType(); 6645 break; 6646 } 6647 } 6648 } 6649 } 6650 if (CDT.isNull()) 6651 CDT = C.IntTy; 6652 CDT = CDT->getCanonicalTypeUnqualified(); 6653 if (CDT->isRecordType() || CDT->isUnionType()) 6654 CDT = C.IntTy; 6655 return C.getTypeSize(CDT); 6656 } 6657 6658 static void 6659 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 6660 const llvm::APSInt &VLENVal, 6661 ArrayRef<ParamAttrTy> ParamAttrs, 6662 OMPDeclareSimdDeclAttr::BranchStateTy State) { 6663 struct ISADataTy { 6664 char ISA; 6665 unsigned VecRegSize; 6666 }; 6667 ISADataTy ISAData[] = { 6668 { 6669 'b', 128 6670 }, // SSE 6671 { 6672 'c', 256 6673 }, // AVX 6674 { 6675 'd', 256 6676 }, // AVX2 6677 { 6678 'e', 512 6679 }, // AVX512 6680 }; 6681 llvm::SmallVector<char, 2> Masked; 6682 switch (State) { 6683 case OMPDeclareSimdDeclAttr::BS_Undefined: 6684 Masked.push_back('N'); 6685 Masked.push_back('M'); 6686 break; 6687 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 6688 Masked.push_back('N'); 6689 break; 6690 case OMPDeclareSimdDeclAttr::BS_Inbranch: 6691 Masked.push_back('M'); 6692 break; 6693 } 6694 for (auto Mask : Masked) { 6695 for (auto &Data : ISAData) { 6696 SmallString<256> Buffer; 6697 llvm::raw_svector_ostream Out(Buffer); 6698 Out << "_ZGV" << Data.ISA << Mask; 6699 if (!VLENVal) { 6700 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / 6701 evaluateCDTSize(FD, ParamAttrs)); 6702 } else 6703 Out << VLENVal; 6704 for (auto &ParamAttr : ParamAttrs) { 6705 switch (ParamAttr.Kind){ 6706 case LinearWithVarStride: 6707 Out << 's' << ParamAttr.StrideOrArg; 6708 break; 6709 case Linear: 6710 Out << 'l'; 6711 if (!!ParamAttr.StrideOrArg) 6712 Out << ParamAttr.StrideOrArg; 6713 break; 6714 case Uniform: 6715 Out << 'u'; 6716 break; 6717 case Vector: 6718 Out << 'v'; 6719 break; 6720 } 6721 if (!!ParamAttr.Alignment) 6722 Out << 'a' << ParamAttr.Alignment; 6723 } 6724 Out << '_' << Fn->getName(); 6725 Fn->addFnAttr(Out.str()); 6726 } 6727 } 6728 } 6729 6730 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 6731 llvm::Function *Fn) { 6732 ASTContext &C = CGM.getContext(); 6733 FD = FD->getCanonicalDecl(); 6734 // Map params to their positions in function decl. 6735 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 6736 if (isa<CXXMethodDecl>(FD)) 6737 ParamPositions.insert({FD, 0}); 6738 unsigned ParamPos = ParamPositions.size(); 6739 for (auto *P : FD->parameters()) { 6740 ParamPositions.insert({P->getCanonicalDecl(), ParamPos}); 6741 ++ParamPos; 6742 } 6743 for (auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 6744 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 6745 // Mark uniform parameters. 6746 for (auto *E : Attr->uniforms()) { 6747 E = E->IgnoreParenImpCasts(); 6748 unsigned Pos; 6749 if (isa<CXXThisExpr>(E)) 6750 Pos = ParamPositions[FD]; 6751 else { 6752 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 6753 ->getCanonicalDecl(); 6754 Pos = ParamPositions[PVD]; 6755 } 6756 ParamAttrs[Pos].Kind = Uniform; 6757 } 6758 // Get alignment info. 6759 auto NI = Attr->alignments_begin(); 6760 for (auto *E : Attr->aligneds()) { 6761 E = E->IgnoreParenImpCasts(); 6762 unsigned Pos; 6763 QualType ParmTy; 6764 if (isa<CXXThisExpr>(E)) { 6765 Pos = ParamPositions[FD]; 6766 ParmTy = E->getType(); 6767 } else { 6768 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 6769 ->getCanonicalDecl(); 6770 Pos = ParamPositions[PVD]; 6771 ParmTy = PVD->getType(); 6772 } 6773 ParamAttrs[Pos].Alignment = 6774 (*NI) ? (*NI)->EvaluateKnownConstInt(C) 6775 : llvm::APSInt::getUnsigned( 6776 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 6777 .getQuantity()); 6778 ++NI; 6779 } 6780 // Mark linear parameters. 6781 auto SI = Attr->steps_begin(); 6782 auto MI = Attr->modifiers_begin(); 6783 for (auto *E : Attr->linears()) { 6784 E = E->IgnoreParenImpCasts(); 6785 unsigned Pos; 6786 if (isa<CXXThisExpr>(E)) 6787 Pos = ParamPositions[FD]; 6788 else { 6789 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 6790 ->getCanonicalDecl(); 6791 Pos = ParamPositions[PVD]; 6792 } 6793 auto &ParamAttr = ParamAttrs[Pos]; 6794 ParamAttr.Kind = Linear; 6795 if (*SI) { 6796 if (!(*SI)->EvaluateAsInt(ParamAttr.StrideOrArg, C, 6797 Expr::SE_AllowSideEffects)) { 6798 if (auto *DRE = cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 6799 if (auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 6800 ParamAttr.Kind = LinearWithVarStride; 6801 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 6802 ParamPositions[StridePVD->getCanonicalDecl()]); 6803 } 6804 } 6805 } 6806 } 6807 ++SI; 6808 ++MI; 6809 } 6810 llvm::APSInt VLENVal; 6811 if (const Expr *VLEN = Attr->getSimdlen()) 6812 VLENVal = VLEN->EvaluateKnownConstInt(C); 6813 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 6814 if (CGM.getTriple().getArch() == llvm::Triple::x86 || 6815 CGM.getTriple().getArch() == llvm::Triple::x86_64) 6816 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 6817 } 6818 } 6819 6820 namespace { 6821 /// Cleanup action for doacross support. 6822 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 6823 public: 6824 static const int DoacrossFinArgs = 2; 6825 6826 private: 6827 llvm::Value *RTLFn; 6828 llvm::Value *Args[DoacrossFinArgs]; 6829 6830 public: 6831 DoacrossCleanupTy(llvm::Value *RTLFn, ArrayRef<llvm::Value *> CallArgs) 6832 : RTLFn(RTLFn) { 6833 assert(CallArgs.size() == DoacrossFinArgs); 6834 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 6835 } 6836 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 6837 if (!CGF.HaveInsertPoint()) 6838 return; 6839 CGF.EmitRuntimeCall(RTLFn, Args); 6840 } 6841 }; 6842 } // namespace 6843 6844 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 6845 const OMPLoopDirective &D) { 6846 if (!CGF.HaveInsertPoint()) 6847 return; 6848 6849 ASTContext &C = CGM.getContext(); 6850 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 6851 RecordDecl *RD; 6852 if (KmpDimTy.isNull()) { 6853 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 6854 // kmp_int64 lo; // lower 6855 // kmp_int64 up; // upper 6856 // kmp_int64 st; // stride 6857 // }; 6858 RD = C.buildImplicitRecord("kmp_dim"); 6859 RD->startDefinition(); 6860 addFieldToRecordDecl(C, RD, Int64Ty); 6861 addFieldToRecordDecl(C, RD, Int64Ty); 6862 addFieldToRecordDecl(C, RD, Int64Ty); 6863 RD->completeDefinition(); 6864 KmpDimTy = C.getRecordType(RD); 6865 } else 6866 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 6867 6868 Address DimsAddr = CGF.CreateMemTemp(KmpDimTy, "dims"); 6869 CGF.EmitNullInitialization(DimsAddr, KmpDimTy); 6870 enum { LowerFD = 0, UpperFD, StrideFD }; 6871 // Fill dims with data. 6872 LValue DimsLVal = CGF.MakeAddrLValue(DimsAddr, KmpDimTy); 6873 // dims.upper = num_iterations; 6874 LValue UpperLVal = 6875 CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), UpperFD)); 6876 llvm::Value *NumIterVal = CGF.EmitScalarConversion( 6877 CGF.EmitScalarExpr(D.getNumIterations()), D.getNumIterations()->getType(), 6878 Int64Ty, D.getNumIterations()->getExprLoc()); 6879 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 6880 // dims.stride = 1; 6881 LValue StrideLVal = 6882 CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), StrideFD)); 6883 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 6884 StrideLVal); 6885 6886 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 6887 // kmp_int32 num_dims, struct kmp_dim * dims); 6888 llvm::Value *Args[] = {emitUpdateLocation(CGF, D.getLocStart()), 6889 getThreadID(CGF, D.getLocStart()), 6890 llvm::ConstantInt::getSigned(CGM.Int32Ty, 1), 6891 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6892 DimsAddr.getPointer(), CGM.VoidPtrTy)}; 6893 6894 llvm::Value *RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_init); 6895 CGF.EmitRuntimeCall(RTLFn, Args); 6896 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 6897 emitUpdateLocation(CGF, D.getLocEnd()), getThreadID(CGF, D.getLocEnd())}; 6898 llvm::Value *FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 6899 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 6900 llvm::makeArrayRef(FiniArgs)); 6901 } 6902 6903 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 6904 const OMPDependClause *C) { 6905 QualType Int64Ty = 6906 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 6907 const Expr *CounterVal = C->getCounterValue(); 6908 assert(CounterVal); 6909 llvm::Value *CntVal = CGF.EmitScalarConversion(CGF.EmitScalarExpr(CounterVal), 6910 CounterVal->getType(), Int64Ty, 6911 CounterVal->getExprLoc()); 6912 Address CntAddr = CGF.CreateMemTemp(Int64Ty, ".cnt.addr"); 6913 CGF.EmitStoreOfScalar(CntVal, CntAddr, /*Volatile=*/false, Int64Ty); 6914 llvm::Value *Args[] = {emitUpdateLocation(CGF, C->getLocStart()), 6915 getThreadID(CGF, C->getLocStart()), 6916 CntAddr.getPointer()}; 6917 llvm::Value *RTLFn; 6918 if (C->getDependencyKind() == OMPC_DEPEND_source) 6919 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 6920 else { 6921 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 6922 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 6923 } 6924 CGF.EmitRuntimeCall(RTLFn, Args); 6925 } 6926 6927