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