1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides a class for OpenMP runtime code generation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CGCXXABI.h" 14 #include "CGCleanup.h" 15 #include "CGOpenMPRuntime.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/CodeGen/ConstantInitBuilder.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/StmtOpenMP.h" 21 #include "clang/Basic/BitmaskEnum.h" 22 #include "llvm/ADT/ArrayRef.h" 23 #include "llvm/Bitcode/BitcodeReader.h" 24 #include "llvm/IR/DerivedTypes.h" 25 #include "llvm/IR/GlobalValue.h" 26 #include "llvm/IR/Value.h" 27 #include "llvm/Support/Format.h" 28 #include "llvm/Support/raw_ostream.h" 29 #include <cassert> 30 31 using namespace clang; 32 using namespace CodeGen; 33 34 namespace { 35 /// Base class for handling code generation inside OpenMP regions. 36 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 37 public: 38 /// Kinds of OpenMP regions used in codegen. 39 enum CGOpenMPRegionKind { 40 /// Region with outlined function for standalone 'parallel' 41 /// directive. 42 ParallelOutlinedRegion, 43 /// Region with outlined function for standalone 'task' directive. 44 TaskOutlinedRegion, 45 /// Region for constructs that do not require function outlining, 46 /// like 'for', 'sections', 'atomic' etc. directives. 47 InlinedRegion, 48 /// Region with outlined function for standalone 'target' directive. 49 TargetRegion, 50 }; 51 52 CGOpenMPRegionInfo(const CapturedStmt &CS, 53 const CGOpenMPRegionKind RegionKind, 54 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 55 bool HasCancel) 56 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 57 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 58 59 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 60 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 61 bool HasCancel) 62 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 63 Kind(Kind), HasCancel(HasCancel) {} 64 65 /// Get a variable or parameter for storing global thread id 66 /// inside OpenMP construct. 67 virtual const VarDecl *getThreadIDVariable() const = 0; 68 69 /// Emit the captured statement body. 70 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 71 72 /// Get an LValue for the current ThreadID variable. 73 /// \return LValue for thread id variable. This LValue always has type int32*. 74 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 75 76 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 77 78 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 79 80 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 81 82 bool hasCancel() const { return HasCancel; } 83 84 static bool classof(const CGCapturedStmtInfo *Info) { 85 return Info->getKind() == CR_OpenMP; 86 } 87 88 ~CGOpenMPRegionInfo() override = default; 89 90 protected: 91 CGOpenMPRegionKind RegionKind; 92 RegionCodeGenTy CodeGen; 93 OpenMPDirectiveKind Kind; 94 bool HasCancel; 95 }; 96 97 /// API for captured statement code generation in OpenMP constructs. 98 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 99 public: 100 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 101 const RegionCodeGenTy &CodeGen, 102 OpenMPDirectiveKind Kind, bool HasCancel, 103 StringRef HelperName) 104 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 105 HasCancel), 106 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 107 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 108 } 109 110 /// Get a variable or parameter for storing global thread id 111 /// inside OpenMP construct. 112 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 113 114 /// Get the name of the capture helper. 115 StringRef getHelperName() const override { return HelperName; } 116 117 static bool classof(const CGCapturedStmtInfo *Info) { 118 return CGOpenMPRegionInfo::classof(Info) && 119 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 120 ParallelOutlinedRegion; 121 } 122 123 private: 124 /// A variable or parameter storing global thread id for OpenMP 125 /// constructs. 126 const VarDecl *ThreadIDVar; 127 StringRef HelperName; 128 }; 129 130 /// API for captured statement code generation in OpenMP constructs. 131 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 132 public: 133 class UntiedTaskActionTy final : public PrePostActionTy { 134 bool Untied; 135 const VarDecl *PartIDVar; 136 const RegionCodeGenTy UntiedCodeGen; 137 llvm::SwitchInst *UntiedSwitch = nullptr; 138 139 public: 140 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 141 const RegionCodeGenTy &UntiedCodeGen) 142 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 143 void Enter(CodeGenFunction &CGF) override { 144 if (Untied) { 145 // Emit task switching point. 146 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 147 CGF.GetAddrOfLocalVar(PartIDVar), 148 PartIDVar->getType()->castAs<PointerType>()); 149 llvm::Value *Res = 150 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 151 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 152 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 153 CGF.EmitBlock(DoneBB); 154 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 155 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 156 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 157 CGF.Builder.GetInsertBlock()); 158 emitUntiedSwitch(CGF); 159 } 160 } 161 void emitUntiedSwitch(CodeGenFunction &CGF) const { 162 if (Untied) { 163 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 164 CGF.GetAddrOfLocalVar(PartIDVar), 165 PartIDVar->getType()->castAs<PointerType>()); 166 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 167 PartIdLVal); 168 UntiedCodeGen(CGF); 169 CodeGenFunction::JumpDest CurPoint = 170 CGF.getJumpDestInCurrentScope(".untied.next."); 171 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 172 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 173 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 174 CGF.Builder.GetInsertBlock()); 175 CGF.EmitBranchThroughCleanup(CurPoint); 176 CGF.EmitBlock(CurPoint.getBlock()); 177 } 178 } 179 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 180 }; 181 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 182 const VarDecl *ThreadIDVar, 183 const RegionCodeGenTy &CodeGen, 184 OpenMPDirectiveKind Kind, bool HasCancel, 185 const UntiedTaskActionTy &Action) 186 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 187 ThreadIDVar(ThreadIDVar), Action(Action) { 188 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 189 } 190 191 /// Get a variable or parameter for storing global thread id 192 /// inside OpenMP construct. 193 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 194 195 /// Get an LValue for the current ThreadID variable. 196 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 197 198 /// Get the name of the capture helper. 199 StringRef getHelperName() const override { return ".omp_outlined."; } 200 201 void emitUntiedSwitch(CodeGenFunction &CGF) override { 202 Action.emitUntiedSwitch(CGF); 203 } 204 205 static bool classof(const CGCapturedStmtInfo *Info) { 206 return CGOpenMPRegionInfo::classof(Info) && 207 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 208 TaskOutlinedRegion; 209 } 210 211 private: 212 /// A variable or parameter storing global thread id for OpenMP 213 /// constructs. 214 const VarDecl *ThreadIDVar; 215 /// Action for emitting code for untied tasks. 216 const UntiedTaskActionTy &Action; 217 }; 218 219 /// API for inlined captured statement code generation in OpenMP 220 /// constructs. 221 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 222 public: 223 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 224 const RegionCodeGenTy &CodeGen, 225 OpenMPDirectiveKind Kind, bool HasCancel) 226 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 227 OldCSI(OldCSI), 228 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 229 230 // Retrieve the value of the context parameter. 231 llvm::Value *getContextValue() const override { 232 if (OuterRegionInfo) 233 return OuterRegionInfo->getContextValue(); 234 llvm_unreachable("No context value for inlined OpenMP region"); 235 } 236 237 void setContextValue(llvm::Value *V) override { 238 if (OuterRegionInfo) { 239 OuterRegionInfo->setContextValue(V); 240 return; 241 } 242 llvm_unreachable("No context value for inlined OpenMP region"); 243 } 244 245 /// Lookup the captured field decl for a variable. 246 const FieldDecl *lookup(const VarDecl *VD) const override { 247 if (OuterRegionInfo) 248 return OuterRegionInfo->lookup(VD); 249 // If there is no outer outlined region,no need to lookup in a list of 250 // captured variables, we can use the original one. 251 return nullptr; 252 } 253 254 FieldDecl *getThisFieldDecl() const override { 255 if (OuterRegionInfo) 256 return OuterRegionInfo->getThisFieldDecl(); 257 return nullptr; 258 } 259 260 /// Get a variable or parameter for storing global thread id 261 /// inside OpenMP construct. 262 const VarDecl *getThreadIDVariable() const override { 263 if (OuterRegionInfo) 264 return OuterRegionInfo->getThreadIDVariable(); 265 return nullptr; 266 } 267 268 /// Get an LValue for the current ThreadID variable. 269 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 270 if (OuterRegionInfo) 271 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 272 llvm_unreachable("No LValue for inlined OpenMP construct"); 273 } 274 275 /// Get the name of the capture helper. 276 StringRef getHelperName() const override { 277 if (auto *OuterRegionInfo = getOldCSI()) 278 return OuterRegionInfo->getHelperName(); 279 llvm_unreachable("No helper name for inlined OpenMP construct"); 280 } 281 282 void emitUntiedSwitch(CodeGenFunction &CGF) override { 283 if (OuterRegionInfo) 284 OuterRegionInfo->emitUntiedSwitch(CGF); 285 } 286 287 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 288 289 static bool classof(const CGCapturedStmtInfo *Info) { 290 return CGOpenMPRegionInfo::classof(Info) && 291 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 292 } 293 294 ~CGOpenMPInlinedRegionInfo() override = default; 295 296 private: 297 /// CodeGen info about outer OpenMP region. 298 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 299 CGOpenMPRegionInfo *OuterRegionInfo; 300 }; 301 302 /// API for captured statement code generation in OpenMP target 303 /// constructs. For this captures, implicit parameters are used instead of the 304 /// captured fields. The name of the target region has to be unique in a given 305 /// application so it is provided by the client, because only the client has 306 /// the information to generate that. 307 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 308 public: 309 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 310 const RegionCodeGenTy &CodeGen, StringRef HelperName) 311 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 312 /*HasCancel=*/false), 313 HelperName(HelperName) {} 314 315 /// This is unused for target regions because each starts executing 316 /// with a single thread. 317 const VarDecl *getThreadIDVariable() const override { return nullptr; } 318 319 /// Get the name of the capture helper. 320 StringRef getHelperName() const override { return HelperName; } 321 322 static bool classof(const CGCapturedStmtInfo *Info) { 323 return CGOpenMPRegionInfo::classof(Info) && 324 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 325 } 326 327 private: 328 StringRef HelperName; 329 }; 330 331 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 332 llvm_unreachable("No codegen for expressions"); 333 } 334 /// API for generation of expressions captured in a innermost OpenMP 335 /// region. 336 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 337 public: 338 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 339 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 340 OMPD_unknown, 341 /*HasCancel=*/false), 342 PrivScope(CGF) { 343 // Make sure the globals captured in the provided statement are local by 344 // using the privatization logic. We assume the same variable is not 345 // captured more than once. 346 for (const auto &C : CS.captures()) { 347 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 348 continue; 349 350 const VarDecl *VD = C.getCapturedVar(); 351 if (VD->isLocalVarDeclOrParm()) 352 continue; 353 354 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 355 /*RefersToEnclosingVariableOrCapture=*/false, 356 VD->getType().getNonReferenceType(), VK_LValue, 357 C.getLocation()); 358 PrivScope.addPrivate( 359 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(); }); 360 } 361 (void)PrivScope.Privatize(); 362 } 363 364 /// Lookup the captured field decl for a variable. 365 const FieldDecl *lookup(const VarDecl *VD) const override { 366 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 367 return FD; 368 return nullptr; 369 } 370 371 /// Emit the captured statement body. 372 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 373 llvm_unreachable("No body for expressions"); 374 } 375 376 /// Get a variable or parameter for storing global thread id 377 /// inside OpenMP construct. 378 const VarDecl *getThreadIDVariable() const override { 379 llvm_unreachable("No thread id for expressions"); 380 } 381 382 /// Get the name of the capture helper. 383 StringRef getHelperName() const override { 384 llvm_unreachable("No helper name for expressions"); 385 } 386 387 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 388 389 private: 390 /// Private scope to capture global variables. 391 CodeGenFunction::OMPPrivateScope PrivScope; 392 }; 393 394 /// RAII for emitting code of OpenMP constructs. 395 class InlinedOpenMPRegionRAII { 396 CodeGenFunction &CGF; 397 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 398 FieldDecl *LambdaThisCaptureField = nullptr; 399 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 400 401 public: 402 /// Constructs region for combined constructs. 403 /// \param CodeGen Code generation sequence for combined directives. Includes 404 /// a list of functions used for code generation of implicitly inlined 405 /// regions. 406 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 407 OpenMPDirectiveKind Kind, bool HasCancel) 408 : CGF(CGF) { 409 // Start emission for the construct. 410 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 411 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 412 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 413 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 414 CGF.LambdaThisCaptureField = nullptr; 415 BlockInfo = CGF.BlockInfo; 416 CGF.BlockInfo = nullptr; 417 } 418 419 ~InlinedOpenMPRegionRAII() { 420 // Restore original CapturedStmtInfo only if we're done with code emission. 421 auto *OldCSI = 422 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 423 delete CGF.CapturedStmtInfo; 424 CGF.CapturedStmtInfo = OldCSI; 425 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 426 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 427 CGF.BlockInfo = BlockInfo; 428 } 429 }; 430 431 /// Values for bit flags used in the ident_t to describe the fields. 432 /// All enumeric elements are named and described in accordance with the code 433 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 434 enum OpenMPLocationFlags : unsigned { 435 /// Use trampoline for internal microtask. 436 OMP_IDENT_IMD = 0x01, 437 /// Use c-style ident structure. 438 OMP_IDENT_KMPC = 0x02, 439 /// Atomic reduction option for kmpc_reduce. 440 OMP_ATOMIC_REDUCE = 0x10, 441 /// Explicit 'barrier' directive. 442 OMP_IDENT_BARRIER_EXPL = 0x20, 443 /// Implicit barrier in code. 444 OMP_IDENT_BARRIER_IMPL = 0x40, 445 /// Implicit barrier in 'for' directive. 446 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 447 /// Implicit barrier in 'sections' directive. 448 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 449 /// Implicit barrier in 'single' directive. 450 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 451 /// Call of __kmp_for_static_init for static loop. 452 OMP_IDENT_WORK_LOOP = 0x200, 453 /// Call of __kmp_for_static_init for sections. 454 OMP_IDENT_WORK_SECTIONS = 0x400, 455 /// Call of __kmp_for_static_init for distribute. 456 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 457 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 458 }; 459 460 namespace { 461 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 462 /// Values for bit flags for marking which requires clauses have been used. 463 enum OpenMPOffloadingRequiresDirFlags : int64_t { 464 /// flag undefined. 465 OMP_REQ_UNDEFINED = 0x000, 466 /// no requires clause present. 467 OMP_REQ_NONE = 0x001, 468 /// reverse_offload clause. 469 OMP_REQ_REVERSE_OFFLOAD = 0x002, 470 /// unified_address clause. 471 OMP_REQ_UNIFIED_ADDRESS = 0x004, 472 /// unified_shared_memory clause. 473 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 474 /// dynamic_allocators clause. 475 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 476 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 477 }; 478 479 enum OpenMPOffloadingReservedDeviceIDs { 480 /// Device ID if the device was not defined, runtime should get it 481 /// from environment variables in the spec. 482 OMP_DEVICEID_UNDEF = -1, 483 }; 484 } // anonymous namespace 485 486 /// Describes ident structure that describes a source location. 487 /// All descriptions are taken from 488 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 489 /// Original structure: 490 /// typedef struct ident { 491 /// kmp_int32 reserved_1; /**< might be used in Fortran; 492 /// see above */ 493 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 494 /// KMP_IDENT_KMPC identifies this union 495 /// member */ 496 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 497 /// see above */ 498 ///#if USE_ITT_BUILD 499 /// /* but currently used for storing 500 /// region-specific ITT */ 501 /// /* contextual information. */ 502 ///#endif /* USE_ITT_BUILD */ 503 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 504 /// C++ */ 505 /// char const *psource; /**< String describing the source location. 506 /// The string is composed of semi-colon separated 507 // fields which describe the source file, 508 /// the function and a pair of line numbers that 509 /// delimit the construct. 510 /// */ 511 /// } ident_t; 512 enum IdentFieldIndex { 513 /// might be used in Fortran 514 IdentField_Reserved_1, 515 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 516 IdentField_Flags, 517 /// Not really used in Fortran any more 518 IdentField_Reserved_2, 519 /// Source[4] in Fortran, do not use for C++ 520 IdentField_Reserved_3, 521 /// String describing the source location. The string is composed of 522 /// semi-colon separated fields which describe the source file, the function 523 /// and a pair of line numbers that delimit the construct. 524 IdentField_PSource 525 }; 526 527 /// Schedule types for 'omp for' loops (these enumerators are taken from 528 /// the enum sched_type in kmp.h). 529 enum OpenMPSchedType { 530 /// Lower bound for default (unordered) versions. 531 OMP_sch_lower = 32, 532 OMP_sch_static_chunked = 33, 533 OMP_sch_static = 34, 534 OMP_sch_dynamic_chunked = 35, 535 OMP_sch_guided_chunked = 36, 536 OMP_sch_runtime = 37, 537 OMP_sch_auto = 38, 538 /// static with chunk adjustment (e.g., simd) 539 OMP_sch_static_balanced_chunked = 45, 540 /// Lower bound for 'ordered' versions. 541 OMP_ord_lower = 64, 542 OMP_ord_static_chunked = 65, 543 OMP_ord_static = 66, 544 OMP_ord_dynamic_chunked = 67, 545 OMP_ord_guided_chunked = 68, 546 OMP_ord_runtime = 69, 547 OMP_ord_auto = 70, 548 OMP_sch_default = OMP_sch_static, 549 /// dist_schedule types 550 OMP_dist_sch_static_chunked = 91, 551 OMP_dist_sch_static = 92, 552 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 553 /// Set if the monotonic schedule modifier was present. 554 OMP_sch_modifier_monotonic = (1 << 29), 555 /// Set if the nonmonotonic schedule modifier was present. 556 OMP_sch_modifier_nonmonotonic = (1 << 30), 557 }; 558 559 enum OpenMPRTLFunction { 560 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 561 /// kmpc_micro microtask, ...); 562 OMPRTL__kmpc_fork_call, 563 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 564 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 565 OMPRTL__kmpc_threadprivate_cached, 566 /// Call to void __kmpc_threadprivate_register( ident_t *, 567 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 568 OMPRTL__kmpc_threadprivate_register, 569 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 570 OMPRTL__kmpc_global_thread_num, 571 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 572 // kmp_critical_name *crit); 573 OMPRTL__kmpc_critical, 574 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 575 // global_tid, kmp_critical_name *crit, uintptr_t hint); 576 OMPRTL__kmpc_critical_with_hint, 577 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 578 // kmp_critical_name *crit); 579 OMPRTL__kmpc_end_critical, 580 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 581 // global_tid); 582 OMPRTL__kmpc_cancel_barrier, 583 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 584 OMPRTL__kmpc_barrier, 585 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 586 OMPRTL__kmpc_for_static_fini, 587 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 588 // global_tid); 589 OMPRTL__kmpc_serialized_parallel, 590 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 591 // global_tid); 592 OMPRTL__kmpc_end_serialized_parallel, 593 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 594 // kmp_int32 num_threads); 595 OMPRTL__kmpc_push_num_threads, 596 // Call to void __kmpc_flush(ident_t *loc); 597 OMPRTL__kmpc_flush, 598 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 599 OMPRTL__kmpc_master, 600 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 601 OMPRTL__kmpc_end_master, 602 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 603 // int end_part); 604 OMPRTL__kmpc_omp_taskyield, 605 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 606 OMPRTL__kmpc_single, 607 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 608 OMPRTL__kmpc_end_single, 609 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 610 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 611 // kmp_routine_entry_t *task_entry); 612 OMPRTL__kmpc_omp_task_alloc, 613 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 614 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 615 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 616 // kmp_int64 device_id); 617 OMPRTL__kmpc_omp_target_task_alloc, 618 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 619 // new_task); 620 OMPRTL__kmpc_omp_task, 621 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 622 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 623 // kmp_int32 didit); 624 OMPRTL__kmpc_copyprivate, 625 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 626 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 627 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 628 OMPRTL__kmpc_reduce, 629 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 630 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 631 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 632 // *lck); 633 OMPRTL__kmpc_reduce_nowait, 634 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 635 // kmp_critical_name *lck); 636 OMPRTL__kmpc_end_reduce, 637 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 638 // kmp_critical_name *lck); 639 OMPRTL__kmpc_end_reduce_nowait, 640 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 641 // kmp_task_t * new_task); 642 OMPRTL__kmpc_omp_task_begin_if0, 643 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 644 // kmp_task_t * new_task); 645 OMPRTL__kmpc_omp_task_complete_if0, 646 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 647 OMPRTL__kmpc_ordered, 648 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 649 OMPRTL__kmpc_end_ordered, 650 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 651 // global_tid); 652 OMPRTL__kmpc_omp_taskwait, 653 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 654 OMPRTL__kmpc_taskgroup, 655 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 656 OMPRTL__kmpc_end_taskgroup, 657 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 658 // int proc_bind); 659 OMPRTL__kmpc_push_proc_bind, 660 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 661 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 662 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 663 OMPRTL__kmpc_omp_task_with_deps, 664 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 665 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 666 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 667 OMPRTL__kmpc_omp_wait_deps, 668 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 669 // global_tid, kmp_int32 cncl_kind); 670 OMPRTL__kmpc_cancellationpoint, 671 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 672 // kmp_int32 cncl_kind); 673 OMPRTL__kmpc_cancel, 674 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 675 // kmp_int32 num_teams, kmp_int32 thread_limit); 676 OMPRTL__kmpc_push_num_teams, 677 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 678 // microtask, ...); 679 OMPRTL__kmpc_fork_teams, 680 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 681 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 682 // sched, kmp_uint64 grainsize, void *task_dup); 683 OMPRTL__kmpc_taskloop, 684 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 685 // num_dims, struct kmp_dim *dims); 686 OMPRTL__kmpc_doacross_init, 687 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 688 OMPRTL__kmpc_doacross_fini, 689 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 690 // *vec); 691 OMPRTL__kmpc_doacross_post, 692 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 693 // *vec); 694 OMPRTL__kmpc_doacross_wait, 695 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 696 // *data); 697 OMPRTL__kmpc_task_reduction_init, 698 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 699 // *d); 700 OMPRTL__kmpc_task_reduction_get_th_data, 701 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 702 OMPRTL__kmpc_alloc, 703 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 704 OMPRTL__kmpc_free, 705 706 // 707 // Offloading related calls 708 // 709 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 710 // size); 711 OMPRTL__kmpc_push_target_tripcount, 712 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 713 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t 714 // *arg_types); 715 OMPRTL__tgt_target, 716 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 717 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t 718 // *arg_types); 719 OMPRTL__tgt_target_nowait, 720 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 721 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t 722 // *arg_types, int32_t num_teams, int32_t thread_limit); 723 OMPRTL__tgt_target_teams, 724 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 725 // *host_ptr, int32_t arg_num, void** args_base, void **args, size_t 726 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 727 OMPRTL__tgt_target_teams_nowait, 728 // Call to void __tgt_register_requires(int64_t flags); 729 OMPRTL__tgt_register_requires, 730 // Call to void __tgt_register_lib(__tgt_bin_desc *desc); 731 OMPRTL__tgt_register_lib, 732 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); 733 OMPRTL__tgt_unregister_lib, 734 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 735 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 736 OMPRTL__tgt_target_data_begin, 737 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 738 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t 739 // *arg_types); 740 OMPRTL__tgt_target_data_begin_nowait, 741 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 742 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 743 OMPRTL__tgt_target_data_end, 744 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 745 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t 746 // *arg_types); 747 OMPRTL__tgt_target_data_end_nowait, 748 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 749 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 750 OMPRTL__tgt_target_data_update, 751 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 752 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t 753 // *arg_types); 754 OMPRTL__tgt_target_data_update_nowait, 755 }; 756 757 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 758 /// region. 759 class CleanupTy final : public EHScopeStack::Cleanup { 760 PrePostActionTy *Action; 761 762 public: 763 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 764 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 765 if (!CGF.HaveInsertPoint()) 766 return; 767 Action->Exit(CGF); 768 } 769 }; 770 771 } // anonymous namespace 772 773 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 774 CodeGenFunction::RunCleanupsScope Scope(CGF); 775 if (PrePostAction) { 776 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 777 Callback(CodeGen, CGF, *PrePostAction); 778 } else { 779 PrePostActionTy Action; 780 Callback(CodeGen, CGF, Action); 781 } 782 } 783 784 /// Check if the combiner is a call to UDR combiner and if it is so return the 785 /// UDR decl used for reduction. 786 static const OMPDeclareReductionDecl * 787 getReductionInit(const Expr *ReductionOp) { 788 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 789 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 790 if (const auto *DRE = 791 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 792 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 793 return DRD; 794 return nullptr; 795 } 796 797 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 798 const OMPDeclareReductionDecl *DRD, 799 const Expr *InitOp, 800 Address Private, Address Original, 801 QualType Ty) { 802 if (DRD->getInitializer()) { 803 std::pair<llvm::Function *, llvm::Function *> Reduction = 804 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 805 const auto *CE = cast<CallExpr>(InitOp); 806 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 807 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 808 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 809 const auto *LHSDRE = 810 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 811 const auto *RHSDRE = 812 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 813 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 814 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 815 [=]() { return Private; }); 816 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 817 [=]() { return Original; }); 818 (void)PrivateScope.Privatize(); 819 RValue Func = RValue::get(Reduction.second); 820 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 821 CGF.EmitIgnoredExpr(InitOp); 822 } else { 823 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 824 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 825 auto *GV = new llvm::GlobalVariable( 826 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 827 llvm::GlobalValue::PrivateLinkage, Init, Name); 828 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 829 RValue InitRVal; 830 switch (CGF.getEvaluationKind(Ty)) { 831 case TEK_Scalar: 832 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 833 break; 834 case TEK_Complex: 835 InitRVal = 836 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 837 break; 838 case TEK_Aggregate: 839 InitRVal = RValue::getAggregate(LV.getAddress()); 840 break; 841 } 842 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 843 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 844 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 845 /*IsInitializer=*/false); 846 } 847 } 848 849 /// Emit initialization of arrays of complex types. 850 /// \param DestAddr Address of the array. 851 /// \param Type Type of array. 852 /// \param Init Initial expression of array. 853 /// \param SrcAddr Address of the original array. 854 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 855 QualType Type, bool EmitDeclareReductionInit, 856 const Expr *Init, 857 const OMPDeclareReductionDecl *DRD, 858 Address SrcAddr = Address::invalid()) { 859 // Perform element-by-element initialization. 860 QualType ElementTy; 861 862 // Drill down to the base element type on both arrays. 863 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 864 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 865 DestAddr = 866 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 867 if (DRD) 868 SrcAddr = 869 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 870 871 llvm::Value *SrcBegin = nullptr; 872 if (DRD) 873 SrcBegin = SrcAddr.getPointer(); 874 llvm::Value *DestBegin = DestAddr.getPointer(); 875 // Cast from pointer to array type to pointer to single element. 876 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 877 // The basic structure here is a while-do loop. 878 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 879 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 880 llvm::Value *IsEmpty = 881 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 882 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 883 884 // Enter the loop body, making that address the current address. 885 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 886 CGF.EmitBlock(BodyBB); 887 888 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 889 890 llvm::PHINode *SrcElementPHI = nullptr; 891 Address SrcElementCurrent = Address::invalid(); 892 if (DRD) { 893 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 894 "omp.arraycpy.srcElementPast"); 895 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 896 SrcElementCurrent = 897 Address(SrcElementPHI, 898 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 899 } 900 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 901 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 902 DestElementPHI->addIncoming(DestBegin, EntryBB); 903 Address DestElementCurrent = 904 Address(DestElementPHI, 905 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 906 907 // Emit copy. 908 { 909 CodeGenFunction::RunCleanupsScope InitScope(CGF); 910 if (EmitDeclareReductionInit) { 911 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 912 SrcElementCurrent, ElementTy); 913 } else 914 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 915 /*IsInitializer=*/false); 916 } 917 918 if (DRD) { 919 // Shift the address forward by one element. 920 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 921 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 922 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 923 } 924 925 // Shift the address forward by one element. 926 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 927 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 928 // Check whether we've reached the end. 929 llvm::Value *Done = 930 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 931 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 932 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 933 934 // Done. 935 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 936 } 937 938 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 939 return CGF.EmitOMPSharedLValue(E); 940 } 941 942 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 943 const Expr *E) { 944 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 945 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 946 return LValue(); 947 } 948 949 void ReductionCodeGen::emitAggregateInitialization( 950 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 951 const OMPDeclareReductionDecl *DRD) { 952 // Emit VarDecl with copy init for arrays. 953 // Get the address of the original variable captured in current 954 // captured region. 955 const auto *PrivateVD = 956 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 957 bool EmitDeclareReductionInit = 958 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 959 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 960 EmitDeclareReductionInit, 961 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 962 : PrivateVD->getInit(), 963 DRD, SharedLVal.getAddress()); 964 } 965 966 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 967 ArrayRef<const Expr *> Privates, 968 ArrayRef<const Expr *> ReductionOps) { 969 ClausesData.reserve(Shareds.size()); 970 SharedAddresses.reserve(Shareds.size()); 971 Sizes.reserve(Shareds.size()); 972 BaseDecls.reserve(Shareds.size()); 973 auto IPriv = Privates.begin(); 974 auto IRed = ReductionOps.begin(); 975 for (const Expr *Ref : Shareds) { 976 ClausesData.emplace_back(Ref, *IPriv, *IRed); 977 std::advance(IPriv, 1); 978 std::advance(IRed, 1); 979 } 980 } 981 982 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 983 assert(SharedAddresses.size() == N && 984 "Number of generated lvalues must be exactly N."); 985 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 986 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 987 SharedAddresses.emplace_back(First, Second); 988 } 989 990 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 991 const auto *PrivateVD = 992 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 993 QualType PrivateType = PrivateVD->getType(); 994 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 995 if (!PrivateType->isVariablyModifiedType()) { 996 Sizes.emplace_back( 997 CGF.getTypeSize( 998 SharedAddresses[N].first.getType().getNonReferenceType()), 999 nullptr); 1000 return; 1001 } 1002 llvm::Value *Size; 1003 llvm::Value *SizeInChars; 1004 auto *ElemType = 1005 cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType()) 1006 ->getElementType(); 1007 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1008 if (AsArraySection) { 1009 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(), 1010 SharedAddresses[N].first.getPointer()); 1011 Size = CGF.Builder.CreateNUWAdd( 1012 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1013 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1014 } else { 1015 SizeInChars = CGF.getTypeSize( 1016 SharedAddresses[N].first.getType().getNonReferenceType()); 1017 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1018 } 1019 Sizes.emplace_back(SizeInChars, Size); 1020 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1021 CGF, 1022 cast<OpaqueValueExpr>( 1023 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1024 RValue::get(Size)); 1025 CGF.EmitVariablyModifiedType(PrivateType); 1026 } 1027 1028 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1029 llvm::Value *Size) { 1030 const auto *PrivateVD = 1031 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1032 QualType PrivateType = PrivateVD->getType(); 1033 if (!PrivateType->isVariablyModifiedType()) { 1034 assert(!Size && !Sizes[N].second && 1035 "Size should be nullptr for non-variably modified reduction " 1036 "items."); 1037 return; 1038 } 1039 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1040 CGF, 1041 cast<OpaqueValueExpr>( 1042 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1043 RValue::get(Size)); 1044 CGF.EmitVariablyModifiedType(PrivateType); 1045 } 1046 1047 void ReductionCodeGen::emitInitialization( 1048 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1049 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1050 assert(SharedAddresses.size() > N && "No variable was generated"); 1051 const auto *PrivateVD = 1052 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1053 const OMPDeclareReductionDecl *DRD = 1054 getReductionInit(ClausesData[N].ReductionOp); 1055 QualType PrivateType = PrivateVD->getType(); 1056 PrivateAddr = CGF.Builder.CreateElementBitCast( 1057 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1058 QualType SharedType = SharedAddresses[N].first.getType(); 1059 SharedLVal = CGF.MakeAddrLValue( 1060 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(), 1061 CGF.ConvertTypeForMem(SharedType)), 1062 SharedType, SharedAddresses[N].first.getBaseInfo(), 1063 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1064 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1065 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1066 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1067 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1068 PrivateAddr, SharedLVal.getAddress(), 1069 SharedLVal.getType()); 1070 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1071 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1072 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1073 PrivateVD->getType().getQualifiers(), 1074 /*IsInitializer=*/false); 1075 } 1076 } 1077 1078 bool ReductionCodeGen::needCleanups(unsigned N) { 1079 const auto *PrivateVD = 1080 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1081 QualType PrivateType = PrivateVD->getType(); 1082 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1083 return DTorKind != QualType::DK_none; 1084 } 1085 1086 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1087 Address PrivateAddr) { 1088 const auto *PrivateVD = 1089 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1090 QualType PrivateType = PrivateVD->getType(); 1091 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1092 if (needCleanups(N)) { 1093 PrivateAddr = CGF.Builder.CreateElementBitCast( 1094 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1095 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1096 } 1097 } 1098 1099 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1100 LValue BaseLV) { 1101 BaseTy = BaseTy.getNonReferenceType(); 1102 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1103 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1104 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1105 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy); 1106 } else { 1107 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy); 1108 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1109 } 1110 BaseTy = BaseTy->getPointeeType(); 1111 } 1112 return CGF.MakeAddrLValue( 1113 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(), 1114 CGF.ConvertTypeForMem(ElTy)), 1115 BaseLV.getType(), BaseLV.getBaseInfo(), 1116 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1117 } 1118 1119 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1120 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1121 llvm::Value *Addr) { 1122 Address Tmp = Address::invalid(); 1123 Address TopTmp = Address::invalid(); 1124 Address MostTopTmp = Address::invalid(); 1125 BaseTy = BaseTy.getNonReferenceType(); 1126 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1127 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1128 Tmp = CGF.CreateMemTemp(BaseTy); 1129 if (TopTmp.isValid()) 1130 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1131 else 1132 MostTopTmp = Tmp; 1133 TopTmp = Tmp; 1134 BaseTy = BaseTy->getPointeeType(); 1135 } 1136 llvm::Type *Ty = BaseLVType; 1137 if (Tmp.isValid()) 1138 Ty = Tmp.getElementType(); 1139 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1140 if (Tmp.isValid()) { 1141 CGF.Builder.CreateStore(Addr, Tmp); 1142 return MostTopTmp; 1143 } 1144 return Address(Addr, BaseLVAlignment); 1145 } 1146 1147 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1148 const VarDecl *OrigVD = nullptr; 1149 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1150 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1151 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1152 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1153 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1154 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1155 DE = cast<DeclRefExpr>(Base); 1156 OrigVD = cast<VarDecl>(DE->getDecl()); 1157 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1158 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1159 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1160 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1161 DE = cast<DeclRefExpr>(Base); 1162 OrigVD = cast<VarDecl>(DE->getDecl()); 1163 } 1164 return OrigVD; 1165 } 1166 1167 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1168 Address PrivateAddr) { 1169 const DeclRefExpr *DE; 1170 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1171 BaseDecls.emplace_back(OrigVD); 1172 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1173 LValue BaseLValue = 1174 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1175 OriginalBaseLValue); 1176 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1177 BaseLValue.getPointer(), SharedAddresses[N].first.getPointer()); 1178 llvm::Value *PrivatePointer = 1179 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1180 PrivateAddr.getPointer(), 1181 SharedAddresses[N].first.getAddress().getType()); 1182 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1183 return castToBase(CGF, OrigVD->getType(), 1184 SharedAddresses[N].first.getType(), 1185 OriginalBaseLValue.getAddress().getType(), 1186 OriginalBaseLValue.getAlignment(), Ptr); 1187 } 1188 BaseDecls.emplace_back( 1189 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1190 return PrivateAddr; 1191 } 1192 1193 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1194 const OMPDeclareReductionDecl *DRD = 1195 getReductionInit(ClausesData[N].ReductionOp); 1196 return DRD && DRD->getInitializer(); 1197 } 1198 1199 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1200 return CGF.EmitLoadOfPointerLValue( 1201 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1202 getThreadIDVariable()->getType()->castAs<PointerType>()); 1203 } 1204 1205 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1206 if (!CGF.HaveInsertPoint()) 1207 return; 1208 // 1.2.2 OpenMP Language Terminology 1209 // Structured block - An executable statement with a single entry at the 1210 // top and a single exit at the bottom. 1211 // The point of exit cannot be a branch out of the structured block. 1212 // longjmp() and throw() must not violate the entry/exit criteria. 1213 CGF.EHStack.pushTerminate(); 1214 CodeGen(CGF); 1215 CGF.EHStack.popTerminate(); 1216 } 1217 1218 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1219 CodeGenFunction &CGF) { 1220 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1221 getThreadIDVariable()->getType(), 1222 AlignmentSource::Decl); 1223 } 1224 1225 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1226 QualType FieldTy) { 1227 auto *Field = FieldDecl::Create( 1228 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1229 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1230 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1231 Field->setAccess(AS_public); 1232 DC->addDecl(Field); 1233 return Field; 1234 } 1235 1236 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1237 StringRef Separator) 1238 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1239 OffloadEntriesInfoManager(CGM) { 1240 ASTContext &C = CGM.getContext(); 1241 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1242 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1243 RD->startDefinition(); 1244 // reserved_1 1245 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1246 // flags 1247 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1248 // reserved_2 1249 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1250 // reserved_3 1251 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1252 // psource 1253 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1254 RD->completeDefinition(); 1255 IdentQTy = C.getRecordType(RD); 1256 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1257 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1258 1259 loadOffloadInfoMetadata(); 1260 } 1261 1262 void CGOpenMPRuntime::clear() { 1263 InternalVars.clear(); 1264 // Clean non-target variable declarations possibly used only in debug info. 1265 for (const auto &Data : EmittedNonTargetVariables) { 1266 if (!Data.getValue().pointsToAliveValue()) 1267 continue; 1268 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1269 if (!GV) 1270 continue; 1271 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1272 continue; 1273 GV->eraseFromParent(); 1274 } 1275 } 1276 1277 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1278 SmallString<128> Buffer; 1279 llvm::raw_svector_ostream OS(Buffer); 1280 StringRef Sep = FirstSeparator; 1281 for (StringRef Part : Parts) { 1282 OS << Sep << Part; 1283 Sep = Separator; 1284 } 1285 return OS.str(); 1286 } 1287 1288 static llvm::Function * 1289 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1290 const Expr *CombinerInitializer, const VarDecl *In, 1291 const VarDecl *Out, bool IsCombiner) { 1292 // void .omp_combiner.(Ty *in, Ty *out); 1293 ASTContext &C = CGM.getContext(); 1294 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1295 FunctionArgList Args; 1296 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1297 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1298 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1299 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1300 Args.push_back(&OmpOutParm); 1301 Args.push_back(&OmpInParm); 1302 const CGFunctionInfo &FnInfo = 1303 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1304 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1305 std::string Name = CGM.getOpenMPRuntime().getName( 1306 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1307 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1308 Name, &CGM.getModule()); 1309 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1310 if (CGM.getLangOpts().Optimize) { 1311 Fn->removeFnAttr(llvm::Attribute::NoInline); 1312 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1313 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1314 } 1315 CodeGenFunction CGF(CGM); 1316 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1317 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1318 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1319 Out->getLocation()); 1320 CodeGenFunction::OMPPrivateScope Scope(CGF); 1321 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1322 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1323 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1324 .getAddress(); 1325 }); 1326 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1327 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1328 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1329 .getAddress(); 1330 }); 1331 (void)Scope.Privatize(); 1332 if (!IsCombiner && Out->hasInit() && 1333 !CGF.isTrivialInitializer(Out->getInit())) { 1334 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1335 Out->getType().getQualifiers(), 1336 /*IsInitializer=*/true); 1337 } 1338 if (CombinerInitializer) 1339 CGF.EmitIgnoredExpr(CombinerInitializer); 1340 Scope.ForceCleanup(); 1341 CGF.FinishFunction(); 1342 return Fn; 1343 } 1344 1345 void CGOpenMPRuntime::emitUserDefinedReduction( 1346 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1347 if (UDRMap.count(D) > 0) 1348 return; 1349 llvm::Function *Combiner = emitCombinerOrInitializer( 1350 CGM, D->getType(), D->getCombiner(), 1351 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1352 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1353 /*IsCombiner=*/true); 1354 llvm::Function *Initializer = nullptr; 1355 if (const Expr *Init = D->getInitializer()) { 1356 Initializer = emitCombinerOrInitializer( 1357 CGM, D->getType(), 1358 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1359 : nullptr, 1360 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1361 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1362 /*IsCombiner=*/false); 1363 } 1364 UDRMap.try_emplace(D, Combiner, Initializer); 1365 if (CGF) { 1366 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1367 Decls.second.push_back(D); 1368 } 1369 } 1370 1371 std::pair<llvm::Function *, llvm::Function *> 1372 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1373 auto I = UDRMap.find(D); 1374 if (I != UDRMap.end()) 1375 return I->second; 1376 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1377 return UDRMap.lookup(D); 1378 } 1379 1380 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1381 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1382 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1383 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1384 assert(ThreadIDVar->getType()->isPointerType() && 1385 "thread id variable must be of type kmp_int32 *"); 1386 CodeGenFunction CGF(CGM, true); 1387 bool HasCancel = false; 1388 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1389 HasCancel = OPD->hasCancel(); 1390 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1391 HasCancel = OPSD->hasCancel(); 1392 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1393 HasCancel = OPFD->hasCancel(); 1394 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1395 HasCancel = OPFD->hasCancel(); 1396 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1397 HasCancel = OPFD->hasCancel(); 1398 else if (const auto *OPFD = 1399 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1400 HasCancel = OPFD->hasCancel(); 1401 else if (const auto *OPFD = 1402 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1403 HasCancel = OPFD->hasCancel(); 1404 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1405 HasCancel, OutlinedHelperName); 1406 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1407 return CGF.GenerateOpenMPCapturedStmtFunction(*CS); 1408 } 1409 1410 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1411 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1412 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1413 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1414 return emitParallelOrTeamsOutlinedFunction( 1415 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1416 } 1417 1418 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1419 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1420 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1421 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1422 return emitParallelOrTeamsOutlinedFunction( 1423 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1424 } 1425 1426 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1427 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1428 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1429 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1430 bool Tied, unsigned &NumberOfParts) { 1431 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1432 PrePostActionTy &) { 1433 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1434 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1435 llvm::Value *TaskArgs[] = { 1436 UpLoc, ThreadID, 1437 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1438 TaskTVar->getType()->castAs<PointerType>()) 1439 .getPointer()}; 1440 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1441 }; 1442 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1443 UntiedCodeGen); 1444 CodeGen.setAction(Action); 1445 assert(!ThreadIDVar->getType()->isPointerType() && 1446 "thread id variable must be of type kmp_int32 for tasks"); 1447 const OpenMPDirectiveKind Region = 1448 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1449 : OMPD_task; 1450 const CapturedStmt *CS = D.getCapturedStmt(Region); 1451 const auto *TD = dyn_cast<OMPTaskDirective>(&D); 1452 CodeGenFunction CGF(CGM, true); 1453 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1454 InnermostKind, 1455 TD ? TD->hasCancel() : false, Action); 1456 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1457 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1458 if (!Tied) 1459 NumberOfParts = Action.getNumberOfParts(); 1460 return Res; 1461 } 1462 1463 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1464 const RecordDecl *RD, const CGRecordLayout &RL, 1465 ArrayRef<llvm::Constant *> Data) { 1466 llvm::StructType *StructTy = RL.getLLVMType(); 1467 unsigned PrevIdx = 0; 1468 ConstantInitBuilder CIBuilder(CGM); 1469 auto DI = Data.begin(); 1470 for (const FieldDecl *FD : RD->fields()) { 1471 unsigned Idx = RL.getLLVMFieldNo(FD); 1472 // Fill the alignment. 1473 for (unsigned I = PrevIdx; I < Idx; ++I) 1474 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1475 PrevIdx = Idx + 1; 1476 Fields.add(*DI); 1477 ++DI; 1478 } 1479 } 1480 1481 template <class... As> 1482 static llvm::GlobalVariable * 1483 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1484 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1485 As &&... Args) { 1486 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1487 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1488 ConstantInitBuilder CIBuilder(CGM); 1489 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1490 buildStructValue(Fields, CGM, RD, RL, Data); 1491 return Fields.finishAndCreateGlobal( 1492 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1493 std::forward<As>(Args)...); 1494 } 1495 1496 template <typename T> 1497 static void 1498 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1499 ArrayRef<llvm::Constant *> Data, 1500 T &Parent) { 1501 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1502 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1503 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1504 buildStructValue(Fields, CGM, RD, RL, Data); 1505 Fields.finishAndAddTo(Parent); 1506 } 1507 1508 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1509 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1510 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1511 FlagsTy FlagsKey(Flags, Reserved2Flags); 1512 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1513 if (!Entry) { 1514 if (!DefaultOpenMPPSource) { 1515 // Initialize default location for psource field of ident_t structure of 1516 // all ident_t objects. Format is ";file;function;line;column;;". 1517 // Taken from 1518 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1519 DefaultOpenMPPSource = 1520 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1521 DefaultOpenMPPSource = 1522 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1523 } 1524 1525 llvm::Constant *Data[] = { 1526 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1527 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1528 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1529 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1530 llvm::GlobalValue *DefaultOpenMPLocation = 1531 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1532 llvm::GlobalValue::PrivateLinkage); 1533 DefaultOpenMPLocation->setUnnamedAddr( 1534 llvm::GlobalValue::UnnamedAddr::Global); 1535 1536 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1537 } 1538 return Address(Entry, Align); 1539 } 1540 1541 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1542 bool AtCurrentPoint) { 1543 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1544 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1545 1546 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1547 if (AtCurrentPoint) { 1548 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1549 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1550 } else { 1551 Elem.second.ServiceInsertPt = 1552 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1553 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1554 } 1555 } 1556 1557 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1558 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1559 if (Elem.second.ServiceInsertPt) { 1560 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1561 Elem.second.ServiceInsertPt = nullptr; 1562 Ptr->eraseFromParent(); 1563 } 1564 } 1565 1566 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1567 SourceLocation Loc, 1568 unsigned Flags) { 1569 Flags |= OMP_IDENT_KMPC; 1570 // If no debug info is generated - return global default location. 1571 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1572 Loc.isInvalid()) 1573 return getOrCreateDefaultLocation(Flags).getPointer(); 1574 1575 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1576 1577 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1578 Address LocValue = Address::invalid(); 1579 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1580 if (I != OpenMPLocThreadIDMap.end()) 1581 LocValue = Address(I->second.DebugLoc, Align); 1582 1583 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1584 // GetOpenMPThreadID was called before this routine. 1585 if (!LocValue.isValid()) { 1586 // Generate "ident_t .kmpc_loc.addr;" 1587 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1588 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1589 Elem.second.DebugLoc = AI.getPointer(); 1590 LocValue = AI; 1591 1592 if (!Elem.second.ServiceInsertPt) 1593 setLocThreadIdInsertPt(CGF); 1594 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1595 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1596 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1597 CGF.getTypeSize(IdentQTy)); 1598 } 1599 1600 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1601 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1602 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1603 LValue PSource = 1604 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1605 1606 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1607 if (OMPDebugLoc == nullptr) { 1608 SmallString<128> Buffer2; 1609 llvm::raw_svector_ostream OS2(Buffer2); 1610 // Build debug location 1611 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1612 OS2 << ";" << PLoc.getFilename() << ";"; 1613 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1614 OS2 << FD->getQualifiedNameAsString(); 1615 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1616 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1617 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1618 } 1619 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1620 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1621 1622 // Our callers always pass this to a runtime function, so for 1623 // convenience, go ahead and return a naked pointer. 1624 return LocValue.getPointer(); 1625 } 1626 1627 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1628 SourceLocation Loc) { 1629 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1630 1631 llvm::Value *ThreadID = nullptr; 1632 // Check whether we've already cached a load of the thread id in this 1633 // function. 1634 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1635 if (I != OpenMPLocThreadIDMap.end()) { 1636 ThreadID = I->second.ThreadID; 1637 if (ThreadID != nullptr) 1638 return ThreadID; 1639 } 1640 // If exceptions are enabled, do not use parameter to avoid possible crash. 1641 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1642 !CGF.getLangOpts().CXXExceptions || 1643 CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 1644 if (auto *OMPRegionInfo = 1645 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1646 if (OMPRegionInfo->getThreadIDVariable()) { 1647 // Check if this an outlined function with thread id passed as argument. 1648 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1649 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1650 // If value loaded in entry block, cache it and use it everywhere in 1651 // function. 1652 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 1653 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1654 Elem.second.ThreadID = ThreadID; 1655 } 1656 return ThreadID; 1657 } 1658 } 1659 } 1660 1661 // This is not an outlined function region - need to call __kmpc_int32 1662 // kmpc_global_thread_num(ident_t *loc). 1663 // Generate thread id value and cache this value for use across the 1664 // function. 1665 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1666 if (!Elem.second.ServiceInsertPt) 1667 setLocThreadIdInsertPt(CGF); 1668 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1669 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1670 llvm::CallInst *Call = CGF.Builder.CreateCall( 1671 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1672 emitUpdateLocation(CGF, Loc)); 1673 Call->setCallingConv(CGF.getRuntimeCC()); 1674 Elem.second.ThreadID = Call; 1675 return Call; 1676 } 1677 1678 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1679 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1680 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1681 clearLocThreadIdInsertPt(CGF); 1682 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1683 } 1684 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1685 for(auto *D : FunctionUDRMap[CGF.CurFn]) 1686 UDRMap.erase(D); 1687 FunctionUDRMap.erase(CGF.CurFn); 1688 } 1689 } 1690 1691 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1692 return IdentTy->getPointerTo(); 1693 } 1694 1695 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1696 if (!Kmpc_MicroTy) { 1697 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1698 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1699 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1700 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1701 } 1702 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1703 } 1704 1705 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1706 llvm::FunctionCallee RTLFn = nullptr; 1707 switch (static_cast<OpenMPRTLFunction>(Function)) { 1708 case OMPRTL__kmpc_fork_call: { 1709 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1710 // microtask, ...); 1711 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1712 getKmpc_MicroPointerTy()}; 1713 auto *FnTy = 1714 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1715 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1716 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1717 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1718 llvm::LLVMContext &Ctx = F->getContext(); 1719 llvm::MDBuilder MDB(Ctx); 1720 // Annotate the callback behavior of the __kmpc_fork_call: 1721 // - The callback callee is argument number 2 (microtask). 1722 // - The first two arguments of the callback callee are unknown (-1). 1723 // - All variadic arguments to the __kmpc_fork_call are passed to the 1724 // callback callee. 1725 F->addMetadata( 1726 llvm::LLVMContext::MD_callback, 1727 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1728 2, {-1, -1}, 1729 /* VarArgsArePassed */ true)})); 1730 } 1731 } 1732 break; 1733 } 1734 case OMPRTL__kmpc_global_thread_num: { 1735 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1736 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1737 auto *FnTy = 1738 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1739 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1740 break; 1741 } 1742 case OMPRTL__kmpc_threadprivate_cached: { 1743 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1744 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1745 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1746 CGM.VoidPtrTy, CGM.SizeTy, 1747 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1748 auto *FnTy = 1749 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1750 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1751 break; 1752 } 1753 case OMPRTL__kmpc_critical: { 1754 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1755 // kmp_critical_name *crit); 1756 llvm::Type *TypeParams[] = { 1757 getIdentTyPointerTy(), CGM.Int32Ty, 1758 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1759 auto *FnTy = 1760 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1761 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1762 break; 1763 } 1764 case OMPRTL__kmpc_critical_with_hint: { 1765 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1766 // kmp_critical_name *crit, uintptr_t hint); 1767 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1768 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1769 CGM.IntPtrTy}; 1770 auto *FnTy = 1771 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1772 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1773 break; 1774 } 1775 case OMPRTL__kmpc_threadprivate_register: { 1776 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1777 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1778 // typedef void *(*kmpc_ctor)(void *); 1779 auto *KmpcCtorTy = 1780 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1781 /*isVarArg*/ false)->getPointerTo(); 1782 // typedef void *(*kmpc_cctor)(void *, void *); 1783 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1784 auto *KmpcCopyCtorTy = 1785 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1786 /*isVarArg*/ false) 1787 ->getPointerTo(); 1788 // typedef void (*kmpc_dtor)(void *); 1789 auto *KmpcDtorTy = 1790 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1791 ->getPointerTo(); 1792 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1793 KmpcCopyCtorTy, KmpcDtorTy}; 1794 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1795 /*isVarArg*/ false); 1796 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1797 break; 1798 } 1799 case OMPRTL__kmpc_end_critical: { 1800 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1801 // kmp_critical_name *crit); 1802 llvm::Type *TypeParams[] = { 1803 getIdentTyPointerTy(), CGM.Int32Ty, 1804 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1805 auto *FnTy = 1806 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1807 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1808 break; 1809 } 1810 case OMPRTL__kmpc_cancel_barrier: { 1811 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1812 // global_tid); 1813 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1814 auto *FnTy = 1815 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1816 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1817 break; 1818 } 1819 case OMPRTL__kmpc_barrier: { 1820 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1821 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1822 auto *FnTy = 1823 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1824 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1825 break; 1826 } 1827 case OMPRTL__kmpc_for_static_fini: { 1828 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1829 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1830 auto *FnTy = 1831 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1832 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1833 break; 1834 } 1835 case OMPRTL__kmpc_push_num_threads: { 1836 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1837 // kmp_int32 num_threads) 1838 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1839 CGM.Int32Ty}; 1840 auto *FnTy = 1841 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1842 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1843 break; 1844 } 1845 case OMPRTL__kmpc_serialized_parallel: { 1846 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1847 // global_tid); 1848 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1849 auto *FnTy = 1850 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1851 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1852 break; 1853 } 1854 case OMPRTL__kmpc_end_serialized_parallel: { 1855 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1856 // global_tid); 1857 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1858 auto *FnTy = 1859 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1860 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1861 break; 1862 } 1863 case OMPRTL__kmpc_flush: { 1864 // Build void __kmpc_flush(ident_t *loc); 1865 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1866 auto *FnTy = 1867 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1868 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1869 break; 1870 } 1871 case OMPRTL__kmpc_master: { 1872 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1873 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1874 auto *FnTy = 1875 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1876 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 1877 break; 1878 } 1879 case OMPRTL__kmpc_end_master: { 1880 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 1881 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1882 auto *FnTy = 1883 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1884 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 1885 break; 1886 } 1887 case OMPRTL__kmpc_omp_taskyield: { 1888 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 1889 // int end_part); 1890 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1891 auto *FnTy = 1892 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1893 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 1894 break; 1895 } 1896 case OMPRTL__kmpc_single: { 1897 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 1898 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1899 auto *FnTy = 1900 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1901 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 1902 break; 1903 } 1904 case OMPRTL__kmpc_end_single: { 1905 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 1906 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1907 auto *FnTy = 1908 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1909 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 1910 break; 1911 } 1912 case OMPRTL__kmpc_omp_task_alloc: { 1913 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 1914 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1915 // kmp_routine_entry_t *task_entry); 1916 assert(KmpRoutineEntryPtrTy != nullptr && 1917 "Type kmp_routine_entry_t must be created."); 1918 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1919 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 1920 // Return void * and then cast to particular kmp_task_t type. 1921 auto *FnTy = 1922 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 1923 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 1924 break; 1925 } 1926 case OMPRTL__kmpc_omp_target_task_alloc: { 1927 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 1928 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1929 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 1930 assert(KmpRoutineEntryPtrTy != nullptr && 1931 "Type kmp_routine_entry_t must be created."); 1932 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1933 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 1934 CGM.Int64Ty}; 1935 // Return void * and then cast to particular kmp_task_t type. 1936 auto *FnTy = 1937 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 1938 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 1939 break; 1940 } 1941 case OMPRTL__kmpc_omp_task: { 1942 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 1943 // *new_task); 1944 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1945 CGM.VoidPtrTy}; 1946 auto *FnTy = 1947 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1948 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 1949 break; 1950 } 1951 case OMPRTL__kmpc_copyprivate: { 1952 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 1953 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 1954 // kmp_int32 didit); 1955 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1956 auto *CpyFnTy = 1957 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 1958 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 1959 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 1960 CGM.Int32Ty}; 1961 auto *FnTy = 1962 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1963 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 1964 break; 1965 } 1966 case OMPRTL__kmpc_reduce: { 1967 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 1968 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 1969 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 1970 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1971 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 1972 /*isVarArg=*/false); 1973 llvm::Type *TypeParams[] = { 1974 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 1975 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 1976 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1977 auto *FnTy = 1978 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1979 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 1980 break; 1981 } 1982 case OMPRTL__kmpc_reduce_nowait: { 1983 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 1984 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 1985 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 1986 // *lck); 1987 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1988 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 1989 /*isVarArg=*/false); 1990 llvm::Type *TypeParams[] = { 1991 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 1992 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 1993 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1994 auto *FnTy = 1995 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1996 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 1997 break; 1998 } 1999 case OMPRTL__kmpc_end_reduce: { 2000 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2001 // kmp_critical_name *lck); 2002 llvm::Type *TypeParams[] = { 2003 getIdentTyPointerTy(), CGM.Int32Ty, 2004 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2005 auto *FnTy = 2006 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2007 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2008 break; 2009 } 2010 case OMPRTL__kmpc_end_reduce_nowait: { 2011 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2012 // kmp_critical_name *lck); 2013 llvm::Type *TypeParams[] = { 2014 getIdentTyPointerTy(), CGM.Int32Ty, 2015 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2016 auto *FnTy = 2017 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2018 RTLFn = 2019 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2020 break; 2021 } 2022 case OMPRTL__kmpc_omp_task_begin_if0: { 2023 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2024 // *new_task); 2025 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2026 CGM.VoidPtrTy}; 2027 auto *FnTy = 2028 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2029 RTLFn = 2030 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2031 break; 2032 } 2033 case OMPRTL__kmpc_omp_task_complete_if0: { 2034 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2035 // *new_task); 2036 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2037 CGM.VoidPtrTy}; 2038 auto *FnTy = 2039 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2040 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2041 /*Name=*/"__kmpc_omp_task_complete_if0"); 2042 break; 2043 } 2044 case OMPRTL__kmpc_ordered: { 2045 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2046 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2047 auto *FnTy = 2048 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2049 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2050 break; 2051 } 2052 case OMPRTL__kmpc_end_ordered: { 2053 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2054 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2055 auto *FnTy = 2056 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2057 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2058 break; 2059 } 2060 case OMPRTL__kmpc_omp_taskwait: { 2061 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2062 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2063 auto *FnTy = 2064 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2065 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2066 break; 2067 } 2068 case OMPRTL__kmpc_taskgroup: { 2069 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2070 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2071 auto *FnTy = 2072 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2073 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2074 break; 2075 } 2076 case OMPRTL__kmpc_end_taskgroup: { 2077 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2078 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2079 auto *FnTy = 2080 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2081 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2082 break; 2083 } 2084 case OMPRTL__kmpc_push_proc_bind: { 2085 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2086 // int proc_bind) 2087 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2088 auto *FnTy = 2089 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2090 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2091 break; 2092 } 2093 case OMPRTL__kmpc_omp_task_with_deps: { 2094 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2095 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2096 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2097 llvm::Type *TypeParams[] = { 2098 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2099 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2100 auto *FnTy = 2101 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2102 RTLFn = 2103 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2104 break; 2105 } 2106 case OMPRTL__kmpc_omp_wait_deps: { 2107 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2108 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2109 // kmp_depend_info_t *noalias_dep_list); 2110 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2111 CGM.Int32Ty, CGM.VoidPtrTy, 2112 CGM.Int32Ty, CGM.VoidPtrTy}; 2113 auto *FnTy = 2114 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2115 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2116 break; 2117 } 2118 case OMPRTL__kmpc_cancellationpoint: { 2119 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2120 // global_tid, kmp_int32 cncl_kind) 2121 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2122 auto *FnTy = 2123 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2124 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2125 break; 2126 } 2127 case OMPRTL__kmpc_cancel: { 2128 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2129 // kmp_int32 cncl_kind) 2130 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2131 auto *FnTy = 2132 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2133 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2134 break; 2135 } 2136 case OMPRTL__kmpc_push_num_teams: { 2137 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2138 // kmp_int32 num_teams, kmp_int32 num_threads) 2139 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2140 CGM.Int32Ty}; 2141 auto *FnTy = 2142 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2143 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2144 break; 2145 } 2146 case OMPRTL__kmpc_fork_teams: { 2147 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2148 // microtask, ...); 2149 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2150 getKmpc_MicroPointerTy()}; 2151 auto *FnTy = 2152 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2153 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2154 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2155 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2156 llvm::LLVMContext &Ctx = F->getContext(); 2157 llvm::MDBuilder MDB(Ctx); 2158 // Annotate the callback behavior of the __kmpc_fork_teams: 2159 // - The callback callee is argument number 2 (microtask). 2160 // - The first two arguments of the callback callee are unknown (-1). 2161 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2162 // callback callee. 2163 F->addMetadata( 2164 llvm::LLVMContext::MD_callback, 2165 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2166 2, {-1, -1}, 2167 /* VarArgsArePassed */ true)})); 2168 } 2169 } 2170 break; 2171 } 2172 case OMPRTL__kmpc_taskloop: { 2173 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2174 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2175 // sched, kmp_uint64 grainsize, void *task_dup); 2176 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2177 CGM.IntTy, 2178 CGM.VoidPtrTy, 2179 CGM.IntTy, 2180 CGM.Int64Ty->getPointerTo(), 2181 CGM.Int64Ty->getPointerTo(), 2182 CGM.Int64Ty, 2183 CGM.IntTy, 2184 CGM.IntTy, 2185 CGM.Int64Ty, 2186 CGM.VoidPtrTy}; 2187 auto *FnTy = 2188 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2189 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2190 break; 2191 } 2192 case OMPRTL__kmpc_doacross_init: { 2193 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2194 // num_dims, struct kmp_dim *dims); 2195 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2196 CGM.Int32Ty, 2197 CGM.Int32Ty, 2198 CGM.VoidPtrTy}; 2199 auto *FnTy = 2200 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2201 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2202 break; 2203 } 2204 case OMPRTL__kmpc_doacross_fini: { 2205 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2206 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2207 auto *FnTy = 2208 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2209 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2210 break; 2211 } 2212 case OMPRTL__kmpc_doacross_post: { 2213 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2214 // *vec); 2215 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2216 CGM.Int64Ty->getPointerTo()}; 2217 auto *FnTy = 2218 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2219 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2220 break; 2221 } 2222 case OMPRTL__kmpc_doacross_wait: { 2223 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2224 // *vec); 2225 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2226 CGM.Int64Ty->getPointerTo()}; 2227 auto *FnTy = 2228 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2229 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2230 break; 2231 } 2232 case OMPRTL__kmpc_task_reduction_init: { 2233 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2234 // *data); 2235 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2236 auto *FnTy = 2237 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2238 RTLFn = 2239 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2240 break; 2241 } 2242 case OMPRTL__kmpc_task_reduction_get_th_data: { 2243 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2244 // *d); 2245 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2246 auto *FnTy = 2247 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2248 RTLFn = CGM.CreateRuntimeFunction( 2249 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2250 break; 2251 } 2252 case OMPRTL__kmpc_alloc: { 2253 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2254 // al); omp_allocator_handle_t type is void *. 2255 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2256 auto *FnTy = 2257 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2258 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2259 break; 2260 } 2261 case OMPRTL__kmpc_free: { 2262 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2263 // al); omp_allocator_handle_t type is void *. 2264 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2265 auto *FnTy = 2266 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2267 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2268 break; 2269 } 2270 case OMPRTL__kmpc_push_target_tripcount: { 2271 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2272 // size); 2273 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2274 llvm::FunctionType *FnTy = 2275 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2276 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2277 break; 2278 } 2279 case OMPRTL__tgt_target: { 2280 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2281 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t 2282 // *arg_types); 2283 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2284 CGM.VoidPtrTy, 2285 CGM.Int32Ty, 2286 CGM.VoidPtrPtrTy, 2287 CGM.VoidPtrPtrTy, 2288 CGM.SizeTy->getPointerTo(), 2289 CGM.Int64Ty->getPointerTo()}; 2290 auto *FnTy = 2291 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2292 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2293 break; 2294 } 2295 case OMPRTL__tgt_target_nowait: { 2296 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2297 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, 2298 // int64_t *arg_types); 2299 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2300 CGM.VoidPtrTy, 2301 CGM.Int32Ty, 2302 CGM.VoidPtrPtrTy, 2303 CGM.VoidPtrPtrTy, 2304 CGM.SizeTy->getPointerTo(), 2305 CGM.Int64Ty->getPointerTo()}; 2306 auto *FnTy = 2307 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2308 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2309 break; 2310 } 2311 case OMPRTL__tgt_target_teams: { 2312 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2313 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, 2314 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2315 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2316 CGM.VoidPtrTy, 2317 CGM.Int32Ty, 2318 CGM.VoidPtrPtrTy, 2319 CGM.VoidPtrPtrTy, 2320 CGM.SizeTy->getPointerTo(), 2321 CGM.Int64Ty->getPointerTo(), 2322 CGM.Int32Ty, 2323 CGM.Int32Ty}; 2324 auto *FnTy = 2325 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2326 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2327 break; 2328 } 2329 case OMPRTL__tgt_target_teams_nowait: { 2330 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2331 // *host_ptr, int32_t arg_num, void** args_base, void **args, size_t 2332 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2333 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2334 CGM.VoidPtrTy, 2335 CGM.Int32Ty, 2336 CGM.VoidPtrPtrTy, 2337 CGM.VoidPtrPtrTy, 2338 CGM.SizeTy->getPointerTo(), 2339 CGM.Int64Ty->getPointerTo(), 2340 CGM.Int32Ty, 2341 CGM.Int32Ty}; 2342 auto *FnTy = 2343 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2344 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2345 break; 2346 } 2347 case OMPRTL__tgt_register_requires: { 2348 // Build void __tgt_register_requires(int64_t flags); 2349 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2350 auto *FnTy = 2351 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2352 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2353 break; 2354 } 2355 case OMPRTL__tgt_register_lib: { 2356 // Build void __tgt_register_lib(__tgt_bin_desc *desc); 2357 QualType ParamTy = 2358 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2359 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2360 auto *FnTy = 2361 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2362 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); 2363 break; 2364 } 2365 case OMPRTL__tgt_unregister_lib: { 2366 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); 2367 QualType ParamTy = 2368 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2369 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2370 auto *FnTy = 2371 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2372 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); 2373 break; 2374 } 2375 case OMPRTL__tgt_target_data_begin: { 2376 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2377 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 2378 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2379 CGM.Int32Ty, 2380 CGM.VoidPtrPtrTy, 2381 CGM.VoidPtrPtrTy, 2382 CGM.SizeTy->getPointerTo(), 2383 CGM.Int64Ty->getPointerTo()}; 2384 auto *FnTy = 2385 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2386 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2387 break; 2388 } 2389 case OMPRTL__tgt_target_data_begin_nowait: { 2390 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2391 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t 2392 // *arg_types); 2393 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2394 CGM.Int32Ty, 2395 CGM.VoidPtrPtrTy, 2396 CGM.VoidPtrPtrTy, 2397 CGM.SizeTy->getPointerTo(), 2398 CGM.Int64Ty->getPointerTo()}; 2399 auto *FnTy = 2400 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2401 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2402 break; 2403 } 2404 case OMPRTL__tgt_target_data_end: { 2405 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2406 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 2407 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2408 CGM.Int32Ty, 2409 CGM.VoidPtrPtrTy, 2410 CGM.VoidPtrPtrTy, 2411 CGM.SizeTy->getPointerTo(), 2412 CGM.Int64Ty->getPointerTo()}; 2413 auto *FnTy = 2414 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2415 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2416 break; 2417 } 2418 case OMPRTL__tgt_target_data_end_nowait: { 2419 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2420 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t 2421 // *arg_types); 2422 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2423 CGM.Int32Ty, 2424 CGM.VoidPtrPtrTy, 2425 CGM.VoidPtrPtrTy, 2426 CGM.SizeTy->getPointerTo(), 2427 CGM.Int64Ty->getPointerTo()}; 2428 auto *FnTy = 2429 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2430 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2431 break; 2432 } 2433 case OMPRTL__tgt_target_data_update: { 2434 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2435 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 2436 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2437 CGM.Int32Ty, 2438 CGM.VoidPtrPtrTy, 2439 CGM.VoidPtrPtrTy, 2440 CGM.SizeTy->getPointerTo(), 2441 CGM.Int64Ty->getPointerTo()}; 2442 auto *FnTy = 2443 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2444 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2445 break; 2446 } 2447 case OMPRTL__tgt_target_data_update_nowait: { 2448 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2449 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t 2450 // *arg_types); 2451 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2452 CGM.Int32Ty, 2453 CGM.VoidPtrPtrTy, 2454 CGM.VoidPtrPtrTy, 2455 CGM.SizeTy->getPointerTo(), 2456 CGM.Int64Ty->getPointerTo()}; 2457 auto *FnTy = 2458 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2459 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2460 break; 2461 } 2462 } 2463 assert(RTLFn && "Unable to find OpenMP runtime function"); 2464 return RTLFn; 2465 } 2466 2467 llvm::FunctionCallee 2468 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2469 assert((IVSize == 32 || IVSize == 64) && 2470 "IV size is not compatible with the omp runtime"); 2471 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2472 : "__kmpc_for_static_init_4u") 2473 : (IVSigned ? "__kmpc_for_static_init_8" 2474 : "__kmpc_for_static_init_8u"); 2475 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2476 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2477 llvm::Type *TypeParams[] = { 2478 getIdentTyPointerTy(), // loc 2479 CGM.Int32Ty, // tid 2480 CGM.Int32Ty, // schedtype 2481 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2482 PtrTy, // p_lower 2483 PtrTy, // p_upper 2484 PtrTy, // p_stride 2485 ITy, // incr 2486 ITy // chunk 2487 }; 2488 auto *FnTy = 2489 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2490 return CGM.CreateRuntimeFunction(FnTy, Name); 2491 } 2492 2493 llvm::FunctionCallee 2494 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2495 assert((IVSize == 32 || IVSize == 64) && 2496 "IV size is not compatible with the omp runtime"); 2497 StringRef Name = 2498 IVSize == 32 2499 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2500 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2501 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2502 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2503 CGM.Int32Ty, // tid 2504 CGM.Int32Ty, // schedtype 2505 ITy, // lower 2506 ITy, // upper 2507 ITy, // stride 2508 ITy // chunk 2509 }; 2510 auto *FnTy = 2511 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2512 return CGM.CreateRuntimeFunction(FnTy, Name); 2513 } 2514 2515 llvm::FunctionCallee 2516 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2517 assert((IVSize == 32 || IVSize == 64) && 2518 "IV size is not compatible with the omp runtime"); 2519 StringRef Name = 2520 IVSize == 32 2521 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2522 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2523 llvm::Type *TypeParams[] = { 2524 getIdentTyPointerTy(), // loc 2525 CGM.Int32Ty, // tid 2526 }; 2527 auto *FnTy = 2528 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2529 return CGM.CreateRuntimeFunction(FnTy, Name); 2530 } 2531 2532 llvm::FunctionCallee 2533 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2534 assert((IVSize == 32 || IVSize == 64) && 2535 "IV size is not compatible with the omp runtime"); 2536 StringRef Name = 2537 IVSize == 32 2538 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2539 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2540 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2541 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2542 llvm::Type *TypeParams[] = { 2543 getIdentTyPointerTy(), // loc 2544 CGM.Int32Ty, // tid 2545 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2546 PtrTy, // p_lower 2547 PtrTy, // p_upper 2548 PtrTy // p_stride 2549 }; 2550 auto *FnTy = 2551 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2552 return CGM.CreateRuntimeFunction(FnTy, Name); 2553 } 2554 2555 Address CGOpenMPRuntime::getAddrOfDeclareTargetLink(const VarDecl *VD) { 2556 if (CGM.getLangOpts().OpenMPSimd) 2557 return Address::invalid(); 2558 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2559 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2560 if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) { 2561 SmallString<64> PtrName; 2562 { 2563 llvm::raw_svector_ostream OS(PtrName); 2564 OS << CGM.getMangledName(GlobalDecl(VD)) << "_decl_tgt_link_ptr"; 2565 } 2566 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2567 if (!Ptr) { 2568 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2569 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2570 PtrName); 2571 if (!CGM.getLangOpts().OpenMPIsDevice) { 2572 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2573 GV->setLinkage(llvm::GlobalValue::ExternalLinkage); 2574 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2575 } 2576 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ptr)); 2577 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2578 } 2579 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2580 } 2581 return Address::invalid(); 2582 } 2583 2584 llvm::Constant * 2585 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2586 assert(!CGM.getLangOpts().OpenMPUseTLS || 2587 !CGM.getContext().getTargetInfo().isTLSSupported()); 2588 // Lookup the entry, lazily creating it if necessary. 2589 std::string Suffix = getName({"cache", ""}); 2590 return getOrCreateInternalVariable( 2591 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2592 } 2593 2594 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2595 const VarDecl *VD, 2596 Address VDAddr, 2597 SourceLocation Loc) { 2598 if (CGM.getLangOpts().OpenMPUseTLS && 2599 CGM.getContext().getTargetInfo().isTLSSupported()) 2600 return VDAddr; 2601 2602 llvm::Type *VarTy = VDAddr.getElementType(); 2603 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2604 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2605 CGM.Int8PtrTy), 2606 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2607 getOrCreateThreadPrivateCache(VD)}; 2608 return Address(CGF.EmitRuntimeCall( 2609 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2610 VDAddr.getAlignment()); 2611 } 2612 2613 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2614 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2615 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2616 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2617 // library. 2618 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2619 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2620 OMPLoc); 2621 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2622 // to register constructor/destructor for variable. 2623 llvm::Value *Args[] = { 2624 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2625 Ctor, CopyCtor, Dtor}; 2626 CGF.EmitRuntimeCall( 2627 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2628 } 2629 2630 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2631 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2632 bool PerformInit, CodeGenFunction *CGF) { 2633 if (CGM.getLangOpts().OpenMPUseTLS && 2634 CGM.getContext().getTargetInfo().isTLSSupported()) 2635 return nullptr; 2636 2637 VD = VD->getDefinition(CGM.getContext()); 2638 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2639 QualType ASTTy = VD->getType(); 2640 2641 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2642 const Expr *Init = VD->getAnyInitializer(); 2643 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2644 // Generate function that re-emits the declaration's initializer into the 2645 // threadprivate copy of the variable VD 2646 CodeGenFunction CtorCGF(CGM); 2647 FunctionArgList Args; 2648 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2649 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2650 ImplicitParamDecl::Other); 2651 Args.push_back(&Dst); 2652 2653 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2654 CGM.getContext().VoidPtrTy, Args); 2655 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2656 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2657 llvm::Function *Fn = 2658 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2659 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2660 Args, Loc, Loc); 2661 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2662 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2663 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2664 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2665 Arg = CtorCGF.Builder.CreateElementBitCast( 2666 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2667 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2668 /*IsInitializer=*/true); 2669 ArgVal = CtorCGF.EmitLoadOfScalar( 2670 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2671 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2672 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2673 CtorCGF.FinishFunction(); 2674 Ctor = Fn; 2675 } 2676 if (VD->getType().isDestructedType() != QualType::DK_none) { 2677 // Generate function that emits destructor call for the threadprivate copy 2678 // of the variable VD 2679 CodeGenFunction DtorCGF(CGM); 2680 FunctionArgList Args; 2681 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2682 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2683 ImplicitParamDecl::Other); 2684 Args.push_back(&Dst); 2685 2686 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2687 CGM.getContext().VoidTy, Args); 2688 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2689 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2690 llvm::Function *Fn = 2691 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2692 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2693 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2694 Loc, Loc); 2695 // Create a scope with an artificial location for the body of this function. 2696 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2697 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2698 DtorCGF.GetAddrOfLocalVar(&Dst), 2699 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2700 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2701 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2702 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2703 DtorCGF.FinishFunction(); 2704 Dtor = Fn; 2705 } 2706 // Do not emit init function if it is not required. 2707 if (!Ctor && !Dtor) 2708 return nullptr; 2709 2710 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2711 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2712 /*isVarArg=*/false) 2713 ->getPointerTo(); 2714 // Copying constructor for the threadprivate variable. 2715 // Must be NULL - reserved by runtime, but currently it requires that this 2716 // parameter is always NULL. Otherwise it fires assertion. 2717 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2718 if (Ctor == nullptr) { 2719 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2720 /*isVarArg=*/false) 2721 ->getPointerTo(); 2722 Ctor = llvm::Constant::getNullValue(CtorTy); 2723 } 2724 if (Dtor == nullptr) { 2725 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2726 /*isVarArg=*/false) 2727 ->getPointerTo(); 2728 Dtor = llvm::Constant::getNullValue(DtorTy); 2729 } 2730 if (!CGF) { 2731 auto *InitFunctionTy = 2732 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2733 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2734 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2735 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2736 CodeGenFunction InitCGF(CGM); 2737 FunctionArgList ArgList; 2738 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2739 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2740 Loc, Loc); 2741 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2742 InitCGF.FinishFunction(); 2743 return InitFunction; 2744 } 2745 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2746 } 2747 return nullptr; 2748 } 2749 2750 /// Obtain information that uniquely identifies a target entry. This 2751 /// consists of the file and device IDs as well as line number associated with 2752 /// the relevant entry source location. 2753 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2754 unsigned &DeviceID, unsigned &FileID, 2755 unsigned &LineNum) { 2756 SourceManager &SM = C.getSourceManager(); 2757 2758 // The loc should be always valid and have a file ID (the user cannot use 2759 // #pragma directives in macros) 2760 2761 assert(Loc.isValid() && "Source location is expected to be always valid."); 2762 2763 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2764 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2765 2766 llvm::sys::fs::UniqueID ID; 2767 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2768 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2769 << PLoc.getFilename() << EC.message(); 2770 2771 DeviceID = ID.getDevice(); 2772 FileID = ID.getFile(); 2773 LineNum = PLoc.getLine(); 2774 } 2775 2776 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2777 llvm::GlobalVariable *Addr, 2778 bool PerformInit) { 2779 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2780 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2781 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link) 2782 return CGM.getLangOpts().OpenMPIsDevice; 2783 VD = VD->getDefinition(CGM.getContext()); 2784 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2785 return CGM.getLangOpts().OpenMPIsDevice; 2786 2787 QualType ASTTy = VD->getType(); 2788 2789 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2790 // Produce the unique prefix to identify the new target regions. We use 2791 // the source location of the variable declaration which we know to not 2792 // conflict with any target region. 2793 unsigned DeviceID; 2794 unsigned FileID; 2795 unsigned Line; 2796 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2797 SmallString<128> Buffer, Out; 2798 { 2799 llvm::raw_svector_ostream OS(Buffer); 2800 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2801 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2802 } 2803 2804 const Expr *Init = VD->getAnyInitializer(); 2805 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2806 llvm::Constant *Ctor; 2807 llvm::Constant *ID; 2808 if (CGM.getLangOpts().OpenMPIsDevice) { 2809 // Generate function that re-emits the declaration's initializer into 2810 // the threadprivate copy of the variable VD 2811 CodeGenFunction CtorCGF(CGM); 2812 2813 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2814 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2815 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2816 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2817 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2818 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2819 FunctionArgList(), Loc, Loc); 2820 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2821 CtorCGF.EmitAnyExprToMem(Init, 2822 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2823 Init->getType().getQualifiers(), 2824 /*IsInitializer=*/true); 2825 CtorCGF.FinishFunction(); 2826 Ctor = Fn; 2827 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2828 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2829 } else { 2830 Ctor = new llvm::GlobalVariable( 2831 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2832 llvm::GlobalValue::PrivateLinkage, 2833 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2834 ID = Ctor; 2835 } 2836 2837 // Register the information for the entry associated with the constructor. 2838 Out.clear(); 2839 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2840 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2841 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2842 } 2843 if (VD->getType().isDestructedType() != QualType::DK_none) { 2844 llvm::Constant *Dtor; 2845 llvm::Constant *ID; 2846 if (CGM.getLangOpts().OpenMPIsDevice) { 2847 // Generate function that emits destructor call for the threadprivate 2848 // copy of the variable VD 2849 CodeGenFunction DtorCGF(CGM); 2850 2851 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2852 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2853 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2854 FTy, Twine(Buffer, "_dtor"), FI, Loc); 2855 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2856 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2857 FunctionArgList(), Loc, Loc); 2858 // Create a scope with an artificial location for the body of this 2859 // function. 2860 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2861 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 2862 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2863 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2864 DtorCGF.FinishFunction(); 2865 Dtor = Fn; 2866 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2867 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 2868 } else { 2869 Dtor = new llvm::GlobalVariable( 2870 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2871 llvm::GlobalValue::PrivateLinkage, 2872 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 2873 ID = Dtor; 2874 } 2875 // Register the information for the entry associated with the destructor. 2876 Out.clear(); 2877 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2878 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 2879 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 2880 } 2881 return CGM.getLangOpts().OpenMPIsDevice; 2882 } 2883 2884 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2885 QualType VarType, 2886 StringRef Name) { 2887 std::string Suffix = getName({"artificial", ""}); 2888 std::string CacheSuffix = getName({"cache", ""}); 2889 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2890 llvm::Value *GAddr = 2891 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 2892 llvm::Value *Args[] = { 2893 emitUpdateLocation(CGF, SourceLocation()), 2894 getThreadID(CGF, SourceLocation()), 2895 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 2896 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 2897 /*IsSigned=*/false), 2898 getOrCreateInternalVariable( 2899 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 2900 return Address( 2901 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2902 CGF.EmitRuntimeCall( 2903 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2904 VarLVType->getPointerTo(/*AddrSpace=*/0)), 2905 CGM.getPointerAlign()); 2906 } 2907 2908 void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, 2909 const RegionCodeGenTy &ThenGen, 2910 const RegionCodeGenTy &ElseGen) { 2911 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 2912 2913 // If the condition constant folds and can be elided, try to avoid emitting 2914 // the condition and the dead arm of the if/else. 2915 bool CondConstant; 2916 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 2917 if (CondConstant) 2918 ThenGen(CGF); 2919 else 2920 ElseGen(CGF); 2921 return; 2922 } 2923 2924 // Otherwise, the condition did not fold, or we couldn't elide it. Just 2925 // emit the conditional branch. 2926 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2927 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 2928 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 2929 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 2930 2931 // Emit the 'then' code. 2932 CGF.EmitBlock(ThenBlock); 2933 ThenGen(CGF); 2934 CGF.EmitBranch(ContBlock); 2935 // Emit the 'else' code if present. 2936 // There is no need to emit line number for unconditional branch. 2937 (void)ApplyDebugLocation::CreateEmpty(CGF); 2938 CGF.EmitBlock(ElseBlock); 2939 ElseGen(CGF); 2940 // There is no need to emit line number for unconditional branch. 2941 (void)ApplyDebugLocation::CreateEmpty(CGF); 2942 CGF.EmitBranch(ContBlock); 2943 // Emit the continuation block for code after the if. 2944 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 2945 } 2946 2947 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 2948 llvm::Function *OutlinedFn, 2949 ArrayRef<llvm::Value *> CapturedVars, 2950 const Expr *IfCond) { 2951 if (!CGF.HaveInsertPoint()) 2952 return; 2953 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 2954 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 2955 PrePostActionTy &) { 2956 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 2957 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2958 llvm::Value *Args[] = { 2959 RTLoc, 2960 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 2961 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 2962 llvm::SmallVector<llvm::Value *, 16> RealArgs; 2963 RealArgs.append(std::begin(Args), std::end(Args)); 2964 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 2965 2966 llvm::FunctionCallee RTLFn = 2967 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 2968 CGF.EmitRuntimeCall(RTLFn, RealArgs); 2969 }; 2970 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 2971 PrePostActionTy &) { 2972 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2973 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 2974 // Build calls: 2975 // __kmpc_serialized_parallel(&Loc, GTid); 2976 llvm::Value *Args[] = {RTLoc, ThreadID}; 2977 CGF.EmitRuntimeCall( 2978 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 2979 2980 // OutlinedFn(>id, &zero, CapturedStruct); 2981 Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 2982 /*Name*/ ".zero.addr"); 2983 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); 2984 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 2985 // ThreadId for serialized parallels is 0. 2986 OutlinedFnArgs.push_back(ZeroAddr.getPointer()); 2987 OutlinedFnArgs.push_back(ZeroAddr.getPointer()); 2988 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 2989 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 2990 2991 // __kmpc_end_serialized_parallel(&Loc, GTid); 2992 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 2993 CGF.EmitRuntimeCall( 2994 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 2995 EndArgs); 2996 }; 2997 if (IfCond) { 2998 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 2999 } else { 3000 RegionCodeGenTy ThenRCG(ThenGen); 3001 ThenRCG(CGF); 3002 } 3003 } 3004 3005 // If we're inside an (outlined) parallel region, use the region info's 3006 // thread-ID variable (it is passed in a first argument of the outlined function 3007 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3008 // regular serial code region, get thread ID by calling kmp_int32 3009 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3010 // return the address of that temp. 3011 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3012 SourceLocation Loc) { 3013 if (auto *OMPRegionInfo = 3014 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3015 if (OMPRegionInfo->getThreadIDVariable()) 3016 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); 3017 3018 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3019 QualType Int32Ty = 3020 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3021 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3022 CGF.EmitStoreOfScalar(ThreadID, 3023 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3024 3025 return ThreadIDTemp; 3026 } 3027 3028 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3029 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3030 SmallString<256> Buffer; 3031 llvm::raw_svector_ostream Out(Buffer); 3032 Out << Name; 3033 StringRef RuntimeName = Out.str(); 3034 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3035 if (Elem.second) { 3036 assert(Elem.second->getType()->getPointerElementType() == Ty && 3037 "OMP internal variable has different type than requested"); 3038 return &*Elem.second; 3039 } 3040 3041 return Elem.second = new llvm::GlobalVariable( 3042 CGM.getModule(), Ty, /*IsConstant*/ false, 3043 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3044 Elem.first(), /*InsertBefore=*/nullptr, 3045 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3046 } 3047 3048 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3049 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3050 std::string Name = getName({Prefix, "var"}); 3051 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3052 } 3053 3054 namespace { 3055 /// Common pre(post)-action for different OpenMP constructs. 3056 class CommonActionTy final : public PrePostActionTy { 3057 llvm::FunctionCallee EnterCallee; 3058 ArrayRef<llvm::Value *> EnterArgs; 3059 llvm::FunctionCallee ExitCallee; 3060 ArrayRef<llvm::Value *> ExitArgs; 3061 bool Conditional; 3062 llvm::BasicBlock *ContBlock = nullptr; 3063 3064 public: 3065 CommonActionTy(llvm::FunctionCallee EnterCallee, 3066 ArrayRef<llvm::Value *> EnterArgs, 3067 llvm::FunctionCallee ExitCallee, 3068 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3069 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3070 ExitArgs(ExitArgs), Conditional(Conditional) {} 3071 void Enter(CodeGenFunction &CGF) override { 3072 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3073 if (Conditional) { 3074 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3075 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3076 ContBlock = CGF.createBasicBlock("omp_if.end"); 3077 // Generate the branch (If-stmt) 3078 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3079 CGF.EmitBlock(ThenBlock); 3080 } 3081 } 3082 void Done(CodeGenFunction &CGF) { 3083 // Emit the rest of blocks/branches 3084 CGF.EmitBranch(ContBlock); 3085 CGF.EmitBlock(ContBlock, true); 3086 } 3087 void Exit(CodeGenFunction &CGF) override { 3088 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3089 } 3090 }; 3091 } // anonymous namespace 3092 3093 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3094 StringRef CriticalName, 3095 const RegionCodeGenTy &CriticalOpGen, 3096 SourceLocation Loc, const Expr *Hint) { 3097 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3098 // CriticalOpGen(); 3099 // __kmpc_end_critical(ident_t *, gtid, Lock); 3100 // Prepare arguments and build a call to __kmpc_critical 3101 if (!CGF.HaveInsertPoint()) 3102 return; 3103 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3104 getCriticalRegionLock(CriticalName)}; 3105 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3106 std::end(Args)); 3107 if (Hint) { 3108 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3109 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3110 } 3111 CommonActionTy Action( 3112 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3113 : OMPRTL__kmpc_critical), 3114 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3115 CriticalOpGen.setAction(Action); 3116 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3117 } 3118 3119 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3120 const RegionCodeGenTy &MasterOpGen, 3121 SourceLocation Loc) { 3122 if (!CGF.HaveInsertPoint()) 3123 return; 3124 // if(__kmpc_master(ident_t *, gtid)) { 3125 // MasterOpGen(); 3126 // __kmpc_end_master(ident_t *, gtid); 3127 // } 3128 // Prepare arguments and build a call to __kmpc_master 3129 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3130 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3131 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3132 /*Conditional=*/true); 3133 MasterOpGen.setAction(Action); 3134 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3135 Action.Done(CGF); 3136 } 3137 3138 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3139 SourceLocation Loc) { 3140 if (!CGF.HaveInsertPoint()) 3141 return; 3142 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3143 llvm::Value *Args[] = { 3144 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3145 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3146 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 3147 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3148 Region->emitUntiedSwitch(CGF); 3149 } 3150 3151 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3152 const RegionCodeGenTy &TaskgroupOpGen, 3153 SourceLocation Loc) { 3154 if (!CGF.HaveInsertPoint()) 3155 return; 3156 // __kmpc_taskgroup(ident_t *, gtid); 3157 // TaskgroupOpGen(); 3158 // __kmpc_end_taskgroup(ident_t *, gtid); 3159 // Prepare arguments and build a call to __kmpc_taskgroup 3160 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3161 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3162 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3163 Args); 3164 TaskgroupOpGen.setAction(Action); 3165 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3166 } 3167 3168 /// Given an array of pointers to variables, project the address of a 3169 /// given variable. 3170 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3171 unsigned Index, const VarDecl *Var) { 3172 // Pull out the pointer to the variable. 3173 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3174 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3175 3176 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3177 Addr = CGF.Builder.CreateElementBitCast( 3178 Addr, CGF.ConvertTypeForMem(Var->getType())); 3179 return Addr; 3180 } 3181 3182 static llvm::Value *emitCopyprivateCopyFunction( 3183 CodeGenModule &CGM, llvm::Type *ArgsType, 3184 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3185 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3186 SourceLocation Loc) { 3187 ASTContext &C = CGM.getContext(); 3188 // void copy_func(void *LHSArg, void *RHSArg); 3189 FunctionArgList Args; 3190 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3191 ImplicitParamDecl::Other); 3192 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3193 ImplicitParamDecl::Other); 3194 Args.push_back(&LHSArg); 3195 Args.push_back(&RHSArg); 3196 const auto &CGFI = 3197 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3198 std::string Name = 3199 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3200 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3201 llvm::GlobalValue::InternalLinkage, Name, 3202 &CGM.getModule()); 3203 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3204 Fn->setDoesNotRecurse(); 3205 CodeGenFunction CGF(CGM); 3206 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3207 // Dest = (void*[n])(LHSArg); 3208 // Src = (void*[n])(RHSArg); 3209 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3210 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3211 ArgsType), CGF.getPointerAlign()); 3212 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3213 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3214 ArgsType), CGF.getPointerAlign()); 3215 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3216 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3217 // ... 3218 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3219 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3220 const auto *DestVar = 3221 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3222 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3223 3224 const auto *SrcVar = 3225 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3226 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3227 3228 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3229 QualType Type = VD->getType(); 3230 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3231 } 3232 CGF.FinishFunction(); 3233 return Fn; 3234 } 3235 3236 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3237 const RegionCodeGenTy &SingleOpGen, 3238 SourceLocation Loc, 3239 ArrayRef<const Expr *> CopyprivateVars, 3240 ArrayRef<const Expr *> SrcExprs, 3241 ArrayRef<const Expr *> DstExprs, 3242 ArrayRef<const Expr *> AssignmentOps) { 3243 if (!CGF.HaveInsertPoint()) 3244 return; 3245 assert(CopyprivateVars.size() == SrcExprs.size() && 3246 CopyprivateVars.size() == DstExprs.size() && 3247 CopyprivateVars.size() == AssignmentOps.size()); 3248 ASTContext &C = CGM.getContext(); 3249 // int32 did_it = 0; 3250 // if(__kmpc_single(ident_t *, gtid)) { 3251 // SingleOpGen(); 3252 // __kmpc_end_single(ident_t *, gtid); 3253 // did_it = 1; 3254 // } 3255 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3256 // <copy_func>, did_it); 3257 3258 Address DidIt = Address::invalid(); 3259 if (!CopyprivateVars.empty()) { 3260 // int32 did_it = 0; 3261 QualType KmpInt32Ty = 3262 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3263 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3264 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3265 } 3266 // Prepare arguments and build a call to __kmpc_single 3267 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3268 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3269 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3270 /*Conditional=*/true); 3271 SingleOpGen.setAction(Action); 3272 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3273 if (DidIt.isValid()) { 3274 // did_it = 1; 3275 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3276 } 3277 Action.Done(CGF); 3278 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3279 // <copy_func>, did_it); 3280 if (DidIt.isValid()) { 3281 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3282 QualType CopyprivateArrayTy = 3283 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 3284 /*IndexTypeQuals=*/0); 3285 // Create a list of all private variables for copyprivate. 3286 Address CopyprivateList = 3287 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3288 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3289 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3290 CGF.Builder.CreateStore( 3291 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3292 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy), 3293 Elem); 3294 } 3295 // Build function that copies private values from single region to all other 3296 // threads in the corresponding parallel region. 3297 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3298 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3299 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3300 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3301 Address CL = 3302 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3303 CGF.VoidPtrTy); 3304 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3305 llvm::Value *Args[] = { 3306 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3307 getThreadID(CGF, Loc), // i32 <gtid> 3308 BufSize, // size_t <buf_size> 3309 CL.getPointer(), // void *<copyprivate list> 3310 CpyFn, // void (*) (void *, void *) <copy_func> 3311 DidItVal // i32 did_it 3312 }; 3313 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3314 } 3315 } 3316 3317 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3318 const RegionCodeGenTy &OrderedOpGen, 3319 SourceLocation Loc, bool IsThreads) { 3320 if (!CGF.HaveInsertPoint()) 3321 return; 3322 // __kmpc_ordered(ident_t *, gtid); 3323 // OrderedOpGen(); 3324 // __kmpc_end_ordered(ident_t *, gtid); 3325 // Prepare arguments and build a call to __kmpc_ordered 3326 if (IsThreads) { 3327 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3328 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3329 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3330 Args); 3331 OrderedOpGen.setAction(Action); 3332 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3333 return; 3334 } 3335 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3336 } 3337 3338 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3339 unsigned Flags; 3340 if (Kind == OMPD_for) 3341 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3342 else if (Kind == OMPD_sections) 3343 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3344 else if (Kind == OMPD_single) 3345 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3346 else if (Kind == OMPD_barrier) 3347 Flags = OMP_IDENT_BARRIER_EXPL; 3348 else 3349 Flags = OMP_IDENT_BARRIER_IMPL; 3350 return Flags; 3351 } 3352 3353 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3354 CodeGenFunction &CGF, const OMPLoopDirective &S, 3355 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3356 // Check if the loop directive is actually a doacross loop directive. In this 3357 // case choose static, 1 schedule. 3358 if (llvm::any_of( 3359 S.getClausesOfKind<OMPOrderedClause>(), 3360 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3361 ScheduleKind = OMPC_SCHEDULE_static; 3362 // Chunk size is 1 in this case. 3363 llvm::APInt ChunkSize(32, 1); 3364 ChunkExpr = IntegerLiteral::Create( 3365 CGF.getContext(), ChunkSize, 3366 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3367 SourceLocation()); 3368 } 3369 } 3370 3371 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3372 OpenMPDirectiveKind Kind, bool EmitChecks, 3373 bool ForceSimpleCall) { 3374 if (!CGF.HaveInsertPoint()) 3375 return; 3376 // Build call __kmpc_cancel_barrier(loc, thread_id); 3377 // Build call __kmpc_barrier(loc, thread_id); 3378 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3379 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3380 // thread_id); 3381 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3382 getThreadID(CGF, Loc)}; 3383 if (auto *OMPRegionInfo = 3384 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 3385 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3386 llvm::Value *Result = CGF.EmitRuntimeCall( 3387 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3388 if (EmitChecks) { 3389 // if (__kmpc_cancel_barrier()) { 3390 // exit from construct; 3391 // } 3392 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3393 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3394 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3395 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3396 CGF.EmitBlock(ExitBB); 3397 // exit from construct; 3398 CodeGenFunction::JumpDest CancelDestination = 3399 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3400 CGF.EmitBranchThroughCleanup(CancelDestination); 3401 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3402 } 3403 return; 3404 } 3405 } 3406 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3407 } 3408 3409 /// Map the OpenMP loop schedule to the runtime enumeration. 3410 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3411 bool Chunked, bool Ordered) { 3412 switch (ScheduleKind) { 3413 case OMPC_SCHEDULE_static: 3414 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3415 : (Ordered ? OMP_ord_static : OMP_sch_static); 3416 case OMPC_SCHEDULE_dynamic: 3417 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3418 case OMPC_SCHEDULE_guided: 3419 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3420 case OMPC_SCHEDULE_runtime: 3421 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3422 case OMPC_SCHEDULE_auto: 3423 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3424 case OMPC_SCHEDULE_unknown: 3425 assert(!Chunked && "chunk was specified but schedule kind not known"); 3426 return Ordered ? OMP_ord_static : OMP_sch_static; 3427 } 3428 llvm_unreachable("Unexpected runtime schedule"); 3429 } 3430 3431 /// Map the OpenMP distribute schedule to the runtime enumeration. 3432 static OpenMPSchedType 3433 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3434 // only static is allowed for dist_schedule 3435 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3436 } 3437 3438 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3439 bool Chunked) const { 3440 OpenMPSchedType Schedule = 3441 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3442 return Schedule == OMP_sch_static; 3443 } 3444 3445 bool CGOpenMPRuntime::isStaticNonchunked( 3446 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3447 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3448 return Schedule == OMP_dist_sch_static; 3449 } 3450 3451 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3452 bool Chunked) const { 3453 OpenMPSchedType Schedule = 3454 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3455 return Schedule == OMP_sch_static_chunked; 3456 } 3457 3458 bool CGOpenMPRuntime::isStaticChunked( 3459 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3460 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3461 return Schedule == OMP_dist_sch_static_chunked; 3462 } 3463 3464 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3465 OpenMPSchedType Schedule = 3466 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3467 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3468 return Schedule != OMP_sch_static; 3469 } 3470 3471 static int addMonoNonMonoModifier(OpenMPSchedType Schedule, 3472 OpenMPScheduleClauseModifier M1, 3473 OpenMPScheduleClauseModifier M2) { 3474 int Modifier = 0; 3475 switch (M1) { 3476 case OMPC_SCHEDULE_MODIFIER_monotonic: 3477 Modifier = OMP_sch_modifier_monotonic; 3478 break; 3479 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3480 Modifier = OMP_sch_modifier_nonmonotonic; 3481 break; 3482 case OMPC_SCHEDULE_MODIFIER_simd: 3483 if (Schedule == OMP_sch_static_chunked) 3484 Schedule = OMP_sch_static_balanced_chunked; 3485 break; 3486 case OMPC_SCHEDULE_MODIFIER_last: 3487 case OMPC_SCHEDULE_MODIFIER_unknown: 3488 break; 3489 } 3490 switch (M2) { 3491 case OMPC_SCHEDULE_MODIFIER_monotonic: 3492 Modifier = OMP_sch_modifier_monotonic; 3493 break; 3494 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3495 Modifier = OMP_sch_modifier_nonmonotonic; 3496 break; 3497 case OMPC_SCHEDULE_MODIFIER_simd: 3498 if (Schedule == OMP_sch_static_chunked) 3499 Schedule = OMP_sch_static_balanced_chunked; 3500 break; 3501 case OMPC_SCHEDULE_MODIFIER_last: 3502 case OMPC_SCHEDULE_MODIFIER_unknown: 3503 break; 3504 } 3505 return Schedule | Modifier; 3506 } 3507 3508 void CGOpenMPRuntime::emitForDispatchInit( 3509 CodeGenFunction &CGF, SourceLocation Loc, 3510 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3511 bool Ordered, const DispatchRTInput &DispatchValues) { 3512 if (!CGF.HaveInsertPoint()) 3513 return; 3514 OpenMPSchedType Schedule = getRuntimeSchedule( 3515 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3516 assert(Ordered || 3517 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3518 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3519 Schedule != OMP_sch_static_balanced_chunked)); 3520 // Call __kmpc_dispatch_init( 3521 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3522 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3523 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3524 3525 // If the Chunk was not specified in the clause - use default value 1. 3526 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3527 : CGF.Builder.getIntN(IVSize, 1); 3528 llvm::Value *Args[] = { 3529 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3530 CGF.Builder.getInt32(addMonoNonMonoModifier( 3531 Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3532 DispatchValues.LB, // Lower 3533 DispatchValues.UB, // Upper 3534 CGF.Builder.getIntN(IVSize, 1), // Stride 3535 Chunk // Chunk 3536 }; 3537 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3538 } 3539 3540 static void emitForStaticInitCall( 3541 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3542 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3543 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3544 const CGOpenMPRuntime::StaticRTInput &Values) { 3545 if (!CGF.HaveInsertPoint()) 3546 return; 3547 3548 assert(!Values.Ordered); 3549 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3550 Schedule == OMP_sch_static_balanced_chunked || 3551 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3552 Schedule == OMP_dist_sch_static || 3553 Schedule == OMP_dist_sch_static_chunked); 3554 3555 // Call __kmpc_for_static_init( 3556 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3557 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3558 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3559 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3560 llvm::Value *Chunk = Values.Chunk; 3561 if (Chunk == nullptr) { 3562 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3563 Schedule == OMP_dist_sch_static) && 3564 "expected static non-chunked schedule"); 3565 // If the Chunk was not specified in the clause - use default value 1. 3566 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3567 } else { 3568 assert((Schedule == OMP_sch_static_chunked || 3569 Schedule == OMP_sch_static_balanced_chunked || 3570 Schedule == OMP_ord_static_chunked || 3571 Schedule == OMP_dist_sch_static_chunked) && 3572 "expected static chunked schedule"); 3573 } 3574 llvm::Value *Args[] = { 3575 UpdateLocation, 3576 ThreadId, 3577 CGF.Builder.getInt32(addMonoNonMonoModifier(Schedule, M1, 3578 M2)), // Schedule type 3579 Values.IL.getPointer(), // &isLastIter 3580 Values.LB.getPointer(), // &LB 3581 Values.UB.getPointer(), // &UB 3582 Values.ST.getPointer(), // &Stride 3583 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3584 Chunk // Chunk 3585 }; 3586 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3587 } 3588 3589 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3590 SourceLocation Loc, 3591 OpenMPDirectiveKind DKind, 3592 const OpenMPScheduleTy &ScheduleKind, 3593 const StaticRTInput &Values) { 3594 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3595 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3596 assert(isOpenMPWorksharingDirective(DKind) && 3597 "Expected loop-based or sections-based directive."); 3598 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3599 isOpenMPLoopDirective(DKind) 3600 ? OMP_IDENT_WORK_LOOP 3601 : OMP_IDENT_WORK_SECTIONS); 3602 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3603 llvm::FunctionCallee StaticInitFunction = 3604 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3605 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3606 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3607 } 3608 3609 void CGOpenMPRuntime::emitDistributeStaticInit( 3610 CodeGenFunction &CGF, SourceLocation Loc, 3611 OpenMPDistScheduleClauseKind SchedKind, 3612 const CGOpenMPRuntime::StaticRTInput &Values) { 3613 OpenMPSchedType ScheduleNum = 3614 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3615 llvm::Value *UpdatedLocation = 3616 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3617 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3618 llvm::FunctionCallee StaticInitFunction = 3619 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3620 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3621 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3622 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3623 } 3624 3625 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3626 SourceLocation Loc, 3627 OpenMPDirectiveKind DKind) { 3628 if (!CGF.HaveInsertPoint()) 3629 return; 3630 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3631 llvm::Value *Args[] = { 3632 emitUpdateLocation(CGF, Loc, 3633 isOpenMPDistributeDirective(DKind) 3634 ? OMP_IDENT_WORK_DISTRIBUTE 3635 : isOpenMPLoopDirective(DKind) 3636 ? OMP_IDENT_WORK_LOOP 3637 : OMP_IDENT_WORK_SECTIONS), 3638 getThreadID(CGF, Loc)}; 3639 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3640 Args); 3641 } 3642 3643 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3644 SourceLocation Loc, 3645 unsigned IVSize, 3646 bool IVSigned) { 3647 if (!CGF.HaveInsertPoint()) 3648 return; 3649 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3650 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3651 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3652 } 3653 3654 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3655 SourceLocation Loc, unsigned IVSize, 3656 bool IVSigned, Address IL, 3657 Address LB, Address UB, 3658 Address ST) { 3659 // Call __kmpc_dispatch_next( 3660 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3661 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3662 // kmp_int[32|64] *p_stride); 3663 llvm::Value *Args[] = { 3664 emitUpdateLocation(CGF, Loc), 3665 getThreadID(CGF, Loc), 3666 IL.getPointer(), // &isLastIter 3667 LB.getPointer(), // &Lower 3668 UB.getPointer(), // &Upper 3669 ST.getPointer() // &Stride 3670 }; 3671 llvm::Value *Call = 3672 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3673 return CGF.EmitScalarConversion( 3674 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3675 CGF.getContext().BoolTy, Loc); 3676 } 3677 3678 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3679 llvm::Value *NumThreads, 3680 SourceLocation Loc) { 3681 if (!CGF.HaveInsertPoint()) 3682 return; 3683 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3684 llvm::Value *Args[] = { 3685 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3686 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3687 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3688 Args); 3689 } 3690 3691 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3692 OpenMPProcBindClauseKind ProcBind, 3693 SourceLocation Loc) { 3694 if (!CGF.HaveInsertPoint()) 3695 return; 3696 // Constants for proc bind value accepted by the runtime. 3697 enum ProcBindTy { 3698 ProcBindFalse = 0, 3699 ProcBindTrue, 3700 ProcBindMaster, 3701 ProcBindClose, 3702 ProcBindSpread, 3703 ProcBindIntel, 3704 ProcBindDefault 3705 } RuntimeProcBind; 3706 switch (ProcBind) { 3707 case OMPC_PROC_BIND_master: 3708 RuntimeProcBind = ProcBindMaster; 3709 break; 3710 case OMPC_PROC_BIND_close: 3711 RuntimeProcBind = ProcBindClose; 3712 break; 3713 case OMPC_PROC_BIND_spread: 3714 RuntimeProcBind = ProcBindSpread; 3715 break; 3716 case OMPC_PROC_BIND_unknown: 3717 llvm_unreachable("Unsupported proc_bind value."); 3718 } 3719 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3720 llvm::Value *Args[] = { 3721 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3722 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; 3723 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3724 } 3725 3726 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3727 SourceLocation Loc) { 3728 if (!CGF.HaveInsertPoint()) 3729 return; 3730 // Build call void __kmpc_flush(ident_t *loc) 3731 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3732 emitUpdateLocation(CGF, Loc)); 3733 } 3734 3735 namespace { 3736 /// Indexes of fields for type kmp_task_t. 3737 enum KmpTaskTFields { 3738 /// List of shared variables. 3739 KmpTaskTShareds, 3740 /// Task routine. 3741 KmpTaskTRoutine, 3742 /// Partition id for the untied tasks. 3743 KmpTaskTPartId, 3744 /// Function with call of destructors for private variables. 3745 Data1, 3746 /// Task priority. 3747 Data2, 3748 /// (Taskloops only) Lower bound. 3749 KmpTaskTLowerBound, 3750 /// (Taskloops only) Upper bound. 3751 KmpTaskTUpperBound, 3752 /// (Taskloops only) Stride. 3753 KmpTaskTStride, 3754 /// (Taskloops only) Is last iteration flag. 3755 KmpTaskTLastIter, 3756 /// (Taskloops only) Reduction data. 3757 KmpTaskTReductions, 3758 }; 3759 } // anonymous namespace 3760 3761 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3762 return OffloadEntriesTargetRegion.empty() && 3763 OffloadEntriesDeviceGlobalVar.empty(); 3764 } 3765 3766 /// Initialize target region entry. 3767 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3768 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3769 StringRef ParentName, unsigned LineNum, 3770 unsigned Order) { 3771 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3772 "only required for the device " 3773 "code generation."); 3774 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3775 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3776 OMPTargetRegionEntryTargetRegion); 3777 ++OffloadingEntriesNum; 3778 } 3779 3780 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3781 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3782 StringRef ParentName, unsigned LineNum, 3783 llvm::Constant *Addr, llvm::Constant *ID, 3784 OMPTargetRegionEntryKind Flags) { 3785 // If we are emitting code for a target, the entry is already initialized, 3786 // only has to be registered. 3787 if (CGM.getLangOpts().OpenMPIsDevice) { 3788 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3789 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3790 DiagnosticsEngine::Error, 3791 "Unable to find target region on line '%0' in the device code."); 3792 CGM.getDiags().Report(DiagID) << LineNum; 3793 return; 3794 } 3795 auto &Entry = 3796 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3797 assert(Entry.isValid() && "Entry not initialized!"); 3798 Entry.setAddress(Addr); 3799 Entry.setID(ID); 3800 Entry.setFlags(Flags); 3801 } else { 3802 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3803 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3804 ++OffloadingEntriesNum; 3805 } 3806 } 3807 3808 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3809 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3810 unsigned LineNum) const { 3811 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3812 if (PerDevice == OffloadEntriesTargetRegion.end()) 3813 return false; 3814 auto PerFile = PerDevice->second.find(FileID); 3815 if (PerFile == PerDevice->second.end()) 3816 return false; 3817 auto PerParentName = PerFile->second.find(ParentName); 3818 if (PerParentName == PerFile->second.end()) 3819 return false; 3820 auto PerLine = PerParentName->second.find(LineNum); 3821 if (PerLine == PerParentName->second.end()) 3822 return false; 3823 // Fail if this entry is already registered. 3824 if (PerLine->second.getAddress() || PerLine->second.getID()) 3825 return false; 3826 return true; 3827 } 3828 3829 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3830 const OffloadTargetRegionEntryInfoActTy &Action) { 3831 // Scan all target region entries and perform the provided action. 3832 for (const auto &D : OffloadEntriesTargetRegion) 3833 for (const auto &F : D.second) 3834 for (const auto &P : F.second) 3835 for (const auto &L : P.second) 3836 Action(D.first, F.first, P.first(), L.first, L.second); 3837 } 3838 3839 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3840 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3841 OMPTargetGlobalVarEntryKind Flags, 3842 unsigned Order) { 3843 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3844 "only required for the device " 3845 "code generation."); 3846 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3847 ++OffloadingEntriesNum; 3848 } 3849 3850 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3851 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3852 CharUnits VarSize, 3853 OMPTargetGlobalVarEntryKind Flags, 3854 llvm::GlobalValue::LinkageTypes Linkage) { 3855 if (CGM.getLangOpts().OpenMPIsDevice) { 3856 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3857 assert(Entry.isValid() && Entry.getFlags() == Flags && 3858 "Entry not initialized!"); 3859 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3860 "Resetting with the new address."); 3861 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3862 if (Entry.getVarSize().isZero()) { 3863 Entry.setVarSize(VarSize); 3864 Entry.setLinkage(Linkage); 3865 } 3866 return; 3867 } 3868 Entry.setVarSize(VarSize); 3869 Entry.setLinkage(Linkage); 3870 Entry.setAddress(Addr); 3871 } else { 3872 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3873 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3874 assert(Entry.isValid() && Entry.getFlags() == Flags && 3875 "Entry not initialized!"); 3876 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3877 "Resetting with the new address."); 3878 if (Entry.getVarSize().isZero()) { 3879 Entry.setVarSize(VarSize); 3880 Entry.setLinkage(Linkage); 3881 } 3882 return; 3883 } 3884 OffloadEntriesDeviceGlobalVar.try_emplace( 3885 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 3886 ++OffloadingEntriesNum; 3887 } 3888 } 3889 3890 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3891 actOnDeviceGlobalVarEntriesInfo( 3892 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 3893 // Scan all target region entries and perform the provided action. 3894 for (const auto &E : OffloadEntriesDeviceGlobalVar) 3895 Action(E.getKey(), E.getValue()); 3896 } 3897 3898 llvm::Function * 3899 CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() { 3900 // If we don't have entries or if we are emitting code for the device, we 3901 // don't need to do anything. 3902 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty()) 3903 return nullptr; 3904 3905 llvm::Module &M = CGM.getModule(); 3906 ASTContext &C = CGM.getContext(); 3907 3908 // Get list of devices we care about 3909 const std::vector<llvm::Triple> &Devices = CGM.getLangOpts().OMPTargetTriples; 3910 3911 // We should be creating an offloading descriptor only if there are devices 3912 // specified. 3913 assert(!Devices.empty() && "No OpenMP offloading devices??"); 3914 3915 // Create the external variables that will point to the begin and end of the 3916 // host entries section. These will be defined by the linker. 3917 llvm::Type *OffloadEntryTy = 3918 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()); 3919 std::string EntriesBeginName = getName({"omp_offloading", "entries_begin"}); 3920 auto *HostEntriesBegin = new llvm::GlobalVariable( 3921 M, OffloadEntryTy, /*isConstant=*/true, 3922 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr, 3923 EntriesBeginName); 3924 std::string EntriesEndName = getName({"omp_offloading", "entries_end"}); 3925 auto *HostEntriesEnd = 3926 new llvm::GlobalVariable(M, OffloadEntryTy, /*isConstant=*/true, 3927 llvm::GlobalValue::ExternalLinkage, 3928 /*Initializer=*/nullptr, EntriesEndName); 3929 3930 // Create all device images 3931 auto *DeviceImageTy = cast<llvm::StructType>( 3932 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy())); 3933 ConstantInitBuilder DeviceImagesBuilder(CGM); 3934 ConstantArrayBuilder DeviceImagesEntries = 3935 DeviceImagesBuilder.beginArray(DeviceImageTy); 3936 3937 for (const llvm::Triple &Device : Devices) { 3938 StringRef T = Device.getTriple(); 3939 std::string BeginName = getName({"omp_offloading", "img_start", ""}); 3940 auto *ImgBegin = new llvm::GlobalVariable( 3941 M, CGM.Int8Ty, /*isConstant=*/true, 3942 llvm::GlobalValue::ExternalWeakLinkage, 3943 /*Initializer=*/nullptr, Twine(BeginName).concat(T)); 3944 std::string EndName = getName({"omp_offloading", "img_end", ""}); 3945 auto *ImgEnd = new llvm::GlobalVariable( 3946 M, CGM.Int8Ty, /*isConstant=*/true, 3947 llvm::GlobalValue::ExternalWeakLinkage, 3948 /*Initializer=*/nullptr, Twine(EndName).concat(T)); 3949 3950 llvm::Constant *Data[] = {ImgBegin, ImgEnd, HostEntriesBegin, 3951 HostEntriesEnd}; 3952 createConstantGlobalStructAndAddToParent(CGM, getTgtDeviceImageQTy(), Data, 3953 DeviceImagesEntries); 3954 } 3955 3956 // Create device images global array. 3957 std::string ImagesName = getName({"omp_offloading", "device_images"}); 3958 llvm::GlobalVariable *DeviceImages = 3959 DeviceImagesEntries.finishAndCreateGlobal(ImagesName, 3960 CGM.getPointerAlign(), 3961 /*isConstant=*/true); 3962 DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 3963 3964 // This is a Zero array to be used in the creation of the constant expressions 3965 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty), 3966 llvm::Constant::getNullValue(CGM.Int32Ty)}; 3967 3968 // Create the target region descriptor. 3969 llvm::Constant *Data[] = { 3970 llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()), 3971 llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(), 3972 DeviceImages, Index), 3973 HostEntriesBegin, HostEntriesEnd}; 3974 std::string Descriptor = getName({"omp_offloading", "descriptor"}); 3975 llvm::GlobalVariable *Desc = createGlobalStruct( 3976 CGM, getTgtBinaryDescriptorQTy(), /*IsConstant=*/true, Data, Descriptor); 3977 3978 // Emit code to register or unregister the descriptor at execution 3979 // startup or closing, respectively. 3980 3981 llvm::Function *UnRegFn; 3982 { 3983 FunctionArgList Args; 3984 ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other); 3985 Args.push_back(&DummyPtr); 3986 3987 CodeGenFunction CGF(CGM); 3988 // Disable debug info for global (de-)initializer because they are not part 3989 // of some particular construct. 3990 CGF.disableDebugInfo(); 3991 const auto &FI = 3992 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3993 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 3994 std::string UnregName = getName({"omp_offloading", "descriptor_unreg"}); 3995 UnRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, UnregName, FI); 3996 CGF.StartFunction(GlobalDecl(), C.VoidTy, UnRegFn, FI, Args); 3997 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib), 3998 Desc); 3999 CGF.FinishFunction(); 4000 } 4001 llvm::Function *RegFn; 4002 { 4003 CodeGenFunction CGF(CGM); 4004 // Disable debug info for global (de-)initializer because they are not part 4005 // of some particular construct. 4006 CGF.disableDebugInfo(); 4007 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 4008 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 4009 4010 // Encode offload target triples into the registration function name. It 4011 // will serve as a comdat key for the registration/unregistration code for 4012 // this particular combination of offloading targets. 4013 SmallVector<StringRef, 4U> RegFnNameParts(Devices.size() + 2U); 4014 RegFnNameParts[0] = "omp_offloading"; 4015 RegFnNameParts[1] = "descriptor_reg"; 4016 llvm::transform(Devices, std::next(RegFnNameParts.begin(), 2), 4017 [](const llvm::Triple &T) -> const std::string& { 4018 return T.getTriple(); 4019 }); 4020 llvm::sort(std::next(RegFnNameParts.begin(), 2), RegFnNameParts.end()); 4021 std::string Descriptor = getName(RegFnNameParts); 4022 RegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, Descriptor, FI); 4023 CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList()); 4024 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc); 4025 // Create a variable to drive the registration and unregistration of the 4026 // descriptor, so we can reuse the logic that emits Ctors and Dtors. 4027 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), 4028 SourceLocation(), nullptr, C.CharTy, 4029 ImplicitParamDecl::Other); 4030 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc); 4031 CGF.FinishFunction(); 4032 } 4033 if (CGM.supportsCOMDAT()) { 4034 // It is sufficient to call registration function only once, so create a 4035 // COMDAT group for registration/unregistration functions and associated 4036 // data. That would reduce startup time and code size. Registration 4037 // function serves as a COMDAT group key. 4038 llvm::Comdat *ComdatKey = M.getOrInsertComdat(RegFn->getName()); 4039 RegFn->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage); 4040 RegFn->setVisibility(llvm::GlobalValue::HiddenVisibility); 4041 RegFn->setComdat(ComdatKey); 4042 UnRegFn->setComdat(ComdatKey); 4043 DeviceImages->setComdat(ComdatKey); 4044 Desc->setComdat(ComdatKey); 4045 } 4046 return RegFn; 4047 } 4048 4049 void CGOpenMPRuntime::createOffloadEntry( 4050 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4051 llvm::GlobalValue::LinkageTypes Linkage) { 4052 StringRef Name = Addr->getName(); 4053 llvm::Module &M = CGM.getModule(); 4054 llvm::LLVMContext &C = M.getContext(); 4055 4056 // Create constant string with the name. 4057 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4058 4059 std::string StringName = getName({"omp_offloading", "entry_name"}); 4060 auto *Str = new llvm::GlobalVariable( 4061 M, StrPtrInit->getType(), /*isConstant=*/true, 4062 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4063 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4064 4065 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4066 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4067 llvm::ConstantInt::get(CGM.SizeTy, Size), 4068 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4069 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4070 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4071 llvm::GlobalVariable *Entry = createGlobalStruct( 4072 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4073 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4074 4075 // The entry has to be created in the section the linker expects it to be. 4076 std::string Section = getName({"omp_offloading", "entries"}); 4077 Entry->setSection(Section); 4078 } 4079 4080 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4081 // Emit the offloading entries and metadata so that the device codegen side 4082 // can easily figure out what to emit. The produced metadata looks like 4083 // this: 4084 // 4085 // !omp_offload.info = !{!1, ...} 4086 // 4087 // Right now we only generate metadata for function that contain target 4088 // regions. 4089 4090 // If we do not have entries, we don't need to do anything. 4091 if (OffloadEntriesInfoManager.empty()) 4092 return; 4093 4094 llvm::Module &M = CGM.getModule(); 4095 llvm::LLVMContext &C = M.getContext(); 4096 SmallVector<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16> 4097 OrderedEntries(OffloadEntriesInfoManager.size()); 4098 llvm::SmallVector<StringRef, 16> ParentFunctions( 4099 OffloadEntriesInfoManager.size()); 4100 4101 // Auxiliary methods to create metadata values and strings. 4102 auto &&GetMDInt = [this](unsigned V) { 4103 return llvm::ConstantAsMetadata::get( 4104 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4105 }; 4106 4107 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4108 4109 // Create the offloading info metadata node. 4110 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4111 4112 // Create function that emits metadata for each target region entry; 4113 auto &&TargetRegionMetadataEmitter = 4114 [&C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, &GetMDString]( 4115 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4116 unsigned Line, 4117 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4118 // Generate metadata for target regions. Each entry of this metadata 4119 // contains: 4120 // - Entry 0 -> Kind of this type of metadata (0). 4121 // - Entry 1 -> Device ID of the file where the entry was identified. 4122 // - Entry 2 -> File ID of the file where the entry was identified. 4123 // - Entry 3 -> Mangled name of the function where the entry was 4124 // identified. 4125 // - Entry 4 -> Line in the file where the entry was identified. 4126 // - Entry 5 -> Order the entry was created. 4127 // The first element of the metadata node is the kind. 4128 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4129 GetMDInt(FileID), GetMDString(ParentName), 4130 GetMDInt(Line), GetMDInt(E.getOrder())}; 4131 4132 // Save this entry in the right position of the ordered entries array. 4133 OrderedEntries[E.getOrder()] = &E; 4134 ParentFunctions[E.getOrder()] = ParentName; 4135 4136 // Add metadata to the named metadata node. 4137 MD->addOperand(llvm::MDNode::get(C, Ops)); 4138 }; 4139 4140 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4141 TargetRegionMetadataEmitter); 4142 4143 // Create function that emits metadata for each device global variable entry; 4144 auto &&DeviceGlobalVarMetadataEmitter = 4145 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4146 MD](StringRef MangledName, 4147 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4148 &E) { 4149 // Generate metadata for global variables. Each entry of this metadata 4150 // contains: 4151 // - Entry 0 -> Kind of this type of metadata (1). 4152 // - Entry 1 -> Mangled name of the variable. 4153 // - Entry 2 -> Declare target kind. 4154 // - Entry 3 -> Order the entry was created. 4155 // The first element of the metadata node is the kind. 4156 llvm::Metadata *Ops[] = { 4157 GetMDInt(E.getKind()), GetMDString(MangledName), 4158 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4159 4160 // Save this entry in the right position of the ordered entries array. 4161 OrderedEntries[E.getOrder()] = &E; 4162 4163 // Add metadata to the named metadata node. 4164 MD->addOperand(llvm::MDNode::get(C, Ops)); 4165 }; 4166 4167 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4168 DeviceGlobalVarMetadataEmitter); 4169 4170 for (const auto *E : OrderedEntries) { 4171 assert(E && "All ordered entries must exist!"); 4172 if (const auto *CE = 4173 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4174 E)) { 4175 if (!CE->getID() || !CE->getAddress()) { 4176 // Do not blame the entry if the parent funtion is not emitted. 4177 StringRef FnName = ParentFunctions[CE->getOrder()]; 4178 if (!CGM.GetGlobalValue(FnName)) 4179 continue; 4180 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4181 DiagnosticsEngine::Error, 4182 "Offloading entry for target region is incorrect: either the " 4183 "address or the ID is invalid."); 4184 CGM.getDiags().Report(DiagID); 4185 continue; 4186 } 4187 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4188 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4189 } else if (const auto *CE = 4190 dyn_cast<OffloadEntriesInfoManagerTy:: 4191 OffloadEntryInfoDeviceGlobalVar>(E)) { 4192 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4193 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4194 CE->getFlags()); 4195 switch (Flags) { 4196 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4197 if (!CE->getAddress()) { 4198 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4199 DiagnosticsEngine::Error, 4200 "Offloading entry for declare target variable is incorrect: the " 4201 "address is invalid."); 4202 CGM.getDiags().Report(DiagID); 4203 continue; 4204 } 4205 // The vaiable has no definition - no need to add the entry. 4206 if (CE->getVarSize().isZero()) 4207 continue; 4208 break; 4209 } 4210 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4211 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4212 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4213 "Declaret target link address is set."); 4214 if (CGM.getLangOpts().OpenMPIsDevice) 4215 continue; 4216 if (!CE->getAddress()) { 4217 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4218 DiagnosticsEngine::Error, 4219 "Offloading entry for declare target variable is incorrect: the " 4220 "address is invalid."); 4221 CGM.getDiags().Report(DiagID); 4222 continue; 4223 } 4224 break; 4225 } 4226 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4227 CE->getVarSize().getQuantity(), Flags, 4228 CE->getLinkage()); 4229 } else { 4230 llvm_unreachable("Unsupported entry kind."); 4231 } 4232 } 4233 } 4234 4235 /// Loads all the offload entries information from the host IR 4236 /// metadata. 4237 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4238 // If we are in target mode, load the metadata from the host IR. This code has 4239 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4240 4241 if (!CGM.getLangOpts().OpenMPIsDevice) 4242 return; 4243 4244 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4245 return; 4246 4247 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4248 if (auto EC = Buf.getError()) { 4249 CGM.getDiags().Report(diag::err_cannot_open_file) 4250 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4251 return; 4252 } 4253 4254 llvm::LLVMContext C; 4255 auto ME = expectedToErrorOrAndEmitErrors( 4256 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4257 4258 if (auto EC = ME.getError()) { 4259 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4260 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4261 CGM.getDiags().Report(DiagID) 4262 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4263 return; 4264 } 4265 4266 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4267 if (!MD) 4268 return; 4269 4270 for (llvm::MDNode *MN : MD->operands()) { 4271 auto &&GetMDInt = [MN](unsigned Idx) { 4272 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4273 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4274 }; 4275 4276 auto &&GetMDString = [MN](unsigned Idx) { 4277 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4278 return V->getString(); 4279 }; 4280 4281 switch (GetMDInt(0)) { 4282 default: 4283 llvm_unreachable("Unexpected metadata!"); 4284 break; 4285 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4286 OffloadingEntryInfoTargetRegion: 4287 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4288 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4289 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4290 /*Order=*/GetMDInt(5)); 4291 break; 4292 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4293 OffloadingEntryInfoDeviceGlobalVar: 4294 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4295 /*MangledName=*/GetMDString(1), 4296 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4297 /*Flags=*/GetMDInt(2)), 4298 /*Order=*/GetMDInt(3)); 4299 break; 4300 } 4301 } 4302 } 4303 4304 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4305 if (!KmpRoutineEntryPtrTy) { 4306 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4307 ASTContext &C = CGM.getContext(); 4308 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4309 FunctionProtoType::ExtProtoInfo EPI; 4310 KmpRoutineEntryPtrQTy = C.getPointerType( 4311 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4312 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4313 } 4314 } 4315 4316 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4317 // Make sure the type of the entry is already created. This is the type we 4318 // have to create: 4319 // struct __tgt_offload_entry{ 4320 // void *addr; // Pointer to the offload entry info. 4321 // // (function or global) 4322 // char *name; // Name of the function or global. 4323 // size_t size; // Size of the entry info (0 if it a function). 4324 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4325 // int32_t reserved; // Reserved, to use by the runtime library. 4326 // }; 4327 if (TgtOffloadEntryQTy.isNull()) { 4328 ASTContext &C = CGM.getContext(); 4329 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4330 RD->startDefinition(); 4331 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4332 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4333 addFieldToRecordDecl(C, RD, C.getSizeType()); 4334 addFieldToRecordDecl( 4335 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4336 addFieldToRecordDecl( 4337 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4338 RD->completeDefinition(); 4339 RD->addAttr(PackedAttr::CreateImplicit(C)); 4340 TgtOffloadEntryQTy = C.getRecordType(RD); 4341 } 4342 return TgtOffloadEntryQTy; 4343 } 4344 4345 QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { 4346 // These are the types we need to build: 4347 // struct __tgt_device_image{ 4348 // void *ImageStart; // Pointer to the target code start. 4349 // void *ImageEnd; // Pointer to the target code end. 4350 // // We also add the host entries to the device image, as it may be useful 4351 // // for the target runtime to have access to that information. 4352 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all 4353 // // the entries. 4354 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4355 // // entries (non inclusive). 4356 // }; 4357 if (TgtDeviceImageQTy.isNull()) { 4358 ASTContext &C = CGM.getContext(); 4359 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image"); 4360 RD->startDefinition(); 4361 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4362 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4363 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4364 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4365 RD->completeDefinition(); 4366 TgtDeviceImageQTy = C.getRecordType(RD); 4367 } 4368 return TgtDeviceImageQTy; 4369 } 4370 4371 QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { 4372 // struct __tgt_bin_desc{ 4373 // int32_t NumDevices; // Number of devices supported. 4374 // __tgt_device_image *DeviceImages; // Arrays of device images 4375 // // (one per device). 4376 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the 4377 // // entries. 4378 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4379 // // entries (non inclusive). 4380 // }; 4381 if (TgtBinaryDescriptorQTy.isNull()) { 4382 ASTContext &C = CGM.getContext(); 4383 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc"); 4384 RD->startDefinition(); 4385 addFieldToRecordDecl( 4386 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4387 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); 4388 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4389 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4390 RD->completeDefinition(); 4391 TgtBinaryDescriptorQTy = C.getRecordType(RD); 4392 } 4393 return TgtBinaryDescriptorQTy; 4394 } 4395 4396 namespace { 4397 struct PrivateHelpersTy { 4398 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4399 const VarDecl *PrivateElemInit) 4400 : Original(Original), PrivateCopy(PrivateCopy), 4401 PrivateElemInit(PrivateElemInit) {} 4402 const VarDecl *Original; 4403 const VarDecl *PrivateCopy; 4404 const VarDecl *PrivateElemInit; 4405 }; 4406 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4407 } // anonymous namespace 4408 4409 static RecordDecl * 4410 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4411 if (!Privates.empty()) { 4412 ASTContext &C = CGM.getContext(); 4413 // Build struct .kmp_privates_t. { 4414 // /* private vars */ 4415 // }; 4416 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4417 RD->startDefinition(); 4418 for (const auto &Pair : Privates) { 4419 const VarDecl *VD = Pair.second.Original; 4420 QualType Type = VD->getType().getNonReferenceType(); 4421 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4422 if (VD->hasAttrs()) { 4423 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4424 E(VD->getAttrs().end()); 4425 I != E; ++I) 4426 FD->addAttr(*I); 4427 } 4428 } 4429 RD->completeDefinition(); 4430 return RD; 4431 } 4432 return nullptr; 4433 } 4434 4435 static RecordDecl * 4436 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4437 QualType KmpInt32Ty, 4438 QualType KmpRoutineEntryPointerQTy) { 4439 ASTContext &C = CGM.getContext(); 4440 // Build struct kmp_task_t { 4441 // void * shareds; 4442 // kmp_routine_entry_t routine; 4443 // kmp_int32 part_id; 4444 // kmp_cmplrdata_t data1; 4445 // kmp_cmplrdata_t data2; 4446 // For taskloops additional fields: 4447 // kmp_uint64 lb; 4448 // kmp_uint64 ub; 4449 // kmp_int64 st; 4450 // kmp_int32 liter; 4451 // void * reductions; 4452 // }; 4453 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4454 UD->startDefinition(); 4455 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4456 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4457 UD->completeDefinition(); 4458 QualType KmpCmplrdataTy = C.getRecordType(UD); 4459 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4460 RD->startDefinition(); 4461 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4462 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4463 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4464 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4465 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4466 if (isOpenMPTaskLoopDirective(Kind)) { 4467 QualType KmpUInt64Ty = 4468 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4469 QualType KmpInt64Ty = 4470 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4471 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4472 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4473 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4474 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4475 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4476 } 4477 RD->completeDefinition(); 4478 return RD; 4479 } 4480 4481 static RecordDecl * 4482 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4483 ArrayRef<PrivateDataTy> Privates) { 4484 ASTContext &C = CGM.getContext(); 4485 // Build struct kmp_task_t_with_privates { 4486 // kmp_task_t task_data; 4487 // .kmp_privates_t. privates; 4488 // }; 4489 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4490 RD->startDefinition(); 4491 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4492 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4493 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4494 RD->completeDefinition(); 4495 return RD; 4496 } 4497 4498 /// Emit a proxy function which accepts kmp_task_t as the second 4499 /// argument. 4500 /// \code 4501 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4502 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4503 /// For taskloops: 4504 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4505 /// tt->reductions, tt->shareds); 4506 /// return 0; 4507 /// } 4508 /// \endcode 4509 static llvm::Function * 4510 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4511 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4512 QualType KmpTaskTWithPrivatesPtrQTy, 4513 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4514 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4515 llvm::Value *TaskPrivatesMap) { 4516 ASTContext &C = CGM.getContext(); 4517 FunctionArgList Args; 4518 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4519 ImplicitParamDecl::Other); 4520 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4521 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4522 ImplicitParamDecl::Other); 4523 Args.push_back(&GtidArg); 4524 Args.push_back(&TaskTypeArg); 4525 const auto &TaskEntryFnInfo = 4526 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4527 llvm::FunctionType *TaskEntryTy = 4528 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4529 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4530 auto *TaskEntry = llvm::Function::Create( 4531 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4532 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4533 TaskEntry->setDoesNotRecurse(); 4534 CodeGenFunction CGF(CGM); 4535 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4536 Loc, Loc); 4537 4538 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4539 // tt, 4540 // For taskloops: 4541 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4542 // tt->task_data.shareds); 4543 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4544 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4545 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4546 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4547 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4548 const auto *KmpTaskTWithPrivatesQTyRD = 4549 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4550 LValue Base = 4551 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4552 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4553 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4554 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4555 llvm::Value *PartidParam = PartIdLVal.getPointer(); 4556 4557 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4558 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4559 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4560 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4561 CGF.ConvertTypeForMem(SharedsPtrTy)); 4562 4563 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4564 llvm::Value *PrivatesParam; 4565 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4566 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4567 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4568 PrivatesLVal.getPointer(), CGF.VoidPtrTy); 4569 } else { 4570 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4571 } 4572 4573 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4574 TaskPrivatesMap, 4575 CGF.Builder 4576 .CreatePointerBitCastOrAddrSpaceCast( 4577 TDBase.getAddress(), CGF.VoidPtrTy) 4578 .getPointer()}; 4579 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4580 std::end(CommonArgs)); 4581 if (isOpenMPTaskLoopDirective(Kind)) { 4582 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4583 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4584 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4585 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4586 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4587 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4588 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4589 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4590 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4591 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4592 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4593 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4594 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4595 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4596 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4597 CallArgs.push_back(LBParam); 4598 CallArgs.push_back(UBParam); 4599 CallArgs.push_back(StParam); 4600 CallArgs.push_back(LIParam); 4601 CallArgs.push_back(RParam); 4602 } 4603 CallArgs.push_back(SharedsParam); 4604 4605 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4606 CallArgs); 4607 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4608 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4609 CGF.FinishFunction(); 4610 return TaskEntry; 4611 } 4612 4613 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4614 SourceLocation Loc, 4615 QualType KmpInt32Ty, 4616 QualType KmpTaskTWithPrivatesPtrQTy, 4617 QualType KmpTaskTWithPrivatesQTy) { 4618 ASTContext &C = CGM.getContext(); 4619 FunctionArgList Args; 4620 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4621 ImplicitParamDecl::Other); 4622 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4623 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4624 ImplicitParamDecl::Other); 4625 Args.push_back(&GtidArg); 4626 Args.push_back(&TaskTypeArg); 4627 const auto &DestructorFnInfo = 4628 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4629 llvm::FunctionType *DestructorFnTy = 4630 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4631 std::string Name = 4632 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4633 auto *DestructorFn = 4634 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4635 Name, &CGM.getModule()); 4636 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4637 DestructorFnInfo); 4638 DestructorFn->setDoesNotRecurse(); 4639 CodeGenFunction CGF(CGM); 4640 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4641 Args, Loc, Loc); 4642 4643 LValue Base = CGF.EmitLoadOfPointerLValue( 4644 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4645 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4646 const auto *KmpTaskTWithPrivatesQTyRD = 4647 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4648 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4649 Base = CGF.EmitLValueForField(Base, *FI); 4650 for (const auto *Field : 4651 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4652 if (QualType::DestructionKind DtorKind = 4653 Field->getType().isDestructedType()) { 4654 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4655 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType()); 4656 } 4657 } 4658 CGF.FinishFunction(); 4659 return DestructorFn; 4660 } 4661 4662 /// Emit a privates mapping function for correct handling of private and 4663 /// firstprivate variables. 4664 /// \code 4665 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4666 /// **noalias priv1,..., <tyn> **noalias privn) { 4667 /// *priv1 = &.privates.priv1; 4668 /// ...; 4669 /// *privn = &.privates.privn; 4670 /// } 4671 /// \endcode 4672 static llvm::Value * 4673 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4674 ArrayRef<const Expr *> PrivateVars, 4675 ArrayRef<const Expr *> FirstprivateVars, 4676 ArrayRef<const Expr *> LastprivateVars, 4677 QualType PrivatesQTy, 4678 ArrayRef<PrivateDataTy> Privates) { 4679 ASTContext &C = CGM.getContext(); 4680 FunctionArgList Args; 4681 ImplicitParamDecl TaskPrivatesArg( 4682 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4683 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4684 ImplicitParamDecl::Other); 4685 Args.push_back(&TaskPrivatesArg); 4686 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4687 unsigned Counter = 1; 4688 for (const Expr *E : PrivateVars) { 4689 Args.push_back(ImplicitParamDecl::Create( 4690 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4691 C.getPointerType(C.getPointerType(E->getType())) 4692 .withConst() 4693 .withRestrict(), 4694 ImplicitParamDecl::Other)); 4695 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4696 PrivateVarsPos[VD] = Counter; 4697 ++Counter; 4698 } 4699 for (const Expr *E : FirstprivateVars) { 4700 Args.push_back(ImplicitParamDecl::Create( 4701 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4702 C.getPointerType(C.getPointerType(E->getType())) 4703 .withConst() 4704 .withRestrict(), 4705 ImplicitParamDecl::Other)); 4706 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4707 PrivateVarsPos[VD] = Counter; 4708 ++Counter; 4709 } 4710 for (const Expr *E : LastprivateVars) { 4711 Args.push_back(ImplicitParamDecl::Create( 4712 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4713 C.getPointerType(C.getPointerType(E->getType())) 4714 .withConst() 4715 .withRestrict(), 4716 ImplicitParamDecl::Other)); 4717 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4718 PrivateVarsPos[VD] = Counter; 4719 ++Counter; 4720 } 4721 const auto &TaskPrivatesMapFnInfo = 4722 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4723 llvm::FunctionType *TaskPrivatesMapTy = 4724 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4725 std::string Name = 4726 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4727 auto *TaskPrivatesMap = llvm::Function::Create( 4728 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4729 &CGM.getModule()); 4730 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4731 TaskPrivatesMapFnInfo); 4732 if (CGM.getLangOpts().Optimize) { 4733 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4734 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4735 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4736 } 4737 CodeGenFunction CGF(CGM); 4738 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4739 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4740 4741 // *privi = &.privates.privi; 4742 LValue Base = CGF.EmitLoadOfPointerLValue( 4743 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4744 TaskPrivatesArg.getType()->castAs<PointerType>()); 4745 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4746 Counter = 0; 4747 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4748 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4749 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4750 LValue RefLVal = 4751 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4752 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4753 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>()); 4754 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal); 4755 ++Counter; 4756 } 4757 CGF.FinishFunction(); 4758 return TaskPrivatesMap; 4759 } 4760 4761 /// Emit initialization for private variables in task-based directives. 4762 static void emitPrivatesInit(CodeGenFunction &CGF, 4763 const OMPExecutableDirective &D, 4764 Address KmpTaskSharedsPtr, LValue TDBase, 4765 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4766 QualType SharedsTy, QualType SharedsPtrTy, 4767 const OMPTaskDataTy &Data, 4768 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4769 ASTContext &C = CGF.getContext(); 4770 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4771 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4772 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4773 ? OMPD_taskloop 4774 : OMPD_task; 4775 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4776 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4777 LValue SrcBase; 4778 bool IsTargetTask = 4779 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4780 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4781 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4782 // PointersArray and SizesArray. The original variables for these arrays are 4783 // not captured and we get their addresses explicitly. 4784 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4785 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4786 SrcBase = CGF.MakeAddrLValue( 4787 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4788 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4789 SharedsTy); 4790 } 4791 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4792 for (const PrivateDataTy &Pair : Privates) { 4793 const VarDecl *VD = Pair.second.PrivateCopy; 4794 const Expr *Init = VD->getAnyInitializer(); 4795 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4796 !CGF.isTrivialInitializer(Init)))) { 4797 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4798 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4799 const VarDecl *OriginalVD = Pair.second.Original; 4800 // Check if the variable is the target-based BasePointersArray, 4801 // PointersArray or SizesArray. 4802 LValue SharedRefLValue; 4803 QualType Type = PrivateLValue.getType(); 4804 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4805 if (IsTargetTask && !SharedField) { 4806 assert(isa<ImplicitParamDecl>(OriginalVD) && 4807 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4808 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4809 ->getNumParams() == 0 && 4810 isa<TranslationUnitDecl>( 4811 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4812 ->getDeclContext()) && 4813 "Expected artificial target data variable."); 4814 SharedRefLValue = 4815 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4816 } else { 4817 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4818 SharedRefLValue = CGF.MakeAddrLValue( 4819 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)), 4820 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4821 SharedRefLValue.getTBAAInfo()); 4822 } 4823 if (Type->isArrayType()) { 4824 // Initialize firstprivate array. 4825 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4826 // Perform simple memcpy. 4827 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4828 } else { 4829 // Initialize firstprivate array using element-by-element 4830 // initialization. 4831 CGF.EmitOMPAggregateAssign( 4832 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type, 4833 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4834 Address SrcElement) { 4835 // Clean up any temporaries needed by the initialization. 4836 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4837 InitScope.addPrivate( 4838 Elem, [SrcElement]() -> Address { return SrcElement; }); 4839 (void)InitScope.Privatize(); 4840 // Emit initialization for single element. 4841 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4842 CGF, &CapturesInfo); 4843 CGF.EmitAnyExprToMem(Init, DestElement, 4844 Init->getType().getQualifiers(), 4845 /*IsInitializer=*/false); 4846 }); 4847 } 4848 } else { 4849 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4850 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address { 4851 return SharedRefLValue.getAddress(); 4852 }); 4853 (void)InitScope.Privatize(); 4854 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4855 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4856 /*capturedByInit=*/false); 4857 } 4858 } else { 4859 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4860 } 4861 } 4862 ++FI; 4863 } 4864 } 4865 4866 /// Check if duplication function is required for taskloops. 4867 static bool checkInitIsRequired(CodeGenFunction &CGF, 4868 ArrayRef<PrivateDataTy> Privates) { 4869 bool InitRequired = false; 4870 for (const PrivateDataTy &Pair : Privates) { 4871 const VarDecl *VD = Pair.second.PrivateCopy; 4872 const Expr *Init = VD->getAnyInitializer(); 4873 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4874 !CGF.isTrivialInitializer(Init)); 4875 if (InitRequired) 4876 break; 4877 } 4878 return InitRequired; 4879 } 4880 4881 4882 /// Emit task_dup function (for initialization of 4883 /// private/firstprivate/lastprivate vars and last_iter flag) 4884 /// \code 4885 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4886 /// lastpriv) { 4887 /// // setup lastprivate flag 4888 /// task_dst->last = lastpriv; 4889 /// // could be constructor calls here... 4890 /// } 4891 /// \endcode 4892 static llvm::Value * 4893 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4894 const OMPExecutableDirective &D, 4895 QualType KmpTaskTWithPrivatesPtrQTy, 4896 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4897 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4898 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4899 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4900 ASTContext &C = CGM.getContext(); 4901 FunctionArgList Args; 4902 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4903 KmpTaskTWithPrivatesPtrQTy, 4904 ImplicitParamDecl::Other); 4905 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4906 KmpTaskTWithPrivatesPtrQTy, 4907 ImplicitParamDecl::Other); 4908 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4909 ImplicitParamDecl::Other); 4910 Args.push_back(&DstArg); 4911 Args.push_back(&SrcArg); 4912 Args.push_back(&LastprivArg); 4913 const auto &TaskDupFnInfo = 4914 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4915 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4916 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4917 auto *TaskDup = llvm::Function::Create( 4918 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4919 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4920 TaskDup->setDoesNotRecurse(); 4921 CodeGenFunction CGF(CGM); 4922 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4923 Loc); 4924 4925 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4926 CGF.GetAddrOfLocalVar(&DstArg), 4927 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4928 // task_dst->liter = lastpriv; 4929 if (WithLastIter) { 4930 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4931 LValue Base = CGF.EmitLValueForField( 4932 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4933 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4934 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4935 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4936 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4937 } 4938 4939 // Emit initial values for private copies (if any). 4940 assert(!Privates.empty()); 4941 Address KmpTaskSharedsPtr = Address::invalid(); 4942 if (!Data.FirstprivateVars.empty()) { 4943 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4944 CGF.GetAddrOfLocalVar(&SrcArg), 4945 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4946 LValue Base = CGF.EmitLValueForField( 4947 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4948 KmpTaskSharedsPtr = Address( 4949 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4950 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4951 KmpTaskTShareds)), 4952 Loc), 4953 CGF.getNaturalTypeAlignment(SharedsTy)); 4954 } 4955 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4956 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4957 CGF.FinishFunction(); 4958 return TaskDup; 4959 } 4960 4961 /// Checks if destructor function is required to be generated. 4962 /// \return true if cleanups are required, false otherwise. 4963 static bool 4964 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4965 bool NeedsCleanup = false; 4966 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4967 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4968 for (const FieldDecl *FD : PrivateRD->fields()) { 4969 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4970 if (NeedsCleanup) 4971 break; 4972 } 4973 return NeedsCleanup; 4974 } 4975 4976 CGOpenMPRuntime::TaskResultTy 4977 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4978 const OMPExecutableDirective &D, 4979 llvm::Function *TaskFunction, QualType SharedsTy, 4980 Address Shareds, const OMPTaskDataTy &Data) { 4981 ASTContext &C = CGM.getContext(); 4982 llvm::SmallVector<PrivateDataTy, 4> Privates; 4983 // Aggregate privates and sort them by the alignment. 4984 auto I = Data.PrivateCopies.begin(); 4985 for (const Expr *E : Data.PrivateVars) { 4986 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4987 Privates.emplace_back( 4988 C.getDeclAlign(VD), 4989 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4990 /*PrivateElemInit=*/nullptr)); 4991 ++I; 4992 } 4993 I = Data.FirstprivateCopies.begin(); 4994 auto IElemInitRef = Data.FirstprivateInits.begin(); 4995 for (const Expr *E : Data.FirstprivateVars) { 4996 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4997 Privates.emplace_back( 4998 C.getDeclAlign(VD), 4999 PrivateHelpersTy( 5000 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5001 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 5002 ++I; 5003 ++IElemInitRef; 5004 } 5005 I = Data.LastprivateCopies.begin(); 5006 for (const Expr *E : Data.LastprivateVars) { 5007 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5008 Privates.emplace_back( 5009 C.getDeclAlign(VD), 5010 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5011 /*PrivateElemInit=*/nullptr)); 5012 ++I; 5013 } 5014 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 5015 return L.first > R.first; 5016 }); 5017 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 5018 // Build type kmp_routine_entry_t (if not built yet). 5019 emitKmpRoutineEntryT(KmpInt32Ty); 5020 // Build type kmp_task_t (if not built yet). 5021 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 5022 if (SavedKmpTaskloopTQTy.isNull()) { 5023 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5024 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5025 } 5026 KmpTaskTQTy = SavedKmpTaskloopTQTy; 5027 } else { 5028 assert((D.getDirectiveKind() == OMPD_task || 5029 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 5030 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5031 "Expected taskloop, task or target directive"); 5032 if (SavedKmpTaskTQTy.isNull()) { 5033 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5034 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5035 } 5036 KmpTaskTQTy = SavedKmpTaskTQTy; 5037 } 5038 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5039 // Build particular struct kmp_task_t for the given task. 5040 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5041 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5042 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5043 QualType KmpTaskTWithPrivatesPtrQTy = 5044 C.getPointerType(KmpTaskTWithPrivatesQTy); 5045 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5046 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5047 KmpTaskTWithPrivatesTy->getPointerTo(); 5048 llvm::Value *KmpTaskTWithPrivatesTySize = 5049 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5050 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5051 5052 // Emit initial values for private copies (if any). 5053 llvm::Value *TaskPrivatesMap = nullptr; 5054 llvm::Type *TaskPrivatesMapTy = 5055 std::next(TaskFunction->arg_begin(), 3)->getType(); 5056 if (!Privates.empty()) { 5057 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5058 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5059 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5060 FI->getType(), Privates); 5061 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5062 TaskPrivatesMap, TaskPrivatesMapTy); 5063 } else { 5064 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5065 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5066 } 5067 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5068 // kmp_task_t *tt); 5069 llvm::Function *TaskEntry = emitProxyTaskFunction( 5070 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5071 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5072 TaskPrivatesMap); 5073 5074 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5075 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5076 // kmp_routine_entry_t *task_entry); 5077 // Task flags. Format is taken from 5078 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5079 // description of kmp_tasking_flags struct. 5080 enum { 5081 TiedFlag = 0x1, 5082 FinalFlag = 0x2, 5083 DestructorsFlag = 0x8, 5084 PriorityFlag = 0x20 5085 }; 5086 unsigned Flags = Data.Tied ? TiedFlag : 0; 5087 bool NeedsCleanup = false; 5088 if (!Privates.empty()) { 5089 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5090 if (NeedsCleanup) 5091 Flags = Flags | DestructorsFlag; 5092 } 5093 if (Data.Priority.getInt()) 5094 Flags = Flags | PriorityFlag; 5095 llvm::Value *TaskFlags = 5096 Data.Final.getPointer() 5097 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5098 CGF.Builder.getInt32(FinalFlag), 5099 CGF.Builder.getInt32(/*C=*/0)) 5100 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5101 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5102 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5103 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5104 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5105 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5106 TaskEntry, KmpRoutineEntryPtrTy)}; 5107 llvm::Value *NewTask; 5108 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5109 // Check if we have any device clause associated with the directive. 5110 const Expr *Device = nullptr; 5111 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5112 Device = C->getDevice(); 5113 // Emit device ID if any otherwise use default value. 5114 llvm::Value *DeviceID; 5115 if (Device) 5116 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5117 CGF.Int64Ty, /*isSigned=*/true); 5118 else 5119 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5120 AllocArgs.push_back(DeviceID); 5121 NewTask = CGF.EmitRuntimeCall( 5122 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5123 } else { 5124 NewTask = CGF.EmitRuntimeCall( 5125 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5126 } 5127 llvm::Value *NewTaskNewTaskTTy = 5128 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5129 NewTask, KmpTaskTWithPrivatesPtrTy); 5130 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5131 KmpTaskTWithPrivatesQTy); 5132 LValue TDBase = 5133 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5134 // Fill the data in the resulting kmp_task_t record. 5135 // Copy shareds if there are any. 5136 Address KmpTaskSharedsPtr = Address::invalid(); 5137 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5138 KmpTaskSharedsPtr = 5139 Address(CGF.EmitLoadOfScalar( 5140 CGF.EmitLValueForField( 5141 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5142 KmpTaskTShareds)), 5143 Loc), 5144 CGF.getNaturalTypeAlignment(SharedsTy)); 5145 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5146 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5147 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5148 } 5149 // Emit initial values for private copies (if any). 5150 TaskResultTy Result; 5151 if (!Privates.empty()) { 5152 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5153 SharedsTy, SharedsPtrTy, Data, Privates, 5154 /*ForDup=*/false); 5155 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5156 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5157 Result.TaskDupFn = emitTaskDupFunction( 5158 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5159 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5160 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5161 } 5162 } 5163 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5164 enum { Priority = 0, Destructors = 1 }; 5165 // Provide pointer to function with destructors for privates. 5166 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5167 const RecordDecl *KmpCmplrdataUD = 5168 (*FI)->getType()->getAsUnionType()->getDecl(); 5169 if (NeedsCleanup) { 5170 llvm::Value *DestructorFn = emitDestructorsFunction( 5171 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5172 KmpTaskTWithPrivatesQTy); 5173 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5174 LValue DestructorsLV = CGF.EmitLValueForField( 5175 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5176 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5177 DestructorFn, KmpRoutineEntryPtrTy), 5178 DestructorsLV); 5179 } 5180 // Set priority. 5181 if (Data.Priority.getInt()) { 5182 LValue Data2LV = CGF.EmitLValueForField( 5183 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5184 LValue PriorityLV = CGF.EmitLValueForField( 5185 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5186 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5187 } 5188 Result.NewTask = NewTask; 5189 Result.TaskEntry = TaskEntry; 5190 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5191 Result.TDBase = TDBase; 5192 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5193 return Result; 5194 } 5195 5196 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5197 const OMPExecutableDirective &D, 5198 llvm::Function *TaskFunction, 5199 QualType SharedsTy, Address Shareds, 5200 const Expr *IfCond, 5201 const OMPTaskDataTy &Data) { 5202 if (!CGF.HaveInsertPoint()) 5203 return; 5204 5205 TaskResultTy Result = 5206 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5207 llvm::Value *NewTask = Result.NewTask; 5208 llvm::Function *TaskEntry = Result.TaskEntry; 5209 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5210 LValue TDBase = Result.TDBase; 5211 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5212 ASTContext &C = CGM.getContext(); 5213 // Process list of dependences. 5214 Address DependenciesArray = Address::invalid(); 5215 unsigned NumDependencies = Data.Dependences.size(); 5216 if (NumDependencies) { 5217 // Dependence kind for RTL. 5218 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 }; 5219 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5220 RecordDecl *KmpDependInfoRD; 5221 QualType FlagsTy = 5222 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5223 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5224 if (KmpDependInfoTy.isNull()) { 5225 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5226 KmpDependInfoRD->startDefinition(); 5227 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5228 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5229 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5230 KmpDependInfoRD->completeDefinition(); 5231 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5232 } else { 5233 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5234 } 5235 // Define type kmp_depend_info[<Dependences.size()>]; 5236 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5237 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5238 ArrayType::Normal, /*IndexTypeQuals=*/0); 5239 // kmp_depend_info[<Dependences.size()>] deps; 5240 DependenciesArray = 5241 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5242 for (unsigned I = 0; I < NumDependencies; ++I) { 5243 const Expr *E = Data.Dependences[I].second; 5244 LValue Addr = CGF.EmitLValue(E); 5245 llvm::Value *Size; 5246 QualType Ty = E->getType(); 5247 if (const auto *ASE = 5248 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5249 LValue UpAddrLVal = 5250 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false); 5251 llvm::Value *UpAddr = 5252 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1); 5253 llvm::Value *LowIntPtr = 5254 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy); 5255 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5256 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5257 } else { 5258 Size = CGF.getTypeSize(Ty); 5259 } 5260 LValue Base = CGF.MakeAddrLValue( 5261 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I), 5262 KmpDependInfoTy); 5263 // deps[i].base_addr = &<Dependences[i].second>; 5264 LValue BaseAddrLVal = CGF.EmitLValueForField( 5265 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5266 CGF.EmitStoreOfScalar( 5267 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy), 5268 BaseAddrLVal); 5269 // deps[i].len = sizeof(<Dependences[i].second>); 5270 LValue LenLVal = CGF.EmitLValueForField( 5271 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5272 CGF.EmitStoreOfScalar(Size, LenLVal); 5273 // deps[i].flags = <Dependences[i].first>; 5274 RTLDependenceKindTy DepKind; 5275 switch (Data.Dependences[I].first) { 5276 case OMPC_DEPEND_in: 5277 DepKind = DepIn; 5278 break; 5279 // Out and InOut dependencies must use the same code. 5280 case OMPC_DEPEND_out: 5281 case OMPC_DEPEND_inout: 5282 DepKind = DepInOut; 5283 break; 5284 case OMPC_DEPEND_mutexinoutset: 5285 DepKind = DepMutexInOutSet; 5286 break; 5287 case OMPC_DEPEND_source: 5288 case OMPC_DEPEND_sink: 5289 case OMPC_DEPEND_unknown: 5290 llvm_unreachable("Unknown task dependence type"); 5291 } 5292 LValue FlagsLVal = CGF.EmitLValueForField( 5293 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5294 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5295 FlagsLVal); 5296 } 5297 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5298 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); 5299 } 5300 5301 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5302 // libcall. 5303 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5304 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5305 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5306 // list is not empty 5307 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5308 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5309 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5310 llvm::Value *DepTaskArgs[7]; 5311 if (NumDependencies) { 5312 DepTaskArgs[0] = UpLoc; 5313 DepTaskArgs[1] = ThreadID; 5314 DepTaskArgs[2] = NewTask; 5315 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 5316 DepTaskArgs[4] = DependenciesArray.getPointer(); 5317 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5318 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5319 } 5320 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 5321 &TaskArgs, 5322 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5323 if (!Data.Tied) { 5324 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5325 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5326 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5327 } 5328 if (NumDependencies) { 5329 CGF.EmitRuntimeCall( 5330 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5331 } else { 5332 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5333 TaskArgs); 5334 } 5335 // Check if parent region is untied and build return for untied task; 5336 if (auto *Region = 5337 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5338 Region->emitUntiedSwitch(CGF); 5339 }; 5340 5341 llvm::Value *DepWaitTaskArgs[6]; 5342 if (NumDependencies) { 5343 DepWaitTaskArgs[0] = UpLoc; 5344 DepWaitTaskArgs[1] = ThreadID; 5345 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 5346 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5347 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5348 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5349 } 5350 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5351 NumDependencies, &DepWaitTaskArgs, 5352 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5353 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5354 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5355 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5356 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5357 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5358 // is specified. 5359 if (NumDependencies) 5360 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5361 DepWaitTaskArgs); 5362 // Call proxy_task_entry(gtid, new_task); 5363 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5364 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5365 Action.Enter(CGF); 5366 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5367 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5368 OutlinedFnArgs); 5369 }; 5370 5371 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5372 // kmp_task_t *new_task); 5373 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5374 // kmp_task_t *new_task); 5375 RegionCodeGenTy RCG(CodeGen); 5376 CommonActionTy Action( 5377 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5378 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5379 RCG.setAction(Action); 5380 RCG(CGF); 5381 }; 5382 5383 if (IfCond) { 5384 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5385 } else { 5386 RegionCodeGenTy ThenRCG(ThenCodeGen); 5387 ThenRCG(CGF); 5388 } 5389 } 5390 5391 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5392 const OMPLoopDirective &D, 5393 llvm::Function *TaskFunction, 5394 QualType SharedsTy, Address Shareds, 5395 const Expr *IfCond, 5396 const OMPTaskDataTy &Data) { 5397 if (!CGF.HaveInsertPoint()) 5398 return; 5399 TaskResultTy Result = 5400 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5401 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5402 // libcall. 5403 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5404 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5405 // sched, kmp_uint64 grainsize, void *task_dup); 5406 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5407 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5408 llvm::Value *IfVal; 5409 if (IfCond) { 5410 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5411 /*isSigned=*/true); 5412 } else { 5413 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5414 } 5415 5416 LValue LBLVal = CGF.EmitLValueForField( 5417 Result.TDBase, 5418 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5419 const auto *LBVar = 5420 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5421 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(), 5422 /*IsInitializer=*/true); 5423 LValue UBLVal = CGF.EmitLValueForField( 5424 Result.TDBase, 5425 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5426 const auto *UBVar = 5427 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5428 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(), 5429 /*IsInitializer=*/true); 5430 LValue StLVal = CGF.EmitLValueForField( 5431 Result.TDBase, 5432 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5433 const auto *StVar = 5434 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5435 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(), 5436 /*IsInitializer=*/true); 5437 // Store reductions address. 5438 LValue RedLVal = CGF.EmitLValueForField( 5439 Result.TDBase, 5440 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5441 if (Data.Reductions) { 5442 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5443 } else { 5444 CGF.EmitNullInitialization(RedLVal.getAddress(), 5445 CGF.getContext().VoidPtrTy); 5446 } 5447 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5448 llvm::Value *TaskArgs[] = { 5449 UpLoc, 5450 ThreadID, 5451 Result.NewTask, 5452 IfVal, 5453 LBLVal.getPointer(), 5454 UBLVal.getPointer(), 5455 CGF.EmitLoadOfScalar(StLVal, Loc), 5456 llvm::ConstantInt::getSigned( 5457 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5458 llvm::ConstantInt::getSigned( 5459 CGF.IntTy, Data.Schedule.getPointer() 5460 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5461 : NoSchedule), 5462 Data.Schedule.getPointer() 5463 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5464 /*isSigned=*/false) 5465 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5466 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5467 Result.TaskDupFn, CGF.VoidPtrTy) 5468 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5469 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5470 } 5471 5472 /// Emit reduction operation for each element of array (required for 5473 /// array sections) LHS op = RHS. 5474 /// \param Type Type of array. 5475 /// \param LHSVar Variable on the left side of the reduction operation 5476 /// (references element of array in original variable). 5477 /// \param RHSVar Variable on the right side of the reduction operation 5478 /// (references element of array in original variable). 5479 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5480 /// RHSVar. 5481 static void EmitOMPAggregateReduction( 5482 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5483 const VarDecl *RHSVar, 5484 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5485 const Expr *, const Expr *)> &RedOpGen, 5486 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5487 const Expr *UpExpr = nullptr) { 5488 // Perform element-by-element initialization. 5489 QualType ElementTy; 5490 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5491 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5492 5493 // Drill down to the base element type on both arrays. 5494 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5495 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5496 5497 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5498 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5499 // Cast from pointer to array type to pointer to single element. 5500 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5501 // The basic structure here is a while-do loop. 5502 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5503 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5504 llvm::Value *IsEmpty = 5505 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5506 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5507 5508 // Enter the loop body, making that address the current address. 5509 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5510 CGF.EmitBlock(BodyBB); 5511 5512 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5513 5514 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5515 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5516 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5517 Address RHSElementCurrent = 5518 Address(RHSElementPHI, 5519 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5520 5521 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5522 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5523 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5524 Address LHSElementCurrent = 5525 Address(LHSElementPHI, 5526 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5527 5528 // Emit copy. 5529 CodeGenFunction::OMPPrivateScope Scope(CGF); 5530 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5531 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5532 Scope.Privatize(); 5533 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5534 Scope.ForceCleanup(); 5535 5536 // Shift the address forward by one element. 5537 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5538 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5539 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5540 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5541 // Check whether we've reached the end. 5542 llvm::Value *Done = 5543 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5544 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5545 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5546 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5547 5548 // Done. 5549 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5550 } 5551 5552 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5553 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5554 /// UDR combiner function. 5555 static void emitReductionCombiner(CodeGenFunction &CGF, 5556 const Expr *ReductionOp) { 5557 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5558 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5559 if (const auto *DRE = 5560 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5561 if (const auto *DRD = 5562 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5563 std::pair<llvm::Function *, llvm::Function *> Reduction = 5564 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5565 RValue Func = RValue::get(Reduction.first); 5566 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5567 CGF.EmitIgnoredExpr(ReductionOp); 5568 return; 5569 } 5570 CGF.EmitIgnoredExpr(ReductionOp); 5571 } 5572 5573 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5574 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5575 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5576 ArrayRef<const Expr *> ReductionOps) { 5577 ASTContext &C = CGM.getContext(); 5578 5579 // void reduction_func(void *LHSArg, void *RHSArg); 5580 FunctionArgList Args; 5581 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5582 ImplicitParamDecl::Other); 5583 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5584 ImplicitParamDecl::Other); 5585 Args.push_back(&LHSArg); 5586 Args.push_back(&RHSArg); 5587 const auto &CGFI = 5588 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5589 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5590 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5591 llvm::GlobalValue::InternalLinkage, Name, 5592 &CGM.getModule()); 5593 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5594 Fn->setDoesNotRecurse(); 5595 CodeGenFunction CGF(CGM); 5596 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5597 5598 // Dst = (void*[n])(LHSArg); 5599 // Src = (void*[n])(RHSArg); 5600 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5601 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5602 ArgsType), CGF.getPointerAlign()); 5603 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5604 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5605 ArgsType), CGF.getPointerAlign()); 5606 5607 // ... 5608 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5609 // ... 5610 CodeGenFunction::OMPPrivateScope Scope(CGF); 5611 auto IPriv = Privates.begin(); 5612 unsigned Idx = 0; 5613 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5614 const auto *RHSVar = 5615 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5616 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5617 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5618 }); 5619 const auto *LHSVar = 5620 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5621 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5622 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5623 }); 5624 QualType PrivTy = (*IPriv)->getType(); 5625 if (PrivTy->isVariablyModifiedType()) { 5626 // Get array size and emit VLA type. 5627 ++Idx; 5628 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5629 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5630 const VariableArrayType *VLA = 5631 CGF.getContext().getAsVariableArrayType(PrivTy); 5632 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5633 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5634 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5635 CGF.EmitVariablyModifiedType(PrivTy); 5636 } 5637 } 5638 Scope.Privatize(); 5639 IPriv = Privates.begin(); 5640 auto ILHS = LHSExprs.begin(); 5641 auto IRHS = RHSExprs.begin(); 5642 for (const Expr *E : ReductionOps) { 5643 if ((*IPriv)->getType()->isArrayType()) { 5644 // Emit reduction for array section. 5645 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5646 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5647 EmitOMPAggregateReduction( 5648 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5649 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5650 emitReductionCombiner(CGF, E); 5651 }); 5652 } else { 5653 // Emit reduction for array subscript or single variable. 5654 emitReductionCombiner(CGF, E); 5655 } 5656 ++IPriv; 5657 ++ILHS; 5658 ++IRHS; 5659 } 5660 Scope.ForceCleanup(); 5661 CGF.FinishFunction(); 5662 return Fn; 5663 } 5664 5665 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5666 const Expr *ReductionOp, 5667 const Expr *PrivateRef, 5668 const DeclRefExpr *LHS, 5669 const DeclRefExpr *RHS) { 5670 if (PrivateRef->getType()->isArrayType()) { 5671 // Emit reduction for array section. 5672 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5673 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5674 EmitOMPAggregateReduction( 5675 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5676 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5677 emitReductionCombiner(CGF, ReductionOp); 5678 }); 5679 } else { 5680 // Emit reduction for array subscript or single variable. 5681 emitReductionCombiner(CGF, ReductionOp); 5682 } 5683 } 5684 5685 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5686 ArrayRef<const Expr *> Privates, 5687 ArrayRef<const Expr *> LHSExprs, 5688 ArrayRef<const Expr *> RHSExprs, 5689 ArrayRef<const Expr *> ReductionOps, 5690 ReductionOptionsTy Options) { 5691 if (!CGF.HaveInsertPoint()) 5692 return; 5693 5694 bool WithNowait = Options.WithNowait; 5695 bool SimpleReduction = Options.SimpleReduction; 5696 5697 // Next code should be emitted for reduction: 5698 // 5699 // static kmp_critical_name lock = { 0 }; 5700 // 5701 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5702 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5703 // ... 5704 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5705 // *(Type<n>-1*)rhs[<n>-1]); 5706 // } 5707 // 5708 // ... 5709 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5710 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5711 // RedList, reduce_func, &<lock>)) { 5712 // case 1: 5713 // ... 5714 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5715 // ... 5716 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5717 // break; 5718 // case 2: 5719 // ... 5720 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5721 // ... 5722 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5723 // break; 5724 // default:; 5725 // } 5726 // 5727 // if SimpleReduction is true, only the next code is generated: 5728 // ... 5729 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5730 // ... 5731 5732 ASTContext &C = CGM.getContext(); 5733 5734 if (SimpleReduction) { 5735 CodeGenFunction::RunCleanupsScope Scope(CGF); 5736 auto IPriv = Privates.begin(); 5737 auto ILHS = LHSExprs.begin(); 5738 auto IRHS = RHSExprs.begin(); 5739 for (const Expr *E : ReductionOps) { 5740 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5741 cast<DeclRefExpr>(*IRHS)); 5742 ++IPriv; 5743 ++ILHS; 5744 ++IRHS; 5745 } 5746 return; 5747 } 5748 5749 // 1. Build a list of reduction variables. 5750 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5751 auto Size = RHSExprs.size(); 5752 for (const Expr *E : Privates) { 5753 if (E->getType()->isVariablyModifiedType()) 5754 // Reserve place for array size. 5755 ++Size; 5756 } 5757 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5758 QualType ReductionArrayTy = 5759 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 5760 /*IndexTypeQuals=*/0); 5761 Address ReductionList = 5762 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5763 auto IPriv = Privates.begin(); 5764 unsigned Idx = 0; 5765 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5766 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5767 CGF.Builder.CreateStore( 5768 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5769 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy), 5770 Elem); 5771 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5772 // Store array size. 5773 ++Idx; 5774 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5775 llvm::Value *Size = CGF.Builder.CreateIntCast( 5776 CGF.getVLASize( 5777 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5778 .NumElts, 5779 CGF.SizeTy, /*isSigned=*/false); 5780 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5781 Elem); 5782 } 5783 } 5784 5785 // 2. Emit reduce_func(). 5786 llvm::Function *ReductionFn = emitReductionFunction( 5787 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5788 LHSExprs, RHSExprs, ReductionOps); 5789 5790 // 3. Create static kmp_critical_name lock = { 0 }; 5791 std::string Name = getName({"reduction"}); 5792 llvm::Value *Lock = getCriticalRegionLock(Name); 5793 5794 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5795 // RedList, reduce_func, &<lock>); 5796 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5797 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5798 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5799 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5800 ReductionList.getPointer(), CGF.VoidPtrTy); 5801 llvm::Value *Args[] = { 5802 IdentTLoc, // ident_t *<loc> 5803 ThreadId, // i32 <gtid> 5804 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5805 ReductionArrayTySize, // size_type sizeof(RedList) 5806 RL, // void *RedList 5807 ReductionFn, // void (*) (void *, void *) <reduce_func> 5808 Lock // kmp_critical_name *&<lock> 5809 }; 5810 llvm::Value *Res = CGF.EmitRuntimeCall( 5811 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 5812 : OMPRTL__kmpc_reduce), 5813 Args); 5814 5815 // 5. Build switch(res) 5816 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5817 llvm::SwitchInst *SwInst = 5818 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5819 5820 // 6. Build case 1: 5821 // ... 5822 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5823 // ... 5824 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5825 // break; 5826 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5827 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5828 CGF.EmitBlock(Case1BB); 5829 5830 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5831 llvm::Value *EndArgs[] = { 5832 IdentTLoc, // ident_t *<loc> 5833 ThreadId, // i32 <gtid> 5834 Lock // kmp_critical_name *&<lock> 5835 }; 5836 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5837 CodeGenFunction &CGF, PrePostActionTy &Action) { 5838 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5839 auto IPriv = Privates.begin(); 5840 auto ILHS = LHSExprs.begin(); 5841 auto IRHS = RHSExprs.begin(); 5842 for (const Expr *E : ReductionOps) { 5843 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5844 cast<DeclRefExpr>(*IRHS)); 5845 ++IPriv; 5846 ++ILHS; 5847 ++IRHS; 5848 } 5849 }; 5850 RegionCodeGenTy RCG(CodeGen); 5851 CommonActionTy Action( 5852 nullptr, llvm::None, 5853 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 5854 : OMPRTL__kmpc_end_reduce), 5855 EndArgs); 5856 RCG.setAction(Action); 5857 RCG(CGF); 5858 5859 CGF.EmitBranch(DefaultBB); 5860 5861 // 7. Build case 2: 5862 // ... 5863 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5864 // ... 5865 // break; 5866 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5867 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5868 CGF.EmitBlock(Case2BB); 5869 5870 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5871 CodeGenFunction &CGF, PrePostActionTy &Action) { 5872 auto ILHS = LHSExprs.begin(); 5873 auto IRHS = RHSExprs.begin(); 5874 auto IPriv = Privates.begin(); 5875 for (const Expr *E : ReductionOps) { 5876 const Expr *XExpr = nullptr; 5877 const Expr *EExpr = nullptr; 5878 const Expr *UpExpr = nullptr; 5879 BinaryOperatorKind BO = BO_Comma; 5880 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5881 if (BO->getOpcode() == BO_Assign) { 5882 XExpr = BO->getLHS(); 5883 UpExpr = BO->getRHS(); 5884 } 5885 } 5886 // Try to emit update expression as a simple atomic. 5887 const Expr *RHSExpr = UpExpr; 5888 if (RHSExpr) { 5889 // Analyze RHS part of the whole expression. 5890 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5891 RHSExpr->IgnoreParenImpCasts())) { 5892 // If this is a conditional operator, analyze its condition for 5893 // min/max reduction operator. 5894 RHSExpr = ACO->getCond(); 5895 } 5896 if (const auto *BORHS = 5897 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5898 EExpr = BORHS->getRHS(); 5899 BO = BORHS->getOpcode(); 5900 } 5901 } 5902 if (XExpr) { 5903 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5904 auto &&AtomicRedGen = [BO, VD, 5905 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5906 const Expr *EExpr, const Expr *UpExpr) { 5907 LValue X = CGF.EmitLValue(XExpr); 5908 RValue E; 5909 if (EExpr) 5910 E = CGF.EmitAnyExpr(EExpr); 5911 CGF.EmitOMPAtomicSimpleUpdateExpr( 5912 X, E, BO, /*IsXLHSInRHSPart=*/true, 5913 llvm::AtomicOrdering::Monotonic, Loc, 5914 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5915 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5916 PrivateScope.addPrivate( 5917 VD, [&CGF, VD, XRValue, Loc]() { 5918 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5919 CGF.emitOMPSimpleStore( 5920 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5921 VD->getType().getNonReferenceType(), Loc); 5922 return LHSTemp; 5923 }); 5924 (void)PrivateScope.Privatize(); 5925 return CGF.EmitAnyExpr(UpExpr); 5926 }); 5927 }; 5928 if ((*IPriv)->getType()->isArrayType()) { 5929 // Emit atomic reduction for array section. 5930 const auto *RHSVar = 5931 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5932 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5933 AtomicRedGen, XExpr, EExpr, UpExpr); 5934 } else { 5935 // Emit atomic reduction for array subscript or single variable. 5936 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5937 } 5938 } else { 5939 // Emit as a critical region. 5940 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5941 const Expr *, const Expr *) { 5942 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5943 std::string Name = RT.getName({"atomic_reduction"}); 5944 RT.emitCriticalRegion( 5945 CGF, Name, 5946 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5947 Action.Enter(CGF); 5948 emitReductionCombiner(CGF, E); 5949 }, 5950 Loc); 5951 }; 5952 if ((*IPriv)->getType()->isArrayType()) { 5953 const auto *LHSVar = 5954 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5955 const auto *RHSVar = 5956 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5957 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5958 CritRedGen); 5959 } else { 5960 CritRedGen(CGF, nullptr, nullptr, nullptr); 5961 } 5962 } 5963 ++ILHS; 5964 ++IRHS; 5965 ++IPriv; 5966 } 5967 }; 5968 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5969 if (!WithNowait) { 5970 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5971 llvm::Value *EndArgs[] = { 5972 IdentTLoc, // ident_t *<loc> 5973 ThreadId, // i32 <gtid> 5974 Lock // kmp_critical_name *&<lock> 5975 }; 5976 CommonActionTy Action(nullptr, llvm::None, 5977 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 5978 EndArgs); 5979 AtomicRCG.setAction(Action); 5980 AtomicRCG(CGF); 5981 } else { 5982 AtomicRCG(CGF); 5983 } 5984 5985 CGF.EmitBranch(DefaultBB); 5986 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5987 } 5988 5989 /// Generates unique name for artificial threadprivate variables. 5990 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5991 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5992 const Expr *Ref) { 5993 SmallString<256> Buffer; 5994 llvm::raw_svector_ostream Out(Buffer); 5995 const clang::DeclRefExpr *DE; 5996 const VarDecl *D = ::getBaseDecl(Ref, DE); 5997 if (!D) 5998 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5999 D = D->getCanonicalDecl(); 6000 std::string Name = CGM.getOpenMPRuntime().getName( 6001 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 6002 Out << Prefix << Name << "_" 6003 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 6004 return Out.str(); 6005 } 6006 6007 /// Emits reduction initializer function: 6008 /// \code 6009 /// void @.red_init(void* %arg) { 6010 /// %0 = bitcast void* %arg to <type>* 6011 /// store <type> <init>, <type>* %0 6012 /// ret void 6013 /// } 6014 /// \endcode 6015 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 6016 SourceLocation Loc, 6017 ReductionCodeGen &RCG, unsigned N) { 6018 ASTContext &C = CGM.getContext(); 6019 FunctionArgList Args; 6020 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6021 ImplicitParamDecl::Other); 6022 Args.emplace_back(&Param); 6023 const auto &FnInfo = 6024 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6025 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6026 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6027 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6028 Name, &CGM.getModule()); 6029 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6030 Fn->setDoesNotRecurse(); 6031 CodeGenFunction CGF(CGM); 6032 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6033 Address PrivateAddr = CGF.EmitLoadOfPointer( 6034 CGF.GetAddrOfLocalVar(&Param), 6035 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6036 llvm::Value *Size = nullptr; 6037 // If the size of the reduction item is non-constant, load it from global 6038 // threadprivate variable. 6039 if (RCG.getSizes(N).second) { 6040 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6041 CGF, CGM.getContext().getSizeType(), 6042 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6043 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6044 CGM.getContext().getSizeType(), Loc); 6045 } 6046 RCG.emitAggregateType(CGF, N, Size); 6047 LValue SharedLVal; 6048 // If initializer uses initializer from declare reduction construct, emit a 6049 // pointer to the address of the original reduction item (reuired by reduction 6050 // initializer) 6051 if (RCG.usesReductionInitializer(N)) { 6052 Address SharedAddr = 6053 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6054 CGF, CGM.getContext().VoidPtrTy, 6055 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6056 SharedAddr = CGF.EmitLoadOfPointer( 6057 SharedAddr, 6058 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6059 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6060 } else { 6061 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6062 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6063 CGM.getContext().VoidPtrTy); 6064 } 6065 // Emit the initializer: 6066 // %0 = bitcast void* %arg to <type>* 6067 // store <type> <init>, <type>* %0 6068 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6069 [](CodeGenFunction &) { return false; }); 6070 CGF.FinishFunction(); 6071 return Fn; 6072 } 6073 6074 /// Emits reduction combiner function: 6075 /// \code 6076 /// void @.red_comb(void* %arg0, void* %arg1) { 6077 /// %lhs = bitcast void* %arg0 to <type>* 6078 /// %rhs = bitcast void* %arg1 to <type>* 6079 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6080 /// store <type> %2, <type>* %lhs 6081 /// ret void 6082 /// } 6083 /// \endcode 6084 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6085 SourceLocation Loc, 6086 ReductionCodeGen &RCG, unsigned N, 6087 const Expr *ReductionOp, 6088 const Expr *LHS, const Expr *RHS, 6089 const Expr *PrivateRef) { 6090 ASTContext &C = CGM.getContext(); 6091 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6092 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6093 FunctionArgList Args; 6094 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6095 C.VoidPtrTy, ImplicitParamDecl::Other); 6096 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6097 ImplicitParamDecl::Other); 6098 Args.emplace_back(&ParamInOut); 6099 Args.emplace_back(&ParamIn); 6100 const auto &FnInfo = 6101 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6102 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6103 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6104 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6105 Name, &CGM.getModule()); 6106 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6107 Fn->setDoesNotRecurse(); 6108 CodeGenFunction CGF(CGM); 6109 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6110 llvm::Value *Size = nullptr; 6111 // If the size of the reduction item is non-constant, load it from global 6112 // threadprivate variable. 6113 if (RCG.getSizes(N).second) { 6114 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6115 CGF, CGM.getContext().getSizeType(), 6116 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6117 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6118 CGM.getContext().getSizeType(), Loc); 6119 } 6120 RCG.emitAggregateType(CGF, N, Size); 6121 // Remap lhs and rhs variables to the addresses of the function arguments. 6122 // %lhs = bitcast void* %arg0 to <type>* 6123 // %rhs = bitcast void* %arg1 to <type>* 6124 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6125 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6126 // Pull out the pointer to the variable. 6127 Address PtrAddr = CGF.EmitLoadOfPointer( 6128 CGF.GetAddrOfLocalVar(&ParamInOut), 6129 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6130 return CGF.Builder.CreateElementBitCast( 6131 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6132 }); 6133 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6134 // Pull out the pointer to the variable. 6135 Address PtrAddr = CGF.EmitLoadOfPointer( 6136 CGF.GetAddrOfLocalVar(&ParamIn), 6137 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6138 return CGF.Builder.CreateElementBitCast( 6139 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6140 }); 6141 PrivateScope.Privatize(); 6142 // Emit the combiner body: 6143 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6144 // store <type> %2, <type>* %lhs 6145 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6146 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6147 cast<DeclRefExpr>(RHS)); 6148 CGF.FinishFunction(); 6149 return Fn; 6150 } 6151 6152 /// Emits reduction finalizer function: 6153 /// \code 6154 /// void @.red_fini(void* %arg) { 6155 /// %0 = bitcast void* %arg to <type>* 6156 /// <destroy>(<type>* %0) 6157 /// ret void 6158 /// } 6159 /// \endcode 6160 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6161 SourceLocation Loc, 6162 ReductionCodeGen &RCG, unsigned N) { 6163 if (!RCG.needCleanups(N)) 6164 return nullptr; 6165 ASTContext &C = CGM.getContext(); 6166 FunctionArgList Args; 6167 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6168 ImplicitParamDecl::Other); 6169 Args.emplace_back(&Param); 6170 const auto &FnInfo = 6171 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6172 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6173 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6174 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6175 Name, &CGM.getModule()); 6176 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6177 Fn->setDoesNotRecurse(); 6178 CodeGenFunction CGF(CGM); 6179 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6180 Address PrivateAddr = CGF.EmitLoadOfPointer( 6181 CGF.GetAddrOfLocalVar(&Param), 6182 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6183 llvm::Value *Size = nullptr; 6184 // If the size of the reduction item is non-constant, load it from global 6185 // threadprivate variable. 6186 if (RCG.getSizes(N).second) { 6187 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6188 CGF, CGM.getContext().getSizeType(), 6189 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6190 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6191 CGM.getContext().getSizeType(), Loc); 6192 } 6193 RCG.emitAggregateType(CGF, N, Size); 6194 // Emit the finalizer body: 6195 // <destroy>(<type>* %0) 6196 RCG.emitCleanups(CGF, N, PrivateAddr); 6197 CGF.FinishFunction(); 6198 return Fn; 6199 } 6200 6201 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6202 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6203 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6204 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6205 return nullptr; 6206 6207 // Build typedef struct: 6208 // kmp_task_red_input { 6209 // void *reduce_shar; // shared reduction item 6210 // size_t reduce_size; // size of data item 6211 // void *reduce_init; // data initialization routine 6212 // void *reduce_fini; // data finalization routine 6213 // void *reduce_comb; // data combiner routine 6214 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6215 // } kmp_task_red_input_t; 6216 ASTContext &C = CGM.getContext(); 6217 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6218 RD->startDefinition(); 6219 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6220 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6221 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6222 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6223 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6224 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6225 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6226 RD->completeDefinition(); 6227 QualType RDType = C.getRecordType(RD); 6228 unsigned Size = Data.ReductionVars.size(); 6229 llvm::APInt ArraySize(/*numBits=*/64, Size); 6230 QualType ArrayRDType = C.getConstantArrayType( 6231 RDType, ArraySize, ArrayType::Normal, /*IndexTypeQuals=*/0); 6232 // kmp_task_red_input_t .rd_input.[Size]; 6233 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6234 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6235 Data.ReductionOps); 6236 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6237 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6238 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6239 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6240 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6241 TaskRedInput.getPointer(), Idxs, 6242 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6243 ".rd_input.gep."); 6244 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6245 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6246 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6247 RCG.emitSharedLValue(CGF, Cnt); 6248 llvm::Value *CastedShared = 6249 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer()); 6250 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6251 RCG.emitAggregateType(CGF, Cnt); 6252 llvm::Value *SizeValInChars; 6253 llvm::Value *SizeVal; 6254 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6255 // We use delayed creation/initialization for VLAs, array sections and 6256 // custom reduction initializations. It is required because runtime does not 6257 // provide the way to pass the sizes of VLAs/array sections to 6258 // initializer/combiner/finalizer functions and does not pass the pointer to 6259 // original reduction item to the initializer. Instead threadprivate global 6260 // variables are used to store these values and use them in the functions. 6261 bool DelayedCreation = !!SizeVal; 6262 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6263 /*isSigned=*/false); 6264 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6265 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6266 // ElemLVal.reduce_init = init; 6267 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6268 llvm::Value *InitAddr = 6269 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6270 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6271 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6272 // ElemLVal.reduce_fini = fini; 6273 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6274 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6275 llvm::Value *FiniAddr = Fini 6276 ? CGF.EmitCastToVoidPtr(Fini) 6277 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6278 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6279 // ElemLVal.reduce_comb = comb; 6280 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6281 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6282 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6283 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6284 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6285 // ElemLVal.flags = 0; 6286 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6287 if (DelayedCreation) { 6288 CGF.EmitStoreOfScalar( 6289 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*IsSigned=*/true), 6290 FlagsLVal); 6291 } else 6292 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType()); 6293 } 6294 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6295 // *data); 6296 llvm::Value *Args[] = { 6297 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6298 /*isSigned=*/true), 6299 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6300 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6301 CGM.VoidPtrTy)}; 6302 return CGF.EmitRuntimeCall( 6303 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6304 } 6305 6306 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6307 SourceLocation Loc, 6308 ReductionCodeGen &RCG, 6309 unsigned N) { 6310 auto Sizes = RCG.getSizes(N); 6311 // Emit threadprivate global variable if the type is non-constant 6312 // (Sizes.second = nullptr). 6313 if (Sizes.second) { 6314 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6315 /*isSigned=*/false); 6316 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6317 CGF, CGM.getContext().getSizeType(), 6318 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6319 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6320 } 6321 // Store address of the original reduction item if custom initializer is used. 6322 if (RCG.usesReductionInitializer(N)) { 6323 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6324 CGF, CGM.getContext().VoidPtrTy, 6325 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6326 CGF.Builder.CreateStore( 6327 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6328 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy), 6329 SharedAddr, /*IsVolatile=*/false); 6330 } 6331 } 6332 6333 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6334 SourceLocation Loc, 6335 llvm::Value *ReductionsPtr, 6336 LValue SharedLVal) { 6337 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6338 // *d); 6339 llvm::Value *Args[] = { 6340 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6341 /*isSigned=*/true), 6342 ReductionsPtr, 6343 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(), 6344 CGM.VoidPtrTy)}; 6345 return Address( 6346 CGF.EmitRuntimeCall( 6347 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6348 SharedLVal.getAlignment()); 6349 } 6350 6351 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6352 SourceLocation Loc) { 6353 if (!CGF.HaveInsertPoint()) 6354 return; 6355 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6356 // global_tid); 6357 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6358 // Ignore return result until untied tasks are supported. 6359 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6360 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6361 Region->emitUntiedSwitch(CGF); 6362 } 6363 6364 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6365 OpenMPDirectiveKind InnerKind, 6366 const RegionCodeGenTy &CodeGen, 6367 bool HasCancel) { 6368 if (!CGF.HaveInsertPoint()) 6369 return; 6370 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6371 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6372 } 6373 6374 namespace { 6375 enum RTCancelKind { 6376 CancelNoreq = 0, 6377 CancelParallel = 1, 6378 CancelLoop = 2, 6379 CancelSections = 3, 6380 CancelTaskgroup = 4 6381 }; 6382 } // anonymous namespace 6383 6384 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6385 RTCancelKind CancelKind = CancelNoreq; 6386 if (CancelRegion == OMPD_parallel) 6387 CancelKind = CancelParallel; 6388 else if (CancelRegion == OMPD_for) 6389 CancelKind = CancelLoop; 6390 else if (CancelRegion == OMPD_sections) 6391 CancelKind = CancelSections; 6392 else { 6393 assert(CancelRegion == OMPD_taskgroup); 6394 CancelKind = CancelTaskgroup; 6395 } 6396 return CancelKind; 6397 } 6398 6399 void CGOpenMPRuntime::emitCancellationPointCall( 6400 CodeGenFunction &CGF, SourceLocation Loc, 6401 OpenMPDirectiveKind CancelRegion) { 6402 if (!CGF.HaveInsertPoint()) 6403 return; 6404 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6405 // global_tid, kmp_int32 cncl_kind); 6406 if (auto *OMPRegionInfo = 6407 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6408 // For 'cancellation point taskgroup', the task region info may not have a 6409 // cancel. This may instead happen in another adjacent task. 6410 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6411 llvm::Value *Args[] = { 6412 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6413 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6414 // Ignore return result until untied tasks are supported. 6415 llvm::Value *Result = CGF.EmitRuntimeCall( 6416 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6417 // if (__kmpc_cancellationpoint()) { 6418 // exit from construct; 6419 // } 6420 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6421 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6422 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6423 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6424 CGF.EmitBlock(ExitBB); 6425 // exit from construct; 6426 CodeGenFunction::JumpDest CancelDest = 6427 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6428 CGF.EmitBranchThroughCleanup(CancelDest); 6429 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6430 } 6431 } 6432 } 6433 6434 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6435 const Expr *IfCond, 6436 OpenMPDirectiveKind CancelRegion) { 6437 if (!CGF.HaveInsertPoint()) 6438 return; 6439 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6440 // kmp_int32 cncl_kind); 6441 if (auto *OMPRegionInfo = 6442 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6443 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6444 PrePostActionTy &) { 6445 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6446 llvm::Value *Args[] = { 6447 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6448 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6449 // Ignore return result until untied tasks are supported. 6450 llvm::Value *Result = CGF.EmitRuntimeCall( 6451 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6452 // if (__kmpc_cancel()) { 6453 // exit from construct; 6454 // } 6455 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6456 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6457 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6458 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6459 CGF.EmitBlock(ExitBB); 6460 // exit from construct; 6461 CodeGenFunction::JumpDest CancelDest = 6462 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6463 CGF.EmitBranchThroughCleanup(CancelDest); 6464 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6465 }; 6466 if (IfCond) { 6467 emitOMPIfClause(CGF, IfCond, ThenGen, 6468 [](CodeGenFunction &, PrePostActionTy &) {}); 6469 } else { 6470 RegionCodeGenTy ThenRCG(ThenGen); 6471 ThenRCG(CGF); 6472 } 6473 } 6474 } 6475 6476 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6477 const OMPExecutableDirective &D, StringRef ParentName, 6478 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6479 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6480 assert(!ParentName.empty() && "Invalid target region parent name!"); 6481 HasEmittedTargetRegion = true; 6482 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6483 IsOffloadEntry, CodeGen); 6484 } 6485 6486 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6487 const OMPExecutableDirective &D, StringRef ParentName, 6488 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6489 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6490 // Create a unique name for the entry function using the source location 6491 // information of the current target region. The name will be something like: 6492 // 6493 // __omp_offloading_DD_FFFF_PP_lBB 6494 // 6495 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6496 // mangled name of the function that encloses the target region and BB is the 6497 // line number of the target region. 6498 6499 unsigned DeviceID; 6500 unsigned FileID; 6501 unsigned Line; 6502 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6503 Line); 6504 SmallString<64> EntryFnName; 6505 { 6506 llvm::raw_svector_ostream OS(EntryFnName); 6507 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6508 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6509 } 6510 6511 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6512 6513 CodeGenFunction CGF(CGM, true); 6514 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6515 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6516 6517 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 6518 6519 // If this target outline function is not an offload entry, we don't need to 6520 // register it. 6521 if (!IsOffloadEntry) 6522 return; 6523 6524 // The target region ID is used by the runtime library to identify the current 6525 // target region, so it only has to be unique and not necessarily point to 6526 // anything. It could be the pointer to the outlined function that implements 6527 // the target region, but we aren't using that so that the compiler doesn't 6528 // need to keep that, and could therefore inline the host function if proven 6529 // worthwhile during optimization. In the other hand, if emitting code for the 6530 // device, the ID has to be the function address so that it can retrieved from 6531 // the offloading entry and launched by the runtime library. We also mark the 6532 // outlined function to have external linkage in case we are emitting code for 6533 // the device, because these functions will be entry points to the device. 6534 6535 if (CGM.getLangOpts().OpenMPIsDevice) { 6536 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6537 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6538 OutlinedFn->setDSOLocal(false); 6539 } else { 6540 std::string Name = getName({EntryFnName, "region_id"}); 6541 OutlinedFnID = new llvm::GlobalVariable( 6542 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6543 llvm::GlobalValue::WeakAnyLinkage, 6544 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6545 } 6546 6547 // Register the information for the entry associated with this target region. 6548 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6549 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6550 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6551 } 6552 6553 /// Checks if the expression is constant or does not have non-trivial function 6554 /// calls. 6555 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6556 // We can skip constant expressions. 6557 // We can skip expressions with trivial calls or simple expressions. 6558 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6559 !E->hasNonTrivialCall(Ctx)) && 6560 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6561 } 6562 6563 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6564 const Stmt *Body) { 6565 const Stmt *Child = Body->IgnoreContainers(); 6566 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6567 Child = nullptr; 6568 for (const Stmt *S : C->body()) { 6569 if (const auto *E = dyn_cast<Expr>(S)) { 6570 if (isTrivial(Ctx, E)) 6571 continue; 6572 } 6573 // Some of the statements can be ignored. 6574 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6575 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6576 continue; 6577 // Analyze declarations. 6578 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6579 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6580 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6581 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6582 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6583 isa<UsingDirectiveDecl>(D) || 6584 isa<OMPDeclareReductionDecl>(D) || 6585 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6586 return true; 6587 const auto *VD = dyn_cast<VarDecl>(D); 6588 if (!VD) 6589 return false; 6590 return VD->isConstexpr() || 6591 ((VD->getType().isTrivialType(Ctx) || 6592 VD->getType()->isReferenceType()) && 6593 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6594 })) 6595 continue; 6596 } 6597 // Found multiple children - cannot get the one child only. 6598 if (Child) 6599 return nullptr; 6600 Child = S; 6601 } 6602 if (Child) 6603 Child = Child->IgnoreContainers(); 6604 } 6605 return Child; 6606 } 6607 6608 /// Emit the number of teams for a target directive. Inspect the num_teams 6609 /// clause associated with a teams construct combined or closely nested 6610 /// with the target directive. 6611 /// 6612 /// Emit a team of size one for directives such as 'target parallel' that 6613 /// have no associated teams construct. 6614 /// 6615 /// Otherwise, return nullptr. 6616 static llvm::Value * 6617 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6618 const OMPExecutableDirective &D) { 6619 assert(!CGF.getLangOpts().OpenMPIsDevice && 6620 "Clauses associated with the teams directive expected to be emitted " 6621 "only for the host!"); 6622 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6623 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6624 "Expected target-based executable directive."); 6625 CGBuilderTy &Bld = CGF.Builder; 6626 switch (DirectiveKind) { 6627 case OMPD_target: { 6628 const auto *CS = D.getInnermostCapturedStmt(); 6629 const auto *Body = 6630 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6631 const Stmt *ChildStmt = 6632 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6633 if (const auto *NestedDir = 6634 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6635 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6636 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6637 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6638 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6639 const Expr *NumTeams = 6640 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6641 llvm::Value *NumTeamsVal = 6642 CGF.EmitScalarExpr(NumTeams, 6643 /*IgnoreResultAssign*/ true); 6644 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6645 /*IsSigned=*/true); 6646 } 6647 return Bld.getInt32(0); 6648 } 6649 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6650 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6651 return Bld.getInt32(1); 6652 return Bld.getInt32(0); 6653 } 6654 return nullptr; 6655 } 6656 case OMPD_target_teams: 6657 case OMPD_target_teams_distribute: 6658 case OMPD_target_teams_distribute_simd: 6659 case OMPD_target_teams_distribute_parallel_for: 6660 case OMPD_target_teams_distribute_parallel_for_simd: { 6661 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6662 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6663 const Expr *NumTeams = 6664 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6665 llvm::Value *NumTeamsVal = 6666 CGF.EmitScalarExpr(NumTeams, 6667 /*IgnoreResultAssign*/ true); 6668 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6669 /*IsSigned=*/true); 6670 } 6671 return Bld.getInt32(0); 6672 } 6673 case OMPD_target_parallel: 6674 case OMPD_target_parallel_for: 6675 case OMPD_target_parallel_for_simd: 6676 case OMPD_target_simd: 6677 return Bld.getInt32(1); 6678 case OMPD_parallel: 6679 case OMPD_for: 6680 case OMPD_parallel_for: 6681 case OMPD_parallel_sections: 6682 case OMPD_for_simd: 6683 case OMPD_parallel_for_simd: 6684 case OMPD_cancel: 6685 case OMPD_cancellation_point: 6686 case OMPD_ordered: 6687 case OMPD_threadprivate: 6688 case OMPD_allocate: 6689 case OMPD_task: 6690 case OMPD_simd: 6691 case OMPD_sections: 6692 case OMPD_section: 6693 case OMPD_single: 6694 case OMPD_master: 6695 case OMPD_critical: 6696 case OMPD_taskyield: 6697 case OMPD_barrier: 6698 case OMPD_taskwait: 6699 case OMPD_taskgroup: 6700 case OMPD_atomic: 6701 case OMPD_flush: 6702 case OMPD_teams: 6703 case OMPD_target_data: 6704 case OMPD_target_exit_data: 6705 case OMPD_target_enter_data: 6706 case OMPD_distribute: 6707 case OMPD_distribute_simd: 6708 case OMPD_distribute_parallel_for: 6709 case OMPD_distribute_parallel_for_simd: 6710 case OMPD_teams_distribute: 6711 case OMPD_teams_distribute_simd: 6712 case OMPD_teams_distribute_parallel_for: 6713 case OMPD_teams_distribute_parallel_for_simd: 6714 case OMPD_target_update: 6715 case OMPD_declare_simd: 6716 case OMPD_declare_target: 6717 case OMPD_end_declare_target: 6718 case OMPD_declare_reduction: 6719 case OMPD_declare_mapper: 6720 case OMPD_taskloop: 6721 case OMPD_taskloop_simd: 6722 case OMPD_requires: 6723 case OMPD_unknown: 6724 break; 6725 } 6726 llvm_unreachable("Unexpected directive kind."); 6727 } 6728 6729 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6730 llvm::Value *DefaultThreadLimitVal) { 6731 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6732 CGF.getContext(), CS->getCapturedStmt()); 6733 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6734 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6735 llvm::Value *NumThreads = nullptr; 6736 llvm::Value *CondVal = nullptr; 6737 // Handle if clause. If if clause present, the number of threads is 6738 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6739 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6740 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6741 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6742 const OMPIfClause *IfClause = nullptr; 6743 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6744 if (C->getNameModifier() == OMPD_unknown || 6745 C->getNameModifier() == OMPD_parallel) { 6746 IfClause = C; 6747 break; 6748 } 6749 } 6750 if (IfClause) { 6751 const Expr *Cond = IfClause->getCondition(); 6752 bool Result; 6753 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6754 if (!Result) 6755 return CGF.Builder.getInt32(1); 6756 } else { 6757 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6758 if (const auto *PreInit = 6759 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6760 for (const auto *I : PreInit->decls()) { 6761 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6762 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6763 } else { 6764 CodeGenFunction::AutoVarEmission Emission = 6765 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6766 CGF.EmitAutoVarCleanups(Emission); 6767 } 6768 } 6769 } 6770 CondVal = CGF.EvaluateExprAsBool(Cond); 6771 } 6772 } 6773 } 6774 // Check the value of num_threads clause iff if clause was not specified 6775 // or is not evaluated to false. 6776 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6777 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6778 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6779 const auto *NumThreadsClause = 6780 Dir->getSingleClause<OMPNumThreadsClause>(); 6781 CodeGenFunction::LexicalScope Scope( 6782 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6783 if (const auto *PreInit = 6784 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6785 for (const auto *I : PreInit->decls()) { 6786 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6787 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6788 } else { 6789 CodeGenFunction::AutoVarEmission Emission = 6790 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6791 CGF.EmitAutoVarCleanups(Emission); 6792 } 6793 } 6794 } 6795 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6796 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6797 /*IsSigned=*/false); 6798 if (DefaultThreadLimitVal) 6799 NumThreads = CGF.Builder.CreateSelect( 6800 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6801 DefaultThreadLimitVal, NumThreads); 6802 } else { 6803 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6804 : CGF.Builder.getInt32(0); 6805 } 6806 // Process condition of the if clause. 6807 if (CondVal) { 6808 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6809 CGF.Builder.getInt32(1)); 6810 } 6811 return NumThreads; 6812 } 6813 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6814 return CGF.Builder.getInt32(1); 6815 return DefaultThreadLimitVal; 6816 } 6817 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6818 : CGF.Builder.getInt32(0); 6819 } 6820 6821 /// Emit the number of threads for a target directive. Inspect the 6822 /// thread_limit clause associated with a teams construct combined or closely 6823 /// nested with the target directive. 6824 /// 6825 /// Emit the num_threads clause for directives such as 'target parallel' that 6826 /// have no associated teams construct. 6827 /// 6828 /// Otherwise, return nullptr. 6829 static llvm::Value * 6830 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6831 const OMPExecutableDirective &D) { 6832 assert(!CGF.getLangOpts().OpenMPIsDevice && 6833 "Clauses associated with the teams directive expected to be emitted " 6834 "only for the host!"); 6835 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6836 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6837 "Expected target-based executable directive."); 6838 CGBuilderTy &Bld = CGF.Builder; 6839 llvm::Value *ThreadLimitVal = nullptr; 6840 llvm::Value *NumThreadsVal = nullptr; 6841 switch (DirectiveKind) { 6842 case OMPD_target: { 6843 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6844 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6845 return NumThreads; 6846 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6847 CGF.getContext(), CS->getCapturedStmt()); 6848 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6849 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6850 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6851 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6852 const auto *ThreadLimitClause = 6853 Dir->getSingleClause<OMPThreadLimitClause>(); 6854 CodeGenFunction::LexicalScope Scope( 6855 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6856 if (const auto *PreInit = 6857 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6858 for (const auto *I : PreInit->decls()) { 6859 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6860 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6861 } else { 6862 CodeGenFunction::AutoVarEmission Emission = 6863 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6864 CGF.EmitAutoVarCleanups(Emission); 6865 } 6866 } 6867 } 6868 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6869 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6870 ThreadLimitVal = 6871 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false); 6872 } 6873 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6874 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6875 CS = Dir->getInnermostCapturedStmt(); 6876 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6877 CGF.getContext(), CS->getCapturedStmt()); 6878 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6879 } 6880 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6881 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6882 CS = Dir->getInnermostCapturedStmt(); 6883 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6884 return NumThreads; 6885 } 6886 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6887 return Bld.getInt32(1); 6888 } 6889 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6890 } 6891 case OMPD_target_teams: { 6892 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6893 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6894 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6895 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6896 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6897 ThreadLimitVal = 6898 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false); 6899 } 6900 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6901 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6902 return NumThreads; 6903 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6904 CGF.getContext(), CS->getCapturedStmt()); 6905 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6906 if (Dir->getDirectiveKind() == OMPD_distribute) { 6907 CS = Dir->getInnermostCapturedStmt(); 6908 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6909 return NumThreads; 6910 } 6911 } 6912 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6913 } 6914 case OMPD_target_teams_distribute: 6915 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6916 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6917 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6918 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6919 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6920 ThreadLimitVal = 6921 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false); 6922 } 6923 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6924 case OMPD_target_parallel: 6925 case OMPD_target_parallel_for: 6926 case OMPD_target_parallel_for_simd: 6927 case OMPD_target_teams_distribute_parallel_for: 6928 case OMPD_target_teams_distribute_parallel_for_simd: { 6929 llvm::Value *CondVal = nullptr; 6930 // Handle if clause. If if clause present, the number of threads is 6931 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6932 if (D.hasClausesOfKind<OMPIfClause>()) { 6933 const OMPIfClause *IfClause = nullptr; 6934 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6935 if (C->getNameModifier() == OMPD_unknown || 6936 C->getNameModifier() == OMPD_parallel) { 6937 IfClause = C; 6938 break; 6939 } 6940 } 6941 if (IfClause) { 6942 const Expr *Cond = IfClause->getCondition(); 6943 bool Result; 6944 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6945 if (!Result) 6946 return Bld.getInt32(1); 6947 } else { 6948 CodeGenFunction::RunCleanupsScope Scope(CGF); 6949 CondVal = CGF.EvaluateExprAsBool(Cond); 6950 } 6951 } 6952 } 6953 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6954 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6955 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6956 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6957 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6958 ThreadLimitVal = 6959 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false); 6960 } 6961 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6962 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6963 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6964 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6965 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6966 NumThreadsVal = 6967 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*IsSigned=*/false); 6968 ThreadLimitVal = ThreadLimitVal 6969 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6970 ThreadLimitVal), 6971 NumThreadsVal, ThreadLimitVal) 6972 : NumThreadsVal; 6973 } 6974 if (!ThreadLimitVal) 6975 ThreadLimitVal = Bld.getInt32(0); 6976 if (CondVal) 6977 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 6978 return ThreadLimitVal; 6979 } 6980 case OMPD_target_teams_distribute_simd: 6981 case OMPD_target_simd: 6982 return Bld.getInt32(1); 6983 case OMPD_parallel: 6984 case OMPD_for: 6985 case OMPD_parallel_for: 6986 case OMPD_parallel_sections: 6987 case OMPD_for_simd: 6988 case OMPD_parallel_for_simd: 6989 case OMPD_cancel: 6990 case OMPD_cancellation_point: 6991 case OMPD_ordered: 6992 case OMPD_threadprivate: 6993 case OMPD_allocate: 6994 case OMPD_task: 6995 case OMPD_simd: 6996 case OMPD_sections: 6997 case OMPD_section: 6998 case OMPD_single: 6999 case OMPD_master: 7000 case OMPD_critical: 7001 case OMPD_taskyield: 7002 case OMPD_barrier: 7003 case OMPD_taskwait: 7004 case OMPD_taskgroup: 7005 case OMPD_atomic: 7006 case OMPD_flush: 7007 case OMPD_teams: 7008 case OMPD_target_data: 7009 case OMPD_target_exit_data: 7010 case OMPD_target_enter_data: 7011 case OMPD_distribute: 7012 case OMPD_distribute_simd: 7013 case OMPD_distribute_parallel_for: 7014 case OMPD_distribute_parallel_for_simd: 7015 case OMPD_teams_distribute: 7016 case OMPD_teams_distribute_simd: 7017 case OMPD_teams_distribute_parallel_for: 7018 case OMPD_teams_distribute_parallel_for_simd: 7019 case OMPD_target_update: 7020 case OMPD_declare_simd: 7021 case OMPD_declare_target: 7022 case OMPD_end_declare_target: 7023 case OMPD_declare_reduction: 7024 case OMPD_declare_mapper: 7025 case OMPD_taskloop: 7026 case OMPD_taskloop_simd: 7027 case OMPD_requires: 7028 case OMPD_unknown: 7029 break; 7030 } 7031 llvm_unreachable("Unsupported directive kind."); 7032 } 7033 7034 namespace { 7035 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7036 7037 // Utility to handle information from clauses associated with a given 7038 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7039 // It provides a convenient interface to obtain the information and generate 7040 // code for that information. 7041 class MappableExprsHandler { 7042 public: 7043 /// Values for bit flags used to specify the mapping type for 7044 /// offloading. 7045 enum OpenMPOffloadMappingFlags : uint64_t { 7046 /// No flags 7047 OMP_MAP_NONE = 0x0, 7048 /// Allocate memory on the device and move data from host to device. 7049 OMP_MAP_TO = 0x01, 7050 /// Allocate memory on the device and move data from device to host. 7051 OMP_MAP_FROM = 0x02, 7052 /// Always perform the requested mapping action on the element, even 7053 /// if it was already mapped before. 7054 OMP_MAP_ALWAYS = 0x04, 7055 /// Delete the element from the device environment, ignoring the 7056 /// current reference count associated with the element. 7057 OMP_MAP_DELETE = 0x08, 7058 /// The element being mapped is a pointer-pointee pair; both the 7059 /// pointer and the pointee should be mapped. 7060 OMP_MAP_PTR_AND_OBJ = 0x10, 7061 /// This flags signals that the base address of an entry should be 7062 /// passed to the target kernel as an argument. 7063 OMP_MAP_TARGET_PARAM = 0x20, 7064 /// Signal that the runtime library has to return the device pointer 7065 /// in the current position for the data being mapped. Used when we have the 7066 /// use_device_ptr clause. 7067 OMP_MAP_RETURN_PARAM = 0x40, 7068 /// This flag signals that the reference being passed is a pointer to 7069 /// private data. 7070 OMP_MAP_PRIVATE = 0x80, 7071 /// Pass the element to the device by value. 7072 OMP_MAP_LITERAL = 0x100, 7073 /// Implicit map 7074 OMP_MAP_IMPLICIT = 0x200, 7075 /// The 16 MSBs of the flags indicate whether the entry is member of some 7076 /// struct/class. 7077 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7078 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7079 }; 7080 7081 /// Class that associates information with a base pointer to be passed to the 7082 /// runtime library. 7083 class BasePointerInfo { 7084 /// The base pointer. 7085 llvm::Value *Ptr = nullptr; 7086 /// The base declaration that refers to this device pointer, or null if 7087 /// there is none. 7088 const ValueDecl *DevPtrDecl = nullptr; 7089 7090 public: 7091 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7092 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7093 llvm::Value *operator*() const { return Ptr; } 7094 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7095 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7096 }; 7097 7098 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7099 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7100 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7101 7102 /// Map between a struct and the its lowest & highest elements which have been 7103 /// mapped. 7104 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7105 /// HE(FieldIndex, Pointer)} 7106 struct StructRangeInfoTy { 7107 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7108 0, Address::invalid()}; 7109 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7110 0, Address::invalid()}; 7111 Address Base = Address::invalid(); 7112 }; 7113 7114 private: 7115 /// Kind that defines how a device pointer has to be returned. 7116 struct MapInfo { 7117 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7118 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7119 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7120 bool ReturnDevicePointer = false; 7121 bool IsImplicit = false; 7122 7123 MapInfo() = default; 7124 MapInfo( 7125 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7126 OpenMPMapClauseKind MapType, 7127 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7128 bool ReturnDevicePointer, bool IsImplicit) 7129 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7130 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7131 }; 7132 7133 /// If use_device_ptr is used on a pointer which is a struct member and there 7134 /// is no map information about it, then emission of that entry is deferred 7135 /// until the whole struct has been processed. 7136 struct DeferredDevicePtrEntryTy { 7137 const Expr *IE = nullptr; 7138 const ValueDecl *VD = nullptr; 7139 7140 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7141 : IE(IE), VD(VD) {} 7142 }; 7143 7144 /// Directive from where the map clauses were extracted. 7145 const OMPExecutableDirective &CurDir; 7146 7147 /// Function the directive is being generated for. 7148 CodeGenFunction &CGF; 7149 7150 /// Set of all first private variables in the current directive. 7151 llvm::SmallPtrSet<const VarDecl *, 8> FirstPrivateDecls; 7152 7153 /// Map between device pointer declarations and their expression components. 7154 /// The key value for declarations in 'this' is null. 7155 llvm::DenseMap< 7156 const ValueDecl *, 7157 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7158 DevPointersMap; 7159 7160 llvm::Value *getExprTypeSize(const Expr *E) const { 7161 QualType ExprTy = E->getType().getCanonicalType(); 7162 7163 // Reference types are ignored for mapping purposes. 7164 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7165 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7166 7167 // Given that an array section is considered a built-in type, we need to 7168 // do the calculation based on the length of the section instead of relying 7169 // on CGF.getTypeSize(E->getType()). 7170 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7171 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7172 OAE->getBase()->IgnoreParenImpCasts()) 7173 .getCanonicalType(); 7174 7175 // If there is no length associated with the expression, that means we 7176 // are using the whole length of the base. 7177 if (!OAE->getLength() && OAE->getColonLoc().isValid()) 7178 return CGF.getTypeSize(BaseTy); 7179 7180 llvm::Value *ElemSize; 7181 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7182 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7183 } else { 7184 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7185 assert(ATy && "Expecting array type if not a pointer type."); 7186 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7187 } 7188 7189 // If we don't have a length at this point, that is because we have an 7190 // array section with a single element. 7191 if (!OAE->getLength()) 7192 return ElemSize; 7193 7194 llvm::Value *LengthVal = CGF.EmitScalarExpr(OAE->getLength()); 7195 LengthVal = 7196 CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false); 7197 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7198 } 7199 return CGF.getTypeSize(ExprTy); 7200 } 7201 7202 /// Return the corresponding bits for a given map clause modifier. Add 7203 /// a flag marking the map as a pointer if requested. Add a flag marking the 7204 /// map as the first one of a series of maps that relate to the same map 7205 /// expression. 7206 OpenMPOffloadMappingFlags getMapTypeBits( 7207 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7208 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7209 OpenMPOffloadMappingFlags Bits = 7210 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7211 switch (MapType) { 7212 case OMPC_MAP_alloc: 7213 case OMPC_MAP_release: 7214 // alloc and release is the default behavior in the runtime library, i.e. 7215 // if we don't pass any bits alloc/release that is what the runtime is 7216 // going to do. Therefore, we don't need to signal anything for these two 7217 // type modifiers. 7218 break; 7219 case OMPC_MAP_to: 7220 Bits |= OMP_MAP_TO; 7221 break; 7222 case OMPC_MAP_from: 7223 Bits |= OMP_MAP_FROM; 7224 break; 7225 case OMPC_MAP_tofrom: 7226 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7227 break; 7228 case OMPC_MAP_delete: 7229 Bits |= OMP_MAP_DELETE; 7230 break; 7231 case OMPC_MAP_unknown: 7232 llvm_unreachable("Unexpected map type!"); 7233 } 7234 if (AddPtrFlag) 7235 Bits |= OMP_MAP_PTR_AND_OBJ; 7236 if (AddIsTargetParamFlag) 7237 Bits |= OMP_MAP_TARGET_PARAM; 7238 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7239 != MapModifiers.end()) 7240 Bits |= OMP_MAP_ALWAYS; 7241 return Bits; 7242 } 7243 7244 /// Return true if the provided expression is a final array section. A 7245 /// final array section, is one whose length can't be proved to be one. 7246 bool isFinalArraySectionExpression(const Expr *E) const { 7247 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7248 7249 // It is not an array section and therefore not a unity-size one. 7250 if (!OASE) 7251 return false; 7252 7253 // An array section with no colon always refer to a single element. 7254 if (OASE->getColonLoc().isInvalid()) 7255 return false; 7256 7257 const Expr *Length = OASE->getLength(); 7258 7259 // If we don't have a length we have to check if the array has size 1 7260 // for this dimension. Also, we should always expect a length if the 7261 // base type is pointer. 7262 if (!Length) { 7263 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7264 OASE->getBase()->IgnoreParenImpCasts()) 7265 .getCanonicalType(); 7266 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7267 return ATy->getSize().getSExtValue() != 1; 7268 // If we don't have a constant dimension length, we have to consider 7269 // the current section as having any size, so it is not necessarily 7270 // unitary. If it happen to be unity size, that's user fault. 7271 return true; 7272 } 7273 7274 // Check if the length evaluates to 1. 7275 Expr::EvalResult Result; 7276 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7277 return true; // Can have more that size 1. 7278 7279 llvm::APSInt ConstLength = Result.Val.getInt(); 7280 return ConstLength.getSExtValue() != 1; 7281 } 7282 7283 /// Generate the base pointers, section pointers, sizes and map type 7284 /// bits for the provided map type, map modifier, and expression components. 7285 /// \a IsFirstComponent should be set to true if the provided set of 7286 /// components is the first associated with a capture. 7287 void generateInfoForComponentList( 7288 OpenMPMapClauseKind MapType, 7289 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7290 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7291 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7292 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7293 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7294 bool IsImplicit, 7295 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7296 OverlappedElements = llvm::None) const { 7297 // The following summarizes what has to be generated for each map and the 7298 // types below. The generated information is expressed in this order: 7299 // base pointer, section pointer, size, flags 7300 // (to add to the ones that come from the map type and modifier). 7301 // 7302 // double d; 7303 // int i[100]; 7304 // float *p; 7305 // 7306 // struct S1 { 7307 // int i; 7308 // float f[50]; 7309 // } 7310 // struct S2 { 7311 // int i; 7312 // float f[50]; 7313 // S1 s; 7314 // double *p; 7315 // struct S2 *ps; 7316 // } 7317 // S2 s; 7318 // S2 *ps; 7319 // 7320 // map(d) 7321 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7322 // 7323 // map(i) 7324 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7325 // 7326 // map(i[1:23]) 7327 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7328 // 7329 // map(p) 7330 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7331 // 7332 // map(p[1:24]) 7333 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7334 // 7335 // map(s) 7336 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7337 // 7338 // map(s.i) 7339 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7340 // 7341 // map(s.s.f) 7342 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7343 // 7344 // map(s.p) 7345 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7346 // 7347 // map(to: s.p[:22]) 7348 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7349 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7350 // &(s.p), &(s.p[0]), 22*sizeof(double), 7351 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7352 // (*) alloc space for struct members, only this is a target parameter 7353 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7354 // optimizes this entry out, same in the examples below) 7355 // (***) map the pointee (map: to) 7356 // 7357 // map(s.ps) 7358 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7359 // 7360 // map(from: s.ps->s.i) 7361 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7362 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7363 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7364 // 7365 // map(to: s.ps->ps) 7366 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7367 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7368 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7369 // 7370 // map(s.ps->ps->ps) 7371 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7372 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7373 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7374 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7375 // 7376 // map(to: s.ps->ps->s.f[:22]) 7377 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7378 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7379 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7380 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7381 // 7382 // map(ps) 7383 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7384 // 7385 // map(ps->i) 7386 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7387 // 7388 // map(ps->s.f) 7389 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7390 // 7391 // map(from: ps->p) 7392 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7393 // 7394 // map(to: ps->p[:22]) 7395 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7396 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7397 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7398 // 7399 // map(ps->ps) 7400 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7401 // 7402 // map(from: ps->ps->s.i) 7403 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7404 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7405 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7406 // 7407 // map(from: ps->ps->ps) 7408 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7409 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7410 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7411 // 7412 // map(ps->ps->ps->ps) 7413 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7414 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7415 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7416 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7417 // 7418 // map(to: ps->ps->ps->s.f[:22]) 7419 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7420 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7421 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7422 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7423 // 7424 // map(to: s.f[:22]) map(from: s.p[:33]) 7425 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7426 // sizeof(double*) (**), TARGET_PARAM 7427 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7428 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7429 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7430 // (*) allocate contiguous space needed to fit all mapped members even if 7431 // we allocate space for members not mapped (in this example, 7432 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7433 // them as well because they fall between &s.f[0] and &s.p) 7434 // 7435 // map(from: s.f[:22]) map(to: ps->p[:33]) 7436 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7437 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7438 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7439 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7440 // (*) the struct this entry pertains to is the 2nd element in the list of 7441 // arguments, hence MEMBER_OF(2) 7442 // 7443 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7444 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7445 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7446 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7447 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7448 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7449 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7450 // (*) the struct this entry pertains to is the 4th element in the list 7451 // of arguments, hence MEMBER_OF(4) 7452 7453 // Track if the map information being generated is the first for a capture. 7454 bool IsCaptureFirstInfo = IsFirstComponentList; 7455 bool IsLink = false; // Is this variable a "declare target link"? 7456 7457 // Scan the components from the base to the complete expression. 7458 auto CI = Components.rbegin(); 7459 auto CE = Components.rend(); 7460 auto I = CI; 7461 7462 // Track if the map information being generated is the first for a list of 7463 // components. 7464 bool IsExpressionFirstInfo = true; 7465 Address BP = Address::invalid(); 7466 const Expr *AssocExpr = I->getAssociatedExpression(); 7467 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7468 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7469 7470 if (isa<MemberExpr>(AssocExpr)) { 7471 // The base is the 'this' pointer. The content of the pointer is going 7472 // to be the base of the field being mapped. 7473 BP = CGF.LoadCXXThisAddress(); 7474 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7475 (OASE && 7476 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7477 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); 7478 } else { 7479 // The base is the reference to the variable. 7480 // BP = &Var. 7481 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); 7482 if (const auto *VD = 7483 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7484 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7485 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) 7486 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) { 7487 IsLink = true; 7488 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD); 7489 } 7490 } 7491 7492 // If the variable is a pointer and is being dereferenced (i.e. is not 7493 // the last component), the base has to be the pointer itself, not its 7494 // reference. References are ignored for mapping purposes. 7495 QualType Ty = 7496 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7497 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7498 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7499 7500 // We do not need to generate individual map information for the 7501 // pointer, it can be associated with the combined storage. 7502 ++I; 7503 } 7504 } 7505 7506 // Track whether a component of the list should be marked as MEMBER_OF some 7507 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7508 // in a component list should be marked as MEMBER_OF, all subsequent entries 7509 // do not belong to the base struct. E.g. 7510 // struct S2 s; 7511 // s.ps->ps->ps->f[:] 7512 // (1) (2) (3) (4) 7513 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7514 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7515 // is the pointee of ps(2) which is not member of struct s, so it should not 7516 // be marked as such (it is still PTR_AND_OBJ). 7517 // The variable is initialized to false so that PTR_AND_OBJ entries which 7518 // are not struct members are not considered (e.g. array of pointers to 7519 // data). 7520 bool ShouldBeMemberOf = false; 7521 7522 // Variable keeping track of whether or not we have encountered a component 7523 // in the component list which is a member expression. Useful when we have a 7524 // pointer or a final array section, in which case it is the previous 7525 // component in the list which tells us whether we have a member expression. 7526 // E.g. X.f[:] 7527 // While processing the final array section "[:]" it is "f" which tells us 7528 // whether we are dealing with a member of a declared struct. 7529 const MemberExpr *EncounteredME = nullptr; 7530 7531 for (; I != CE; ++I) { 7532 // If the current component is member of a struct (parent struct) mark it. 7533 if (!EncounteredME) { 7534 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7535 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7536 // as MEMBER_OF the parent struct. 7537 if (EncounteredME) 7538 ShouldBeMemberOf = true; 7539 } 7540 7541 auto Next = std::next(I); 7542 7543 // We need to generate the addresses and sizes if this is the last 7544 // component, if the component is a pointer or if it is an array section 7545 // whose length can't be proved to be one. If this is a pointer, it 7546 // becomes the base address for the following components. 7547 7548 // A final array section, is one whose length can't be proved to be one. 7549 bool IsFinalArraySection = 7550 isFinalArraySectionExpression(I->getAssociatedExpression()); 7551 7552 // Get information on whether the element is a pointer. Have to do a 7553 // special treatment for array sections given that they are built-in 7554 // types. 7555 const auto *OASE = 7556 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7557 bool IsPointer = 7558 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7559 .getCanonicalType() 7560 ->isAnyPointerType()) || 7561 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7562 7563 if (Next == CE || IsPointer || IsFinalArraySection) { 7564 // If this is not the last component, we expect the pointer to be 7565 // associated with an array expression or member expression. 7566 assert((Next == CE || 7567 isa<MemberExpr>(Next->getAssociatedExpression()) || 7568 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7569 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 7570 "Unexpected expression"); 7571 7572 Address LB = 7573 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress(); 7574 7575 // If this component is a pointer inside the base struct then we don't 7576 // need to create any entry for it - it will be combined with the object 7577 // it is pointing to into a single PTR_AND_OBJ entry. 7578 bool IsMemberPointer = 7579 IsPointer && EncounteredME && 7580 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7581 EncounteredME); 7582 if (!OverlappedElements.empty()) { 7583 // Handle base element with the info for overlapped elements. 7584 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7585 assert(Next == CE && 7586 "Expected last element for the overlapped elements."); 7587 assert(!IsPointer && 7588 "Unexpected base element with the pointer type."); 7589 // Mark the whole struct as the struct that requires allocation on the 7590 // device. 7591 PartialStruct.LowestElem = {0, LB}; 7592 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7593 I->getAssociatedExpression()->getType()); 7594 Address HB = CGF.Builder.CreateConstGEP( 7595 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7596 CGF.VoidPtrTy), 7597 TypeSize.getQuantity() - 1); 7598 PartialStruct.HighestElem = { 7599 std::numeric_limits<decltype( 7600 PartialStruct.HighestElem.first)>::max(), 7601 HB}; 7602 PartialStruct.Base = BP; 7603 // Emit data for non-overlapped data. 7604 OpenMPOffloadMappingFlags Flags = 7605 OMP_MAP_MEMBER_OF | 7606 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7607 /*AddPtrFlag=*/false, 7608 /*AddIsTargetParamFlag=*/false); 7609 LB = BP; 7610 llvm::Value *Size = nullptr; 7611 // Do bitcopy of all non-overlapped structure elements. 7612 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7613 Component : OverlappedElements) { 7614 Address ComponentLB = Address::invalid(); 7615 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7616 Component) { 7617 if (MC.getAssociatedDeclaration()) { 7618 ComponentLB = 7619 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7620 .getAddress(); 7621 Size = CGF.Builder.CreatePtrDiff( 7622 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7623 CGF.EmitCastToVoidPtr(LB.getPointer())); 7624 break; 7625 } 7626 } 7627 BasePointers.push_back(BP.getPointer()); 7628 Pointers.push_back(LB.getPointer()); 7629 Sizes.push_back(Size); 7630 Types.push_back(Flags); 7631 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7632 } 7633 BasePointers.push_back(BP.getPointer()); 7634 Pointers.push_back(LB.getPointer()); 7635 Size = CGF.Builder.CreatePtrDiff( 7636 CGF.EmitCastToVoidPtr( 7637 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7638 CGF.EmitCastToVoidPtr(LB.getPointer())); 7639 Sizes.push_back(Size); 7640 Types.push_back(Flags); 7641 break; 7642 } 7643 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7644 if (!IsMemberPointer) { 7645 BasePointers.push_back(BP.getPointer()); 7646 Pointers.push_back(LB.getPointer()); 7647 Sizes.push_back(Size); 7648 7649 // We need to add a pointer flag for each map that comes from the 7650 // same expression except for the first one. We also need to signal 7651 // this map is the first one that relates with the current capture 7652 // (there is a set of entries for each capture). 7653 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7654 MapType, MapModifiers, IsImplicit, 7655 !IsExpressionFirstInfo || IsLink, IsCaptureFirstInfo && !IsLink); 7656 7657 if (!IsExpressionFirstInfo) { 7658 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7659 // then we reset the TO/FROM/ALWAYS/DELETE flags. 7660 if (IsPointer) 7661 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7662 OMP_MAP_DELETE); 7663 7664 if (ShouldBeMemberOf) { 7665 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7666 // should be later updated with the correct value of MEMBER_OF. 7667 Flags |= OMP_MAP_MEMBER_OF; 7668 // From now on, all subsequent PTR_AND_OBJ entries should not be 7669 // marked as MEMBER_OF. 7670 ShouldBeMemberOf = false; 7671 } 7672 } 7673 7674 Types.push_back(Flags); 7675 } 7676 7677 // If we have encountered a member expression so far, keep track of the 7678 // mapped member. If the parent is "*this", then the value declaration 7679 // is nullptr. 7680 if (EncounteredME) { 7681 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl()); 7682 unsigned FieldIndex = FD->getFieldIndex(); 7683 7684 // Update info about the lowest and highest elements for this struct 7685 if (!PartialStruct.Base.isValid()) { 7686 PartialStruct.LowestElem = {FieldIndex, LB}; 7687 PartialStruct.HighestElem = {FieldIndex, LB}; 7688 PartialStruct.Base = BP; 7689 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7690 PartialStruct.LowestElem = {FieldIndex, LB}; 7691 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7692 PartialStruct.HighestElem = {FieldIndex, LB}; 7693 } 7694 } 7695 7696 // If we have a final array section, we are done with this expression. 7697 if (IsFinalArraySection) 7698 break; 7699 7700 // The pointer becomes the base for the next element. 7701 if (Next != CE) 7702 BP = LB; 7703 7704 IsExpressionFirstInfo = false; 7705 IsCaptureFirstInfo = false; 7706 } 7707 } 7708 } 7709 7710 /// Return the adjusted map modifiers if the declaration a capture refers to 7711 /// appears in a first-private clause. This is expected to be used only with 7712 /// directives that start with 'target'. 7713 MappableExprsHandler::OpenMPOffloadMappingFlags 7714 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7715 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7716 7717 // A first private variable captured by reference will use only the 7718 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7719 // declaration is known as first-private in this handler. 7720 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7721 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7722 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7723 return MappableExprsHandler::OMP_MAP_ALWAYS | 7724 MappableExprsHandler::OMP_MAP_TO; 7725 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7726 return MappableExprsHandler::OMP_MAP_TO | 7727 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7728 return MappableExprsHandler::OMP_MAP_PRIVATE | 7729 MappableExprsHandler::OMP_MAP_TO; 7730 } 7731 return MappableExprsHandler::OMP_MAP_TO | 7732 MappableExprsHandler::OMP_MAP_FROM; 7733 } 7734 7735 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7736 // Member of is given by the 16 MSB of the flag, so rotate by 48 bits. 7737 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7738 << 48); 7739 } 7740 7741 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7742 OpenMPOffloadMappingFlags MemberOfFlag) { 7743 // If the entry is PTR_AND_OBJ but has not been marked with the special 7744 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7745 // marked as MEMBER_OF. 7746 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7747 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7748 return; 7749 7750 // Reset the placeholder value to prepare the flag for the assignment of the 7751 // proper MEMBER_OF value. 7752 Flags &= ~OMP_MAP_MEMBER_OF; 7753 Flags |= MemberOfFlag; 7754 } 7755 7756 void getPlainLayout(const CXXRecordDecl *RD, 7757 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7758 bool AsBase) const { 7759 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7760 7761 llvm::StructType *St = 7762 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7763 7764 unsigned NumElements = St->getNumElements(); 7765 llvm::SmallVector< 7766 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7767 RecordLayout(NumElements); 7768 7769 // Fill bases. 7770 for (const auto &I : RD->bases()) { 7771 if (I.isVirtual()) 7772 continue; 7773 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7774 // Ignore empty bases. 7775 if (Base->isEmpty() || CGF.getContext() 7776 .getASTRecordLayout(Base) 7777 .getNonVirtualSize() 7778 .isZero()) 7779 continue; 7780 7781 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7782 RecordLayout[FieldIndex] = Base; 7783 } 7784 // Fill in virtual bases. 7785 for (const auto &I : RD->vbases()) { 7786 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7787 // Ignore empty bases. 7788 if (Base->isEmpty()) 7789 continue; 7790 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7791 if (RecordLayout[FieldIndex]) 7792 continue; 7793 RecordLayout[FieldIndex] = Base; 7794 } 7795 // Fill in all the fields. 7796 assert(!RD->isUnion() && "Unexpected union."); 7797 for (const auto *Field : RD->fields()) { 7798 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7799 // will fill in later.) 7800 if (!Field->isBitField()) { 7801 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7802 RecordLayout[FieldIndex] = Field; 7803 } 7804 } 7805 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7806 &Data : RecordLayout) { 7807 if (Data.isNull()) 7808 continue; 7809 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7810 getPlainLayout(Base, Layout, /*AsBase=*/true); 7811 else 7812 Layout.push_back(Data.get<const FieldDecl *>()); 7813 } 7814 } 7815 7816 public: 7817 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7818 : CurDir(Dir), CGF(CGF) { 7819 // Extract firstprivate clause information. 7820 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7821 for (const auto *D : C->varlists()) 7822 FirstPrivateDecls.insert( 7823 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl()); 7824 // Extract device pointer clause information. 7825 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 7826 for (auto L : C->component_lists()) 7827 DevPointersMap[L.first].push_back(L.second); 7828 } 7829 7830 /// Generate code for the combined entry if we have a partially mapped struct 7831 /// and take care of the mapping flags of the arguments corresponding to 7832 /// individual struct members. 7833 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 7834 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7835 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 7836 const StructRangeInfoTy &PartialStruct) const { 7837 // Base is the base of the struct 7838 BasePointers.push_back(PartialStruct.Base.getPointer()); 7839 // Pointer is the address of the lowest element 7840 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 7841 Pointers.push_back(LB); 7842 // Size is (addr of {highest+1} element) - (addr of lowest element) 7843 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 7844 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 7845 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 7846 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 7847 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 7848 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.SizeTy, 7849 /*isSinged=*/false); 7850 Sizes.push_back(Size); 7851 // Map type is always TARGET_PARAM 7852 Types.push_back(OMP_MAP_TARGET_PARAM); 7853 // Remove TARGET_PARAM flag from the first element 7854 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 7855 7856 // All other current entries will be MEMBER_OF the combined entry 7857 // (except for PTR_AND_OBJ entries which do not have a placeholder value 7858 // 0xFFFF in the MEMBER_OF field). 7859 OpenMPOffloadMappingFlags MemberOfFlag = 7860 getMemberOfFlag(BasePointers.size() - 1); 7861 for (auto &M : CurTypes) 7862 setCorrectMemberOfFlag(M, MemberOfFlag); 7863 } 7864 7865 /// Generate all the base pointers, section pointers, sizes and map 7866 /// types for the extracted mappable expressions. Also, for each item that 7867 /// relates with a device pointer, a pair of the relevant declaration and 7868 /// index where it occurs is appended to the device pointers info array. 7869 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 7870 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7871 MapFlagsArrayTy &Types) const { 7872 // We have to process the component lists that relate with the same 7873 // declaration in a single chunk so that we can generate the map flags 7874 // correctly. Therefore, we organize all lists in a map. 7875 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7876 7877 // Helper function to fill the information map for the different supported 7878 // clauses. 7879 auto &&InfoGen = [&Info]( 7880 const ValueDecl *D, 7881 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 7882 OpenMPMapClauseKind MapType, 7883 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7884 bool ReturnDevicePointer, bool IsImplicit) { 7885 const ValueDecl *VD = 7886 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 7887 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 7888 IsImplicit); 7889 }; 7890 7891 // FIXME: MSVC 2013 seems to require this-> to find member CurDir. 7892 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) 7893 for (const auto &L : C->component_lists()) { 7894 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 7895 /*ReturnDevicePointer=*/false, C->isImplicit()); 7896 } 7897 for (const auto *C : this->CurDir.getClausesOfKind<OMPToClause>()) 7898 for (const auto &L : C->component_lists()) { 7899 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 7900 /*ReturnDevicePointer=*/false, C->isImplicit()); 7901 } 7902 for (const auto *C : this->CurDir.getClausesOfKind<OMPFromClause>()) 7903 for (const auto &L : C->component_lists()) { 7904 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 7905 /*ReturnDevicePointer=*/false, C->isImplicit()); 7906 } 7907 7908 // Look at the use_device_ptr clause information and mark the existing map 7909 // entries as such. If there is no map information for an entry in the 7910 // use_device_ptr list, we create one with map type 'alloc' and zero size 7911 // section. It is the user fault if that was not mapped before. If there is 7912 // no map information and the pointer is a struct member, then we defer the 7913 // emission of that entry until the whole struct has been processed. 7914 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 7915 DeferredInfo; 7916 7917 // FIXME: MSVC 2013 seems to require this-> to find member CurDir. 7918 for (const auto *C : 7919 this->CurDir.getClausesOfKind<OMPUseDevicePtrClause>()) { 7920 for (const auto &L : C->component_lists()) { 7921 assert(!L.second.empty() && "Not expecting empty list of components!"); 7922 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 7923 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 7924 const Expr *IE = L.second.back().getAssociatedExpression(); 7925 // If the first component is a member expression, we have to look into 7926 // 'this', which maps to null in the map of map information. Otherwise 7927 // look directly for the information. 7928 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 7929 7930 // We potentially have map information for this declaration already. 7931 // Look for the first set of components that refer to it. 7932 if (It != Info.end()) { 7933 auto CI = std::find_if( 7934 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 7935 return MI.Components.back().getAssociatedDeclaration() == VD; 7936 }); 7937 // If we found a map entry, signal that the pointer has to be returned 7938 // and move on to the next declaration. 7939 if (CI != It->second.end()) { 7940 CI->ReturnDevicePointer = true; 7941 continue; 7942 } 7943 } 7944 7945 // We didn't find any match in our map information - generate a zero 7946 // size array section - if the pointer is a struct member we defer this 7947 // action until the whole struct has been processed. 7948 // FIXME: MSVC 2013 seems to require this-> to find member CGF. 7949 if (isa<MemberExpr>(IE)) { 7950 // Insert the pointer into Info to be processed by 7951 // generateInfoForComponentList. Because it is a member pointer 7952 // without a pointee, no entry will be generated for it, therefore 7953 // we need to generate one after the whole struct has been processed. 7954 // Nonetheless, generateInfoForComponentList must be called to take 7955 // the pointer into account for the calculation of the range of the 7956 // partial struct. 7957 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 7958 /*ReturnDevicePointer=*/false, C->isImplicit()); 7959 DeferredInfo[nullptr].emplace_back(IE, VD); 7960 } else { 7961 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 7962 this->CGF.EmitLValue(IE), IE->getExprLoc()); 7963 BasePointers.emplace_back(Ptr, VD); 7964 Pointers.push_back(Ptr); 7965 Sizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy)); 7966 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 7967 } 7968 } 7969 } 7970 7971 for (const auto &M : Info) { 7972 // We need to know when we generate information for the first component 7973 // associated with a capture, because the mapping flags depend on it. 7974 bool IsFirstComponentList = true; 7975 7976 // Temporary versions of arrays 7977 MapBaseValuesArrayTy CurBasePointers; 7978 MapValuesArrayTy CurPointers; 7979 MapValuesArrayTy CurSizes; 7980 MapFlagsArrayTy CurTypes; 7981 StructRangeInfoTy PartialStruct; 7982 7983 for (const MapInfo &L : M.second) { 7984 assert(!L.Components.empty() && 7985 "Not expecting declaration with no component lists."); 7986 7987 // Remember the current base pointer index. 7988 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 7989 // FIXME: MSVC 2013 seems to require this-> to find the member method. 7990 this->generateInfoForComponentList( 7991 L.MapType, L.MapModifiers, L.Components, CurBasePointers, 7992 CurPointers, CurSizes, CurTypes, PartialStruct, 7993 IsFirstComponentList, L.IsImplicit); 7994 7995 // If this entry relates with a device pointer, set the relevant 7996 // declaration and add the 'return pointer' flag. 7997 if (L.ReturnDevicePointer) { 7998 assert(CurBasePointers.size() > CurrentBasePointersIdx && 7999 "Unexpected number of mapped base pointers."); 8000 8001 const ValueDecl *RelevantVD = 8002 L.Components.back().getAssociatedDeclaration(); 8003 assert(RelevantVD && 8004 "No relevant declaration related with device pointer??"); 8005 8006 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8007 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8008 } 8009 IsFirstComponentList = false; 8010 } 8011 8012 // Append any pending zero-length pointers which are struct members and 8013 // used with use_device_ptr. 8014 auto CI = DeferredInfo.find(M.first); 8015 if (CI != DeferredInfo.end()) { 8016 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8017 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(); 8018 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8019 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8020 CurBasePointers.emplace_back(BasePtr, L.VD); 8021 CurPointers.push_back(Ptr); 8022 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy)); 8023 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8024 // value MEMBER_OF=FFFF so that the entry is later updated with the 8025 // correct value of MEMBER_OF. 8026 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8027 OMP_MAP_MEMBER_OF); 8028 } 8029 } 8030 8031 // If there is an entry in PartialStruct it means we have a struct with 8032 // individual members mapped. Emit an extra combined entry. 8033 if (PartialStruct.Base.isValid()) 8034 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8035 PartialStruct); 8036 8037 // We need to append the results of this capture to what we already have. 8038 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8039 Pointers.append(CurPointers.begin(), CurPointers.end()); 8040 Sizes.append(CurSizes.begin(), CurSizes.end()); 8041 Types.append(CurTypes.begin(), CurTypes.end()); 8042 } 8043 } 8044 8045 /// Emit capture info for lambdas for variables captured by reference. 8046 void generateInfoForLambdaCaptures( 8047 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8048 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8049 MapFlagsArrayTy &Types, 8050 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8051 const auto *RD = VD->getType() 8052 .getCanonicalType() 8053 .getNonReferenceType() 8054 ->getAsCXXRecordDecl(); 8055 if (!RD || !RD->isLambda()) 8056 return; 8057 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8058 LValue VDLVal = CGF.MakeAddrLValue( 8059 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8060 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8061 FieldDecl *ThisCapture = nullptr; 8062 RD->getCaptureFields(Captures, ThisCapture); 8063 if (ThisCapture) { 8064 LValue ThisLVal = 8065 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8066 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8067 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer()); 8068 BasePointers.push_back(ThisLVal.getPointer()); 8069 Pointers.push_back(ThisLValVal.getPointer()); 8070 Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy)); 8071 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8072 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8073 } 8074 for (const LambdaCapture &LC : RD->captures()) { 8075 if (LC.getCaptureKind() != LCK_ByRef) 8076 continue; 8077 const VarDecl *VD = LC.getCapturedVar(); 8078 auto It = Captures.find(VD); 8079 assert(It != Captures.end() && "Found lambda capture without field."); 8080 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8081 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8082 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer()); 8083 BasePointers.push_back(VarLVal.getPointer()); 8084 Pointers.push_back(VarLValVal.getPointer()); 8085 Sizes.push_back(CGF.getTypeSize( 8086 VD->getType().getCanonicalType().getNonReferenceType())); 8087 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8088 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8089 } 8090 } 8091 8092 /// Set correct indices for lambdas captures. 8093 void adjustMemberOfForLambdaCaptures( 8094 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8095 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8096 MapFlagsArrayTy &Types) const { 8097 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8098 // Set correct member_of idx for all implicit lambda captures. 8099 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8100 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8101 continue; 8102 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8103 assert(BasePtr && "Unable to find base lambda address."); 8104 int TgtIdx = -1; 8105 for (unsigned J = I; J > 0; --J) { 8106 unsigned Idx = J - 1; 8107 if (Pointers[Idx] != BasePtr) 8108 continue; 8109 TgtIdx = Idx; 8110 break; 8111 } 8112 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8113 // All other current entries will be MEMBER_OF the combined entry 8114 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8115 // 0xFFFF in the MEMBER_OF field). 8116 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8117 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8118 } 8119 } 8120 8121 /// Generate the base pointers, section pointers, sizes and map types 8122 /// associated to a given capture. 8123 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8124 llvm::Value *Arg, 8125 MapBaseValuesArrayTy &BasePointers, 8126 MapValuesArrayTy &Pointers, 8127 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8128 StructRangeInfoTy &PartialStruct) const { 8129 assert(!Cap->capturesVariableArrayType() && 8130 "Not expecting to generate map info for a variable array type!"); 8131 8132 // We need to know when we generating information for the first component 8133 const ValueDecl *VD = Cap->capturesThis() 8134 ? nullptr 8135 : Cap->getCapturedVar()->getCanonicalDecl(); 8136 8137 // If this declaration appears in a is_device_ptr clause we just have to 8138 // pass the pointer by value. If it is a reference to a declaration, we just 8139 // pass its value. 8140 if (DevPointersMap.count(VD)) { 8141 BasePointers.emplace_back(Arg, VD); 8142 Pointers.push_back(Arg); 8143 Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy)); 8144 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8145 return; 8146 } 8147 8148 using MapData = 8149 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8150 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8151 SmallVector<MapData, 4> DeclComponentLists; 8152 // FIXME: MSVC 2013 seems to require this-> to find member CurDir. 8153 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) { 8154 for (const auto &L : C->decl_component_lists(VD)) { 8155 assert(L.first == VD && 8156 "We got information for the wrong declaration??"); 8157 assert(!L.second.empty() && 8158 "Not expecting declaration with no component lists."); 8159 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8160 C->getMapTypeModifiers(), 8161 C->isImplicit()); 8162 } 8163 } 8164 8165 // Find overlapping elements (including the offset from the base element). 8166 llvm::SmallDenseMap< 8167 const MapData *, 8168 llvm::SmallVector< 8169 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8170 4> 8171 OverlappedData; 8172 size_t Count = 0; 8173 for (const MapData &L : DeclComponentLists) { 8174 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8175 OpenMPMapClauseKind MapType; 8176 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8177 bool IsImplicit; 8178 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8179 ++Count; 8180 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8181 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8182 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8183 auto CI = Components.rbegin(); 8184 auto CE = Components.rend(); 8185 auto SI = Components1.rbegin(); 8186 auto SE = Components1.rend(); 8187 for (; CI != CE && SI != SE; ++CI, ++SI) { 8188 if (CI->getAssociatedExpression()->getStmtClass() != 8189 SI->getAssociatedExpression()->getStmtClass()) 8190 break; 8191 // Are we dealing with different variables/fields? 8192 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8193 break; 8194 } 8195 // Found overlapping if, at least for one component, reached the head of 8196 // the components list. 8197 if (CI == CE || SI == SE) { 8198 assert((CI != CE || SI != SE) && 8199 "Unexpected full match of the mapping components."); 8200 const MapData &BaseData = CI == CE ? L : L1; 8201 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8202 SI == SE ? Components : Components1; 8203 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8204 OverlappedElements.getSecond().push_back(SubData); 8205 } 8206 } 8207 } 8208 // Sort the overlapped elements for each item. 8209 llvm::SmallVector<const FieldDecl *, 4> Layout; 8210 if (!OverlappedData.empty()) { 8211 if (const auto *CRD = 8212 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8213 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8214 else { 8215 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8216 Layout.append(RD->field_begin(), RD->field_end()); 8217 } 8218 } 8219 for (auto &Pair : OverlappedData) { 8220 llvm::sort( 8221 Pair.getSecond(), 8222 [&Layout]( 8223 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8224 OMPClauseMappableExprCommon::MappableExprComponentListRef 8225 Second) { 8226 auto CI = First.rbegin(); 8227 auto CE = First.rend(); 8228 auto SI = Second.rbegin(); 8229 auto SE = Second.rend(); 8230 for (; CI != CE && SI != SE; ++CI, ++SI) { 8231 if (CI->getAssociatedExpression()->getStmtClass() != 8232 SI->getAssociatedExpression()->getStmtClass()) 8233 break; 8234 // Are we dealing with different variables/fields? 8235 if (CI->getAssociatedDeclaration() != 8236 SI->getAssociatedDeclaration()) 8237 break; 8238 } 8239 8240 // Lists contain the same elements. 8241 if (CI == CE && SI == SE) 8242 return false; 8243 8244 // List with less elements is less than list with more elements. 8245 if (CI == CE || SI == SE) 8246 return CI == CE; 8247 8248 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8249 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8250 if (FD1->getParent() == FD2->getParent()) 8251 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8252 const auto It = 8253 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8254 return FD == FD1 || FD == FD2; 8255 }); 8256 return *It == FD1; 8257 }); 8258 } 8259 8260 // Associated with a capture, because the mapping flags depend on it. 8261 // Go through all of the elements with the overlapped elements. 8262 for (const auto &Pair : OverlappedData) { 8263 const MapData &L = *Pair.getFirst(); 8264 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8265 OpenMPMapClauseKind MapType; 8266 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8267 bool IsImplicit; 8268 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8269 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8270 OverlappedComponents = Pair.getSecond(); 8271 bool IsFirstComponentList = true; 8272 generateInfoForComponentList(MapType, MapModifiers, Components, 8273 BasePointers, Pointers, Sizes, Types, 8274 PartialStruct, IsFirstComponentList, 8275 IsImplicit, OverlappedComponents); 8276 } 8277 // Go through other elements without overlapped elements. 8278 bool IsFirstComponentList = OverlappedData.empty(); 8279 for (const MapData &L : DeclComponentLists) { 8280 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8281 OpenMPMapClauseKind MapType; 8282 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8283 bool IsImplicit; 8284 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8285 auto It = OverlappedData.find(&L); 8286 if (It == OverlappedData.end()) 8287 generateInfoForComponentList(MapType, MapModifiers, Components, 8288 BasePointers, Pointers, Sizes, Types, 8289 PartialStruct, IsFirstComponentList, 8290 IsImplicit); 8291 IsFirstComponentList = false; 8292 } 8293 } 8294 8295 /// Generate the base pointers, section pointers, sizes and map types 8296 /// associated with the declare target link variables. 8297 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8298 MapValuesArrayTy &Pointers, 8299 MapValuesArrayTy &Sizes, 8300 MapFlagsArrayTy &Types) const { 8301 // Map other list items in the map clause which are not captured variables 8302 // but "declare target link" global variables. 8303 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) { 8304 for (const auto &L : C->component_lists()) { 8305 if (!L.first) 8306 continue; 8307 const auto *VD = dyn_cast<VarDecl>(L.first); 8308 if (!VD) 8309 continue; 8310 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8311 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8312 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8313 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8314 continue; 8315 StructRangeInfoTy PartialStruct; 8316 generateInfoForComponentList( 8317 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8318 Pointers, Sizes, Types, PartialStruct, 8319 /*IsFirstComponentList=*/true, C->isImplicit()); 8320 assert(!PartialStruct.Base.isValid() && 8321 "No partial structs for declare target link expected."); 8322 } 8323 } 8324 } 8325 8326 /// Generate the default map information for a given capture \a CI, 8327 /// record field declaration \a RI and captured value \a CV. 8328 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8329 const FieldDecl &RI, llvm::Value *CV, 8330 MapBaseValuesArrayTy &CurBasePointers, 8331 MapValuesArrayTy &CurPointers, 8332 MapValuesArrayTy &CurSizes, 8333 MapFlagsArrayTy &CurMapTypes) const { 8334 // Do the default mapping. 8335 if (CI.capturesThis()) { 8336 CurBasePointers.push_back(CV); 8337 CurPointers.push_back(CV); 8338 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8339 CurSizes.push_back(CGF.getTypeSize(PtrTy->getPointeeType())); 8340 // Default map type. 8341 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8342 } else if (CI.capturesVariableByCopy()) { 8343 CurBasePointers.push_back(CV); 8344 CurPointers.push_back(CV); 8345 if (!RI.getType()->isAnyPointerType()) { 8346 // We have to signal to the runtime captures passed by value that are 8347 // not pointers. 8348 CurMapTypes.push_back(OMP_MAP_LITERAL); 8349 CurSizes.push_back(CGF.getTypeSize(RI.getType())); 8350 } else { 8351 // Pointers are implicitly mapped with a zero size and no flags 8352 // (other than first map that is added for all implicit maps). 8353 CurMapTypes.push_back(OMP_MAP_NONE); 8354 CurSizes.push_back(llvm::Constant::getNullValue(CGF.SizeTy)); 8355 } 8356 } else { 8357 assert(CI.capturesVariable() && "Expected captured reference."); 8358 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8359 QualType ElementType = PtrTy->getPointeeType(); 8360 CurSizes.push_back(CGF.getTypeSize(ElementType)); 8361 // The default map type for a scalar/complex type is 'to' because by 8362 // default the value doesn't have to be retrieved. For an aggregate 8363 // type, the default is 'tofrom'. 8364 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8365 const VarDecl *VD = CI.getCapturedVar(); 8366 if (FirstPrivateDecls.count(VD) && 8367 VD->getType().isConstant(CGF.getContext())) { 8368 llvm::Constant *Addr = 8369 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8370 // Copy the value of the original variable to the new global copy. 8371 CGF.Builder.CreateMemCpy( 8372 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(), 8373 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8374 CurSizes.back(), /*isVolatile=*/false); 8375 // Use new global variable as the base pointers. 8376 CurBasePointers.push_back(Addr); 8377 CurPointers.push_back(Addr); 8378 } else { 8379 CurBasePointers.push_back(CV); 8380 if (FirstPrivateDecls.count(VD) && ElementType->isAnyPointerType()) { 8381 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8382 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8383 AlignmentSource::Decl)); 8384 CurPointers.push_back(PtrAddr.getPointer()); 8385 } else { 8386 CurPointers.push_back(CV); 8387 } 8388 } 8389 } 8390 // Every default map produces a single argument which is a target parameter. 8391 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8392 8393 // Add flag stating this is an implicit map. 8394 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8395 } 8396 }; 8397 } // anonymous namespace 8398 8399 /// Emit the arrays used to pass the captures and map information to the 8400 /// offloading runtime library. If there is no map or capture information, 8401 /// return nullptr by reference. 8402 static void 8403 emitOffloadingArrays(CodeGenFunction &CGF, 8404 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8405 MappableExprsHandler::MapValuesArrayTy &Pointers, 8406 MappableExprsHandler::MapValuesArrayTy &Sizes, 8407 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8408 CGOpenMPRuntime::TargetDataInfo &Info) { 8409 CodeGenModule &CGM = CGF.CGM; 8410 ASTContext &Ctx = CGF.getContext(); 8411 8412 // Reset the array information. 8413 Info.clearArrayInfo(); 8414 Info.NumberOfPtrs = BasePointers.size(); 8415 8416 if (Info.NumberOfPtrs) { 8417 // Detect if we have any capture size requiring runtime evaluation of the 8418 // size so that a constant array could be eventually used. 8419 bool hasRuntimeEvaluationCaptureSize = false; 8420 for (llvm::Value *S : Sizes) 8421 if (!isa<llvm::Constant>(S)) { 8422 hasRuntimeEvaluationCaptureSize = true; 8423 break; 8424 } 8425 8426 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8427 QualType PointerArrayType = 8428 Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal, 8429 /*IndexTypeQuals=*/0); 8430 8431 Info.BasePointersArray = 8432 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8433 Info.PointersArray = 8434 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8435 8436 // If we don't have any VLA types or other types that require runtime 8437 // evaluation, we can use a constant array for the map sizes, otherwise we 8438 // need to fill up the arrays as we do for the pointers. 8439 if (hasRuntimeEvaluationCaptureSize) { 8440 QualType SizeArrayType = Ctx.getConstantArrayType( 8441 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal, 8442 /*IndexTypeQuals=*/0); 8443 Info.SizesArray = 8444 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8445 } else { 8446 // We expect all the sizes to be constant, so we collect them to create 8447 // a constant array. 8448 SmallVector<llvm::Constant *, 16> ConstSizes; 8449 for (llvm::Value *S : Sizes) 8450 ConstSizes.push_back(cast<llvm::Constant>(S)); 8451 8452 auto *SizesArrayInit = llvm::ConstantArray::get( 8453 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes); 8454 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8455 auto *SizesArrayGbl = new llvm::GlobalVariable( 8456 CGM.getModule(), SizesArrayInit->getType(), 8457 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8458 SizesArrayInit, Name); 8459 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8460 Info.SizesArray = SizesArrayGbl; 8461 } 8462 8463 // The map types are always constant so we don't need to generate code to 8464 // fill arrays. Instead, we create an array constant. 8465 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8466 llvm::copy(MapTypes, Mapping.begin()); 8467 llvm::Constant *MapTypesArrayInit = 8468 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8469 std::string MaptypesName = 8470 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8471 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8472 CGM.getModule(), MapTypesArrayInit->getType(), 8473 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8474 MapTypesArrayInit, MaptypesName); 8475 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8476 Info.MapTypesArray = MapTypesArrayGbl; 8477 8478 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8479 llvm::Value *BPVal = *BasePointers[I]; 8480 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8481 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8482 Info.BasePointersArray, 0, I); 8483 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8484 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8485 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8486 CGF.Builder.CreateStore(BPVal, BPAddr); 8487 8488 if (Info.requiresDevicePointerInfo()) 8489 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8490 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8491 8492 llvm::Value *PVal = Pointers[I]; 8493 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8494 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8495 Info.PointersArray, 0, I); 8496 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8497 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8498 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8499 CGF.Builder.CreateStore(PVal, PAddr); 8500 8501 if (hasRuntimeEvaluationCaptureSize) { 8502 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8503 llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), 8504 Info.SizesArray, 8505 /*Idx0=*/0, 8506 /*Idx1=*/I); 8507 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType())); 8508 CGF.Builder.CreateStore( 8509 CGF.Builder.CreateIntCast(Sizes[I], CGM.SizeTy, /*isSigned=*/true), 8510 SAddr); 8511 } 8512 } 8513 } 8514 } 8515 /// Emit the arguments to be passed to the runtime library based on the 8516 /// arrays of pointers, sizes and map types. 8517 static void emitOffloadingArraysArgument( 8518 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8519 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8520 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8521 CodeGenModule &CGM = CGF.CGM; 8522 if (Info.NumberOfPtrs) { 8523 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8524 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8525 Info.BasePointersArray, 8526 /*Idx0=*/0, /*Idx1=*/0); 8527 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8528 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8529 Info.PointersArray, 8530 /*Idx0=*/0, 8531 /*Idx1=*/0); 8532 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8533 llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), Info.SizesArray, 8534 /*Idx0=*/0, /*Idx1=*/0); 8535 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8536 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8537 Info.MapTypesArray, 8538 /*Idx0=*/0, 8539 /*Idx1=*/0); 8540 } else { 8541 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8542 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8543 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo()); 8544 MapTypesArrayArg = 8545 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8546 } 8547 } 8548 8549 /// Check for inner distribute directive. 8550 static const OMPExecutableDirective * 8551 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8552 const auto *CS = D.getInnermostCapturedStmt(); 8553 const auto *Body = 8554 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8555 const Stmt *ChildStmt = 8556 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8557 8558 if (const auto *NestedDir = 8559 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8560 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8561 switch (D.getDirectiveKind()) { 8562 case OMPD_target: 8563 if (isOpenMPDistributeDirective(DKind)) 8564 return NestedDir; 8565 if (DKind == OMPD_teams) { 8566 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8567 /*IgnoreCaptured=*/true); 8568 if (!Body) 8569 return nullptr; 8570 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8571 if (const auto *NND = 8572 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8573 DKind = NND->getDirectiveKind(); 8574 if (isOpenMPDistributeDirective(DKind)) 8575 return NND; 8576 } 8577 } 8578 return nullptr; 8579 case OMPD_target_teams: 8580 if (isOpenMPDistributeDirective(DKind)) 8581 return NestedDir; 8582 return nullptr; 8583 case OMPD_target_parallel: 8584 case OMPD_target_simd: 8585 case OMPD_target_parallel_for: 8586 case OMPD_target_parallel_for_simd: 8587 return nullptr; 8588 case OMPD_target_teams_distribute: 8589 case OMPD_target_teams_distribute_simd: 8590 case OMPD_target_teams_distribute_parallel_for: 8591 case OMPD_target_teams_distribute_parallel_for_simd: 8592 case OMPD_parallel: 8593 case OMPD_for: 8594 case OMPD_parallel_for: 8595 case OMPD_parallel_sections: 8596 case OMPD_for_simd: 8597 case OMPD_parallel_for_simd: 8598 case OMPD_cancel: 8599 case OMPD_cancellation_point: 8600 case OMPD_ordered: 8601 case OMPD_threadprivate: 8602 case OMPD_allocate: 8603 case OMPD_task: 8604 case OMPD_simd: 8605 case OMPD_sections: 8606 case OMPD_section: 8607 case OMPD_single: 8608 case OMPD_master: 8609 case OMPD_critical: 8610 case OMPD_taskyield: 8611 case OMPD_barrier: 8612 case OMPD_taskwait: 8613 case OMPD_taskgroup: 8614 case OMPD_atomic: 8615 case OMPD_flush: 8616 case OMPD_teams: 8617 case OMPD_target_data: 8618 case OMPD_target_exit_data: 8619 case OMPD_target_enter_data: 8620 case OMPD_distribute: 8621 case OMPD_distribute_simd: 8622 case OMPD_distribute_parallel_for: 8623 case OMPD_distribute_parallel_for_simd: 8624 case OMPD_teams_distribute: 8625 case OMPD_teams_distribute_simd: 8626 case OMPD_teams_distribute_parallel_for: 8627 case OMPD_teams_distribute_parallel_for_simd: 8628 case OMPD_target_update: 8629 case OMPD_declare_simd: 8630 case OMPD_declare_target: 8631 case OMPD_end_declare_target: 8632 case OMPD_declare_reduction: 8633 case OMPD_declare_mapper: 8634 case OMPD_taskloop: 8635 case OMPD_taskloop_simd: 8636 case OMPD_requires: 8637 case OMPD_unknown: 8638 llvm_unreachable("Unexpected directive."); 8639 } 8640 } 8641 8642 return nullptr; 8643 } 8644 8645 void CGOpenMPRuntime::emitTargetNumIterationsCall( 8646 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *Device, 8647 const llvm::function_ref<llvm::Value *( 8648 CodeGenFunction &CGF, const OMPLoopDirective &D)> &SizeEmitter) { 8649 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 8650 const OMPExecutableDirective *TD = &D; 8651 // Get nested teams distribute kind directive, if any. 8652 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 8653 TD = getNestedDistributeDirective(CGM.getContext(), D); 8654 if (!TD) 8655 return; 8656 const auto *LD = cast<OMPLoopDirective>(TD); 8657 auto &&CodeGen = [LD, &Device, &SizeEmitter, this](CodeGenFunction &CGF, 8658 PrePostActionTy &) { 8659 llvm::Value *NumIterations = SizeEmitter(CGF, *LD); 8660 8661 // Emit device ID if any. 8662 llvm::Value *DeviceID; 8663 if (Device) 8664 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 8665 CGF.Int64Ty, /*isSigned=*/true); 8666 else 8667 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 8668 8669 llvm::Value *Args[] = {DeviceID, NumIterations}; 8670 CGF.EmitRuntimeCall( 8671 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 8672 }; 8673 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 8674 } 8675 8676 void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF, 8677 const OMPExecutableDirective &D, 8678 llvm::Function *OutlinedFn, 8679 llvm::Value *OutlinedFnID, 8680 const Expr *IfCond, const Expr *Device) { 8681 if (!CGF.HaveInsertPoint()) 8682 return; 8683 8684 assert(OutlinedFn && "Invalid outlined function!"); 8685 8686 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 8687 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 8688 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 8689 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 8690 PrePostActionTy &) { 8691 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 8692 }; 8693 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 8694 8695 CodeGenFunction::OMPTargetDataInfo InputInfo; 8696 llvm::Value *MapTypesArray = nullptr; 8697 // Fill up the pointer arrays and transfer execution to the device. 8698 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 8699 &MapTypesArray, &CS, RequiresOuterTask, 8700 &CapturedVars](CodeGenFunction &CGF, PrePostActionTy &) { 8701 // On top of the arrays that were filled up, the target offloading call 8702 // takes as arguments the device id as well as the host pointer. The host 8703 // pointer is used by the runtime library to identify the current target 8704 // region, so it only has to be unique and not necessarily point to 8705 // anything. It could be the pointer to the outlined function that 8706 // implements the target region, but we aren't using that so that the 8707 // compiler doesn't need to keep that, and could therefore inline the host 8708 // function if proven worthwhile during optimization. 8709 8710 // From this point on, we need to have an ID of the target region defined. 8711 assert(OutlinedFnID && "Invalid outlined function ID!"); 8712 8713 // Emit device ID if any. 8714 llvm::Value *DeviceID; 8715 if (Device) { 8716 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 8717 CGF.Int64Ty, /*isSigned=*/true); 8718 } else { 8719 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 8720 } 8721 8722 // Emit the number of elements in the offloading arrays. 8723 llvm::Value *PointerNum = 8724 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 8725 8726 // Return value of the runtime offloading call. 8727 llvm::Value *Return; 8728 8729 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 8730 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 8731 8732 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 8733 // The target region is an outlined function launched by the runtime 8734 // via calls __tgt_target() or __tgt_target_teams(). 8735 // 8736 // __tgt_target() launches a target region with one team and one thread, 8737 // executing a serial region. This master thread may in turn launch 8738 // more threads within its team upon encountering a parallel region, 8739 // however, no additional teams can be launched on the device. 8740 // 8741 // __tgt_target_teams() launches a target region with one or more teams, 8742 // each with one or more threads. This call is required for target 8743 // constructs such as: 8744 // 'target teams' 8745 // 'target' / 'teams' 8746 // 'target teams distribute parallel for' 8747 // 'target parallel' 8748 // and so on. 8749 // 8750 // Note that on the host and CPU targets, the runtime implementation of 8751 // these calls simply call the outlined function without forking threads. 8752 // The outlined functions themselves have runtime calls to 8753 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 8754 // the compiler in emitTeamsCall() and emitParallelCall(). 8755 // 8756 // In contrast, on the NVPTX target, the implementation of 8757 // __tgt_target_teams() launches a GPU kernel with the requested number 8758 // of teams and threads so no additional calls to the runtime are required. 8759 if (NumTeams) { 8760 // If we have NumTeams defined this means that we have an enclosed teams 8761 // region. Therefore we also expect to have NumThreads defined. These two 8762 // values should be defined in the presence of a teams directive, 8763 // regardless of having any clauses associated. If the user is using teams 8764 // but no clauses, these two values will be the default that should be 8765 // passed to the runtime library - a 32-bit integer with the value zero. 8766 assert(NumThreads && "Thread limit expression should be available along " 8767 "with number of teams."); 8768 llvm::Value *OffloadingArgs[] = {DeviceID, 8769 OutlinedFnID, 8770 PointerNum, 8771 InputInfo.BasePointersArray.getPointer(), 8772 InputInfo.PointersArray.getPointer(), 8773 InputInfo.SizesArray.getPointer(), 8774 MapTypesArray, 8775 NumTeams, 8776 NumThreads}; 8777 Return = CGF.EmitRuntimeCall( 8778 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 8779 : OMPRTL__tgt_target_teams), 8780 OffloadingArgs); 8781 } else { 8782 llvm::Value *OffloadingArgs[] = {DeviceID, 8783 OutlinedFnID, 8784 PointerNum, 8785 InputInfo.BasePointersArray.getPointer(), 8786 InputInfo.PointersArray.getPointer(), 8787 InputInfo.SizesArray.getPointer(), 8788 MapTypesArray}; 8789 Return = CGF.EmitRuntimeCall( 8790 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 8791 : OMPRTL__tgt_target), 8792 OffloadingArgs); 8793 } 8794 8795 // Check the error code and execute the host version if required. 8796 llvm::BasicBlock *OffloadFailedBlock = 8797 CGF.createBasicBlock("omp_offload.failed"); 8798 llvm::BasicBlock *OffloadContBlock = 8799 CGF.createBasicBlock("omp_offload.cont"); 8800 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 8801 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 8802 8803 CGF.EmitBlock(OffloadFailedBlock); 8804 if (RequiresOuterTask) { 8805 CapturedVars.clear(); 8806 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 8807 } 8808 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 8809 CGF.EmitBranch(OffloadContBlock); 8810 8811 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 8812 }; 8813 8814 // Notify that the host version must be executed. 8815 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 8816 RequiresOuterTask](CodeGenFunction &CGF, 8817 PrePostActionTy &) { 8818 if (RequiresOuterTask) { 8819 CapturedVars.clear(); 8820 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 8821 } 8822 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 8823 }; 8824 8825 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 8826 &CapturedVars, RequiresOuterTask, 8827 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 8828 // Fill up the arrays with all the captured variables. 8829 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 8830 MappableExprsHandler::MapValuesArrayTy Pointers; 8831 MappableExprsHandler::MapValuesArrayTy Sizes; 8832 MappableExprsHandler::MapFlagsArrayTy MapTypes; 8833 8834 // Get mappable expression information. 8835 MappableExprsHandler MEHandler(D, CGF); 8836 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 8837 8838 auto RI = CS.getCapturedRecordDecl()->field_begin(); 8839 auto CV = CapturedVars.begin(); 8840 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 8841 CE = CS.capture_end(); 8842 CI != CE; ++CI, ++RI, ++CV) { 8843 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 8844 MappableExprsHandler::MapValuesArrayTy CurPointers; 8845 MappableExprsHandler::MapValuesArrayTy CurSizes; 8846 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 8847 MappableExprsHandler::StructRangeInfoTy PartialStruct; 8848 8849 // VLA sizes are passed to the outlined region by copy and do not have map 8850 // information associated. 8851 if (CI->capturesVariableArrayType()) { 8852 CurBasePointers.push_back(*CV); 8853 CurPointers.push_back(*CV); 8854 CurSizes.push_back(CGF.getTypeSize(RI->getType())); 8855 // Copy to the device as an argument. No need to retrieve it. 8856 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 8857 MappableExprsHandler::OMP_MAP_TARGET_PARAM); 8858 } else { 8859 // If we have any information in the map clause, we use it, otherwise we 8860 // just do a default mapping. 8861 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 8862 CurSizes, CurMapTypes, PartialStruct); 8863 if (CurBasePointers.empty()) 8864 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 8865 CurPointers, CurSizes, CurMapTypes); 8866 // Generate correct mapping for variables captured by reference in 8867 // lambdas. 8868 if (CI->capturesVariable()) 8869 MEHandler.generateInfoForLambdaCaptures( 8870 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 8871 CurMapTypes, LambdaPointers); 8872 } 8873 // We expect to have at least an element of information for this capture. 8874 assert(!CurBasePointers.empty() && 8875 "Non-existing map pointer for capture!"); 8876 assert(CurBasePointers.size() == CurPointers.size() && 8877 CurBasePointers.size() == CurSizes.size() && 8878 CurBasePointers.size() == CurMapTypes.size() && 8879 "Inconsistent map information sizes!"); 8880 8881 // If there is an entry in PartialStruct it means we have a struct with 8882 // individual members mapped. Emit an extra combined entry. 8883 if (PartialStruct.Base.isValid()) 8884 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 8885 CurMapTypes, PartialStruct); 8886 8887 // We need to append the results of this capture to what we already have. 8888 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8889 Pointers.append(CurPointers.begin(), CurPointers.end()); 8890 Sizes.append(CurSizes.begin(), CurSizes.end()); 8891 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 8892 } 8893 // Adjust MEMBER_OF flags for the lambdas captures. 8894 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 8895 Pointers, MapTypes); 8896 // Map other list items in the map clause which are not captured variables 8897 // but "declare target link" global variables. 8898 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 8899 MapTypes); 8900 8901 TargetDataInfo Info; 8902 // Fill up the arrays and create the arguments. 8903 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 8904 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 8905 Info.PointersArray, Info.SizesArray, 8906 Info.MapTypesArray, Info); 8907 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 8908 InputInfo.BasePointersArray = 8909 Address(Info.BasePointersArray, CGM.getPointerAlign()); 8910 InputInfo.PointersArray = 8911 Address(Info.PointersArray, CGM.getPointerAlign()); 8912 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 8913 MapTypesArray = Info.MapTypesArray; 8914 if (RequiresOuterTask) 8915 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 8916 else 8917 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 8918 }; 8919 8920 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 8921 CodeGenFunction &CGF, PrePostActionTy &) { 8922 if (RequiresOuterTask) { 8923 CodeGenFunction::OMPTargetDataInfo InputInfo; 8924 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 8925 } else { 8926 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 8927 } 8928 }; 8929 8930 // If we have a target function ID it means that we need to support 8931 // offloading, otherwise, just execute on the host. We need to execute on host 8932 // regardless of the conditional in the if clause if, e.g., the user do not 8933 // specify target triples. 8934 if (OutlinedFnID) { 8935 if (IfCond) { 8936 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 8937 } else { 8938 RegionCodeGenTy ThenRCG(TargetThenGen); 8939 ThenRCG(CGF); 8940 } 8941 } else { 8942 RegionCodeGenTy ElseRCG(TargetElseGen); 8943 ElseRCG(CGF); 8944 } 8945 } 8946 8947 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 8948 StringRef ParentName) { 8949 if (!S) 8950 return; 8951 8952 // Codegen OMP target directives that offload compute to the device. 8953 bool RequiresDeviceCodegen = 8954 isa<OMPExecutableDirective>(S) && 8955 isOpenMPTargetExecutionDirective( 8956 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 8957 8958 if (RequiresDeviceCodegen) { 8959 const auto &E = *cast<OMPExecutableDirective>(S); 8960 unsigned DeviceID; 8961 unsigned FileID; 8962 unsigned Line; 8963 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 8964 FileID, Line); 8965 8966 // Is this a target region that should not be emitted as an entry point? If 8967 // so just signal we are done with this target region. 8968 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 8969 ParentName, Line)) 8970 return; 8971 8972 switch (E.getDirectiveKind()) { 8973 case OMPD_target: 8974 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 8975 cast<OMPTargetDirective>(E)); 8976 break; 8977 case OMPD_target_parallel: 8978 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 8979 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 8980 break; 8981 case OMPD_target_teams: 8982 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 8983 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 8984 break; 8985 case OMPD_target_teams_distribute: 8986 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 8987 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 8988 break; 8989 case OMPD_target_teams_distribute_simd: 8990 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 8991 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 8992 break; 8993 case OMPD_target_parallel_for: 8994 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 8995 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 8996 break; 8997 case OMPD_target_parallel_for_simd: 8998 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 8999 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9000 break; 9001 case OMPD_target_simd: 9002 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9003 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9004 break; 9005 case OMPD_target_teams_distribute_parallel_for: 9006 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9007 CGM, ParentName, 9008 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9009 break; 9010 case OMPD_target_teams_distribute_parallel_for_simd: 9011 CodeGenFunction:: 9012 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9013 CGM, ParentName, 9014 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9015 break; 9016 case OMPD_parallel: 9017 case OMPD_for: 9018 case OMPD_parallel_for: 9019 case OMPD_parallel_sections: 9020 case OMPD_for_simd: 9021 case OMPD_parallel_for_simd: 9022 case OMPD_cancel: 9023 case OMPD_cancellation_point: 9024 case OMPD_ordered: 9025 case OMPD_threadprivate: 9026 case OMPD_allocate: 9027 case OMPD_task: 9028 case OMPD_simd: 9029 case OMPD_sections: 9030 case OMPD_section: 9031 case OMPD_single: 9032 case OMPD_master: 9033 case OMPD_critical: 9034 case OMPD_taskyield: 9035 case OMPD_barrier: 9036 case OMPD_taskwait: 9037 case OMPD_taskgroup: 9038 case OMPD_atomic: 9039 case OMPD_flush: 9040 case OMPD_teams: 9041 case OMPD_target_data: 9042 case OMPD_target_exit_data: 9043 case OMPD_target_enter_data: 9044 case OMPD_distribute: 9045 case OMPD_distribute_simd: 9046 case OMPD_distribute_parallel_for: 9047 case OMPD_distribute_parallel_for_simd: 9048 case OMPD_teams_distribute: 9049 case OMPD_teams_distribute_simd: 9050 case OMPD_teams_distribute_parallel_for: 9051 case OMPD_teams_distribute_parallel_for_simd: 9052 case OMPD_target_update: 9053 case OMPD_declare_simd: 9054 case OMPD_declare_target: 9055 case OMPD_end_declare_target: 9056 case OMPD_declare_reduction: 9057 case OMPD_declare_mapper: 9058 case OMPD_taskloop: 9059 case OMPD_taskloop_simd: 9060 case OMPD_requires: 9061 case OMPD_unknown: 9062 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9063 } 9064 return; 9065 } 9066 9067 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9068 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9069 return; 9070 9071 scanForTargetRegionsFunctions( 9072 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9073 return; 9074 } 9075 9076 // If this is a lambda function, look into its body. 9077 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9078 S = L->getBody(); 9079 9080 // Keep looking for target regions recursively. 9081 for (const Stmt *II : S->children()) 9082 scanForTargetRegionsFunctions(II, ParentName); 9083 } 9084 9085 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9086 // If emitting code for the host, we do not process FD here. Instead we do 9087 // the normal code generation. 9088 if (!CGM.getLangOpts().OpenMPIsDevice) 9089 return false; 9090 9091 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9092 StringRef Name = CGM.getMangledName(GD); 9093 // Try to detect target regions in the function. 9094 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) 9095 scanForTargetRegionsFunctions(FD->getBody(), Name); 9096 9097 // Do not to emit function if it is not marked as declare target. 9098 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9099 AlreadyEmittedTargetFunctions.count(Name) == 0; 9100 } 9101 9102 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9103 if (!CGM.getLangOpts().OpenMPIsDevice) 9104 return false; 9105 9106 // Check if there are Ctors/Dtors in this declaration and look for target 9107 // regions in it. We use the complete variant to produce the kernel name 9108 // mangling. 9109 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9110 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9111 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9112 StringRef ParentName = 9113 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9114 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9115 } 9116 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9117 StringRef ParentName = 9118 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9119 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9120 } 9121 } 9122 9123 // Do not to emit variable if it is not marked as declare target. 9124 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9125 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9126 cast<VarDecl>(GD.getDecl())); 9127 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link) { 9128 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9129 return true; 9130 } 9131 return false; 9132 } 9133 9134 llvm::Constant * 9135 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9136 const VarDecl *VD) { 9137 assert(VD->getType().isConstant(CGM.getContext()) && 9138 "Expected constant variable."); 9139 StringRef VarName; 9140 llvm::Constant *Addr; 9141 llvm::GlobalValue::LinkageTypes Linkage; 9142 QualType Ty = VD->getType(); 9143 SmallString<128> Buffer; 9144 { 9145 unsigned DeviceID; 9146 unsigned FileID; 9147 unsigned Line; 9148 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9149 FileID, Line); 9150 llvm::raw_svector_ostream OS(Buffer); 9151 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9152 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9153 VarName = OS.str(); 9154 } 9155 Linkage = llvm::GlobalValue::InternalLinkage; 9156 Addr = 9157 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9158 getDefaultFirstprivateAddressSpace()); 9159 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9160 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9161 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9162 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9163 VarName, Addr, VarSize, 9164 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9165 return Addr; 9166 } 9167 9168 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9169 llvm::Constant *Addr) { 9170 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9171 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9172 if (!Res) { 9173 if (CGM.getLangOpts().OpenMPIsDevice) { 9174 // Register non-target variables being emitted in device code (debug info 9175 // may cause this). 9176 StringRef VarName = CGM.getMangledName(VD); 9177 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9178 } 9179 return; 9180 } 9181 // Register declare target variables. 9182 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9183 StringRef VarName; 9184 CharUnits VarSize; 9185 llvm::GlobalValue::LinkageTypes Linkage; 9186 switch (*Res) { 9187 case OMPDeclareTargetDeclAttr::MT_To: 9188 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9189 VarName = CGM.getMangledName(VD); 9190 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9191 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9192 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9193 } else { 9194 VarSize = CharUnits::Zero(); 9195 } 9196 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9197 // Temp solution to prevent optimizations of the internal variables. 9198 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9199 std::string RefName = getName({VarName, "ref"}); 9200 if (!CGM.GetGlobalValue(RefName)) { 9201 llvm::Constant *AddrRef = 9202 getOrCreateInternalVariable(Addr->getType(), RefName); 9203 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9204 GVAddrRef->setConstant(/*Val=*/true); 9205 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9206 GVAddrRef->setInitializer(Addr); 9207 CGM.addCompilerUsedGlobal(GVAddrRef); 9208 } 9209 } 9210 break; 9211 case OMPDeclareTargetDeclAttr::MT_Link: 9212 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9213 if (CGM.getLangOpts().OpenMPIsDevice) { 9214 VarName = Addr->getName(); 9215 Addr = nullptr; 9216 } else { 9217 VarName = getAddrOfDeclareTargetLink(VD).getName(); 9218 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetLink(VD).getPointer()); 9219 } 9220 VarSize = CGM.getPointerSize(); 9221 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9222 break; 9223 } 9224 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9225 VarName, Addr, VarSize, Flags, Linkage); 9226 } 9227 9228 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9229 if (isa<FunctionDecl>(GD.getDecl()) || 9230 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9231 return emitTargetFunctions(GD); 9232 9233 return emitTargetGlobalVariable(GD); 9234 } 9235 9236 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9237 for (const VarDecl *VD : DeferredGlobalVariables) { 9238 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9239 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9240 if (!Res) 9241 continue; 9242 if (*Res == OMPDeclareTargetDeclAttr::MT_To) { 9243 CGM.EmitGlobal(VD); 9244 } else { 9245 assert(*Res == OMPDeclareTargetDeclAttr::MT_Link && 9246 "Expected to or link clauses."); 9247 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD); 9248 } 9249 } 9250 } 9251 9252 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9253 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9254 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9255 " Expected target-based directive."); 9256 } 9257 9258 void CGOpenMPRuntime::checkArchForUnifiedAddressing( 9259 const OMPRequiresDecl *D) { 9260 for (const OMPClause *Clause : D->clauselists()) { 9261 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9262 HasRequiresUnifiedSharedMemory = true; 9263 break; 9264 } 9265 } 9266 } 9267 9268 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9269 LangAS &AS) { 9270 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9271 return false; 9272 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9273 switch(A->getAllocatorType()) { 9274 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9275 // Not supported, fallback to the default mem space. 9276 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9277 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9278 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9279 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9280 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9281 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9282 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9283 AS = LangAS::Default; 9284 return true; 9285 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9286 llvm_unreachable("Expected predefined allocator for the variables with the " 9287 "static storage."); 9288 } 9289 return false; 9290 } 9291 9292 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9293 return HasRequiresUnifiedSharedMemory; 9294 } 9295 9296 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9297 CodeGenModule &CGM) 9298 : CGM(CGM) { 9299 if (CGM.getLangOpts().OpenMPIsDevice) { 9300 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9301 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9302 } 9303 } 9304 9305 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9306 if (CGM.getLangOpts().OpenMPIsDevice) 9307 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9308 } 9309 9310 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9311 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9312 return true; 9313 9314 StringRef Name = CGM.getMangledName(GD); 9315 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9316 // Do not to emit function if it is marked as declare target as it was already 9317 // emitted. 9318 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9319 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) { 9320 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name))) 9321 return !F->isDeclaration(); 9322 return false; 9323 } 9324 return true; 9325 } 9326 9327 return !AlreadyEmittedTargetFunctions.insert(Name).second; 9328 } 9329 9330 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9331 // If we don't have entries or if we are emitting code for the device, we 9332 // don't need to do anything. 9333 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9334 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9335 (OffloadEntriesInfoManager.empty() && 9336 !HasEmittedDeclareTargetRegion && 9337 !HasEmittedTargetRegion)) 9338 return nullptr; 9339 9340 // Create and register the function that handles the requires directives. 9341 ASTContext &C = CGM.getContext(); 9342 9343 llvm::Function *RequiresRegFn; 9344 { 9345 CodeGenFunction CGF(CGM); 9346 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 9347 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 9348 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 9349 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 9350 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 9351 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 9352 // TODO: check for other requires clauses. 9353 // The requires directive takes effect only when a target region is 9354 // present in the compilation unit. Otherwise it is ignored and not 9355 // passed to the runtime. This avoids the runtime from throwing an error 9356 // for mismatching requires clauses across compilation units that don't 9357 // contain at least 1 target region. 9358 assert((HasEmittedTargetRegion || 9359 HasEmittedDeclareTargetRegion || 9360 !OffloadEntriesInfoManager.empty()) && 9361 "Target or declare target region expected."); 9362 if (HasRequiresUnifiedSharedMemory) 9363 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 9364 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 9365 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 9366 CGF.FinishFunction(); 9367 } 9368 return RequiresRegFn; 9369 } 9370 9371 llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() { 9372 // If we have offloading in the current module, we need to emit the entries 9373 // now and register the offloading descriptor. 9374 createOffloadEntriesAndInfoMetadata(); 9375 9376 // Create and register the offloading binary descriptors. This is the main 9377 // entity that captures all the information about offloading in the current 9378 // compilation unit. 9379 return createOffloadingBinaryDescriptorRegistration(); 9380 } 9381 9382 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 9383 const OMPExecutableDirective &D, 9384 SourceLocation Loc, 9385 llvm::Function *OutlinedFn, 9386 ArrayRef<llvm::Value *> CapturedVars) { 9387 if (!CGF.HaveInsertPoint()) 9388 return; 9389 9390 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9391 CodeGenFunction::RunCleanupsScope Scope(CGF); 9392 9393 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 9394 llvm::Value *Args[] = { 9395 RTLoc, 9396 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 9397 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 9398 llvm::SmallVector<llvm::Value *, 16> RealArgs; 9399 RealArgs.append(std::begin(Args), std::end(Args)); 9400 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 9401 9402 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 9403 CGF.EmitRuntimeCall(RTLFn, RealArgs); 9404 } 9405 9406 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 9407 const Expr *NumTeams, 9408 const Expr *ThreadLimit, 9409 SourceLocation Loc) { 9410 if (!CGF.HaveInsertPoint()) 9411 return; 9412 9413 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9414 9415 llvm::Value *NumTeamsVal = 9416 NumTeams 9417 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 9418 CGF.CGM.Int32Ty, /* isSigned = */ true) 9419 : CGF.Builder.getInt32(0); 9420 9421 llvm::Value *ThreadLimitVal = 9422 ThreadLimit 9423 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 9424 CGF.CGM.Int32Ty, /* isSigned = */ true) 9425 : CGF.Builder.getInt32(0); 9426 9427 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 9428 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 9429 ThreadLimitVal}; 9430 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 9431 PushNumTeamsArgs); 9432 } 9433 9434 void CGOpenMPRuntime::emitTargetDataCalls( 9435 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 9436 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 9437 if (!CGF.HaveInsertPoint()) 9438 return; 9439 9440 // Action used to replace the default codegen action and turn privatization 9441 // off. 9442 PrePostActionTy NoPrivAction; 9443 9444 // Generate the code for the opening of the data environment. Capture all the 9445 // arguments of the runtime call by reference because they are used in the 9446 // closing of the region. 9447 auto &&BeginThenGen = [this, &D, Device, &Info, 9448 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 9449 // Fill up the arrays with all the mapped variables. 9450 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9451 MappableExprsHandler::MapValuesArrayTy Pointers; 9452 MappableExprsHandler::MapValuesArrayTy Sizes; 9453 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9454 9455 // Get map clause information. 9456 MappableExprsHandler MCHandler(D, CGF); 9457 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 9458 9459 // Fill up the arrays and create the arguments. 9460 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9461 9462 llvm::Value *BasePointersArrayArg = nullptr; 9463 llvm::Value *PointersArrayArg = nullptr; 9464 llvm::Value *SizesArrayArg = nullptr; 9465 llvm::Value *MapTypesArrayArg = nullptr; 9466 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 9467 SizesArrayArg, MapTypesArrayArg, Info); 9468 9469 // Emit device ID if any. 9470 llvm::Value *DeviceID = nullptr; 9471 if (Device) { 9472 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9473 CGF.Int64Ty, /*isSigned=*/true); 9474 } else { 9475 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9476 } 9477 9478 // Emit the number of elements in the offloading arrays. 9479 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 9480 9481 llvm::Value *OffloadingArgs[] = { 9482 DeviceID, PointerNum, BasePointersArrayArg, 9483 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 9484 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 9485 OffloadingArgs); 9486 9487 // If device pointer privatization is required, emit the body of the region 9488 // here. It will have to be duplicated: with and without privatization. 9489 if (!Info.CaptureDeviceAddrMap.empty()) 9490 CodeGen(CGF); 9491 }; 9492 9493 // Generate code for the closing of the data region. 9494 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 9495 PrePostActionTy &) { 9496 assert(Info.isValid() && "Invalid data environment closing arguments."); 9497 9498 llvm::Value *BasePointersArrayArg = nullptr; 9499 llvm::Value *PointersArrayArg = nullptr; 9500 llvm::Value *SizesArrayArg = nullptr; 9501 llvm::Value *MapTypesArrayArg = nullptr; 9502 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 9503 SizesArrayArg, MapTypesArrayArg, Info); 9504 9505 // Emit device ID if any. 9506 llvm::Value *DeviceID = nullptr; 9507 if (Device) { 9508 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9509 CGF.Int64Ty, /*isSigned=*/true); 9510 } else { 9511 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9512 } 9513 9514 // Emit the number of elements in the offloading arrays. 9515 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 9516 9517 llvm::Value *OffloadingArgs[] = { 9518 DeviceID, PointerNum, BasePointersArrayArg, 9519 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 9520 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 9521 OffloadingArgs); 9522 }; 9523 9524 // If we need device pointer privatization, we need to emit the body of the 9525 // region with no privatization in the 'else' branch of the conditional. 9526 // Otherwise, we don't have to do anything. 9527 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 9528 PrePostActionTy &) { 9529 if (!Info.CaptureDeviceAddrMap.empty()) { 9530 CodeGen.setAction(NoPrivAction); 9531 CodeGen(CGF); 9532 } 9533 }; 9534 9535 // We don't have to do anything to close the region if the if clause evaluates 9536 // to false. 9537 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 9538 9539 if (IfCond) { 9540 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 9541 } else { 9542 RegionCodeGenTy RCG(BeginThenGen); 9543 RCG(CGF); 9544 } 9545 9546 // If we don't require privatization of device pointers, we emit the body in 9547 // between the runtime calls. This avoids duplicating the body code. 9548 if (Info.CaptureDeviceAddrMap.empty()) { 9549 CodeGen.setAction(NoPrivAction); 9550 CodeGen(CGF); 9551 } 9552 9553 if (IfCond) { 9554 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen); 9555 } else { 9556 RegionCodeGenTy RCG(EndThenGen); 9557 RCG(CGF); 9558 } 9559 } 9560 9561 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 9562 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 9563 const Expr *Device) { 9564 if (!CGF.HaveInsertPoint()) 9565 return; 9566 9567 assert((isa<OMPTargetEnterDataDirective>(D) || 9568 isa<OMPTargetExitDataDirective>(D) || 9569 isa<OMPTargetUpdateDirective>(D)) && 9570 "Expecting either target enter, exit data, or update directives."); 9571 9572 CodeGenFunction::OMPTargetDataInfo InputInfo; 9573 llvm::Value *MapTypesArray = nullptr; 9574 // Generate the code for the opening of the data environment. 9575 auto &&ThenGen = [this, &D, Device, &InputInfo, 9576 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 9577 // Emit device ID if any. 9578 llvm::Value *DeviceID = nullptr; 9579 if (Device) { 9580 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9581 CGF.Int64Ty, /*isSigned=*/true); 9582 } else { 9583 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9584 } 9585 9586 // Emit the number of elements in the offloading arrays. 9587 llvm::Constant *PointerNum = 9588 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9589 9590 llvm::Value *OffloadingArgs[] = {DeviceID, 9591 PointerNum, 9592 InputInfo.BasePointersArray.getPointer(), 9593 InputInfo.PointersArray.getPointer(), 9594 InputInfo.SizesArray.getPointer(), 9595 MapTypesArray}; 9596 9597 // Select the right runtime function call for each expected standalone 9598 // directive. 9599 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9600 OpenMPRTLFunction RTLFn; 9601 switch (D.getDirectiveKind()) { 9602 case OMPD_target_enter_data: 9603 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 9604 : OMPRTL__tgt_target_data_begin; 9605 break; 9606 case OMPD_target_exit_data: 9607 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 9608 : OMPRTL__tgt_target_data_end; 9609 break; 9610 case OMPD_target_update: 9611 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 9612 : OMPRTL__tgt_target_data_update; 9613 break; 9614 case OMPD_parallel: 9615 case OMPD_for: 9616 case OMPD_parallel_for: 9617 case OMPD_parallel_sections: 9618 case OMPD_for_simd: 9619 case OMPD_parallel_for_simd: 9620 case OMPD_cancel: 9621 case OMPD_cancellation_point: 9622 case OMPD_ordered: 9623 case OMPD_threadprivate: 9624 case OMPD_allocate: 9625 case OMPD_task: 9626 case OMPD_simd: 9627 case OMPD_sections: 9628 case OMPD_section: 9629 case OMPD_single: 9630 case OMPD_master: 9631 case OMPD_critical: 9632 case OMPD_taskyield: 9633 case OMPD_barrier: 9634 case OMPD_taskwait: 9635 case OMPD_taskgroup: 9636 case OMPD_atomic: 9637 case OMPD_flush: 9638 case OMPD_teams: 9639 case OMPD_target_data: 9640 case OMPD_distribute: 9641 case OMPD_distribute_simd: 9642 case OMPD_distribute_parallel_for: 9643 case OMPD_distribute_parallel_for_simd: 9644 case OMPD_teams_distribute: 9645 case OMPD_teams_distribute_simd: 9646 case OMPD_teams_distribute_parallel_for: 9647 case OMPD_teams_distribute_parallel_for_simd: 9648 case OMPD_declare_simd: 9649 case OMPD_declare_target: 9650 case OMPD_end_declare_target: 9651 case OMPD_declare_reduction: 9652 case OMPD_declare_mapper: 9653 case OMPD_taskloop: 9654 case OMPD_taskloop_simd: 9655 case OMPD_target: 9656 case OMPD_target_simd: 9657 case OMPD_target_teams_distribute: 9658 case OMPD_target_teams_distribute_simd: 9659 case OMPD_target_teams_distribute_parallel_for: 9660 case OMPD_target_teams_distribute_parallel_for_simd: 9661 case OMPD_target_teams: 9662 case OMPD_target_parallel: 9663 case OMPD_target_parallel_for: 9664 case OMPD_target_parallel_for_simd: 9665 case OMPD_requires: 9666 case OMPD_unknown: 9667 llvm_unreachable("Unexpected standalone target data directive."); 9668 break; 9669 } 9670 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 9671 }; 9672 9673 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 9674 CodeGenFunction &CGF, PrePostActionTy &) { 9675 // Fill up the arrays with all the mapped variables. 9676 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9677 MappableExprsHandler::MapValuesArrayTy Pointers; 9678 MappableExprsHandler::MapValuesArrayTy Sizes; 9679 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9680 9681 // Get map clause information. 9682 MappableExprsHandler MEHandler(D, CGF); 9683 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 9684 9685 TargetDataInfo Info; 9686 // Fill up the arrays and create the arguments. 9687 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9688 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9689 Info.PointersArray, Info.SizesArray, 9690 Info.MapTypesArray, Info); 9691 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9692 InputInfo.BasePointersArray = 9693 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9694 InputInfo.PointersArray = 9695 Address(Info.PointersArray, CGM.getPointerAlign()); 9696 InputInfo.SizesArray = 9697 Address(Info.SizesArray, CGM.getPointerAlign()); 9698 MapTypesArray = Info.MapTypesArray; 9699 if (D.hasClausesOfKind<OMPDependClause>()) 9700 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9701 else 9702 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9703 }; 9704 9705 if (IfCond) { 9706 emitOMPIfClause(CGF, IfCond, TargetThenGen, 9707 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 9708 } else { 9709 RegionCodeGenTy ThenRCG(TargetThenGen); 9710 ThenRCG(CGF); 9711 } 9712 } 9713 9714 namespace { 9715 /// Kind of parameter in a function with 'declare simd' directive. 9716 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 9717 /// Attribute set of the parameter. 9718 struct ParamAttrTy { 9719 ParamKindTy Kind = Vector; 9720 llvm::APSInt StrideOrArg; 9721 llvm::APSInt Alignment; 9722 }; 9723 } // namespace 9724 9725 static unsigned evaluateCDTSize(const FunctionDecl *FD, 9726 ArrayRef<ParamAttrTy> ParamAttrs) { 9727 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 9728 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 9729 // of that clause. The VLEN value must be power of 2. 9730 // In other case the notion of the function`s "characteristic data type" (CDT) 9731 // is used to compute the vector length. 9732 // CDT is defined in the following order: 9733 // a) For non-void function, the CDT is the return type. 9734 // b) If the function has any non-uniform, non-linear parameters, then the 9735 // CDT is the type of the first such parameter. 9736 // c) If the CDT determined by a) or b) above is struct, union, or class 9737 // type which is pass-by-value (except for the type that maps to the 9738 // built-in complex data type), the characteristic data type is int. 9739 // d) If none of the above three cases is applicable, the CDT is int. 9740 // The VLEN is then determined based on the CDT and the size of vector 9741 // register of that ISA for which current vector version is generated. The 9742 // VLEN is computed using the formula below: 9743 // VLEN = sizeof(vector_register) / sizeof(CDT), 9744 // where vector register size specified in section 3.2.1 Registers and the 9745 // Stack Frame of original AMD64 ABI document. 9746 QualType RetType = FD->getReturnType(); 9747 if (RetType.isNull()) 9748 return 0; 9749 ASTContext &C = FD->getASTContext(); 9750 QualType CDT; 9751 if (!RetType.isNull() && !RetType->isVoidType()) { 9752 CDT = RetType; 9753 } else { 9754 unsigned Offset = 0; 9755 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 9756 if (ParamAttrs[Offset].Kind == Vector) 9757 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 9758 ++Offset; 9759 } 9760 if (CDT.isNull()) { 9761 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 9762 if (ParamAttrs[I + Offset].Kind == Vector) { 9763 CDT = FD->getParamDecl(I)->getType(); 9764 break; 9765 } 9766 } 9767 } 9768 } 9769 if (CDT.isNull()) 9770 CDT = C.IntTy; 9771 CDT = CDT->getCanonicalTypeUnqualified(); 9772 if (CDT->isRecordType() || CDT->isUnionType()) 9773 CDT = C.IntTy; 9774 return C.getTypeSize(CDT); 9775 } 9776 9777 static void 9778 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 9779 const llvm::APSInt &VLENVal, 9780 ArrayRef<ParamAttrTy> ParamAttrs, 9781 OMPDeclareSimdDeclAttr::BranchStateTy State) { 9782 struct ISADataTy { 9783 char ISA; 9784 unsigned VecRegSize; 9785 }; 9786 ISADataTy ISAData[] = { 9787 { 9788 'b', 128 9789 }, // SSE 9790 { 9791 'c', 256 9792 }, // AVX 9793 { 9794 'd', 256 9795 }, // AVX2 9796 { 9797 'e', 512 9798 }, // AVX512 9799 }; 9800 llvm::SmallVector<char, 2> Masked; 9801 switch (State) { 9802 case OMPDeclareSimdDeclAttr::BS_Undefined: 9803 Masked.push_back('N'); 9804 Masked.push_back('M'); 9805 break; 9806 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 9807 Masked.push_back('N'); 9808 break; 9809 case OMPDeclareSimdDeclAttr::BS_Inbranch: 9810 Masked.push_back('M'); 9811 break; 9812 } 9813 for (char Mask : Masked) { 9814 for (const ISADataTy &Data : ISAData) { 9815 SmallString<256> Buffer; 9816 llvm::raw_svector_ostream Out(Buffer); 9817 Out << "_ZGV" << Data.ISA << Mask; 9818 if (!VLENVal) { 9819 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 9820 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 9821 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 9822 } else { 9823 Out << VLENVal; 9824 } 9825 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 9826 switch (ParamAttr.Kind){ 9827 case LinearWithVarStride: 9828 Out << 's' << ParamAttr.StrideOrArg; 9829 break; 9830 case Linear: 9831 Out << 'l'; 9832 if (!!ParamAttr.StrideOrArg) 9833 Out << ParamAttr.StrideOrArg; 9834 break; 9835 case Uniform: 9836 Out << 'u'; 9837 break; 9838 case Vector: 9839 Out << 'v'; 9840 break; 9841 } 9842 if (!!ParamAttr.Alignment) 9843 Out << 'a' << ParamAttr.Alignment; 9844 } 9845 Out << '_' << Fn->getName(); 9846 Fn->addFnAttr(Out.str()); 9847 } 9848 } 9849 } 9850 9851 // This are the Functions that are needed to mangle the name of the 9852 // vector functions generated by the compiler, according to the rules 9853 // defined in the "Vector Function ABI specifications for AArch64", 9854 // available at 9855 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 9856 9857 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 9858 /// 9859 /// TODO: Need to implement the behavior for reference marked with a 9860 /// var or no linear modifiers (1.b in the section). For this, we 9861 /// need to extend ParamKindTy to support the linear modifiers. 9862 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 9863 QT = QT.getCanonicalType(); 9864 9865 if (QT->isVoidType()) 9866 return false; 9867 9868 if (Kind == ParamKindTy::Uniform) 9869 return false; 9870 9871 if (Kind == ParamKindTy::Linear) 9872 return false; 9873 9874 // TODO: Handle linear references with modifiers 9875 9876 if (Kind == ParamKindTy::LinearWithVarStride) 9877 return false; 9878 9879 return true; 9880 } 9881 9882 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 9883 static bool getAArch64PBV(QualType QT, ASTContext &C) { 9884 QT = QT.getCanonicalType(); 9885 unsigned Size = C.getTypeSize(QT); 9886 9887 // Only scalars and complex within 16 bytes wide set PVB to true. 9888 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 9889 return false; 9890 9891 if (QT->isFloatingType()) 9892 return true; 9893 9894 if (QT->isIntegerType()) 9895 return true; 9896 9897 if (QT->isPointerType()) 9898 return true; 9899 9900 // TODO: Add support for complex types (section 3.1.2, item 2). 9901 9902 return false; 9903 } 9904 9905 /// Computes the lane size (LS) of a return type or of an input parameter, 9906 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 9907 /// TODO: Add support for references, section 3.2.1, item 1. 9908 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 9909 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 9910 QualType PTy = QT.getCanonicalType()->getPointeeType(); 9911 if (getAArch64PBV(PTy, C)) 9912 return C.getTypeSize(PTy); 9913 } 9914 if (getAArch64PBV(QT, C)) 9915 return C.getTypeSize(QT); 9916 9917 return C.getTypeSize(C.getUIntPtrType()); 9918 } 9919 9920 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 9921 // signature of the scalar function, as defined in 3.2.2 of the 9922 // AAVFABI. 9923 static std::tuple<unsigned, unsigned, bool> 9924 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 9925 QualType RetType = FD->getReturnType().getCanonicalType(); 9926 9927 ASTContext &C = FD->getASTContext(); 9928 9929 bool OutputBecomesInput = false; 9930 9931 llvm::SmallVector<unsigned, 8> Sizes; 9932 if (!RetType->isVoidType()) { 9933 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 9934 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 9935 OutputBecomesInput = true; 9936 } 9937 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 9938 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 9939 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 9940 } 9941 9942 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 9943 // The LS of a function parameter / return value can only be a power 9944 // of 2, starting from 8 bits, up to 128. 9945 assert(std::all_of(Sizes.begin(), Sizes.end(), 9946 [](unsigned Size) { 9947 return Size == 8 || Size == 16 || Size == 32 || 9948 Size == 64 || Size == 128; 9949 }) && 9950 "Invalid size"); 9951 9952 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 9953 *std::max_element(std::begin(Sizes), std::end(Sizes)), 9954 OutputBecomesInput); 9955 } 9956 9957 /// Mangle the parameter part of the vector function name according to 9958 /// their OpenMP classification. The mangling function is defined in 9959 /// section 3.5 of the AAVFABI. 9960 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 9961 SmallString<256> Buffer; 9962 llvm::raw_svector_ostream Out(Buffer); 9963 for (const auto &ParamAttr : ParamAttrs) { 9964 switch (ParamAttr.Kind) { 9965 case LinearWithVarStride: 9966 Out << "ls" << ParamAttr.StrideOrArg; 9967 break; 9968 case Linear: 9969 Out << 'l'; 9970 // Don't print the step value if it is not present or if it is 9971 // equal to 1. 9972 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 9973 Out << ParamAttr.StrideOrArg; 9974 break; 9975 case Uniform: 9976 Out << 'u'; 9977 break; 9978 case Vector: 9979 Out << 'v'; 9980 break; 9981 } 9982 9983 if (!!ParamAttr.Alignment) 9984 Out << 'a' << ParamAttr.Alignment; 9985 } 9986 9987 return Out.str(); 9988 } 9989 9990 // Function used to add the attribute. The parameter `VLEN` is 9991 // templated to allow the use of "x" when targeting scalable functions 9992 // for SVE. 9993 template <typename T> 9994 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 9995 char ISA, StringRef ParSeq, 9996 StringRef MangledName, bool OutputBecomesInput, 9997 llvm::Function *Fn) { 9998 SmallString<256> Buffer; 9999 llvm::raw_svector_ostream Out(Buffer); 10000 Out << Prefix << ISA << LMask << VLEN; 10001 if (OutputBecomesInput) 10002 Out << "v"; 10003 Out << ParSeq << "_" << MangledName; 10004 Fn->addFnAttr(Out.str()); 10005 } 10006 10007 // Helper function to generate the Advanced SIMD names depending on 10008 // the value of the NDS when simdlen is not present. 10009 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10010 StringRef Prefix, char ISA, 10011 StringRef ParSeq, StringRef MangledName, 10012 bool OutputBecomesInput, 10013 llvm::Function *Fn) { 10014 switch (NDS) { 10015 case 8: 10016 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10017 OutputBecomesInput, Fn); 10018 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10019 OutputBecomesInput, Fn); 10020 break; 10021 case 16: 10022 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10023 OutputBecomesInput, Fn); 10024 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10025 OutputBecomesInput, Fn); 10026 break; 10027 case 32: 10028 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10029 OutputBecomesInput, Fn); 10030 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10031 OutputBecomesInput, Fn); 10032 break; 10033 case 64: 10034 case 128: 10035 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10036 OutputBecomesInput, Fn); 10037 break; 10038 default: 10039 llvm_unreachable("Scalar type is too wide."); 10040 } 10041 } 10042 10043 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10044 static void emitAArch64DeclareSimdFunction( 10045 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10046 ArrayRef<ParamAttrTy> ParamAttrs, 10047 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10048 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10049 10050 // Get basic data for building the vector signature. 10051 const auto Data = getNDSWDS(FD, ParamAttrs); 10052 const unsigned NDS = std::get<0>(Data); 10053 const unsigned WDS = std::get<1>(Data); 10054 const bool OutputBecomesInput = std::get<2>(Data); 10055 10056 // Check the values provided via `simdlen` by the user. 10057 // 1. A `simdlen(1)` doesn't produce vector signatures, 10058 if (UserVLEN == 1) { 10059 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10060 DiagnosticsEngine::Warning, 10061 "The clause simdlen(1) has no effect when targeting aarch64."); 10062 CGM.getDiags().Report(SLoc, DiagID); 10063 return; 10064 } 10065 10066 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10067 // Advanced SIMD output. 10068 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10069 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10070 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10071 "power of 2 when targeting Advanced SIMD."); 10072 CGM.getDiags().Report(SLoc, DiagID); 10073 return; 10074 } 10075 10076 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10077 // limits. 10078 if (ISA == 's' && UserVLEN != 0) { 10079 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10080 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10081 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10082 "lanes in the architectural constraints " 10083 "for SVE (min is 128-bit, max is " 10084 "2048-bit, by steps of 128-bit)"); 10085 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10086 return; 10087 } 10088 } 10089 10090 // Sort out parameter sequence. 10091 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10092 StringRef Prefix = "_ZGV"; 10093 // Generate simdlen from user input (if any). 10094 if (UserVLEN) { 10095 if (ISA == 's') { 10096 // SVE generates only a masked function. 10097 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10098 OutputBecomesInput, Fn); 10099 } else { 10100 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10101 // Advanced SIMD generates one or two functions, depending on 10102 // the `[not]inbranch` clause. 10103 switch (State) { 10104 case OMPDeclareSimdDeclAttr::BS_Undefined: 10105 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10106 OutputBecomesInput, Fn); 10107 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10108 OutputBecomesInput, Fn); 10109 break; 10110 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10111 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10112 OutputBecomesInput, Fn); 10113 break; 10114 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10115 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10116 OutputBecomesInput, Fn); 10117 break; 10118 } 10119 } 10120 } else { 10121 // If no user simdlen is provided, follow the AAVFABI rules for 10122 // generating the vector length. 10123 if (ISA == 's') { 10124 // SVE, section 3.4.1, item 1. 10125 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10126 OutputBecomesInput, Fn); 10127 } else { 10128 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10129 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10130 // two vector names depending on the use of the clause 10131 // `[not]inbranch`. 10132 switch (State) { 10133 case OMPDeclareSimdDeclAttr::BS_Undefined: 10134 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10135 OutputBecomesInput, Fn); 10136 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10137 OutputBecomesInput, Fn); 10138 break; 10139 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10140 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10141 OutputBecomesInput, Fn); 10142 break; 10143 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10144 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10145 OutputBecomesInput, Fn); 10146 break; 10147 } 10148 } 10149 } 10150 } 10151 10152 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10153 llvm::Function *Fn) { 10154 ASTContext &C = CGM.getContext(); 10155 FD = FD->getMostRecentDecl(); 10156 // Map params to their positions in function decl. 10157 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10158 if (isa<CXXMethodDecl>(FD)) 10159 ParamPositions.try_emplace(FD, 0); 10160 unsigned ParamPos = ParamPositions.size(); 10161 for (const ParmVarDecl *P : FD->parameters()) { 10162 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10163 ++ParamPos; 10164 } 10165 while (FD) { 10166 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10167 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10168 // Mark uniform parameters. 10169 for (const Expr *E : Attr->uniforms()) { 10170 E = E->IgnoreParenImpCasts(); 10171 unsigned Pos; 10172 if (isa<CXXThisExpr>(E)) { 10173 Pos = ParamPositions[FD]; 10174 } else { 10175 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10176 ->getCanonicalDecl(); 10177 Pos = ParamPositions[PVD]; 10178 } 10179 ParamAttrs[Pos].Kind = Uniform; 10180 } 10181 // Get alignment info. 10182 auto NI = Attr->alignments_begin(); 10183 for (const Expr *E : Attr->aligneds()) { 10184 E = E->IgnoreParenImpCasts(); 10185 unsigned Pos; 10186 QualType ParmTy; 10187 if (isa<CXXThisExpr>(E)) { 10188 Pos = ParamPositions[FD]; 10189 ParmTy = E->getType(); 10190 } else { 10191 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10192 ->getCanonicalDecl(); 10193 Pos = ParamPositions[PVD]; 10194 ParmTy = PVD->getType(); 10195 } 10196 ParamAttrs[Pos].Alignment = 10197 (*NI) 10198 ? (*NI)->EvaluateKnownConstInt(C) 10199 : llvm::APSInt::getUnsigned( 10200 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10201 .getQuantity()); 10202 ++NI; 10203 } 10204 // Mark linear parameters. 10205 auto SI = Attr->steps_begin(); 10206 auto MI = Attr->modifiers_begin(); 10207 for (const Expr *E : Attr->linears()) { 10208 E = E->IgnoreParenImpCasts(); 10209 unsigned Pos; 10210 if (isa<CXXThisExpr>(E)) { 10211 Pos = ParamPositions[FD]; 10212 } else { 10213 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10214 ->getCanonicalDecl(); 10215 Pos = ParamPositions[PVD]; 10216 } 10217 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10218 ParamAttr.Kind = Linear; 10219 if (*SI) { 10220 Expr::EvalResult Result; 10221 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10222 if (const auto *DRE = 10223 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10224 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10225 ParamAttr.Kind = LinearWithVarStride; 10226 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10227 ParamPositions[StridePVD->getCanonicalDecl()]); 10228 } 10229 } 10230 } else { 10231 ParamAttr.StrideOrArg = Result.Val.getInt(); 10232 } 10233 } 10234 ++SI; 10235 ++MI; 10236 } 10237 llvm::APSInt VLENVal; 10238 SourceLocation ExprLoc; 10239 const Expr *VLENExpr = Attr->getSimdlen(); 10240 if (VLENExpr) { 10241 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10242 ExprLoc = VLENExpr->getExprLoc(); 10243 } 10244 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10245 if (CGM.getTriple().getArch() == llvm::Triple::x86 || 10246 CGM.getTriple().getArch() == llvm::Triple::x86_64) { 10247 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10248 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10249 unsigned VLEN = VLENVal.getExtValue(); 10250 StringRef MangledName = Fn->getName(); 10251 if (CGM.getTarget().hasFeature("sve")) 10252 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10253 MangledName, 's', 128, Fn, ExprLoc); 10254 if (CGM.getTarget().hasFeature("neon")) 10255 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10256 MangledName, 'n', 128, Fn, ExprLoc); 10257 } 10258 } 10259 FD = FD->getPreviousDecl(); 10260 } 10261 } 10262 10263 namespace { 10264 /// Cleanup action for doacross support. 10265 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10266 public: 10267 static const int DoacrossFinArgs = 2; 10268 10269 private: 10270 llvm::FunctionCallee RTLFn; 10271 llvm::Value *Args[DoacrossFinArgs]; 10272 10273 public: 10274 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10275 ArrayRef<llvm::Value *> CallArgs) 10276 : RTLFn(RTLFn) { 10277 assert(CallArgs.size() == DoacrossFinArgs); 10278 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10279 } 10280 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10281 if (!CGF.HaveInsertPoint()) 10282 return; 10283 CGF.EmitRuntimeCall(RTLFn, Args); 10284 } 10285 }; 10286 } // namespace 10287 10288 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10289 const OMPLoopDirective &D, 10290 ArrayRef<Expr *> NumIterations) { 10291 if (!CGF.HaveInsertPoint()) 10292 return; 10293 10294 ASTContext &C = CGM.getContext(); 10295 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10296 RecordDecl *RD; 10297 if (KmpDimTy.isNull()) { 10298 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10299 // kmp_int64 lo; // lower 10300 // kmp_int64 up; // upper 10301 // kmp_int64 st; // stride 10302 // }; 10303 RD = C.buildImplicitRecord("kmp_dim"); 10304 RD->startDefinition(); 10305 addFieldToRecordDecl(C, RD, Int64Ty); 10306 addFieldToRecordDecl(C, RD, Int64Ty); 10307 addFieldToRecordDecl(C, RD, Int64Ty); 10308 RD->completeDefinition(); 10309 KmpDimTy = C.getRecordType(RD); 10310 } else { 10311 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10312 } 10313 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10314 QualType ArrayTy = 10315 C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0); 10316 10317 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10318 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10319 enum { LowerFD = 0, UpperFD, StrideFD }; 10320 // Fill dims with data. 10321 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10322 LValue DimsLVal = CGF.MakeAddrLValue( 10323 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10324 // dims.upper = num_iterations; 10325 LValue UpperLVal = CGF.EmitLValueForField( 10326 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10327 llvm::Value *NumIterVal = 10328 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 10329 D.getNumIterations()->getType(), Int64Ty, 10330 D.getNumIterations()->getExprLoc()); 10331 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10332 // dims.stride = 1; 10333 LValue StrideLVal = CGF.EmitLValueForField( 10334 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10335 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10336 StrideLVal); 10337 } 10338 10339 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10340 // kmp_int32 num_dims, struct kmp_dim * dims); 10341 llvm::Value *Args[] = { 10342 emitUpdateLocation(CGF, D.getBeginLoc()), 10343 getThreadID(CGF, D.getBeginLoc()), 10344 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 10345 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10346 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 10347 CGM.VoidPtrTy)}; 10348 10349 llvm::FunctionCallee RTLFn = 10350 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 10351 CGF.EmitRuntimeCall(RTLFn, Args); 10352 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 10353 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 10354 llvm::FunctionCallee FiniRTLFn = 10355 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 10356 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10357 llvm::makeArrayRef(FiniArgs)); 10358 } 10359 10360 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10361 const OMPDependClause *C) { 10362 QualType Int64Ty = 10363 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 10364 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 10365 QualType ArrayTy = CGM.getContext().getConstantArrayType( 10366 Int64Ty, Size, ArrayType::Normal, 0); 10367 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 10368 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 10369 const Expr *CounterVal = C->getLoopData(I); 10370 assert(CounterVal); 10371 llvm::Value *CntVal = CGF.EmitScalarConversion( 10372 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 10373 CounterVal->getExprLoc()); 10374 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 10375 /*Volatile=*/false, Int64Ty); 10376 } 10377 llvm::Value *Args[] = { 10378 emitUpdateLocation(CGF, C->getBeginLoc()), 10379 getThreadID(CGF, C->getBeginLoc()), 10380 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 10381 llvm::FunctionCallee RTLFn; 10382 if (C->getDependencyKind() == OMPC_DEPEND_source) { 10383 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 10384 } else { 10385 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 10386 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 10387 } 10388 CGF.EmitRuntimeCall(RTLFn, Args); 10389 } 10390 10391 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 10392 llvm::FunctionCallee Callee, 10393 ArrayRef<llvm::Value *> Args) const { 10394 assert(Loc.isValid() && "Outlined function call location must be valid."); 10395 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 10396 10397 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 10398 if (Fn->doesNotThrow()) { 10399 CGF.EmitNounwindRuntimeCall(Fn, Args); 10400 return; 10401 } 10402 } 10403 CGF.EmitRuntimeCall(Callee, Args); 10404 } 10405 10406 void CGOpenMPRuntime::emitOutlinedFunctionCall( 10407 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 10408 ArrayRef<llvm::Value *> Args) const { 10409 emitCall(CGF, Loc, OutlinedFn, Args); 10410 } 10411 10412 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 10413 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 10414 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 10415 HasEmittedDeclareTargetRegion = true; 10416 } 10417 10418 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 10419 const VarDecl *NativeParam, 10420 const VarDecl *TargetParam) const { 10421 return CGF.GetAddrOfLocalVar(NativeParam); 10422 } 10423 10424 namespace { 10425 /// Cleanup action for allocate support. 10426 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 10427 public: 10428 static const int CleanupArgs = 3; 10429 10430 private: 10431 llvm::FunctionCallee RTLFn; 10432 llvm::Value *Args[CleanupArgs]; 10433 10434 public: 10435 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 10436 ArrayRef<llvm::Value *> CallArgs) 10437 : RTLFn(RTLFn) { 10438 assert(CallArgs.size() == CleanupArgs && 10439 "Size of arguments does not match."); 10440 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10441 } 10442 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10443 if (!CGF.HaveInsertPoint()) 10444 return; 10445 CGF.EmitRuntimeCall(RTLFn, Args); 10446 } 10447 }; 10448 } // namespace 10449 10450 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 10451 const VarDecl *VD) { 10452 if (!VD) 10453 return Address::invalid(); 10454 const VarDecl *CVD = VD->getCanonicalDecl(); 10455 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 10456 return Address::invalid(); 10457 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 10458 // Use the default allocation. 10459 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 10460 !AA->getAllocator()) 10461 return Address::invalid(); 10462 llvm::Value *Size; 10463 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 10464 if (CVD->getType()->isVariablyModifiedType()) { 10465 Size = CGF.getTypeSize(CVD->getType()); 10466 // Align the size: ((size + align - 1) / align) * align 10467 Size = CGF.Builder.CreateNUWAdd( 10468 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 10469 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 10470 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 10471 } else { 10472 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 10473 Size = CGM.getSize(Sz.alignTo(Align)); 10474 } 10475 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 10476 assert(AA->getAllocator() && 10477 "Expected allocator expression for non-default allocator."); 10478 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 10479 // According to the standard, the original allocator type is a enum (integer). 10480 // Convert to pointer type, if required. 10481 if (Allocator->getType()->isIntegerTy()) 10482 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 10483 else if (Allocator->getType()->isPointerTy()) 10484 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 10485 CGM.VoidPtrTy); 10486 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 10487 10488 llvm::Value *Addr = 10489 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 10490 CVD->getName() + ".void.addr"); 10491 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 10492 Allocator}; 10493 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 10494 10495 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10496 llvm::makeArrayRef(FiniArgs)); 10497 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10498 Addr, 10499 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 10500 CVD->getName() + ".addr"); 10501 return Address(Addr, Align); 10502 } 10503 10504 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 10505 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 10506 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 10507 llvm_unreachable("Not supported in SIMD-only mode"); 10508 } 10509 10510 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 10511 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 10512 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 10513 llvm_unreachable("Not supported in SIMD-only mode"); 10514 } 10515 10516 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 10517 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 10518 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 10519 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 10520 bool Tied, unsigned &NumberOfParts) { 10521 llvm_unreachable("Not supported in SIMD-only mode"); 10522 } 10523 10524 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 10525 SourceLocation Loc, 10526 llvm::Function *OutlinedFn, 10527 ArrayRef<llvm::Value *> CapturedVars, 10528 const Expr *IfCond) { 10529 llvm_unreachable("Not supported in SIMD-only mode"); 10530 } 10531 10532 void CGOpenMPSIMDRuntime::emitCriticalRegion( 10533 CodeGenFunction &CGF, StringRef CriticalName, 10534 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 10535 const Expr *Hint) { 10536 llvm_unreachable("Not supported in SIMD-only mode"); 10537 } 10538 10539 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 10540 const RegionCodeGenTy &MasterOpGen, 10541 SourceLocation Loc) { 10542 llvm_unreachable("Not supported in SIMD-only mode"); 10543 } 10544 10545 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 10546 SourceLocation Loc) { 10547 llvm_unreachable("Not supported in SIMD-only mode"); 10548 } 10549 10550 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 10551 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 10552 SourceLocation Loc) { 10553 llvm_unreachable("Not supported in SIMD-only mode"); 10554 } 10555 10556 void CGOpenMPSIMDRuntime::emitSingleRegion( 10557 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 10558 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 10559 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 10560 ArrayRef<const Expr *> AssignmentOps) { 10561 llvm_unreachable("Not supported in SIMD-only mode"); 10562 } 10563 10564 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 10565 const RegionCodeGenTy &OrderedOpGen, 10566 SourceLocation Loc, 10567 bool IsThreads) { 10568 llvm_unreachable("Not supported in SIMD-only mode"); 10569 } 10570 10571 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 10572 SourceLocation Loc, 10573 OpenMPDirectiveKind Kind, 10574 bool EmitChecks, 10575 bool ForceSimpleCall) { 10576 llvm_unreachable("Not supported in SIMD-only mode"); 10577 } 10578 10579 void CGOpenMPSIMDRuntime::emitForDispatchInit( 10580 CodeGenFunction &CGF, SourceLocation Loc, 10581 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 10582 bool Ordered, const DispatchRTInput &DispatchValues) { 10583 llvm_unreachable("Not supported in SIMD-only mode"); 10584 } 10585 10586 void CGOpenMPSIMDRuntime::emitForStaticInit( 10587 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 10588 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 10589 llvm_unreachable("Not supported in SIMD-only mode"); 10590 } 10591 10592 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 10593 CodeGenFunction &CGF, SourceLocation Loc, 10594 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 10595 llvm_unreachable("Not supported in SIMD-only mode"); 10596 } 10597 10598 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 10599 SourceLocation Loc, 10600 unsigned IVSize, 10601 bool IVSigned) { 10602 llvm_unreachable("Not supported in SIMD-only mode"); 10603 } 10604 10605 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 10606 SourceLocation Loc, 10607 OpenMPDirectiveKind DKind) { 10608 llvm_unreachable("Not supported in SIMD-only mode"); 10609 } 10610 10611 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 10612 SourceLocation Loc, 10613 unsigned IVSize, bool IVSigned, 10614 Address IL, Address LB, 10615 Address UB, Address ST) { 10616 llvm_unreachable("Not supported in SIMD-only mode"); 10617 } 10618 10619 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 10620 llvm::Value *NumThreads, 10621 SourceLocation Loc) { 10622 llvm_unreachable("Not supported in SIMD-only mode"); 10623 } 10624 10625 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 10626 OpenMPProcBindClauseKind ProcBind, 10627 SourceLocation Loc) { 10628 llvm_unreachable("Not supported in SIMD-only mode"); 10629 } 10630 10631 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 10632 const VarDecl *VD, 10633 Address VDAddr, 10634 SourceLocation Loc) { 10635 llvm_unreachable("Not supported in SIMD-only mode"); 10636 } 10637 10638 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 10639 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 10640 CodeGenFunction *CGF) { 10641 llvm_unreachable("Not supported in SIMD-only mode"); 10642 } 10643 10644 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 10645 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 10646 llvm_unreachable("Not supported in SIMD-only mode"); 10647 } 10648 10649 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 10650 ArrayRef<const Expr *> Vars, 10651 SourceLocation Loc) { 10652 llvm_unreachable("Not supported in SIMD-only mode"); 10653 } 10654 10655 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 10656 const OMPExecutableDirective &D, 10657 llvm::Function *TaskFunction, 10658 QualType SharedsTy, Address Shareds, 10659 const Expr *IfCond, 10660 const OMPTaskDataTy &Data) { 10661 llvm_unreachable("Not supported in SIMD-only mode"); 10662 } 10663 10664 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 10665 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 10666 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 10667 const Expr *IfCond, const OMPTaskDataTy &Data) { 10668 llvm_unreachable("Not supported in SIMD-only mode"); 10669 } 10670 10671 void CGOpenMPSIMDRuntime::emitReduction( 10672 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 10673 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 10674 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 10675 assert(Options.SimpleReduction && "Only simple reduction is expected."); 10676 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 10677 ReductionOps, Options); 10678 } 10679 10680 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 10681 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 10682 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 10683 llvm_unreachable("Not supported in SIMD-only mode"); 10684 } 10685 10686 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 10687 SourceLocation Loc, 10688 ReductionCodeGen &RCG, 10689 unsigned N) { 10690 llvm_unreachable("Not supported in SIMD-only mode"); 10691 } 10692 10693 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 10694 SourceLocation Loc, 10695 llvm::Value *ReductionsPtr, 10696 LValue SharedLVal) { 10697 llvm_unreachable("Not supported in SIMD-only mode"); 10698 } 10699 10700 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 10701 SourceLocation Loc) { 10702 llvm_unreachable("Not supported in SIMD-only mode"); 10703 } 10704 10705 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 10706 CodeGenFunction &CGF, SourceLocation Loc, 10707 OpenMPDirectiveKind CancelRegion) { 10708 llvm_unreachable("Not supported in SIMD-only mode"); 10709 } 10710 10711 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 10712 SourceLocation Loc, const Expr *IfCond, 10713 OpenMPDirectiveKind CancelRegion) { 10714 llvm_unreachable("Not supported in SIMD-only mode"); 10715 } 10716 10717 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 10718 const OMPExecutableDirective &D, StringRef ParentName, 10719 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 10720 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 10721 llvm_unreachable("Not supported in SIMD-only mode"); 10722 } 10723 10724 void CGOpenMPSIMDRuntime::emitTargetCall(CodeGenFunction &CGF, 10725 const OMPExecutableDirective &D, 10726 llvm::Function *OutlinedFn, 10727 llvm::Value *OutlinedFnID, 10728 const Expr *IfCond, 10729 const Expr *Device) { 10730 llvm_unreachable("Not supported in SIMD-only mode"); 10731 } 10732 10733 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 10734 llvm_unreachable("Not supported in SIMD-only mode"); 10735 } 10736 10737 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 10738 llvm_unreachable("Not supported in SIMD-only mode"); 10739 } 10740 10741 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 10742 return false; 10743 } 10744 10745 llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() { 10746 return nullptr; 10747 } 10748 10749 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 10750 const OMPExecutableDirective &D, 10751 SourceLocation Loc, 10752 llvm::Function *OutlinedFn, 10753 ArrayRef<llvm::Value *> CapturedVars) { 10754 llvm_unreachable("Not supported in SIMD-only mode"); 10755 } 10756 10757 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 10758 const Expr *NumTeams, 10759 const Expr *ThreadLimit, 10760 SourceLocation Loc) { 10761 llvm_unreachable("Not supported in SIMD-only mode"); 10762 } 10763 10764 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 10765 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10766 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 10767 llvm_unreachable("Not supported in SIMD-only mode"); 10768 } 10769 10770 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 10771 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10772 const Expr *Device) { 10773 llvm_unreachable("Not supported in SIMD-only mode"); 10774 } 10775 10776 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10777 const OMPLoopDirective &D, 10778 ArrayRef<Expr *> NumIterations) { 10779 llvm_unreachable("Not supported in SIMD-only mode"); 10780 } 10781 10782 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10783 const OMPDependClause *C) { 10784 llvm_unreachable("Not supported in SIMD-only mode"); 10785 } 10786 10787 const VarDecl * 10788 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 10789 const VarDecl *NativeParam) const { 10790 llvm_unreachable("Not supported in SIMD-only mode"); 10791 } 10792 10793 Address 10794 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 10795 const VarDecl *NativeParam, 10796 const VarDecl *TargetParam) const { 10797 llvm_unreachable("Not supported in SIMD-only mode"); 10798 } 10799