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