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