1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This provides a class for OpenMP runtime code generation. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "CGOpenMPRuntime.h" 17 #include "CodeGenFunction.h" 18 #include "clang/CodeGen/ConstantInitBuilder.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 llvm::Value *CGOpenMPRuntime::emitReductionFunction( 4261 CodeGenModule &CGM, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 4262 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 4263 ArrayRef<const Expr *> ReductionOps) { 4264 auto &C = CGM.getContext(); 4265 4266 // void reduction_func(void *LHSArg, void *RHSArg); 4267 FunctionArgList Args; 4268 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 4269 C.VoidPtrTy); 4270 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, SourceLocation(), /*Id=*/nullptr, 4271 C.VoidPtrTy); 4272 Args.push_back(&LHSArg); 4273 Args.push_back(&RHSArg); 4274 auto &CGFI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4275 auto *Fn = llvm::Function::Create( 4276 CGM.getTypes().GetFunctionType(CGFI), llvm::GlobalValue::InternalLinkage, 4277 ".omp.reduction.reduction_func", &CGM.getModule()); 4278 CGM.SetInternalFunctionAttributes(/*D=*/nullptr, Fn, CGFI); 4279 CodeGenFunction CGF(CGM); 4280 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args); 4281 4282 // Dst = (void*[n])(LHSArg); 4283 // Src = (void*[n])(RHSArg); 4284 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4285 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 4286 ArgsType), CGF.getPointerAlign()); 4287 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4288 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 4289 ArgsType), CGF.getPointerAlign()); 4290 4291 // ... 4292 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 4293 // ... 4294 CodeGenFunction::OMPPrivateScope Scope(CGF); 4295 auto IPriv = Privates.begin(); 4296 unsigned Idx = 0; 4297 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 4298 auto RHSVar = cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 4299 Scope.addPrivate(RHSVar, [&]() -> Address { 4300 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 4301 }); 4302 auto LHSVar = cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 4303 Scope.addPrivate(LHSVar, [&]() -> Address { 4304 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 4305 }); 4306 QualType PrivTy = (*IPriv)->getType(); 4307 if (PrivTy->isVariablyModifiedType()) { 4308 // Get array size and emit VLA type. 4309 ++Idx; 4310 Address Elem = 4311 CGF.Builder.CreateConstArrayGEP(LHS, Idx, CGF.getPointerSize()); 4312 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 4313 auto *VLA = CGF.getContext().getAsVariableArrayType(PrivTy); 4314 auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 4315 CodeGenFunction::OpaqueValueMapping OpaqueMap( 4316 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 4317 CGF.EmitVariablyModifiedType(PrivTy); 4318 } 4319 } 4320 Scope.Privatize(); 4321 IPriv = Privates.begin(); 4322 auto ILHS = LHSExprs.begin(); 4323 auto IRHS = RHSExprs.begin(); 4324 for (auto *E : ReductionOps) { 4325 if ((*IPriv)->getType()->isArrayType()) { 4326 // Emit reduction for array section. 4327 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 4328 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 4329 EmitOMPAggregateReduction( 4330 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 4331 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 4332 emitReductionCombiner(CGF, E); 4333 }); 4334 } else 4335 // Emit reduction for array subscript or single variable. 4336 emitReductionCombiner(CGF, E); 4337 ++IPriv; 4338 ++ILHS; 4339 ++IRHS; 4340 } 4341 Scope.ForceCleanup(); 4342 CGF.FinishFunction(); 4343 return Fn; 4344 } 4345 4346 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 4347 const Expr *ReductionOp, 4348 const Expr *PrivateRef, 4349 const DeclRefExpr *LHS, 4350 const DeclRefExpr *RHS) { 4351 if (PrivateRef->getType()->isArrayType()) { 4352 // Emit reduction for array section. 4353 auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 4354 auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 4355 EmitOMPAggregateReduction( 4356 CGF, PrivateRef->getType(), LHSVar, RHSVar, 4357 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 4358 emitReductionCombiner(CGF, ReductionOp); 4359 }); 4360 } else 4361 // Emit reduction for array subscript or single variable. 4362 emitReductionCombiner(CGF, ReductionOp); 4363 } 4364 4365 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 4366 ArrayRef<const Expr *> Privates, 4367 ArrayRef<const Expr *> LHSExprs, 4368 ArrayRef<const Expr *> RHSExprs, 4369 ArrayRef<const Expr *> ReductionOps, 4370 ReductionOptionsTy Options) { 4371 if (!CGF.HaveInsertPoint()) 4372 return; 4373 4374 bool WithNowait = Options.WithNowait; 4375 bool SimpleReduction = Options.SimpleReduction; 4376 4377 // Next code should be emitted for reduction: 4378 // 4379 // static kmp_critical_name lock = { 0 }; 4380 // 4381 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 4382 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 4383 // ... 4384 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 4385 // *(Type<n>-1*)rhs[<n>-1]); 4386 // } 4387 // 4388 // ... 4389 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 4390 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 4391 // RedList, reduce_func, &<lock>)) { 4392 // case 1: 4393 // ... 4394 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 4395 // ... 4396 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 4397 // break; 4398 // case 2: 4399 // ... 4400 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 4401 // ... 4402 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 4403 // break; 4404 // default:; 4405 // } 4406 // 4407 // if SimpleReduction is true, only the next code is generated: 4408 // ... 4409 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 4410 // ... 4411 4412 auto &C = CGM.getContext(); 4413 4414 if (SimpleReduction) { 4415 CodeGenFunction::RunCleanupsScope Scope(CGF); 4416 auto IPriv = Privates.begin(); 4417 auto ILHS = LHSExprs.begin(); 4418 auto IRHS = RHSExprs.begin(); 4419 for (auto *E : ReductionOps) { 4420 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 4421 cast<DeclRefExpr>(*IRHS)); 4422 ++IPriv; 4423 ++ILHS; 4424 ++IRHS; 4425 } 4426 return; 4427 } 4428 4429 // 1. Build a list of reduction variables. 4430 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 4431 auto Size = RHSExprs.size(); 4432 for (auto *E : Privates) { 4433 if (E->getType()->isVariablyModifiedType()) 4434 // Reserve place for array size. 4435 ++Size; 4436 } 4437 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 4438 QualType ReductionArrayTy = 4439 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 4440 /*IndexTypeQuals=*/0); 4441 Address ReductionList = 4442 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 4443 auto IPriv = Privates.begin(); 4444 unsigned Idx = 0; 4445 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 4446 Address Elem = 4447 CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, CGF.getPointerSize()); 4448 CGF.Builder.CreateStore( 4449 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4450 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy), 4451 Elem); 4452 if ((*IPriv)->getType()->isVariablyModifiedType()) { 4453 // Store array size. 4454 ++Idx; 4455 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx, 4456 CGF.getPointerSize()); 4457 llvm::Value *Size = CGF.Builder.CreateIntCast( 4458 CGF.getVLASize( 4459 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 4460 .first, 4461 CGF.SizeTy, /*isSigned=*/false); 4462 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 4463 Elem); 4464 } 4465 } 4466 4467 // 2. Emit reduce_func(). 4468 auto *ReductionFn = emitReductionFunction( 4469 CGM, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 4470 LHSExprs, RHSExprs, ReductionOps); 4471 4472 // 3. Create static kmp_critical_name lock = { 0 }; 4473 auto *Lock = getCriticalRegionLock(".reduction"); 4474 4475 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 4476 // RedList, reduce_func, &<lock>); 4477 auto *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 4478 auto *ThreadId = getThreadID(CGF, Loc); 4479 auto *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 4480 auto *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4481 ReductionList.getPointer(), CGF.VoidPtrTy); 4482 llvm::Value *Args[] = { 4483 IdentTLoc, // ident_t *<loc> 4484 ThreadId, // i32 <gtid> 4485 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 4486 ReductionArrayTySize, // size_type sizeof(RedList) 4487 RL, // void *RedList 4488 ReductionFn, // void (*) (void *, void *) <reduce_func> 4489 Lock // kmp_critical_name *&<lock> 4490 }; 4491 auto Res = CGF.EmitRuntimeCall( 4492 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 4493 : OMPRTL__kmpc_reduce), 4494 Args); 4495 4496 // 5. Build switch(res) 4497 auto *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 4498 auto *SwInst = CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 4499 4500 // 6. Build case 1: 4501 // ... 4502 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 4503 // ... 4504 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 4505 // break; 4506 auto *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 4507 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 4508 CGF.EmitBlock(Case1BB); 4509 4510 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 4511 llvm::Value *EndArgs[] = { 4512 IdentTLoc, // ident_t *<loc> 4513 ThreadId, // i32 <gtid> 4514 Lock // kmp_critical_name *&<lock> 4515 }; 4516 auto &&CodeGen = [&Privates, &LHSExprs, &RHSExprs, &ReductionOps]( 4517 CodeGenFunction &CGF, PrePostActionTy &Action) { 4518 auto &RT = CGF.CGM.getOpenMPRuntime(); 4519 auto IPriv = Privates.begin(); 4520 auto ILHS = LHSExprs.begin(); 4521 auto IRHS = RHSExprs.begin(); 4522 for (auto *E : ReductionOps) { 4523 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 4524 cast<DeclRefExpr>(*IRHS)); 4525 ++IPriv; 4526 ++ILHS; 4527 ++IRHS; 4528 } 4529 }; 4530 RegionCodeGenTy RCG(CodeGen); 4531 CommonActionTy Action( 4532 nullptr, llvm::None, 4533 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 4534 : OMPRTL__kmpc_end_reduce), 4535 EndArgs); 4536 RCG.setAction(Action); 4537 RCG(CGF); 4538 4539 CGF.EmitBranch(DefaultBB); 4540 4541 // 7. Build case 2: 4542 // ... 4543 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 4544 // ... 4545 // break; 4546 auto *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 4547 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 4548 CGF.EmitBlock(Case2BB); 4549 4550 auto &&AtomicCodeGen = [Loc, &Privates, &LHSExprs, &RHSExprs, &ReductionOps]( 4551 CodeGenFunction &CGF, PrePostActionTy &Action) { 4552 auto ILHS = LHSExprs.begin(); 4553 auto IRHS = RHSExprs.begin(); 4554 auto IPriv = Privates.begin(); 4555 for (auto *E : ReductionOps) { 4556 const Expr *XExpr = nullptr; 4557 const Expr *EExpr = nullptr; 4558 const Expr *UpExpr = nullptr; 4559 BinaryOperatorKind BO = BO_Comma; 4560 if (auto *BO = dyn_cast<BinaryOperator>(E)) { 4561 if (BO->getOpcode() == BO_Assign) { 4562 XExpr = BO->getLHS(); 4563 UpExpr = BO->getRHS(); 4564 } 4565 } 4566 // Try to emit update expression as a simple atomic. 4567 auto *RHSExpr = UpExpr; 4568 if (RHSExpr) { 4569 // Analyze RHS part of the whole expression. 4570 if (auto *ACO = dyn_cast<AbstractConditionalOperator>( 4571 RHSExpr->IgnoreParenImpCasts())) { 4572 // If this is a conditional operator, analyze its condition for 4573 // min/max reduction operator. 4574 RHSExpr = ACO->getCond(); 4575 } 4576 if (auto *BORHS = 4577 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 4578 EExpr = BORHS->getRHS(); 4579 BO = BORHS->getOpcode(); 4580 } 4581 } 4582 if (XExpr) { 4583 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 4584 auto &&AtomicRedGen = [BO, VD, 4585 Loc](CodeGenFunction &CGF, const Expr *XExpr, 4586 const Expr *EExpr, const Expr *UpExpr) { 4587 LValue X = CGF.EmitLValue(XExpr); 4588 RValue E; 4589 if (EExpr) 4590 E = CGF.EmitAnyExpr(EExpr); 4591 CGF.EmitOMPAtomicSimpleUpdateExpr( 4592 X, E, BO, /*IsXLHSInRHSPart=*/true, 4593 llvm::AtomicOrdering::Monotonic, Loc, 4594 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 4595 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 4596 PrivateScope.addPrivate( 4597 VD, [&CGF, VD, XRValue, Loc]() -> Address { 4598 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 4599 CGF.emitOMPSimpleStore( 4600 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 4601 VD->getType().getNonReferenceType(), Loc); 4602 return LHSTemp; 4603 }); 4604 (void)PrivateScope.Privatize(); 4605 return CGF.EmitAnyExpr(UpExpr); 4606 }); 4607 }; 4608 if ((*IPriv)->getType()->isArrayType()) { 4609 // Emit atomic reduction for array section. 4610 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 4611 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 4612 AtomicRedGen, XExpr, EExpr, UpExpr); 4613 } else 4614 // Emit atomic reduction for array subscript or single variable. 4615 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 4616 } else { 4617 // Emit as a critical region. 4618 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 4619 const Expr *, const Expr *) { 4620 auto &RT = CGF.CGM.getOpenMPRuntime(); 4621 RT.emitCriticalRegion( 4622 CGF, ".atomic_reduction", 4623 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 4624 Action.Enter(CGF); 4625 emitReductionCombiner(CGF, E); 4626 }, 4627 Loc); 4628 }; 4629 if ((*IPriv)->getType()->isArrayType()) { 4630 auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 4631 auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 4632 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 4633 CritRedGen); 4634 } else 4635 CritRedGen(CGF, nullptr, nullptr, nullptr); 4636 } 4637 ++ILHS; 4638 ++IRHS; 4639 ++IPriv; 4640 } 4641 }; 4642 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 4643 if (!WithNowait) { 4644 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 4645 llvm::Value *EndArgs[] = { 4646 IdentTLoc, // ident_t *<loc> 4647 ThreadId, // i32 <gtid> 4648 Lock // kmp_critical_name *&<lock> 4649 }; 4650 CommonActionTy Action(nullptr, llvm::None, 4651 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 4652 EndArgs); 4653 AtomicRCG.setAction(Action); 4654 AtomicRCG(CGF); 4655 } else 4656 AtomicRCG(CGF); 4657 4658 CGF.EmitBranch(DefaultBB); 4659 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 4660 } 4661 4662 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 4663 SourceLocation Loc) { 4664 if (!CGF.HaveInsertPoint()) 4665 return; 4666 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 4667 // global_tid); 4668 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 4669 // Ignore return result until untied tasks are supported. 4670 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 4671 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 4672 Region->emitUntiedSwitch(CGF); 4673 } 4674 4675 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 4676 OpenMPDirectiveKind InnerKind, 4677 const RegionCodeGenTy &CodeGen, 4678 bool HasCancel) { 4679 if (!CGF.HaveInsertPoint()) 4680 return; 4681 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 4682 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 4683 } 4684 4685 namespace { 4686 enum RTCancelKind { 4687 CancelNoreq = 0, 4688 CancelParallel = 1, 4689 CancelLoop = 2, 4690 CancelSections = 3, 4691 CancelTaskgroup = 4 4692 }; 4693 } // anonymous namespace 4694 4695 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 4696 RTCancelKind CancelKind = CancelNoreq; 4697 if (CancelRegion == OMPD_parallel) 4698 CancelKind = CancelParallel; 4699 else if (CancelRegion == OMPD_for) 4700 CancelKind = CancelLoop; 4701 else if (CancelRegion == OMPD_sections) 4702 CancelKind = CancelSections; 4703 else { 4704 assert(CancelRegion == OMPD_taskgroup); 4705 CancelKind = CancelTaskgroup; 4706 } 4707 return CancelKind; 4708 } 4709 4710 void CGOpenMPRuntime::emitCancellationPointCall( 4711 CodeGenFunction &CGF, SourceLocation Loc, 4712 OpenMPDirectiveKind CancelRegion) { 4713 if (!CGF.HaveInsertPoint()) 4714 return; 4715 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 4716 // global_tid, kmp_int32 cncl_kind); 4717 if (auto *OMPRegionInfo = 4718 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 4719 // For 'cancellation point taskgroup', the task region info may not have a 4720 // cancel. This may instead happen in another adjacent task. 4721 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 4722 llvm::Value *Args[] = { 4723 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 4724 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 4725 // Ignore return result until untied tasks are supported. 4726 auto *Result = CGF.EmitRuntimeCall( 4727 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 4728 // if (__kmpc_cancellationpoint()) { 4729 // exit from construct; 4730 // } 4731 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 4732 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 4733 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 4734 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 4735 CGF.EmitBlock(ExitBB); 4736 // exit from construct; 4737 auto CancelDest = 4738 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 4739 CGF.EmitBranchThroughCleanup(CancelDest); 4740 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 4741 } 4742 } 4743 } 4744 4745 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 4746 const Expr *IfCond, 4747 OpenMPDirectiveKind CancelRegion) { 4748 if (!CGF.HaveInsertPoint()) 4749 return; 4750 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 4751 // kmp_int32 cncl_kind); 4752 if (auto *OMPRegionInfo = 4753 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 4754 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 4755 PrePostActionTy &) { 4756 auto &RT = CGF.CGM.getOpenMPRuntime(); 4757 llvm::Value *Args[] = { 4758 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 4759 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 4760 // Ignore return result until untied tasks are supported. 4761 auto *Result = CGF.EmitRuntimeCall( 4762 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 4763 // if (__kmpc_cancel()) { 4764 // exit from construct; 4765 // } 4766 auto *ExitBB = CGF.createBasicBlock(".cancel.exit"); 4767 auto *ContBB = CGF.createBasicBlock(".cancel.continue"); 4768 auto *Cmp = CGF.Builder.CreateIsNotNull(Result); 4769 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 4770 CGF.EmitBlock(ExitBB); 4771 // exit from construct; 4772 auto CancelDest = 4773 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 4774 CGF.EmitBranchThroughCleanup(CancelDest); 4775 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 4776 }; 4777 if (IfCond) 4778 emitOMPIfClause(CGF, IfCond, ThenGen, 4779 [](CodeGenFunction &, PrePostActionTy &) {}); 4780 else { 4781 RegionCodeGenTy ThenRCG(ThenGen); 4782 ThenRCG(CGF); 4783 } 4784 } 4785 } 4786 4787 /// \brief Obtain information that uniquely identifies a target entry. This 4788 /// consists of the file and device IDs as well as line number associated with 4789 /// the relevant entry source location. 4790 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 4791 unsigned &DeviceID, unsigned &FileID, 4792 unsigned &LineNum) { 4793 4794 auto &SM = C.getSourceManager(); 4795 4796 // The loc should be always valid and have a file ID (the user cannot use 4797 // #pragma directives in macros) 4798 4799 assert(Loc.isValid() && "Source location is expected to be always valid."); 4800 assert(Loc.isFileID() && "Source location is expected to refer to a file."); 4801 4802 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 4803 assert(PLoc.isValid() && "Source location is expected to be always valid."); 4804 4805 llvm::sys::fs::UniqueID ID; 4806 if (llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 4807 llvm_unreachable("Source file with target region no longer exists!"); 4808 4809 DeviceID = ID.getDevice(); 4810 FileID = ID.getFile(); 4811 LineNum = PLoc.getLine(); 4812 } 4813 4814 void CGOpenMPRuntime::emitTargetOutlinedFunction( 4815 const OMPExecutableDirective &D, StringRef ParentName, 4816 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 4817 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 4818 assert(!ParentName.empty() && "Invalid target region parent name!"); 4819 4820 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 4821 IsOffloadEntry, CodeGen); 4822 } 4823 4824 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 4825 const OMPExecutableDirective &D, StringRef ParentName, 4826 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 4827 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 4828 // Create a unique name for the entry function using the source location 4829 // information of the current target region. The name will be something like: 4830 // 4831 // __omp_offloading_DD_FFFF_PP_lBB 4832 // 4833 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 4834 // mangled name of the function that encloses the target region and BB is the 4835 // line number of the target region. 4836 4837 unsigned DeviceID; 4838 unsigned FileID; 4839 unsigned Line; 4840 getTargetEntryUniqueInfo(CGM.getContext(), D.getLocStart(), DeviceID, FileID, 4841 Line); 4842 SmallString<64> EntryFnName; 4843 { 4844 llvm::raw_svector_ostream OS(EntryFnName); 4845 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 4846 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 4847 } 4848 4849 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 4850 4851 CodeGenFunction CGF(CGM, true); 4852 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 4853 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 4854 4855 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 4856 4857 // If this target outline function is not an offload entry, we don't need to 4858 // register it. 4859 if (!IsOffloadEntry) 4860 return; 4861 4862 // The target region ID is used by the runtime library to identify the current 4863 // target region, so it only has to be unique and not necessarily point to 4864 // anything. It could be the pointer to the outlined function that implements 4865 // the target region, but we aren't using that so that the compiler doesn't 4866 // need to keep that, and could therefore inline the host function if proven 4867 // worthwhile during optimization. In the other hand, if emitting code for the 4868 // device, the ID has to be the function address so that it can retrieved from 4869 // the offloading entry and launched by the runtime library. We also mark the 4870 // outlined function to have external linkage in case we are emitting code for 4871 // the device, because these functions will be entry points to the device. 4872 4873 if (CGM.getLangOpts().OpenMPIsDevice) { 4874 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 4875 OutlinedFn->setLinkage(llvm::GlobalValue::ExternalLinkage); 4876 } else 4877 OutlinedFnID = new llvm::GlobalVariable( 4878 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 4879 llvm::GlobalValue::PrivateLinkage, 4880 llvm::Constant::getNullValue(CGM.Int8Ty), ".omp_offload.region_id"); 4881 4882 // Register the information for the entry associated with this target region. 4883 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 4884 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 4885 /*Flags=*/0); 4886 } 4887 4888 /// discard all CompoundStmts intervening between two constructs 4889 static const Stmt *ignoreCompoundStmts(const Stmt *Body) { 4890 while (auto *CS = dyn_cast_or_null<CompoundStmt>(Body)) 4891 Body = CS->body_front(); 4892 4893 return Body; 4894 } 4895 4896 /// Emit the number of teams for a target directive. Inspect the num_teams 4897 /// clause associated with a teams construct combined or closely nested 4898 /// with the target directive. 4899 /// 4900 /// Emit a team of size one for directives such as 'target parallel' that 4901 /// have no associated teams construct. 4902 /// 4903 /// Otherwise, return nullptr. 4904 static llvm::Value * 4905 emitNumTeamsForTargetDirective(CGOpenMPRuntime &OMPRuntime, 4906 CodeGenFunction &CGF, 4907 const OMPExecutableDirective &D) { 4908 4909 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the " 4910 "teams directive expected to be " 4911 "emitted only for the host!"); 4912 4913 auto &Bld = CGF.Builder; 4914 4915 // If the target directive is combined with a teams directive: 4916 // Return the value in the num_teams clause, if any. 4917 // Otherwise, return 0 to denote the runtime default. 4918 if (isOpenMPTeamsDirective(D.getDirectiveKind())) { 4919 if (const auto *NumTeamsClause = D.getSingleClause<OMPNumTeamsClause>()) { 4920 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 4921 auto NumTeams = CGF.EmitScalarExpr(NumTeamsClause->getNumTeams(), 4922 /*IgnoreResultAssign*/ true); 4923 return Bld.CreateIntCast(NumTeams, CGF.Int32Ty, 4924 /*IsSigned=*/true); 4925 } 4926 4927 // The default value is 0. 4928 return Bld.getInt32(0); 4929 } 4930 4931 // If the target directive is combined with a parallel directive but not a 4932 // teams directive, start one team. 4933 if (isOpenMPParallelDirective(D.getDirectiveKind())) 4934 return Bld.getInt32(1); 4935 4936 // If the current target region has a teams region enclosed, we need to get 4937 // the number of teams to pass to the runtime function call. This is done 4938 // by generating the expression in a inlined region. This is required because 4939 // the expression is captured in the enclosing target environment when the 4940 // teams directive is not combined with target. 4941 4942 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 4943 4944 // FIXME: Accommodate other combined directives with teams when they become 4945 // available. 4946 if (auto *TeamsDir = dyn_cast_or_null<OMPTeamsDirective>( 4947 ignoreCompoundStmts(CS.getCapturedStmt()))) { 4948 if (auto *NTE = TeamsDir->getSingleClause<OMPNumTeamsClause>()) { 4949 CGOpenMPInnerExprInfo CGInfo(CGF, CS); 4950 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 4951 llvm::Value *NumTeams = CGF.EmitScalarExpr(NTE->getNumTeams()); 4952 return Bld.CreateIntCast(NumTeams, CGF.Int32Ty, 4953 /*IsSigned=*/true); 4954 } 4955 4956 // If we have an enclosed teams directive but no num_teams clause we use 4957 // the default value 0. 4958 return Bld.getInt32(0); 4959 } 4960 4961 // No teams associated with the directive. 4962 return nullptr; 4963 } 4964 4965 /// Emit the number of threads for a target directive. Inspect the 4966 /// thread_limit clause associated with a teams construct combined or closely 4967 /// nested with the target directive. 4968 /// 4969 /// Emit the num_threads clause for directives such as 'target parallel' that 4970 /// have no associated teams construct. 4971 /// 4972 /// Otherwise, return nullptr. 4973 static llvm::Value * 4974 emitNumThreadsForTargetDirective(CGOpenMPRuntime &OMPRuntime, 4975 CodeGenFunction &CGF, 4976 const OMPExecutableDirective &D) { 4977 4978 assert(!CGF.getLangOpts().OpenMPIsDevice && "Clauses associated with the " 4979 "teams directive expected to be " 4980 "emitted only for the host!"); 4981 4982 auto &Bld = CGF.Builder; 4983 4984 // 4985 // If the target directive is combined with a teams directive: 4986 // Return the value in the thread_limit clause, if any. 4987 // 4988 // If the target directive is combined with a parallel directive: 4989 // Return the value in the num_threads clause, if any. 4990 // 4991 // If both clauses are set, select the minimum of the two. 4992 // 4993 // If neither teams or parallel combined directives set the number of threads 4994 // in a team, return 0 to denote the runtime default. 4995 // 4996 // If this is not a teams directive return nullptr. 4997 4998 if (isOpenMPTeamsDirective(D.getDirectiveKind()) || 4999 isOpenMPParallelDirective(D.getDirectiveKind())) { 5000 llvm::Value *DefaultThreadLimitVal = Bld.getInt32(0); 5001 llvm::Value *NumThreadsVal = nullptr; 5002 llvm::Value *ThreadLimitVal = nullptr; 5003 5004 if (const auto *ThreadLimitClause = 5005 D.getSingleClause<OMPThreadLimitClause>()) { 5006 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 5007 auto ThreadLimit = CGF.EmitScalarExpr(ThreadLimitClause->getThreadLimit(), 5008 /*IgnoreResultAssign*/ true); 5009 ThreadLimitVal = Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, 5010 /*IsSigned=*/true); 5011 } 5012 5013 if (const auto *NumThreadsClause = 5014 D.getSingleClause<OMPNumThreadsClause>()) { 5015 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 5016 llvm::Value *NumThreads = 5017 CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(), 5018 /*IgnoreResultAssign*/ true); 5019 NumThreadsVal = 5020 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*IsSigned=*/true); 5021 } 5022 5023 // Select the lesser of thread_limit and num_threads. 5024 if (NumThreadsVal) 5025 ThreadLimitVal = ThreadLimitVal 5026 ? Bld.CreateSelect(Bld.CreateICmpSLT(NumThreadsVal, 5027 ThreadLimitVal), 5028 NumThreadsVal, ThreadLimitVal) 5029 : NumThreadsVal; 5030 5031 // Set default value passed to the runtime if either teams or a target 5032 // parallel type directive is found but no clause is specified. 5033 if (!ThreadLimitVal) 5034 ThreadLimitVal = DefaultThreadLimitVal; 5035 5036 return ThreadLimitVal; 5037 } 5038 5039 // If the current target region has a teams region enclosed, we need to get 5040 // the thread limit to pass to the runtime function call. This is done 5041 // by generating the expression in a inlined region. This is required because 5042 // the expression is captured in the enclosing target environment when the 5043 // teams directive is not combined with target. 5044 5045 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 5046 5047 // FIXME: Accommodate other combined directives with teams when they become 5048 // available. 5049 if (auto *TeamsDir = dyn_cast_or_null<OMPTeamsDirective>( 5050 ignoreCompoundStmts(CS.getCapturedStmt()))) { 5051 if (auto *TLE = TeamsDir->getSingleClause<OMPThreadLimitClause>()) { 5052 CGOpenMPInnerExprInfo CGInfo(CGF, CS); 5053 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 5054 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(TLE->getThreadLimit()); 5055 return CGF.Builder.CreateIntCast(ThreadLimit, CGF.Int32Ty, 5056 /*IsSigned=*/true); 5057 } 5058 5059 // If we have an enclosed teams directive but no thread_limit clause we use 5060 // the default value 0. 5061 return CGF.Builder.getInt32(0); 5062 } 5063 5064 // No teams associated with the directive. 5065 return nullptr; 5066 } 5067 5068 namespace { 5069 // \brief Utility to handle information from clauses associated with a given 5070 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 5071 // It provides a convenient interface to obtain the information and generate 5072 // code for that information. 5073 class MappableExprsHandler { 5074 public: 5075 /// \brief Values for bit flags used to specify the mapping type for 5076 /// offloading. 5077 enum OpenMPOffloadMappingFlags { 5078 /// \brief Allocate memory on the device and move data from host to device. 5079 OMP_MAP_TO = 0x01, 5080 /// \brief Allocate memory on the device and move data from device to host. 5081 OMP_MAP_FROM = 0x02, 5082 /// \brief Always perform the requested mapping action on the element, even 5083 /// if it was already mapped before. 5084 OMP_MAP_ALWAYS = 0x04, 5085 /// \brief Delete the element from the device environment, ignoring the 5086 /// current reference count associated with the element. 5087 OMP_MAP_DELETE = 0x08, 5088 /// \brief The element being mapped is a pointer, therefore the pointee 5089 /// should be mapped as well. 5090 OMP_MAP_IS_PTR = 0x10, 5091 /// \brief This flags signals that an argument is the first one relating to 5092 /// a map/private clause expression. For some cases a single 5093 /// map/privatization results in multiple arguments passed to the runtime 5094 /// library. 5095 OMP_MAP_FIRST_REF = 0x20, 5096 /// \brief Signal that the runtime library has to return the device pointer 5097 /// in the current position for the data being mapped. 5098 OMP_MAP_RETURN_PTR = 0x40, 5099 /// \brief This flag signals that the reference being passed is a pointer to 5100 /// private data. 5101 OMP_MAP_PRIVATE_PTR = 0x80, 5102 /// \brief Pass the element to the device by value. 5103 OMP_MAP_PRIVATE_VAL = 0x100, 5104 }; 5105 5106 /// Class that associates information with a base pointer to be passed to the 5107 /// runtime library. 5108 class BasePointerInfo { 5109 /// The base pointer. 5110 llvm::Value *Ptr = nullptr; 5111 /// The base declaration that refers to this device pointer, or null if 5112 /// there is none. 5113 const ValueDecl *DevPtrDecl = nullptr; 5114 5115 public: 5116 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 5117 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 5118 llvm::Value *operator*() const { return Ptr; } 5119 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 5120 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 5121 }; 5122 5123 typedef SmallVector<BasePointerInfo, 16> MapBaseValuesArrayTy; 5124 typedef SmallVector<llvm::Value *, 16> MapValuesArrayTy; 5125 typedef SmallVector<unsigned, 16> MapFlagsArrayTy; 5126 5127 private: 5128 /// \brief Directive from where the map clauses were extracted. 5129 const OMPExecutableDirective &CurDir; 5130 5131 /// \brief Function the directive is being generated for. 5132 CodeGenFunction &CGF; 5133 5134 /// \brief Set of all first private variables in the current directive. 5135 llvm::SmallPtrSet<const VarDecl *, 8> FirstPrivateDecls; 5136 5137 /// Map between device pointer declarations and their expression components. 5138 /// The key value for declarations in 'this' is null. 5139 llvm::DenseMap< 5140 const ValueDecl *, 5141 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 5142 DevPointersMap; 5143 5144 llvm::Value *getExprTypeSize(const Expr *E) const { 5145 auto ExprTy = E->getType().getCanonicalType(); 5146 5147 // Reference types are ignored for mapping purposes. 5148 if (auto *RefTy = ExprTy->getAs<ReferenceType>()) 5149 ExprTy = RefTy->getPointeeType().getCanonicalType(); 5150 5151 // Given that an array section is considered a built-in type, we need to 5152 // do the calculation based on the length of the section instead of relying 5153 // on CGF.getTypeSize(E->getType()). 5154 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 5155 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 5156 OAE->getBase()->IgnoreParenImpCasts()) 5157 .getCanonicalType(); 5158 5159 // If there is no length associated with the expression, that means we 5160 // are using the whole length of the base. 5161 if (!OAE->getLength() && OAE->getColonLoc().isValid()) 5162 return CGF.getTypeSize(BaseTy); 5163 5164 llvm::Value *ElemSize; 5165 if (auto *PTy = BaseTy->getAs<PointerType>()) 5166 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 5167 else { 5168 auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 5169 assert(ATy && "Expecting array type if not a pointer type."); 5170 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 5171 } 5172 5173 // If we don't have a length at this point, that is because we have an 5174 // array section with a single element. 5175 if (!OAE->getLength()) 5176 return ElemSize; 5177 5178 auto *LengthVal = CGF.EmitScalarExpr(OAE->getLength()); 5179 LengthVal = 5180 CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false); 5181 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 5182 } 5183 return CGF.getTypeSize(ExprTy); 5184 } 5185 5186 /// \brief Return the corresponding bits for a given map clause modifier. Add 5187 /// a flag marking the map as a pointer if requested. Add a flag marking the 5188 /// map as the first one of a series of maps that relate to the same map 5189 /// expression. 5190 unsigned getMapTypeBits(OpenMPMapClauseKind MapType, 5191 OpenMPMapClauseKind MapTypeModifier, bool AddPtrFlag, 5192 bool AddIsFirstFlag) const { 5193 unsigned Bits = 0u; 5194 switch (MapType) { 5195 case OMPC_MAP_alloc: 5196 case OMPC_MAP_release: 5197 // alloc and release is the default behavior in the runtime library, i.e. 5198 // if we don't pass any bits alloc/release that is what the runtime is 5199 // going to do. Therefore, we don't need to signal anything for these two 5200 // type modifiers. 5201 break; 5202 case OMPC_MAP_to: 5203 Bits = OMP_MAP_TO; 5204 break; 5205 case OMPC_MAP_from: 5206 Bits = OMP_MAP_FROM; 5207 break; 5208 case OMPC_MAP_tofrom: 5209 Bits = OMP_MAP_TO | OMP_MAP_FROM; 5210 break; 5211 case OMPC_MAP_delete: 5212 Bits = OMP_MAP_DELETE; 5213 break; 5214 default: 5215 llvm_unreachable("Unexpected map type!"); 5216 break; 5217 } 5218 if (AddPtrFlag) 5219 Bits |= OMP_MAP_IS_PTR; 5220 if (AddIsFirstFlag) 5221 Bits |= OMP_MAP_FIRST_REF; 5222 if (MapTypeModifier == OMPC_MAP_always) 5223 Bits |= OMP_MAP_ALWAYS; 5224 return Bits; 5225 } 5226 5227 /// \brief Return true if the provided expression is a final array section. A 5228 /// final array section, is one whose length can't be proved to be one. 5229 bool isFinalArraySectionExpression(const Expr *E) const { 5230 auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 5231 5232 // It is not an array section and therefore not a unity-size one. 5233 if (!OASE) 5234 return false; 5235 5236 // An array section with no colon always refer to a single element. 5237 if (OASE->getColonLoc().isInvalid()) 5238 return false; 5239 5240 auto *Length = OASE->getLength(); 5241 5242 // If we don't have a length we have to check if the array has size 1 5243 // for this dimension. Also, we should always expect a length if the 5244 // base type is pointer. 5245 if (!Length) { 5246 auto BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 5247 OASE->getBase()->IgnoreParenImpCasts()) 5248 .getCanonicalType(); 5249 if (auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 5250 return ATy->getSize().getSExtValue() != 1; 5251 // If we don't have a constant dimension length, we have to consider 5252 // the current section as having any size, so it is not necessarily 5253 // unitary. If it happen to be unity size, that's user fault. 5254 return true; 5255 } 5256 5257 // Check if the length evaluates to 1. 5258 llvm::APSInt ConstLength; 5259 if (!Length->EvaluateAsInt(ConstLength, CGF.getContext())) 5260 return true; // Can have more that size 1. 5261 5262 return ConstLength.getSExtValue() != 1; 5263 } 5264 5265 /// \brief Generate the base pointers, section pointers, sizes and map type 5266 /// bits for the provided map type, map modifier, and expression components. 5267 /// \a IsFirstComponent should be set to true if the provided set of 5268 /// components is the first associated with a capture. 5269 void generateInfoForComponentList( 5270 OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier, 5271 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 5272 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 5273 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 5274 bool IsFirstComponentList) const { 5275 5276 // The following summarizes what has to be generated for each map and the 5277 // types bellow. The generated information is expressed in this order: 5278 // base pointer, section pointer, size, flags 5279 // (to add to the ones that come from the map type and modifier). 5280 // 5281 // double d; 5282 // int i[100]; 5283 // float *p; 5284 // 5285 // struct S1 { 5286 // int i; 5287 // float f[50]; 5288 // } 5289 // struct S2 { 5290 // int i; 5291 // float f[50]; 5292 // S1 s; 5293 // double *p; 5294 // struct S2 *ps; 5295 // } 5296 // S2 s; 5297 // S2 *ps; 5298 // 5299 // map(d) 5300 // &d, &d, sizeof(double), noflags 5301 // 5302 // map(i) 5303 // &i, &i, 100*sizeof(int), noflags 5304 // 5305 // map(i[1:23]) 5306 // &i(=&i[0]), &i[1], 23*sizeof(int), noflags 5307 // 5308 // map(p) 5309 // &p, &p, sizeof(float*), noflags 5310 // 5311 // map(p[1:24]) 5312 // p, &p[1], 24*sizeof(float), noflags 5313 // 5314 // map(s) 5315 // &s, &s, sizeof(S2), noflags 5316 // 5317 // map(s.i) 5318 // &s, &(s.i), sizeof(int), noflags 5319 // 5320 // map(s.s.f) 5321 // &s, &(s.i.f), 50*sizeof(int), noflags 5322 // 5323 // map(s.p) 5324 // &s, &(s.p), sizeof(double*), noflags 5325 // 5326 // map(s.p[:22], s.a s.b) 5327 // &s, &(s.p), sizeof(double*), noflags 5328 // &(s.p), &(s.p[0]), 22*sizeof(double), ptr_flag + extra_flag 5329 // 5330 // map(s.ps) 5331 // &s, &(s.ps), sizeof(S2*), noflags 5332 // 5333 // map(s.ps->s.i) 5334 // &s, &(s.ps), sizeof(S2*), noflags 5335 // &(s.ps), &(s.ps->s.i), sizeof(int), ptr_flag + extra_flag 5336 // 5337 // map(s.ps->ps) 5338 // &s, &(s.ps), sizeof(S2*), noflags 5339 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag 5340 // 5341 // map(s.ps->ps->ps) 5342 // &s, &(s.ps), sizeof(S2*), noflags 5343 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag 5344 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag 5345 // 5346 // map(s.ps->ps->s.f[:22]) 5347 // &s, &(s.ps), sizeof(S2*), noflags 5348 // &(s.ps), &(s.ps->ps), sizeof(S2*), ptr_flag + extra_flag 5349 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), ptr_flag + extra_flag 5350 // 5351 // map(ps) 5352 // &ps, &ps, sizeof(S2*), noflags 5353 // 5354 // map(ps->i) 5355 // ps, &(ps->i), sizeof(int), noflags 5356 // 5357 // map(ps->s.f) 5358 // ps, &(ps->s.f[0]), 50*sizeof(float), noflags 5359 // 5360 // map(ps->p) 5361 // ps, &(ps->p), sizeof(double*), noflags 5362 // 5363 // map(ps->p[:22]) 5364 // ps, &(ps->p), sizeof(double*), noflags 5365 // &(ps->p), &(ps->p[0]), 22*sizeof(double), ptr_flag + extra_flag 5366 // 5367 // map(ps->ps) 5368 // ps, &(ps->ps), sizeof(S2*), noflags 5369 // 5370 // map(ps->ps->s.i) 5371 // ps, &(ps->ps), sizeof(S2*), noflags 5372 // &(ps->ps), &(ps->ps->s.i), sizeof(int), ptr_flag + extra_flag 5373 // 5374 // map(ps->ps->ps) 5375 // ps, &(ps->ps), sizeof(S2*), noflags 5376 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag 5377 // 5378 // map(ps->ps->ps->ps) 5379 // ps, &(ps->ps), sizeof(S2*), noflags 5380 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag 5381 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag 5382 // 5383 // map(ps->ps->ps->s.f[:22]) 5384 // ps, &(ps->ps), sizeof(S2*), noflags 5385 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), ptr_flag + extra_flag 5386 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), ptr_flag + 5387 // extra_flag 5388 5389 // Track if the map information being generated is the first for a capture. 5390 bool IsCaptureFirstInfo = IsFirstComponentList; 5391 5392 // Scan the components from the base to the complete expression. 5393 auto CI = Components.rbegin(); 5394 auto CE = Components.rend(); 5395 auto I = CI; 5396 5397 // Track if the map information being generated is the first for a list of 5398 // components. 5399 bool IsExpressionFirstInfo = true; 5400 llvm::Value *BP = nullptr; 5401 5402 if (auto *ME = dyn_cast<MemberExpr>(I->getAssociatedExpression())) { 5403 // The base is the 'this' pointer. The content of the pointer is going 5404 // to be the base of the field being mapped. 5405 BP = CGF.EmitScalarExpr(ME->getBase()); 5406 } else { 5407 // The base is the reference to the variable. 5408 // BP = &Var. 5409 BP = CGF.EmitLValue(cast<DeclRefExpr>(I->getAssociatedExpression())) 5410 .getPointer(); 5411 5412 // If the variable is a pointer and is being dereferenced (i.e. is not 5413 // the last component), the base has to be the pointer itself, not its 5414 // reference. References are ignored for mapping purposes. 5415 QualType Ty = 5416 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 5417 if (Ty->isAnyPointerType() && std::next(I) != CE) { 5418 auto PtrAddr = CGF.MakeNaturalAlignAddrLValue(BP, Ty); 5419 BP = CGF.EmitLoadOfPointerLValue(PtrAddr.getAddress(), 5420 Ty->castAs<PointerType>()) 5421 .getPointer(); 5422 5423 // We do not need to generate individual map information for the 5424 // pointer, it can be associated with the combined storage. 5425 ++I; 5426 } 5427 } 5428 5429 for (; I != CE; ++I) { 5430 auto Next = std::next(I); 5431 5432 // We need to generate the addresses and sizes if this is the last 5433 // component, if the component is a pointer or if it is an array section 5434 // whose length can't be proved to be one. If this is a pointer, it 5435 // becomes the base address for the following components. 5436 5437 // A final array section, is one whose length can't be proved to be one. 5438 bool IsFinalArraySection = 5439 isFinalArraySectionExpression(I->getAssociatedExpression()); 5440 5441 // Get information on whether the element is a pointer. Have to do a 5442 // special treatment for array sections given that they are built-in 5443 // types. 5444 const auto *OASE = 5445 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 5446 bool IsPointer = 5447 (OASE && 5448 OMPArraySectionExpr::getBaseOriginalType(OASE) 5449 .getCanonicalType() 5450 ->isAnyPointerType()) || 5451 I->getAssociatedExpression()->getType()->isAnyPointerType(); 5452 5453 if (Next == CE || IsPointer || IsFinalArraySection) { 5454 5455 // If this is not the last component, we expect the pointer to be 5456 // associated with an array expression or member expression. 5457 assert((Next == CE || 5458 isa<MemberExpr>(Next->getAssociatedExpression()) || 5459 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 5460 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 5461 "Unexpected expression"); 5462 5463 auto *LB = CGF.EmitLValue(I->getAssociatedExpression()).getPointer(); 5464 auto *Size = getExprTypeSize(I->getAssociatedExpression()); 5465 5466 // If we have a member expression and the current component is a 5467 // reference, we have to map the reference too. Whenever we have a 5468 // reference, the section that reference refers to is going to be a 5469 // load instruction from the storage assigned to the reference. 5470 if (isa<MemberExpr>(I->getAssociatedExpression()) && 5471 I->getAssociatedDeclaration()->getType()->isReferenceType()) { 5472 auto *LI = cast<llvm::LoadInst>(LB); 5473 auto *RefAddr = LI->getPointerOperand(); 5474 5475 BasePointers.push_back(BP); 5476 Pointers.push_back(RefAddr); 5477 Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy)); 5478 Types.push_back(getMapTypeBits( 5479 /*MapType*/ OMPC_MAP_alloc, /*MapTypeModifier=*/OMPC_MAP_unknown, 5480 !IsExpressionFirstInfo, IsCaptureFirstInfo)); 5481 IsExpressionFirstInfo = false; 5482 IsCaptureFirstInfo = false; 5483 // The reference will be the next base address. 5484 BP = RefAddr; 5485 } 5486 5487 BasePointers.push_back(BP); 5488 Pointers.push_back(LB); 5489 Sizes.push_back(Size); 5490 5491 // We need to add a pointer flag for each map that comes from the 5492 // same expression except for the first one. We also need to signal 5493 // this map is the first one that relates with the current capture 5494 // (there is a set of entries for each capture). 5495 Types.push_back(getMapTypeBits(MapType, MapTypeModifier, 5496 !IsExpressionFirstInfo, 5497 IsCaptureFirstInfo)); 5498 5499 // If we have a final array section, we are done with this expression. 5500 if (IsFinalArraySection) 5501 break; 5502 5503 // The pointer becomes the base for the next element. 5504 if (Next != CE) 5505 BP = LB; 5506 5507 IsExpressionFirstInfo = false; 5508 IsCaptureFirstInfo = false; 5509 continue; 5510 } 5511 } 5512 } 5513 5514 /// \brief Return the adjusted map modifiers if the declaration a capture 5515 /// refers to appears in a first-private clause. This is expected to be used 5516 /// only with directives that start with 'target'. 5517 unsigned adjustMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap, 5518 unsigned CurrentModifiers) { 5519 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 5520 5521 // A first private variable captured by reference will use only the 5522 // 'private ptr' and 'map to' flag. Return the right flags if the captured 5523 // declaration is known as first-private in this handler. 5524 if (FirstPrivateDecls.count(Cap.getCapturedVar())) 5525 return MappableExprsHandler::OMP_MAP_PRIVATE_PTR | 5526 MappableExprsHandler::OMP_MAP_TO; 5527 5528 // We didn't modify anything. 5529 return CurrentModifiers; 5530 } 5531 5532 public: 5533 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 5534 : CurDir(Dir), CGF(CGF) { 5535 // Extract firstprivate clause information. 5536 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 5537 for (const auto *D : C->varlists()) 5538 FirstPrivateDecls.insert( 5539 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl()); 5540 // Extract device pointer clause information. 5541 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 5542 for (auto L : C->component_lists()) 5543 DevPointersMap[L.first].push_back(L.second); 5544 } 5545 5546 /// \brief Generate all the base pointers, section pointers, sizes and map 5547 /// types for the extracted mappable expressions. Also, for each item that 5548 /// relates with a device pointer, a pair of the relevant declaration and 5549 /// index where it occurs is appended to the device pointers info array. 5550 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 5551 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 5552 MapFlagsArrayTy &Types) const { 5553 BasePointers.clear(); 5554 Pointers.clear(); 5555 Sizes.clear(); 5556 Types.clear(); 5557 5558 struct MapInfo { 5559 /// Kind that defines how a device pointer has to be returned. 5560 enum ReturnPointerKind { 5561 // Don't have to return any pointer. 5562 RPK_None, 5563 // Pointer is the base of the declaration. 5564 RPK_Base, 5565 // Pointer is a member of the base declaration - 'this' 5566 RPK_Member, 5567 // Pointer is a reference and a member of the base declaration - 'this' 5568 RPK_MemberReference, 5569 }; 5570 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 5571 OpenMPMapClauseKind MapType; 5572 OpenMPMapClauseKind MapTypeModifier; 5573 ReturnPointerKind ReturnDevicePointer; 5574 5575 MapInfo() 5576 : MapType(OMPC_MAP_unknown), MapTypeModifier(OMPC_MAP_unknown), 5577 ReturnDevicePointer(RPK_None) {} 5578 MapInfo( 5579 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 5580 OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier, 5581 ReturnPointerKind ReturnDevicePointer) 5582 : Components(Components), MapType(MapType), 5583 MapTypeModifier(MapTypeModifier), 5584 ReturnDevicePointer(ReturnDevicePointer) {} 5585 }; 5586 5587 // We have to process the component lists that relate with the same 5588 // declaration in a single chunk so that we can generate the map flags 5589 // correctly. Therefore, we organize all lists in a map. 5590 llvm::DenseMap<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 5591 5592 // Helper function to fill the information map for the different supported 5593 // clauses. 5594 auto &&InfoGen = [&Info]( 5595 const ValueDecl *D, 5596 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 5597 OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapModifier, 5598 MapInfo::ReturnPointerKind ReturnDevicePointer) { 5599 const ValueDecl *VD = 5600 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 5601 Info[VD].push_back({L, MapType, MapModifier, ReturnDevicePointer}); 5602 }; 5603 5604 // FIXME: MSVC 2013 seems to require this-> to find member CurDir. 5605 for (auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) 5606 for (auto L : C->component_lists()) 5607 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifier(), 5608 MapInfo::RPK_None); 5609 for (auto *C : this->CurDir.getClausesOfKind<OMPToClause>()) 5610 for (auto L : C->component_lists()) 5611 InfoGen(L.first, L.second, OMPC_MAP_to, OMPC_MAP_unknown, 5612 MapInfo::RPK_None); 5613 for (auto *C : this->CurDir.getClausesOfKind<OMPFromClause>()) 5614 for (auto L : C->component_lists()) 5615 InfoGen(L.first, L.second, OMPC_MAP_from, OMPC_MAP_unknown, 5616 MapInfo::RPK_None); 5617 5618 // Look at the use_device_ptr clause information and mark the existing map 5619 // entries as such. If there is no map information for an entry in the 5620 // use_device_ptr list, we create one with map type 'alloc' and zero size 5621 // section. It is the user fault if that was not mapped before. 5622 // FIXME: MSVC 2013 seems to require this-> to find member CurDir. 5623 for (auto *C : this->CurDir.getClausesOfKind<OMPUseDevicePtrClause>()) 5624 for (auto L : C->component_lists()) { 5625 assert(!L.second.empty() && "Not expecting empty list of components!"); 5626 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 5627 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 5628 auto *IE = L.second.back().getAssociatedExpression(); 5629 // If the first component is a member expression, we have to look into 5630 // 'this', which maps to null in the map of map information. Otherwise 5631 // look directly for the information. 5632 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 5633 5634 // We potentially have map information for this declaration already. 5635 // Look for the first set of components that refer to it. 5636 if (It != Info.end()) { 5637 auto CI = std::find_if( 5638 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 5639 return MI.Components.back().getAssociatedDeclaration() == VD; 5640 }); 5641 // If we found a map entry, signal that the pointer has to be returned 5642 // and move on to the next declaration. 5643 if (CI != It->second.end()) { 5644 CI->ReturnDevicePointer = isa<MemberExpr>(IE) 5645 ? (VD->getType()->isReferenceType() 5646 ? MapInfo::RPK_MemberReference 5647 : MapInfo::RPK_Member) 5648 : MapInfo::RPK_Base; 5649 continue; 5650 } 5651 } 5652 5653 // We didn't find any match in our map information - generate a zero 5654 // size array section. 5655 // FIXME: MSVC 2013 seems to require this-> to find member CGF. 5656 llvm::Value *Ptr = 5657 this->CGF 5658 .EmitLoadOfLValue(this->CGF.EmitLValue(IE), SourceLocation()) 5659 .getScalarVal(); 5660 BasePointers.push_back({Ptr, VD}); 5661 Pointers.push_back(Ptr); 5662 Sizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy)); 5663 Types.push_back(OMP_MAP_RETURN_PTR | OMP_MAP_FIRST_REF); 5664 } 5665 5666 for (auto &M : Info) { 5667 // We need to know when we generate information for the first component 5668 // associated with a capture, because the mapping flags depend on it. 5669 bool IsFirstComponentList = true; 5670 for (MapInfo &L : M.second) { 5671 assert(!L.Components.empty() && 5672 "Not expecting declaration with no component lists."); 5673 5674 // Remember the current base pointer index. 5675 unsigned CurrentBasePointersIdx = BasePointers.size(); 5676 // FIXME: MSVC 2013 seems to require this-> to find the member method. 5677 this->generateInfoForComponentList(L.MapType, L.MapTypeModifier, 5678 L.Components, BasePointers, Pointers, 5679 Sizes, Types, IsFirstComponentList); 5680 5681 // If this entry relates with a device pointer, set the relevant 5682 // declaration and add the 'return pointer' flag. 5683 if (IsFirstComponentList && 5684 L.ReturnDevicePointer != MapInfo::RPK_None) { 5685 // If the pointer is not the base of the map, we need to skip the 5686 // base. If it is a reference in a member field, we also need to skip 5687 // the map of the reference. 5688 if (L.ReturnDevicePointer != MapInfo::RPK_Base) { 5689 ++CurrentBasePointersIdx; 5690 if (L.ReturnDevicePointer == MapInfo::RPK_MemberReference) 5691 ++CurrentBasePointersIdx; 5692 } 5693 assert(BasePointers.size() > CurrentBasePointersIdx && 5694 "Unexpected number of mapped base pointers."); 5695 5696 auto *RelevantVD = L.Components.back().getAssociatedDeclaration(); 5697 assert(RelevantVD && 5698 "No relevant declaration related with device pointer??"); 5699 5700 BasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 5701 Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PTR; 5702 } 5703 IsFirstComponentList = false; 5704 } 5705 } 5706 } 5707 5708 /// \brief Generate the base pointers, section pointers, sizes and map types 5709 /// associated to a given capture. 5710 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 5711 llvm::Value *Arg, 5712 MapBaseValuesArrayTy &BasePointers, 5713 MapValuesArrayTy &Pointers, 5714 MapValuesArrayTy &Sizes, 5715 MapFlagsArrayTy &Types) const { 5716 assert(!Cap->capturesVariableArrayType() && 5717 "Not expecting to generate map info for a variable array type!"); 5718 5719 BasePointers.clear(); 5720 Pointers.clear(); 5721 Sizes.clear(); 5722 Types.clear(); 5723 5724 // We need to know when we generating information for the first component 5725 // associated with a capture, because the mapping flags depend on it. 5726 bool IsFirstComponentList = true; 5727 5728 const ValueDecl *VD = 5729 Cap->capturesThis() 5730 ? nullptr 5731 : cast<ValueDecl>(Cap->getCapturedVar()->getCanonicalDecl()); 5732 5733 // If this declaration appears in a is_device_ptr clause we just have to 5734 // pass the pointer by value. If it is a reference to a declaration, we just 5735 // pass its value, otherwise, if it is a member expression, we need to map 5736 // 'to' the field. 5737 if (!VD) { 5738 auto It = DevPointersMap.find(VD); 5739 if (It != DevPointersMap.end()) { 5740 for (auto L : It->second) { 5741 generateInfoForComponentList( 5742 /*MapType=*/OMPC_MAP_to, /*MapTypeModifier=*/OMPC_MAP_unknown, L, 5743 BasePointers, Pointers, Sizes, Types, IsFirstComponentList); 5744 IsFirstComponentList = false; 5745 } 5746 return; 5747 } 5748 } else if (DevPointersMap.count(VD)) { 5749 BasePointers.push_back({Arg, VD}); 5750 Pointers.push_back(Arg); 5751 Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy)); 5752 Types.push_back(OMP_MAP_PRIVATE_VAL | OMP_MAP_FIRST_REF); 5753 return; 5754 } 5755 5756 // FIXME: MSVC 2013 seems to require this-> to find member CurDir. 5757 for (auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) 5758 for (auto L : C->decl_component_lists(VD)) { 5759 assert(L.first == VD && 5760 "We got information for the wrong declaration??"); 5761 assert(!L.second.empty() && 5762 "Not expecting declaration with no component lists."); 5763 generateInfoForComponentList(C->getMapType(), C->getMapTypeModifier(), 5764 L.second, BasePointers, Pointers, Sizes, 5765 Types, IsFirstComponentList); 5766 IsFirstComponentList = false; 5767 } 5768 5769 return; 5770 } 5771 5772 /// \brief Generate the default map information for a given capture \a CI, 5773 /// record field declaration \a RI and captured value \a CV. 5774 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 5775 const FieldDecl &RI, llvm::Value *CV, 5776 MapBaseValuesArrayTy &CurBasePointers, 5777 MapValuesArrayTy &CurPointers, 5778 MapValuesArrayTy &CurSizes, 5779 MapFlagsArrayTy &CurMapTypes) { 5780 5781 // Do the default mapping. 5782 if (CI.capturesThis()) { 5783 CurBasePointers.push_back(CV); 5784 CurPointers.push_back(CV); 5785 const PointerType *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 5786 CurSizes.push_back(CGF.getTypeSize(PtrTy->getPointeeType())); 5787 // Default map type. 5788 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 5789 } else if (CI.capturesVariableByCopy()) { 5790 CurBasePointers.push_back(CV); 5791 CurPointers.push_back(CV); 5792 if (!RI.getType()->isAnyPointerType()) { 5793 // We have to signal to the runtime captures passed by value that are 5794 // not pointers. 5795 CurMapTypes.push_back(OMP_MAP_PRIVATE_VAL); 5796 CurSizes.push_back(CGF.getTypeSize(RI.getType())); 5797 } else { 5798 // Pointers are implicitly mapped with a zero size and no flags 5799 // (other than first map that is added for all implicit maps). 5800 CurMapTypes.push_back(0u); 5801 CurSizes.push_back(llvm::Constant::getNullValue(CGF.SizeTy)); 5802 } 5803 } else { 5804 assert(CI.capturesVariable() && "Expected captured reference."); 5805 CurBasePointers.push_back(CV); 5806 CurPointers.push_back(CV); 5807 5808 const ReferenceType *PtrTy = 5809 cast<ReferenceType>(RI.getType().getTypePtr()); 5810 QualType ElementType = PtrTy->getPointeeType(); 5811 CurSizes.push_back(CGF.getTypeSize(ElementType)); 5812 // The default map type for a scalar/complex type is 'to' because by 5813 // default the value doesn't have to be retrieved. For an aggregate 5814 // type, the default is 'tofrom'. 5815 CurMapTypes.push_back(ElementType->isAggregateType() 5816 ? (OMP_MAP_TO | OMP_MAP_FROM) 5817 : OMP_MAP_TO); 5818 5819 // If we have a capture by reference we may need to add the private 5820 // pointer flag if the base declaration shows in some first-private 5821 // clause. 5822 CurMapTypes.back() = 5823 adjustMapModifiersForPrivateClauses(CI, CurMapTypes.back()); 5824 } 5825 // Every default map produces a single argument, so, it is always the 5826 // first one. 5827 CurMapTypes.back() |= OMP_MAP_FIRST_REF; 5828 } 5829 }; 5830 5831 enum OpenMPOffloadingReservedDeviceIDs { 5832 /// \brief Device ID if the device was not defined, runtime should get it 5833 /// from environment variables in the spec. 5834 OMP_DEVICEID_UNDEF = -1, 5835 }; 5836 } // anonymous namespace 5837 5838 /// \brief Emit the arrays used to pass the captures and map information to the 5839 /// offloading runtime library. If there is no map or capture information, 5840 /// return nullptr by reference. 5841 static void 5842 emitOffloadingArrays(CodeGenFunction &CGF, 5843 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 5844 MappableExprsHandler::MapValuesArrayTy &Pointers, 5845 MappableExprsHandler::MapValuesArrayTy &Sizes, 5846 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 5847 CGOpenMPRuntime::TargetDataInfo &Info) { 5848 auto &CGM = CGF.CGM; 5849 auto &Ctx = CGF.getContext(); 5850 5851 // Reset the array information. 5852 Info.clearArrayInfo(); 5853 Info.NumberOfPtrs = BasePointers.size(); 5854 5855 if (Info.NumberOfPtrs) { 5856 // Detect if we have any capture size requiring runtime evaluation of the 5857 // size so that a constant array could be eventually used. 5858 bool hasRuntimeEvaluationCaptureSize = false; 5859 for (auto *S : Sizes) 5860 if (!isa<llvm::Constant>(S)) { 5861 hasRuntimeEvaluationCaptureSize = true; 5862 break; 5863 } 5864 5865 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 5866 QualType PointerArrayType = 5867 Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal, 5868 /*IndexTypeQuals=*/0); 5869 5870 Info.BasePointersArray = 5871 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 5872 Info.PointersArray = 5873 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 5874 5875 // If we don't have any VLA types or other types that require runtime 5876 // evaluation, we can use a constant array for the map sizes, otherwise we 5877 // need to fill up the arrays as we do for the pointers. 5878 if (hasRuntimeEvaluationCaptureSize) { 5879 QualType SizeArrayType = Ctx.getConstantArrayType( 5880 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal, 5881 /*IndexTypeQuals=*/0); 5882 Info.SizesArray = 5883 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 5884 } else { 5885 // We expect all the sizes to be constant, so we collect them to create 5886 // a constant array. 5887 SmallVector<llvm::Constant *, 16> ConstSizes; 5888 for (auto S : Sizes) 5889 ConstSizes.push_back(cast<llvm::Constant>(S)); 5890 5891 auto *SizesArrayInit = llvm::ConstantArray::get( 5892 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes); 5893 auto *SizesArrayGbl = new llvm::GlobalVariable( 5894 CGM.getModule(), SizesArrayInit->getType(), 5895 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 5896 SizesArrayInit, ".offload_sizes"); 5897 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 5898 Info.SizesArray = SizesArrayGbl; 5899 } 5900 5901 // The map types are always constant so we don't need to generate code to 5902 // fill arrays. Instead, we create an array constant. 5903 llvm::Constant *MapTypesArrayInit = 5904 llvm::ConstantDataArray::get(CGF.Builder.getContext(), MapTypes); 5905 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 5906 CGM.getModule(), MapTypesArrayInit->getType(), 5907 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 5908 MapTypesArrayInit, ".offload_maptypes"); 5909 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 5910 Info.MapTypesArray = MapTypesArrayGbl; 5911 5912 for (unsigned i = 0; i < Info.NumberOfPtrs; ++i) { 5913 llvm::Value *BPVal = *BasePointers[i]; 5914 if (BPVal->getType()->isPointerTy()) 5915 BPVal = CGF.Builder.CreateBitCast(BPVal, CGM.VoidPtrTy); 5916 else { 5917 assert(BPVal->getType()->isIntegerTy() && 5918 "If not a pointer, the value type must be an integer."); 5919 BPVal = CGF.Builder.CreateIntToPtr(BPVal, CGM.VoidPtrTy); 5920 } 5921 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 5922 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 5923 Info.BasePointersArray, 0, i); 5924 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 5925 CGF.Builder.CreateStore(BPVal, BPAddr); 5926 5927 if (Info.requiresDevicePointerInfo()) 5928 if (auto *DevVD = BasePointers[i].getDevicePtrDecl()) 5929 Info.CaptureDeviceAddrMap.insert(std::make_pair(DevVD, BPAddr)); 5930 5931 llvm::Value *PVal = Pointers[i]; 5932 if (PVal->getType()->isPointerTy()) 5933 PVal = CGF.Builder.CreateBitCast(PVal, CGM.VoidPtrTy); 5934 else { 5935 assert(PVal->getType()->isIntegerTy() && 5936 "If not a pointer, the value type must be an integer."); 5937 PVal = CGF.Builder.CreateIntToPtr(PVal, CGM.VoidPtrTy); 5938 } 5939 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 5940 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 5941 Info.PointersArray, 0, i); 5942 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 5943 CGF.Builder.CreateStore(PVal, PAddr); 5944 5945 if (hasRuntimeEvaluationCaptureSize) { 5946 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 5947 llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), 5948 Info.SizesArray, 5949 /*Idx0=*/0, 5950 /*Idx1=*/i); 5951 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType())); 5952 CGF.Builder.CreateStore( 5953 CGF.Builder.CreateIntCast(Sizes[i], CGM.SizeTy, /*isSigned=*/true), 5954 SAddr); 5955 } 5956 } 5957 } 5958 } 5959 /// \brief Emit the arguments to be passed to the runtime library based on the 5960 /// arrays of pointers, sizes and map types. 5961 static void emitOffloadingArraysArgument( 5962 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 5963 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 5964 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 5965 auto &CGM = CGF.CGM; 5966 if (Info.NumberOfPtrs) { 5967 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 5968 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 5969 Info.BasePointersArray, 5970 /*Idx0=*/0, /*Idx1=*/0); 5971 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 5972 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 5973 Info.PointersArray, 5974 /*Idx0=*/0, 5975 /*Idx1=*/0); 5976 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 5977 llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), Info.SizesArray, 5978 /*Idx0=*/0, /*Idx1=*/0); 5979 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 5980 llvm::ArrayType::get(CGM.Int32Ty, Info.NumberOfPtrs), 5981 Info.MapTypesArray, 5982 /*Idx0=*/0, 5983 /*Idx1=*/0); 5984 } else { 5985 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 5986 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 5987 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo()); 5988 MapTypesArrayArg = 5989 llvm::ConstantPointerNull::get(CGM.Int32Ty->getPointerTo()); 5990 } 5991 } 5992 5993 void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, 5994 const OMPExecutableDirective &D, 5995 llvm::Value *OutlinedFn, 5996 llvm::Value *OutlinedFnID, 5997 const Expr *IfCond, const Expr *Device, 5998 ArrayRef<llvm::Value *> CapturedVars) { 5999 if (!CGF.HaveInsertPoint()) 6000 return; 6001 6002 assert(OutlinedFn && "Invalid outlined function!"); 6003 6004 auto &Ctx = CGF.getContext(); 6005 6006 // Fill up the arrays with all the captured variables. 6007 MappableExprsHandler::MapValuesArrayTy KernelArgs; 6008 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 6009 MappableExprsHandler::MapValuesArrayTy Pointers; 6010 MappableExprsHandler::MapValuesArrayTy Sizes; 6011 MappableExprsHandler::MapFlagsArrayTy MapTypes; 6012 6013 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 6014 MappableExprsHandler::MapValuesArrayTy CurPointers; 6015 MappableExprsHandler::MapValuesArrayTy CurSizes; 6016 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 6017 6018 // Get mappable expression information. 6019 MappableExprsHandler MEHandler(D, CGF); 6020 6021 const CapturedStmt &CS = *cast<CapturedStmt>(D.getAssociatedStmt()); 6022 auto RI = CS.getCapturedRecordDecl()->field_begin(); 6023 auto CV = CapturedVars.begin(); 6024 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 6025 CE = CS.capture_end(); 6026 CI != CE; ++CI, ++RI, ++CV) { 6027 StringRef Name; 6028 QualType Ty; 6029 6030 CurBasePointers.clear(); 6031 CurPointers.clear(); 6032 CurSizes.clear(); 6033 CurMapTypes.clear(); 6034 6035 // VLA sizes are passed to the outlined region by copy and do not have map 6036 // information associated. 6037 if (CI->capturesVariableArrayType()) { 6038 CurBasePointers.push_back(*CV); 6039 CurPointers.push_back(*CV); 6040 CurSizes.push_back(CGF.getTypeSize(RI->getType())); 6041 // Copy to the device as an argument. No need to retrieve it. 6042 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_PRIVATE_VAL | 6043 MappableExprsHandler::OMP_MAP_FIRST_REF); 6044 } else { 6045 // If we have any information in the map clause, we use it, otherwise we 6046 // just do a default mapping. 6047 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 6048 CurSizes, CurMapTypes); 6049 if (CurBasePointers.empty()) 6050 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 6051 CurPointers, CurSizes, CurMapTypes); 6052 } 6053 // We expect to have at least an element of information for this capture. 6054 assert(!CurBasePointers.empty() && "Non-existing map pointer for capture!"); 6055 assert(CurBasePointers.size() == CurPointers.size() && 6056 CurBasePointers.size() == CurSizes.size() && 6057 CurBasePointers.size() == CurMapTypes.size() && 6058 "Inconsistent map information sizes!"); 6059 6060 // The kernel args are always the first elements of the base pointers 6061 // associated with a capture. 6062 KernelArgs.push_back(*CurBasePointers.front()); 6063 // We need to append the results of this capture to what we already have. 6064 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 6065 Pointers.append(CurPointers.begin(), CurPointers.end()); 6066 Sizes.append(CurSizes.begin(), CurSizes.end()); 6067 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 6068 } 6069 6070 // Keep track on whether the host function has to be executed. 6071 auto OffloadErrorQType = 6072 Ctx.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true); 6073 auto OffloadError = CGF.MakeAddrLValue( 6074 CGF.CreateMemTemp(OffloadErrorQType, ".run_host_version"), 6075 OffloadErrorQType); 6076 CGF.EmitStoreOfScalar(llvm::Constant::getNullValue(CGM.Int32Ty), 6077 OffloadError); 6078 6079 // Fill up the pointer arrays and transfer execution to the device. 6080 auto &&ThenGen = [&BasePointers, &Pointers, &Sizes, &MapTypes, Device, 6081 OutlinedFnID, OffloadError, 6082 &D](CodeGenFunction &CGF, PrePostActionTy &) { 6083 auto &RT = CGF.CGM.getOpenMPRuntime(); 6084 // Emit the offloading arrays. 6085 TargetDataInfo Info; 6086 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 6087 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 6088 Info.PointersArray, Info.SizesArray, 6089 Info.MapTypesArray, Info); 6090 6091 // On top of the arrays that were filled up, the target offloading call 6092 // takes as arguments the device id as well as the host pointer. The host 6093 // pointer is used by the runtime library to identify the current target 6094 // region, so it only has to be unique and not necessarily point to 6095 // anything. It could be the pointer to the outlined function that 6096 // implements the target region, but we aren't using that so that the 6097 // compiler doesn't need to keep that, and could therefore inline the host 6098 // function if proven worthwhile during optimization. 6099 6100 // From this point on, we need to have an ID of the target region defined. 6101 assert(OutlinedFnID && "Invalid outlined function ID!"); 6102 6103 // Emit device ID if any. 6104 llvm::Value *DeviceID; 6105 if (Device) 6106 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 6107 CGF.Int32Ty, /*isSigned=*/true); 6108 else 6109 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF); 6110 6111 // Emit the number of elements in the offloading arrays. 6112 llvm::Value *PointerNum = CGF.Builder.getInt32(BasePointers.size()); 6113 6114 // Return value of the runtime offloading call. 6115 llvm::Value *Return; 6116 6117 auto *NumTeams = emitNumTeamsForTargetDirective(RT, CGF, D); 6118 auto *NumThreads = emitNumThreadsForTargetDirective(RT, CGF, D); 6119 6120 // The target region is an outlined function launched by the runtime 6121 // via calls __tgt_target() or __tgt_target_teams(). 6122 // 6123 // __tgt_target() launches a target region with one team and one thread, 6124 // executing a serial region. This master thread may in turn launch 6125 // more threads within its team upon encountering a parallel region, 6126 // however, no additional teams can be launched on the device. 6127 // 6128 // __tgt_target_teams() launches a target region with one or more teams, 6129 // each with one or more threads. This call is required for target 6130 // constructs such as: 6131 // 'target teams' 6132 // 'target' / 'teams' 6133 // 'target teams distribute parallel for' 6134 // 'target parallel' 6135 // and so on. 6136 // 6137 // Note that on the host and CPU targets, the runtime implementation of 6138 // these calls simply call the outlined function without forking threads. 6139 // The outlined functions themselves have runtime calls to 6140 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 6141 // the compiler in emitTeamsCall() and emitParallelCall(). 6142 // 6143 // In contrast, on the NVPTX target, the implementation of 6144 // __tgt_target_teams() launches a GPU kernel with the requested number 6145 // of teams and threads so no additional calls to the runtime are required. 6146 if (NumTeams) { 6147 // If we have NumTeams defined this means that we have an enclosed teams 6148 // region. Therefore we also expect to have NumThreads defined. These two 6149 // values should be defined in the presence of a teams directive, 6150 // regardless of having any clauses associated. If the user is using teams 6151 // but no clauses, these two values will be the default that should be 6152 // passed to the runtime library - a 32-bit integer with the value zero. 6153 assert(NumThreads && "Thread limit expression should be available along " 6154 "with number of teams."); 6155 llvm::Value *OffloadingArgs[] = { 6156 DeviceID, OutlinedFnID, 6157 PointerNum, Info.BasePointersArray, 6158 Info.PointersArray, Info.SizesArray, 6159 Info.MapTypesArray, NumTeams, 6160 NumThreads}; 6161 Return = CGF.EmitRuntimeCall( 6162 RT.createRuntimeFunction(OMPRTL__tgt_target_teams), OffloadingArgs); 6163 } else { 6164 llvm::Value *OffloadingArgs[] = { 6165 DeviceID, OutlinedFnID, 6166 PointerNum, Info.BasePointersArray, 6167 Info.PointersArray, Info.SizesArray, 6168 Info.MapTypesArray}; 6169 Return = CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target), 6170 OffloadingArgs); 6171 } 6172 6173 CGF.EmitStoreOfScalar(Return, OffloadError); 6174 }; 6175 6176 // Notify that the host version must be executed. 6177 auto &&ElseGen = [OffloadError](CodeGenFunction &CGF, PrePostActionTy &) { 6178 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.Int32Ty, /*V=*/-1u), 6179 OffloadError); 6180 }; 6181 6182 // If we have a target function ID it means that we need to support 6183 // offloading, otherwise, just execute on the host. We need to execute on host 6184 // regardless of the conditional in the if clause if, e.g., the user do not 6185 // specify target triples. 6186 if (OutlinedFnID) { 6187 if (IfCond) 6188 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 6189 else { 6190 RegionCodeGenTy ThenRCG(ThenGen); 6191 ThenRCG(CGF); 6192 } 6193 } else { 6194 RegionCodeGenTy ElseRCG(ElseGen); 6195 ElseRCG(CGF); 6196 } 6197 6198 // Check the error code and execute the host version if required. 6199 auto OffloadFailedBlock = CGF.createBasicBlock("omp_offload.failed"); 6200 auto OffloadContBlock = CGF.createBasicBlock("omp_offload.cont"); 6201 auto OffloadErrorVal = CGF.EmitLoadOfScalar(OffloadError, SourceLocation()); 6202 auto Failed = CGF.Builder.CreateIsNotNull(OffloadErrorVal); 6203 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 6204 6205 CGF.EmitBlock(OffloadFailedBlock); 6206 CGF.Builder.CreateCall(OutlinedFn, KernelArgs); 6207 CGF.EmitBranch(OffloadContBlock); 6208 6209 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 6210 } 6211 6212 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 6213 StringRef ParentName) { 6214 if (!S) 6215 return; 6216 6217 // Codegen OMP target directives that offload compute to the device. 6218 bool requiresDeviceCodegen = 6219 isa<OMPExecutableDirective>(S) && 6220 isOpenMPTargetExecutionDirective( 6221 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 6222 6223 if (requiresDeviceCodegen) { 6224 auto &E = *cast<OMPExecutableDirective>(S); 6225 unsigned DeviceID; 6226 unsigned FileID; 6227 unsigned Line; 6228 getTargetEntryUniqueInfo(CGM.getContext(), E.getLocStart(), DeviceID, 6229 FileID, Line); 6230 6231 // Is this a target region that should not be emitted as an entry point? If 6232 // so just signal we are done with this target region. 6233 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 6234 ParentName, Line)) 6235 return; 6236 6237 switch (S->getStmtClass()) { 6238 case Stmt::OMPTargetDirectiveClass: 6239 CodeGenFunction::EmitOMPTargetDeviceFunction( 6240 CGM, ParentName, cast<OMPTargetDirective>(*S)); 6241 break; 6242 case Stmt::OMPTargetParallelDirectiveClass: 6243 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 6244 CGM, ParentName, cast<OMPTargetParallelDirective>(*S)); 6245 break; 6246 case Stmt::OMPTargetTeamsDirectiveClass: 6247 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 6248 CGM, ParentName, cast<OMPTargetTeamsDirective>(*S)); 6249 break; 6250 default: 6251 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 6252 } 6253 return; 6254 } 6255 6256 if (const OMPExecutableDirective *E = dyn_cast<OMPExecutableDirective>(S)) { 6257 if (!E->hasAssociatedStmt()) 6258 return; 6259 6260 scanForTargetRegionsFunctions( 6261 cast<CapturedStmt>(E->getAssociatedStmt())->getCapturedStmt(), 6262 ParentName); 6263 return; 6264 } 6265 6266 // If this is a lambda function, look into its body. 6267 if (auto *L = dyn_cast<LambdaExpr>(S)) 6268 S = L->getBody(); 6269 6270 // Keep looking for target regions recursively. 6271 for (auto *II : S->children()) 6272 scanForTargetRegionsFunctions(II, ParentName); 6273 } 6274 6275 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 6276 auto &FD = *cast<FunctionDecl>(GD.getDecl()); 6277 6278 // If emitting code for the host, we do not process FD here. Instead we do 6279 // the normal code generation. 6280 if (!CGM.getLangOpts().OpenMPIsDevice) 6281 return false; 6282 6283 // Try to detect target regions in the function. 6284 scanForTargetRegionsFunctions(FD.getBody(), CGM.getMangledName(GD)); 6285 6286 // We should not emit any function other that the ones created during the 6287 // scanning. Therefore, we signal that this function is completely dealt 6288 // with. 6289 return true; 6290 } 6291 6292 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 6293 if (!CGM.getLangOpts().OpenMPIsDevice) 6294 return false; 6295 6296 // Check if there are Ctors/Dtors in this declaration and look for target 6297 // regions in it. We use the complete variant to produce the kernel name 6298 // mangling. 6299 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 6300 if (auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 6301 for (auto *Ctor : RD->ctors()) { 6302 StringRef ParentName = 6303 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 6304 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 6305 } 6306 auto *Dtor = RD->getDestructor(); 6307 if (Dtor) { 6308 StringRef ParentName = 6309 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 6310 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 6311 } 6312 } 6313 6314 // If we are in target mode we do not emit any global (declare target is not 6315 // implemented yet). Therefore we signal that GD was processed in this case. 6316 return true; 6317 } 6318 6319 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 6320 auto *VD = GD.getDecl(); 6321 if (isa<FunctionDecl>(VD)) 6322 return emitTargetFunctions(GD); 6323 6324 return emitTargetGlobalVariable(GD); 6325 } 6326 6327 llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() { 6328 // If we have offloading in the current module, we need to emit the entries 6329 // now and register the offloading descriptor. 6330 createOffloadEntriesAndInfoMetadata(); 6331 6332 // Create and register the offloading binary descriptors. This is the main 6333 // entity that captures all the information about offloading in the current 6334 // compilation unit. 6335 return createOffloadingBinaryDescriptorRegistration(); 6336 } 6337 6338 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 6339 const OMPExecutableDirective &D, 6340 SourceLocation Loc, 6341 llvm::Value *OutlinedFn, 6342 ArrayRef<llvm::Value *> CapturedVars) { 6343 if (!CGF.HaveInsertPoint()) 6344 return; 6345 6346 auto *RTLoc = emitUpdateLocation(CGF, Loc); 6347 CodeGenFunction::RunCleanupsScope Scope(CGF); 6348 6349 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 6350 llvm::Value *Args[] = { 6351 RTLoc, 6352 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 6353 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 6354 llvm::SmallVector<llvm::Value *, 16> RealArgs; 6355 RealArgs.append(std::begin(Args), std::end(Args)); 6356 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 6357 6358 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 6359 CGF.EmitRuntimeCall(RTLFn, RealArgs); 6360 } 6361 6362 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 6363 const Expr *NumTeams, 6364 const Expr *ThreadLimit, 6365 SourceLocation Loc) { 6366 if (!CGF.HaveInsertPoint()) 6367 return; 6368 6369 auto *RTLoc = emitUpdateLocation(CGF, Loc); 6370 6371 llvm::Value *NumTeamsVal = 6372 (NumTeams) 6373 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 6374 CGF.CGM.Int32Ty, /* isSigned = */ true) 6375 : CGF.Builder.getInt32(0); 6376 6377 llvm::Value *ThreadLimitVal = 6378 (ThreadLimit) 6379 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 6380 CGF.CGM.Int32Ty, /* isSigned = */ true) 6381 : CGF.Builder.getInt32(0); 6382 6383 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 6384 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 6385 ThreadLimitVal}; 6386 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 6387 PushNumTeamsArgs); 6388 } 6389 6390 void CGOpenMPRuntime::emitTargetDataCalls( 6391 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 6392 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 6393 if (!CGF.HaveInsertPoint()) 6394 return; 6395 6396 // Action used to replace the default codegen action and turn privatization 6397 // off. 6398 PrePostActionTy NoPrivAction; 6399 6400 // Generate the code for the opening of the data environment. Capture all the 6401 // arguments of the runtime call by reference because they are used in the 6402 // closing of the region. 6403 auto &&BeginThenGen = [&D, Device, &Info, &CodeGen](CodeGenFunction &CGF, 6404 PrePostActionTy &) { 6405 // Fill up the arrays with all the mapped variables. 6406 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 6407 MappableExprsHandler::MapValuesArrayTy Pointers; 6408 MappableExprsHandler::MapValuesArrayTy Sizes; 6409 MappableExprsHandler::MapFlagsArrayTy MapTypes; 6410 6411 // Get map clause information. 6412 MappableExprsHandler MCHandler(D, CGF); 6413 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 6414 6415 // Fill up the arrays and create the arguments. 6416 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 6417 6418 llvm::Value *BasePointersArrayArg = nullptr; 6419 llvm::Value *PointersArrayArg = nullptr; 6420 llvm::Value *SizesArrayArg = nullptr; 6421 llvm::Value *MapTypesArrayArg = nullptr; 6422 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 6423 SizesArrayArg, MapTypesArrayArg, Info); 6424 6425 // Emit device ID if any. 6426 llvm::Value *DeviceID = nullptr; 6427 if (Device) 6428 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 6429 CGF.Int32Ty, /*isSigned=*/true); 6430 else 6431 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF); 6432 6433 // Emit the number of elements in the offloading arrays. 6434 auto *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 6435 6436 llvm::Value *OffloadingArgs[] = { 6437 DeviceID, PointerNum, BasePointersArrayArg, 6438 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 6439 auto &RT = CGF.CGM.getOpenMPRuntime(); 6440 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target_data_begin), 6441 OffloadingArgs); 6442 6443 // If device pointer privatization is required, emit the body of the region 6444 // here. It will have to be duplicated: with and without privatization. 6445 if (!Info.CaptureDeviceAddrMap.empty()) 6446 CodeGen(CGF); 6447 }; 6448 6449 // Generate code for the closing of the data region. 6450 auto &&EndThenGen = [Device, &Info](CodeGenFunction &CGF, PrePostActionTy &) { 6451 assert(Info.isValid() && "Invalid data environment closing arguments."); 6452 6453 llvm::Value *BasePointersArrayArg = nullptr; 6454 llvm::Value *PointersArrayArg = nullptr; 6455 llvm::Value *SizesArrayArg = nullptr; 6456 llvm::Value *MapTypesArrayArg = nullptr; 6457 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 6458 SizesArrayArg, MapTypesArrayArg, Info); 6459 6460 // Emit device ID if any. 6461 llvm::Value *DeviceID = nullptr; 6462 if (Device) 6463 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 6464 CGF.Int32Ty, /*isSigned=*/true); 6465 else 6466 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF); 6467 6468 // Emit the number of elements in the offloading arrays. 6469 auto *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 6470 6471 llvm::Value *OffloadingArgs[] = { 6472 DeviceID, PointerNum, BasePointersArrayArg, 6473 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 6474 auto &RT = CGF.CGM.getOpenMPRuntime(); 6475 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__tgt_target_data_end), 6476 OffloadingArgs); 6477 }; 6478 6479 // If we need device pointer privatization, we need to emit the body of the 6480 // region with no privatization in the 'else' branch of the conditional. 6481 // Otherwise, we don't have to do anything. 6482 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 6483 PrePostActionTy &) { 6484 if (!Info.CaptureDeviceAddrMap.empty()) { 6485 CodeGen.setAction(NoPrivAction); 6486 CodeGen(CGF); 6487 } 6488 }; 6489 6490 // We don't have to do anything to close the region if the if clause evaluates 6491 // to false. 6492 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 6493 6494 if (IfCond) { 6495 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 6496 } else { 6497 RegionCodeGenTy RCG(BeginThenGen); 6498 RCG(CGF); 6499 } 6500 6501 // If we don't require privatization of device pointers, we emit the body in 6502 // between the runtime calls. This avoids duplicating the body code. 6503 if (Info.CaptureDeviceAddrMap.empty()) { 6504 CodeGen.setAction(NoPrivAction); 6505 CodeGen(CGF); 6506 } 6507 6508 if (IfCond) { 6509 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen); 6510 } else { 6511 RegionCodeGenTy RCG(EndThenGen); 6512 RCG(CGF); 6513 } 6514 } 6515 6516 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 6517 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 6518 const Expr *Device) { 6519 if (!CGF.HaveInsertPoint()) 6520 return; 6521 6522 assert((isa<OMPTargetEnterDataDirective>(D) || 6523 isa<OMPTargetExitDataDirective>(D) || 6524 isa<OMPTargetUpdateDirective>(D)) && 6525 "Expecting either target enter, exit data, or update directives."); 6526 6527 // Generate the code for the opening of the data environment. 6528 auto &&ThenGen = [&D, Device](CodeGenFunction &CGF, PrePostActionTy &) { 6529 // Fill up the arrays with all the mapped variables. 6530 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 6531 MappableExprsHandler::MapValuesArrayTy Pointers; 6532 MappableExprsHandler::MapValuesArrayTy Sizes; 6533 MappableExprsHandler::MapFlagsArrayTy MapTypes; 6534 6535 // Get map clause information. 6536 MappableExprsHandler MEHandler(D, CGF); 6537 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 6538 6539 // Fill up the arrays and create the arguments. 6540 TargetDataInfo Info; 6541 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 6542 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 6543 Info.PointersArray, Info.SizesArray, 6544 Info.MapTypesArray, Info); 6545 6546 // Emit device ID if any. 6547 llvm::Value *DeviceID = nullptr; 6548 if (Device) 6549 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 6550 CGF.Int32Ty, /*isSigned=*/true); 6551 else 6552 DeviceID = CGF.Builder.getInt32(OMP_DEVICEID_UNDEF); 6553 6554 // Emit the number of elements in the offloading arrays. 6555 auto *PointerNum = CGF.Builder.getInt32(BasePointers.size()); 6556 6557 llvm::Value *OffloadingArgs[] = { 6558 DeviceID, PointerNum, Info.BasePointersArray, 6559 Info.PointersArray, Info.SizesArray, Info.MapTypesArray}; 6560 6561 auto &RT = CGF.CGM.getOpenMPRuntime(); 6562 // Select the right runtime function call for each expected standalone 6563 // directive. 6564 OpenMPRTLFunction RTLFn; 6565 switch (D.getDirectiveKind()) { 6566 default: 6567 llvm_unreachable("Unexpected standalone target data directive."); 6568 break; 6569 case OMPD_target_enter_data: 6570 RTLFn = OMPRTL__tgt_target_data_begin; 6571 break; 6572 case OMPD_target_exit_data: 6573 RTLFn = OMPRTL__tgt_target_data_end; 6574 break; 6575 case OMPD_target_update: 6576 RTLFn = OMPRTL__tgt_target_data_update; 6577 break; 6578 } 6579 CGF.EmitRuntimeCall(RT.createRuntimeFunction(RTLFn), OffloadingArgs); 6580 }; 6581 6582 // In the event we get an if clause, we don't have to take any action on the 6583 // else side. 6584 auto &&ElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 6585 6586 if (IfCond) { 6587 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 6588 } else { 6589 RegionCodeGenTy ThenGenRCG(ThenGen); 6590 ThenGenRCG(CGF); 6591 } 6592 } 6593 6594 namespace { 6595 /// Kind of parameter in a function with 'declare simd' directive. 6596 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 6597 /// Attribute set of the parameter. 6598 struct ParamAttrTy { 6599 ParamKindTy Kind = Vector; 6600 llvm::APSInt StrideOrArg; 6601 llvm::APSInt Alignment; 6602 }; 6603 } // namespace 6604 6605 static unsigned evaluateCDTSize(const FunctionDecl *FD, 6606 ArrayRef<ParamAttrTy> ParamAttrs) { 6607 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 6608 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 6609 // of that clause. The VLEN value must be power of 2. 6610 // In other case the notion of the function`s "characteristic data type" (CDT) 6611 // is used to compute the vector length. 6612 // CDT is defined in the following order: 6613 // a) For non-void function, the CDT is the return type. 6614 // b) If the function has any non-uniform, non-linear parameters, then the 6615 // CDT is the type of the first such parameter. 6616 // c) If the CDT determined by a) or b) above is struct, union, or class 6617 // type which is pass-by-value (except for the type that maps to the 6618 // built-in complex data type), the characteristic data type is int. 6619 // d) If none of the above three cases is applicable, the CDT is int. 6620 // The VLEN is then determined based on the CDT and the size of vector 6621 // register of that ISA for which current vector version is generated. The 6622 // VLEN is computed using the formula below: 6623 // VLEN = sizeof(vector_register) / sizeof(CDT), 6624 // where vector register size specified in section 3.2.1 Registers and the 6625 // Stack Frame of original AMD64 ABI document. 6626 QualType RetType = FD->getReturnType(); 6627 if (RetType.isNull()) 6628 return 0; 6629 ASTContext &C = FD->getASTContext(); 6630 QualType CDT; 6631 if (!RetType.isNull() && !RetType->isVoidType()) 6632 CDT = RetType; 6633 else { 6634 unsigned Offset = 0; 6635 if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 6636 if (ParamAttrs[Offset].Kind == Vector) 6637 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 6638 ++Offset; 6639 } 6640 if (CDT.isNull()) { 6641 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 6642 if (ParamAttrs[I + Offset].Kind == Vector) { 6643 CDT = FD->getParamDecl(I)->getType(); 6644 break; 6645 } 6646 } 6647 } 6648 } 6649 if (CDT.isNull()) 6650 CDT = C.IntTy; 6651 CDT = CDT->getCanonicalTypeUnqualified(); 6652 if (CDT->isRecordType() || CDT->isUnionType()) 6653 CDT = C.IntTy; 6654 return C.getTypeSize(CDT); 6655 } 6656 6657 static void 6658 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 6659 const llvm::APSInt &VLENVal, 6660 ArrayRef<ParamAttrTy> ParamAttrs, 6661 OMPDeclareSimdDeclAttr::BranchStateTy State) { 6662 struct ISADataTy { 6663 char ISA; 6664 unsigned VecRegSize; 6665 }; 6666 ISADataTy ISAData[] = { 6667 { 6668 'b', 128 6669 }, // SSE 6670 { 6671 'c', 256 6672 }, // AVX 6673 { 6674 'd', 256 6675 }, // AVX2 6676 { 6677 'e', 512 6678 }, // AVX512 6679 }; 6680 llvm::SmallVector<char, 2> Masked; 6681 switch (State) { 6682 case OMPDeclareSimdDeclAttr::BS_Undefined: 6683 Masked.push_back('N'); 6684 Masked.push_back('M'); 6685 break; 6686 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 6687 Masked.push_back('N'); 6688 break; 6689 case OMPDeclareSimdDeclAttr::BS_Inbranch: 6690 Masked.push_back('M'); 6691 break; 6692 } 6693 for (auto Mask : Masked) { 6694 for (auto &Data : ISAData) { 6695 SmallString<256> Buffer; 6696 llvm::raw_svector_ostream Out(Buffer); 6697 Out << "_ZGV" << Data.ISA << Mask; 6698 if (!VLENVal) { 6699 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / 6700 evaluateCDTSize(FD, ParamAttrs)); 6701 } else 6702 Out << VLENVal; 6703 for (auto &ParamAttr : ParamAttrs) { 6704 switch (ParamAttr.Kind){ 6705 case LinearWithVarStride: 6706 Out << 's' << ParamAttr.StrideOrArg; 6707 break; 6708 case Linear: 6709 Out << 'l'; 6710 if (!!ParamAttr.StrideOrArg) 6711 Out << ParamAttr.StrideOrArg; 6712 break; 6713 case Uniform: 6714 Out << 'u'; 6715 break; 6716 case Vector: 6717 Out << 'v'; 6718 break; 6719 } 6720 if (!!ParamAttr.Alignment) 6721 Out << 'a' << ParamAttr.Alignment; 6722 } 6723 Out << '_' << Fn->getName(); 6724 Fn->addFnAttr(Out.str()); 6725 } 6726 } 6727 } 6728 6729 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 6730 llvm::Function *Fn) { 6731 ASTContext &C = CGM.getContext(); 6732 FD = FD->getCanonicalDecl(); 6733 // Map params to their positions in function decl. 6734 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 6735 if (isa<CXXMethodDecl>(FD)) 6736 ParamPositions.insert({FD, 0}); 6737 unsigned ParamPos = ParamPositions.size(); 6738 for (auto *P : FD->parameters()) { 6739 ParamPositions.insert({P->getCanonicalDecl(), ParamPos}); 6740 ++ParamPos; 6741 } 6742 for (auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 6743 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 6744 // Mark uniform parameters. 6745 for (auto *E : Attr->uniforms()) { 6746 E = E->IgnoreParenImpCasts(); 6747 unsigned Pos; 6748 if (isa<CXXThisExpr>(E)) 6749 Pos = ParamPositions[FD]; 6750 else { 6751 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 6752 ->getCanonicalDecl(); 6753 Pos = ParamPositions[PVD]; 6754 } 6755 ParamAttrs[Pos].Kind = Uniform; 6756 } 6757 // Get alignment info. 6758 auto NI = Attr->alignments_begin(); 6759 for (auto *E : Attr->aligneds()) { 6760 E = E->IgnoreParenImpCasts(); 6761 unsigned Pos; 6762 QualType ParmTy; 6763 if (isa<CXXThisExpr>(E)) { 6764 Pos = ParamPositions[FD]; 6765 ParmTy = E->getType(); 6766 } else { 6767 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 6768 ->getCanonicalDecl(); 6769 Pos = ParamPositions[PVD]; 6770 ParmTy = PVD->getType(); 6771 } 6772 ParamAttrs[Pos].Alignment = 6773 (*NI) ? (*NI)->EvaluateKnownConstInt(C) 6774 : llvm::APSInt::getUnsigned( 6775 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 6776 .getQuantity()); 6777 ++NI; 6778 } 6779 // Mark linear parameters. 6780 auto SI = Attr->steps_begin(); 6781 auto MI = Attr->modifiers_begin(); 6782 for (auto *E : Attr->linears()) { 6783 E = E->IgnoreParenImpCasts(); 6784 unsigned Pos; 6785 if (isa<CXXThisExpr>(E)) 6786 Pos = ParamPositions[FD]; 6787 else { 6788 auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 6789 ->getCanonicalDecl(); 6790 Pos = ParamPositions[PVD]; 6791 } 6792 auto &ParamAttr = ParamAttrs[Pos]; 6793 ParamAttr.Kind = Linear; 6794 if (*SI) { 6795 if (!(*SI)->EvaluateAsInt(ParamAttr.StrideOrArg, C, 6796 Expr::SE_AllowSideEffects)) { 6797 if (auto *DRE = cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 6798 if (auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 6799 ParamAttr.Kind = LinearWithVarStride; 6800 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 6801 ParamPositions[StridePVD->getCanonicalDecl()]); 6802 } 6803 } 6804 } 6805 } 6806 ++SI; 6807 ++MI; 6808 } 6809 llvm::APSInt VLENVal; 6810 if (const Expr *VLEN = Attr->getSimdlen()) 6811 VLENVal = VLEN->EvaluateKnownConstInt(C); 6812 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 6813 if (CGM.getTriple().getArch() == llvm::Triple::x86 || 6814 CGM.getTriple().getArch() == llvm::Triple::x86_64) 6815 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 6816 } 6817 } 6818 6819 namespace { 6820 /// Cleanup action for doacross support. 6821 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 6822 public: 6823 static const int DoacrossFinArgs = 2; 6824 6825 private: 6826 llvm::Value *RTLFn; 6827 llvm::Value *Args[DoacrossFinArgs]; 6828 6829 public: 6830 DoacrossCleanupTy(llvm::Value *RTLFn, ArrayRef<llvm::Value *> CallArgs) 6831 : RTLFn(RTLFn) { 6832 assert(CallArgs.size() == DoacrossFinArgs); 6833 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 6834 } 6835 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 6836 if (!CGF.HaveInsertPoint()) 6837 return; 6838 CGF.EmitRuntimeCall(RTLFn, Args); 6839 } 6840 }; 6841 } // namespace 6842 6843 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 6844 const OMPLoopDirective &D) { 6845 if (!CGF.HaveInsertPoint()) 6846 return; 6847 6848 ASTContext &C = CGM.getContext(); 6849 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 6850 RecordDecl *RD; 6851 if (KmpDimTy.isNull()) { 6852 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 6853 // kmp_int64 lo; // lower 6854 // kmp_int64 up; // upper 6855 // kmp_int64 st; // stride 6856 // }; 6857 RD = C.buildImplicitRecord("kmp_dim"); 6858 RD->startDefinition(); 6859 addFieldToRecordDecl(C, RD, Int64Ty); 6860 addFieldToRecordDecl(C, RD, Int64Ty); 6861 addFieldToRecordDecl(C, RD, Int64Ty); 6862 RD->completeDefinition(); 6863 KmpDimTy = C.getRecordType(RD); 6864 } else 6865 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 6866 6867 Address DimsAddr = CGF.CreateMemTemp(KmpDimTy, "dims"); 6868 CGF.EmitNullInitialization(DimsAddr, KmpDimTy); 6869 enum { LowerFD = 0, UpperFD, StrideFD }; 6870 // Fill dims with data. 6871 LValue DimsLVal = CGF.MakeAddrLValue(DimsAddr, KmpDimTy); 6872 // dims.upper = num_iterations; 6873 LValue UpperLVal = 6874 CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), UpperFD)); 6875 llvm::Value *NumIterVal = CGF.EmitScalarConversion( 6876 CGF.EmitScalarExpr(D.getNumIterations()), D.getNumIterations()->getType(), 6877 Int64Ty, D.getNumIterations()->getExprLoc()); 6878 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 6879 // dims.stride = 1; 6880 LValue StrideLVal = 6881 CGF.EmitLValueForField(DimsLVal, *std::next(RD->field_begin(), StrideFD)); 6882 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 6883 StrideLVal); 6884 6885 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 6886 // kmp_int32 num_dims, struct kmp_dim * dims); 6887 llvm::Value *Args[] = {emitUpdateLocation(CGF, D.getLocStart()), 6888 getThreadID(CGF, D.getLocStart()), 6889 llvm::ConstantInt::getSigned(CGM.Int32Ty, 1), 6890 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6891 DimsAddr.getPointer(), CGM.VoidPtrTy)}; 6892 6893 llvm::Value *RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_init); 6894 CGF.EmitRuntimeCall(RTLFn, Args); 6895 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 6896 emitUpdateLocation(CGF, D.getLocEnd()), getThreadID(CGF, D.getLocEnd())}; 6897 llvm::Value *FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 6898 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 6899 llvm::makeArrayRef(FiniArgs)); 6900 } 6901 6902 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 6903 const OMPDependClause *C) { 6904 QualType Int64Ty = 6905 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 6906 const Expr *CounterVal = C->getCounterValue(); 6907 assert(CounterVal); 6908 llvm::Value *CntVal = CGF.EmitScalarConversion(CGF.EmitScalarExpr(CounterVal), 6909 CounterVal->getType(), Int64Ty, 6910 CounterVal->getExprLoc()); 6911 Address CntAddr = CGF.CreateMemTemp(Int64Ty, ".cnt.addr"); 6912 CGF.EmitStoreOfScalar(CntVal, CntAddr, /*Volatile=*/false, Int64Ty); 6913 llvm::Value *Args[] = {emitUpdateLocation(CGF, C->getLocStart()), 6914 getThreadID(CGF, C->getLocStart()), 6915 CntAddr.getPointer()}; 6916 llvm::Value *RTLFn; 6917 if (C->getDependencyKind() == OMPC_DEPEND_source) 6918 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 6919 else { 6920 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 6921 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 6922 } 6923 CGF.EmitRuntimeCall(RTLFn, Args); 6924 } 6925 6926