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, int64_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, int64_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, int64_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, int64_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, int64_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, int64_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, int64_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, int64_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, int64_t *arg_sizes, int64_t 753 // *arg_types); 754 OMPRTL__tgt_target_data_update_nowait, 755 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 756 OMPRTL__tgt_mapper_num_components, 757 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 758 // *base, void *begin, int64_t size, int64_t type); 759 OMPRTL__tgt_push_mapper_component, 760 }; 761 762 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 763 /// region. 764 class CleanupTy final : public EHScopeStack::Cleanup { 765 PrePostActionTy *Action; 766 767 public: 768 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 769 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 770 if (!CGF.HaveInsertPoint()) 771 return; 772 Action->Exit(CGF); 773 } 774 }; 775 776 } // anonymous namespace 777 778 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 779 CodeGenFunction::RunCleanupsScope Scope(CGF); 780 if (PrePostAction) { 781 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 782 Callback(CodeGen, CGF, *PrePostAction); 783 } else { 784 PrePostActionTy Action; 785 Callback(CodeGen, CGF, Action); 786 } 787 } 788 789 /// Check if the combiner is a call to UDR combiner and if it is so return the 790 /// UDR decl used for reduction. 791 static const OMPDeclareReductionDecl * 792 getReductionInit(const Expr *ReductionOp) { 793 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 794 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 795 if (const auto *DRE = 796 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 797 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 798 return DRD; 799 return nullptr; 800 } 801 802 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 803 const OMPDeclareReductionDecl *DRD, 804 const Expr *InitOp, 805 Address Private, Address Original, 806 QualType Ty) { 807 if (DRD->getInitializer()) { 808 std::pair<llvm::Function *, llvm::Function *> Reduction = 809 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 810 const auto *CE = cast<CallExpr>(InitOp); 811 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 812 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 813 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 814 const auto *LHSDRE = 815 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 816 const auto *RHSDRE = 817 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 818 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 819 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 820 [=]() { return Private; }); 821 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 822 [=]() { return Original; }); 823 (void)PrivateScope.Privatize(); 824 RValue Func = RValue::get(Reduction.second); 825 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 826 CGF.EmitIgnoredExpr(InitOp); 827 } else { 828 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 829 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 830 auto *GV = new llvm::GlobalVariable( 831 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 832 llvm::GlobalValue::PrivateLinkage, Init, Name); 833 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 834 RValue InitRVal; 835 switch (CGF.getEvaluationKind(Ty)) { 836 case TEK_Scalar: 837 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 838 break; 839 case TEK_Complex: 840 InitRVal = 841 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 842 break; 843 case TEK_Aggregate: 844 InitRVal = RValue::getAggregate(LV.getAddress()); 845 break; 846 } 847 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 848 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 849 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 850 /*IsInitializer=*/false); 851 } 852 } 853 854 /// Emit initialization of arrays of complex types. 855 /// \param DestAddr Address of the array. 856 /// \param Type Type of array. 857 /// \param Init Initial expression of array. 858 /// \param SrcAddr Address of the original array. 859 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 860 QualType Type, bool EmitDeclareReductionInit, 861 const Expr *Init, 862 const OMPDeclareReductionDecl *DRD, 863 Address SrcAddr = Address::invalid()) { 864 // Perform element-by-element initialization. 865 QualType ElementTy; 866 867 // Drill down to the base element type on both arrays. 868 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 869 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 870 DestAddr = 871 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 872 if (DRD) 873 SrcAddr = 874 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 875 876 llvm::Value *SrcBegin = nullptr; 877 if (DRD) 878 SrcBegin = SrcAddr.getPointer(); 879 llvm::Value *DestBegin = DestAddr.getPointer(); 880 // Cast from pointer to array type to pointer to single element. 881 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 882 // The basic structure here is a while-do loop. 883 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 884 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 885 llvm::Value *IsEmpty = 886 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 887 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 888 889 // Enter the loop body, making that address the current address. 890 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 891 CGF.EmitBlock(BodyBB); 892 893 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 894 895 llvm::PHINode *SrcElementPHI = nullptr; 896 Address SrcElementCurrent = Address::invalid(); 897 if (DRD) { 898 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 899 "omp.arraycpy.srcElementPast"); 900 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 901 SrcElementCurrent = 902 Address(SrcElementPHI, 903 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 904 } 905 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 906 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 907 DestElementPHI->addIncoming(DestBegin, EntryBB); 908 Address DestElementCurrent = 909 Address(DestElementPHI, 910 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 911 912 // Emit copy. 913 { 914 CodeGenFunction::RunCleanupsScope InitScope(CGF); 915 if (EmitDeclareReductionInit) { 916 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 917 SrcElementCurrent, ElementTy); 918 } else 919 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 920 /*IsInitializer=*/false); 921 } 922 923 if (DRD) { 924 // Shift the address forward by one element. 925 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 926 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 927 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 928 } 929 930 // Shift the address forward by one element. 931 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 932 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 933 // Check whether we've reached the end. 934 llvm::Value *Done = 935 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 936 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 937 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 938 939 // Done. 940 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 941 } 942 943 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 944 return CGF.EmitOMPSharedLValue(E); 945 } 946 947 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 948 const Expr *E) { 949 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 950 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 951 return LValue(); 952 } 953 954 void ReductionCodeGen::emitAggregateInitialization( 955 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 956 const OMPDeclareReductionDecl *DRD) { 957 // Emit VarDecl with copy init for arrays. 958 // Get the address of the original variable captured in current 959 // captured region. 960 const auto *PrivateVD = 961 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 962 bool EmitDeclareReductionInit = 963 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 964 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 965 EmitDeclareReductionInit, 966 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 967 : PrivateVD->getInit(), 968 DRD, SharedLVal.getAddress()); 969 } 970 971 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 972 ArrayRef<const Expr *> Privates, 973 ArrayRef<const Expr *> ReductionOps) { 974 ClausesData.reserve(Shareds.size()); 975 SharedAddresses.reserve(Shareds.size()); 976 Sizes.reserve(Shareds.size()); 977 BaseDecls.reserve(Shareds.size()); 978 auto IPriv = Privates.begin(); 979 auto IRed = ReductionOps.begin(); 980 for (const Expr *Ref : Shareds) { 981 ClausesData.emplace_back(Ref, *IPriv, *IRed); 982 std::advance(IPriv, 1); 983 std::advance(IRed, 1); 984 } 985 } 986 987 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 988 assert(SharedAddresses.size() == N && 989 "Number of generated lvalues must be exactly N."); 990 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 991 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 992 SharedAddresses.emplace_back(First, Second); 993 } 994 995 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 996 const auto *PrivateVD = 997 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 998 QualType PrivateType = PrivateVD->getType(); 999 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1000 if (!PrivateType->isVariablyModifiedType()) { 1001 Sizes.emplace_back( 1002 CGF.getTypeSize( 1003 SharedAddresses[N].first.getType().getNonReferenceType()), 1004 nullptr); 1005 return; 1006 } 1007 llvm::Value *Size; 1008 llvm::Value *SizeInChars; 1009 auto *ElemType = 1010 cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType()) 1011 ->getElementType(); 1012 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1013 if (AsArraySection) { 1014 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(), 1015 SharedAddresses[N].first.getPointer()); 1016 Size = CGF.Builder.CreateNUWAdd( 1017 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1018 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1019 } else { 1020 SizeInChars = CGF.getTypeSize( 1021 SharedAddresses[N].first.getType().getNonReferenceType()); 1022 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1023 } 1024 Sizes.emplace_back(SizeInChars, Size); 1025 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1026 CGF, 1027 cast<OpaqueValueExpr>( 1028 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1029 RValue::get(Size)); 1030 CGF.EmitVariablyModifiedType(PrivateType); 1031 } 1032 1033 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1034 llvm::Value *Size) { 1035 const auto *PrivateVD = 1036 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1037 QualType PrivateType = PrivateVD->getType(); 1038 if (!PrivateType->isVariablyModifiedType()) { 1039 assert(!Size && !Sizes[N].second && 1040 "Size should be nullptr for non-variably modified reduction " 1041 "items."); 1042 return; 1043 } 1044 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1045 CGF, 1046 cast<OpaqueValueExpr>( 1047 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1048 RValue::get(Size)); 1049 CGF.EmitVariablyModifiedType(PrivateType); 1050 } 1051 1052 void ReductionCodeGen::emitInitialization( 1053 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1054 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1055 assert(SharedAddresses.size() > N && "No variable was generated"); 1056 const auto *PrivateVD = 1057 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1058 const OMPDeclareReductionDecl *DRD = 1059 getReductionInit(ClausesData[N].ReductionOp); 1060 QualType PrivateType = PrivateVD->getType(); 1061 PrivateAddr = CGF.Builder.CreateElementBitCast( 1062 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1063 QualType SharedType = SharedAddresses[N].first.getType(); 1064 SharedLVal = CGF.MakeAddrLValue( 1065 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(), 1066 CGF.ConvertTypeForMem(SharedType)), 1067 SharedType, SharedAddresses[N].first.getBaseInfo(), 1068 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1069 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1070 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1071 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1072 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1073 PrivateAddr, SharedLVal.getAddress(), 1074 SharedLVal.getType()); 1075 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1076 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1077 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1078 PrivateVD->getType().getQualifiers(), 1079 /*IsInitializer=*/false); 1080 } 1081 } 1082 1083 bool ReductionCodeGen::needCleanups(unsigned N) { 1084 const auto *PrivateVD = 1085 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1086 QualType PrivateType = PrivateVD->getType(); 1087 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1088 return DTorKind != QualType::DK_none; 1089 } 1090 1091 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1092 Address PrivateAddr) { 1093 const auto *PrivateVD = 1094 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1095 QualType PrivateType = PrivateVD->getType(); 1096 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1097 if (needCleanups(N)) { 1098 PrivateAddr = CGF.Builder.CreateElementBitCast( 1099 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1100 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1101 } 1102 } 1103 1104 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1105 LValue BaseLV) { 1106 BaseTy = BaseTy.getNonReferenceType(); 1107 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1108 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1109 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1110 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy); 1111 } else { 1112 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy); 1113 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1114 } 1115 BaseTy = BaseTy->getPointeeType(); 1116 } 1117 return CGF.MakeAddrLValue( 1118 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(), 1119 CGF.ConvertTypeForMem(ElTy)), 1120 BaseLV.getType(), BaseLV.getBaseInfo(), 1121 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1122 } 1123 1124 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1125 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1126 llvm::Value *Addr) { 1127 Address Tmp = Address::invalid(); 1128 Address TopTmp = Address::invalid(); 1129 Address MostTopTmp = Address::invalid(); 1130 BaseTy = BaseTy.getNonReferenceType(); 1131 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1132 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1133 Tmp = CGF.CreateMemTemp(BaseTy); 1134 if (TopTmp.isValid()) 1135 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1136 else 1137 MostTopTmp = Tmp; 1138 TopTmp = Tmp; 1139 BaseTy = BaseTy->getPointeeType(); 1140 } 1141 llvm::Type *Ty = BaseLVType; 1142 if (Tmp.isValid()) 1143 Ty = Tmp.getElementType(); 1144 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1145 if (Tmp.isValid()) { 1146 CGF.Builder.CreateStore(Addr, Tmp); 1147 return MostTopTmp; 1148 } 1149 return Address(Addr, BaseLVAlignment); 1150 } 1151 1152 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1153 const VarDecl *OrigVD = nullptr; 1154 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1155 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1156 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1157 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1158 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1159 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1160 DE = cast<DeclRefExpr>(Base); 1161 OrigVD = cast<VarDecl>(DE->getDecl()); 1162 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1163 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1164 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1165 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1166 DE = cast<DeclRefExpr>(Base); 1167 OrigVD = cast<VarDecl>(DE->getDecl()); 1168 } 1169 return OrigVD; 1170 } 1171 1172 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1173 Address PrivateAddr) { 1174 const DeclRefExpr *DE; 1175 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1176 BaseDecls.emplace_back(OrigVD); 1177 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1178 LValue BaseLValue = 1179 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1180 OriginalBaseLValue); 1181 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1182 BaseLValue.getPointer(), SharedAddresses[N].first.getPointer()); 1183 llvm::Value *PrivatePointer = 1184 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1185 PrivateAddr.getPointer(), 1186 SharedAddresses[N].first.getAddress().getType()); 1187 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1188 return castToBase(CGF, OrigVD->getType(), 1189 SharedAddresses[N].first.getType(), 1190 OriginalBaseLValue.getAddress().getType(), 1191 OriginalBaseLValue.getAlignment(), Ptr); 1192 } 1193 BaseDecls.emplace_back( 1194 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1195 return PrivateAddr; 1196 } 1197 1198 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1199 const OMPDeclareReductionDecl *DRD = 1200 getReductionInit(ClausesData[N].ReductionOp); 1201 return DRD && DRD->getInitializer(); 1202 } 1203 1204 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1205 return CGF.EmitLoadOfPointerLValue( 1206 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1207 getThreadIDVariable()->getType()->castAs<PointerType>()); 1208 } 1209 1210 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1211 if (!CGF.HaveInsertPoint()) 1212 return; 1213 // 1.2.2 OpenMP Language Terminology 1214 // Structured block - An executable statement with a single entry at the 1215 // top and a single exit at the bottom. 1216 // The point of exit cannot be a branch out of the structured block. 1217 // longjmp() and throw() must not violate the entry/exit criteria. 1218 CGF.EHStack.pushTerminate(); 1219 CodeGen(CGF); 1220 CGF.EHStack.popTerminate(); 1221 } 1222 1223 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1224 CodeGenFunction &CGF) { 1225 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1226 getThreadIDVariable()->getType(), 1227 AlignmentSource::Decl); 1228 } 1229 1230 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1231 QualType FieldTy) { 1232 auto *Field = FieldDecl::Create( 1233 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1234 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1235 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1236 Field->setAccess(AS_public); 1237 DC->addDecl(Field); 1238 return Field; 1239 } 1240 1241 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1242 StringRef Separator) 1243 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1244 OffloadEntriesInfoManager(CGM) { 1245 ASTContext &C = CGM.getContext(); 1246 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1247 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1248 RD->startDefinition(); 1249 // reserved_1 1250 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1251 // flags 1252 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1253 // reserved_2 1254 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1255 // reserved_3 1256 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1257 // psource 1258 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1259 RD->completeDefinition(); 1260 IdentQTy = C.getRecordType(RD); 1261 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1262 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1263 1264 loadOffloadInfoMetadata(); 1265 } 1266 1267 static bool tryEmitAlias(CodeGenModule &CGM, const GlobalDecl &NewGD, 1268 const GlobalDecl &OldGD, llvm::GlobalValue *OrigAddr, 1269 bool IsForDefinition) { 1270 // Emit at least a definition for the aliasee if the the address of the 1271 // original function is requested. 1272 if (IsForDefinition || OrigAddr) 1273 (void)CGM.GetAddrOfGlobal(NewGD); 1274 StringRef NewMangledName = CGM.getMangledName(NewGD); 1275 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName); 1276 if (Addr && !Addr->isDeclaration()) { 1277 const auto *D = cast<FunctionDecl>(OldGD.getDecl()); 1278 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(OldGD); 1279 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI); 1280 1281 // Create a reference to the named value. This ensures that it is emitted 1282 // if a deferred decl. 1283 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD); 1284 1285 // Create the new alias itself, but don't set a name yet. 1286 auto *GA = 1287 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule()); 1288 1289 if (OrigAddr) { 1290 assert(OrigAddr->isDeclaration() && "Expected declaration"); 1291 1292 GA->takeName(OrigAddr); 1293 OrigAddr->replaceAllUsesWith( 1294 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType())); 1295 OrigAddr->eraseFromParent(); 1296 } else { 1297 GA->setName(CGM.getMangledName(OldGD)); 1298 } 1299 1300 // Set attributes which are particular to an alias; this is a 1301 // specialization of the attributes which may be set on a global function. 1302 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || 1303 D->isWeakImported()) 1304 GA->setLinkage(llvm::Function::WeakAnyLinkage); 1305 1306 CGM.SetCommonAttributes(OldGD, GA); 1307 return true; 1308 } 1309 return false; 1310 } 1311 1312 void CGOpenMPRuntime::clear() { 1313 InternalVars.clear(); 1314 // Clean non-target variable declarations possibly used only in debug info. 1315 for (const auto &Data : EmittedNonTargetVariables) { 1316 if (!Data.getValue().pointsToAliveValue()) 1317 continue; 1318 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1319 if (!GV) 1320 continue; 1321 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1322 continue; 1323 GV->eraseFromParent(); 1324 } 1325 // Emit aliases for the deferred aliasees. 1326 for (const auto &Pair : DeferredVariantFunction) { 1327 StringRef MangledName = CGM.getMangledName(Pair.second.second); 1328 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName); 1329 // If not able to emit alias, just emit original declaration. 1330 (void)tryEmitAlias(CGM, Pair.second.first, Pair.second.second, Addr, 1331 /*IsForDefinition=*/false); 1332 } 1333 } 1334 1335 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1336 SmallString<128> Buffer; 1337 llvm::raw_svector_ostream OS(Buffer); 1338 StringRef Sep = FirstSeparator; 1339 for (StringRef Part : Parts) { 1340 OS << Sep << Part; 1341 Sep = Separator; 1342 } 1343 return OS.str(); 1344 } 1345 1346 static llvm::Function * 1347 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1348 const Expr *CombinerInitializer, const VarDecl *In, 1349 const VarDecl *Out, bool IsCombiner) { 1350 // void .omp_combiner.(Ty *in, Ty *out); 1351 ASTContext &C = CGM.getContext(); 1352 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1353 FunctionArgList Args; 1354 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1355 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1356 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1357 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1358 Args.push_back(&OmpOutParm); 1359 Args.push_back(&OmpInParm); 1360 const CGFunctionInfo &FnInfo = 1361 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1362 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1363 std::string Name = CGM.getOpenMPRuntime().getName( 1364 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1365 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1366 Name, &CGM.getModule()); 1367 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1368 if (CGM.getLangOpts().Optimize) { 1369 Fn->removeFnAttr(llvm::Attribute::NoInline); 1370 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1371 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1372 } 1373 CodeGenFunction CGF(CGM); 1374 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1375 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1376 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1377 Out->getLocation()); 1378 CodeGenFunction::OMPPrivateScope Scope(CGF); 1379 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1380 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1381 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1382 .getAddress(); 1383 }); 1384 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1385 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1386 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1387 .getAddress(); 1388 }); 1389 (void)Scope.Privatize(); 1390 if (!IsCombiner && Out->hasInit() && 1391 !CGF.isTrivialInitializer(Out->getInit())) { 1392 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1393 Out->getType().getQualifiers(), 1394 /*IsInitializer=*/true); 1395 } 1396 if (CombinerInitializer) 1397 CGF.EmitIgnoredExpr(CombinerInitializer); 1398 Scope.ForceCleanup(); 1399 CGF.FinishFunction(); 1400 return Fn; 1401 } 1402 1403 void CGOpenMPRuntime::emitUserDefinedReduction( 1404 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1405 if (UDRMap.count(D) > 0) 1406 return; 1407 llvm::Function *Combiner = emitCombinerOrInitializer( 1408 CGM, D->getType(), D->getCombiner(), 1409 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1410 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1411 /*IsCombiner=*/true); 1412 llvm::Function *Initializer = nullptr; 1413 if (const Expr *Init = D->getInitializer()) { 1414 Initializer = emitCombinerOrInitializer( 1415 CGM, D->getType(), 1416 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1417 : nullptr, 1418 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1419 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1420 /*IsCombiner=*/false); 1421 } 1422 UDRMap.try_emplace(D, Combiner, Initializer); 1423 if (CGF) { 1424 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1425 Decls.second.push_back(D); 1426 } 1427 } 1428 1429 std::pair<llvm::Function *, llvm::Function *> 1430 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1431 auto I = UDRMap.find(D); 1432 if (I != UDRMap.end()) 1433 return I->second; 1434 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1435 return UDRMap.lookup(D); 1436 } 1437 1438 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1439 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1440 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1441 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1442 assert(ThreadIDVar->getType()->isPointerType() && 1443 "thread id variable must be of type kmp_int32 *"); 1444 CodeGenFunction CGF(CGM, true); 1445 bool HasCancel = false; 1446 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1447 HasCancel = OPD->hasCancel(); 1448 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1449 HasCancel = OPSD->hasCancel(); 1450 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1451 HasCancel = OPFD->hasCancel(); 1452 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1453 HasCancel = OPFD->hasCancel(); 1454 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1455 HasCancel = OPFD->hasCancel(); 1456 else if (const auto *OPFD = 1457 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1458 HasCancel = OPFD->hasCancel(); 1459 else if (const auto *OPFD = 1460 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1461 HasCancel = OPFD->hasCancel(); 1462 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1463 HasCancel, OutlinedHelperName); 1464 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1465 return CGF.GenerateOpenMPCapturedStmtFunction(*CS); 1466 } 1467 1468 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1469 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1470 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1471 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1472 return emitParallelOrTeamsOutlinedFunction( 1473 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1474 } 1475 1476 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1477 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1478 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1479 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1480 return emitParallelOrTeamsOutlinedFunction( 1481 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1482 } 1483 1484 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1485 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1486 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1487 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1488 bool Tied, unsigned &NumberOfParts) { 1489 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1490 PrePostActionTy &) { 1491 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1492 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1493 llvm::Value *TaskArgs[] = { 1494 UpLoc, ThreadID, 1495 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1496 TaskTVar->getType()->castAs<PointerType>()) 1497 .getPointer()}; 1498 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1499 }; 1500 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1501 UntiedCodeGen); 1502 CodeGen.setAction(Action); 1503 assert(!ThreadIDVar->getType()->isPointerType() && 1504 "thread id variable must be of type kmp_int32 for tasks"); 1505 const OpenMPDirectiveKind Region = 1506 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1507 : OMPD_task; 1508 const CapturedStmt *CS = D.getCapturedStmt(Region); 1509 const auto *TD = dyn_cast<OMPTaskDirective>(&D); 1510 CodeGenFunction CGF(CGM, true); 1511 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1512 InnermostKind, 1513 TD ? TD->hasCancel() : false, Action); 1514 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1515 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1516 if (!Tied) 1517 NumberOfParts = Action.getNumberOfParts(); 1518 return Res; 1519 } 1520 1521 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1522 const RecordDecl *RD, const CGRecordLayout &RL, 1523 ArrayRef<llvm::Constant *> Data) { 1524 llvm::StructType *StructTy = RL.getLLVMType(); 1525 unsigned PrevIdx = 0; 1526 ConstantInitBuilder CIBuilder(CGM); 1527 auto DI = Data.begin(); 1528 for (const FieldDecl *FD : RD->fields()) { 1529 unsigned Idx = RL.getLLVMFieldNo(FD); 1530 // Fill the alignment. 1531 for (unsigned I = PrevIdx; I < Idx; ++I) 1532 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1533 PrevIdx = Idx + 1; 1534 Fields.add(*DI); 1535 ++DI; 1536 } 1537 } 1538 1539 template <class... As> 1540 static llvm::GlobalVariable * 1541 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1542 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1543 As &&... Args) { 1544 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1545 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1546 ConstantInitBuilder CIBuilder(CGM); 1547 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1548 buildStructValue(Fields, CGM, RD, RL, Data); 1549 return Fields.finishAndCreateGlobal( 1550 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1551 std::forward<As>(Args)...); 1552 } 1553 1554 template <typename T> 1555 static void 1556 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1557 ArrayRef<llvm::Constant *> Data, 1558 T &Parent) { 1559 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1560 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1561 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1562 buildStructValue(Fields, CGM, RD, RL, Data); 1563 Fields.finishAndAddTo(Parent); 1564 } 1565 1566 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1567 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1568 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1569 FlagsTy FlagsKey(Flags, Reserved2Flags); 1570 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1571 if (!Entry) { 1572 if (!DefaultOpenMPPSource) { 1573 // Initialize default location for psource field of ident_t structure of 1574 // all ident_t objects. Format is ";file;function;line;column;;". 1575 // Taken from 1576 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1577 DefaultOpenMPPSource = 1578 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1579 DefaultOpenMPPSource = 1580 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1581 } 1582 1583 llvm::Constant *Data[] = { 1584 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1585 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1586 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1587 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1588 llvm::GlobalValue *DefaultOpenMPLocation = 1589 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1590 llvm::GlobalValue::PrivateLinkage); 1591 DefaultOpenMPLocation->setUnnamedAddr( 1592 llvm::GlobalValue::UnnamedAddr::Global); 1593 1594 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1595 } 1596 return Address(Entry, Align); 1597 } 1598 1599 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1600 bool AtCurrentPoint) { 1601 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1602 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1603 1604 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1605 if (AtCurrentPoint) { 1606 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1607 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1608 } else { 1609 Elem.second.ServiceInsertPt = 1610 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1611 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1612 } 1613 } 1614 1615 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1616 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1617 if (Elem.second.ServiceInsertPt) { 1618 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1619 Elem.second.ServiceInsertPt = nullptr; 1620 Ptr->eraseFromParent(); 1621 } 1622 } 1623 1624 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1625 SourceLocation Loc, 1626 unsigned Flags) { 1627 Flags |= OMP_IDENT_KMPC; 1628 // If no debug info is generated - return global default location. 1629 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1630 Loc.isInvalid()) 1631 return getOrCreateDefaultLocation(Flags).getPointer(); 1632 1633 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1634 1635 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1636 Address LocValue = Address::invalid(); 1637 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1638 if (I != OpenMPLocThreadIDMap.end()) 1639 LocValue = Address(I->second.DebugLoc, Align); 1640 1641 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1642 // GetOpenMPThreadID was called before this routine. 1643 if (!LocValue.isValid()) { 1644 // Generate "ident_t .kmpc_loc.addr;" 1645 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1646 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1647 Elem.second.DebugLoc = AI.getPointer(); 1648 LocValue = AI; 1649 1650 if (!Elem.second.ServiceInsertPt) 1651 setLocThreadIdInsertPt(CGF); 1652 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1653 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1654 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1655 CGF.getTypeSize(IdentQTy)); 1656 } 1657 1658 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1659 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1660 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1661 LValue PSource = 1662 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1663 1664 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1665 if (OMPDebugLoc == nullptr) { 1666 SmallString<128> Buffer2; 1667 llvm::raw_svector_ostream OS2(Buffer2); 1668 // Build debug location 1669 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1670 OS2 << ";" << PLoc.getFilename() << ";"; 1671 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1672 OS2 << FD->getQualifiedNameAsString(); 1673 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1674 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1675 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1676 } 1677 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1678 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1679 1680 // Our callers always pass this to a runtime function, so for 1681 // convenience, go ahead and return a naked pointer. 1682 return LocValue.getPointer(); 1683 } 1684 1685 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1686 SourceLocation Loc) { 1687 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1688 1689 llvm::Value *ThreadID = nullptr; 1690 // Check whether we've already cached a load of the thread id in this 1691 // function. 1692 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1693 if (I != OpenMPLocThreadIDMap.end()) { 1694 ThreadID = I->second.ThreadID; 1695 if (ThreadID != nullptr) 1696 return ThreadID; 1697 } 1698 // If exceptions are enabled, do not use parameter to avoid possible crash. 1699 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1700 !CGF.getLangOpts().CXXExceptions || 1701 CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 1702 if (auto *OMPRegionInfo = 1703 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1704 if (OMPRegionInfo->getThreadIDVariable()) { 1705 // Check if this an outlined function with thread id passed as argument. 1706 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1707 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1708 // If value loaded in entry block, cache it and use it everywhere in 1709 // function. 1710 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 1711 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1712 Elem.second.ThreadID = ThreadID; 1713 } 1714 return ThreadID; 1715 } 1716 } 1717 } 1718 1719 // This is not an outlined function region - need to call __kmpc_int32 1720 // kmpc_global_thread_num(ident_t *loc). 1721 // Generate thread id value and cache this value for use across the 1722 // function. 1723 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1724 if (!Elem.second.ServiceInsertPt) 1725 setLocThreadIdInsertPt(CGF); 1726 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1727 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1728 llvm::CallInst *Call = CGF.Builder.CreateCall( 1729 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1730 emitUpdateLocation(CGF, Loc)); 1731 Call->setCallingConv(CGF.getRuntimeCC()); 1732 Elem.second.ThreadID = Call; 1733 return Call; 1734 } 1735 1736 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1737 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1738 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1739 clearLocThreadIdInsertPt(CGF); 1740 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1741 } 1742 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1743 for(auto *D : FunctionUDRMap[CGF.CurFn]) 1744 UDRMap.erase(D); 1745 FunctionUDRMap.erase(CGF.CurFn); 1746 } 1747 auto I = FunctionUDMMap.find(CGF.CurFn); 1748 if (I != FunctionUDMMap.end()) { 1749 for(auto *D : I->second) 1750 UDMMap.erase(D); 1751 FunctionUDMMap.erase(I); 1752 } 1753 } 1754 1755 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1756 return IdentTy->getPointerTo(); 1757 } 1758 1759 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1760 if (!Kmpc_MicroTy) { 1761 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1762 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1763 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1764 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1765 } 1766 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1767 } 1768 1769 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1770 llvm::FunctionCallee RTLFn = nullptr; 1771 switch (static_cast<OpenMPRTLFunction>(Function)) { 1772 case OMPRTL__kmpc_fork_call: { 1773 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1774 // microtask, ...); 1775 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1776 getKmpc_MicroPointerTy()}; 1777 auto *FnTy = 1778 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1779 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1780 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1781 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1782 llvm::LLVMContext &Ctx = F->getContext(); 1783 llvm::MDBuilder MDB(Ctx); 1784 // Annotate the callback behavior of the __kmpc_fork_call: 1785 // - The callback callee is argument number 2 (microtask). 1786 // - The first two arguments of the callback callee are unknown (-1). 1787 // - All variadic arguments to the __kmpc_fork_call are passed to the 1788 // callback callee. 1789 F->addMetadata( 1790 llvm::LLVMContext::MD_callback, 1791 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1792 2, {-1, -1}, 1793 /* VarArgsArePassed */ true)})); 1794 } 1795 } 1796 break; 1797 } 1798 case OMPRTL__kmpc_global_thread_num: { 1799 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1800 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1801 auto *FnTy = 1802 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1803 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1804 break; 1805 } 1806 case OMPRTL__kmpc_threadprivate_cached: { 1807 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1808 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1809 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1810 CGM.VoidPtrTy, CGM.SizeTy, 1811 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1812 auto *FnTy = 1813 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1814 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1815 break; 1816 } 1817 case OMPRTL__kmpc_critical: { 1818 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1819 // kmp_critical_name *crit); 1820 llvm::Type *TypeParams[] = { 1821 getIdentTyPointerTy(), CGM.Int32Ty, 1822 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1823 auto *FnTy = 1824 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1825 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1826 break; 1827 } 1828 case OMPRTL__kmpc_critical_with_hint: { 1829 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1830 // kmp_critical_name *crit, uintptr_t hint); 1831 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1832 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1833 CGM.IntPtrTy}; 1834 auto *FnTy = 1835 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1836 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1837 break; 1838 } 1839 case OMPRTL__kmpc_threadprivate_register: { 1840 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1841 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1842 // typedef void *(*kmpc_ctor)(void *); 1843 auto *KmpcCtorTy = 1844 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1845 /*isVarArg*/ false)->getPointerTo(); 1846 // typedef void *(*kmpc_cctor)(void *, void *); 1847 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1848 auto *KmpcCopyCtorTy = 1849 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1850 /*isVarArg*/ false) 1851 ->getPointerTo(); 1852 // typedef void (*kmpc_dtor)(void *); 1853 auto *KmpcDtorTy = 1854 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1855 ->getPointerTo(); 1856 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1857 KmpcCopyCtorTy, KmpcDtorTy}; 1858 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1859 /*isVarArg*/ false); 1860 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1861 break; 1862 } 1863 case OMPRTL__kmpc_end_critical: { 1864 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1865 // kmp_critical_name *crit); 1866 llvm::Type *TypeParams[] = { 1867 getIdentTyPointerTy(), CGM.Int32Ty, 1868 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1869 auto *FnTy = 1870 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1871 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1872 break; 1873 } 1874 case OMPRTL__kmpc_cancel_barrier: { 1875 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1876 // global_tid); 1877 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1878 auto *FnTy = 1879 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1880 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1881 break; 1882 } 1883 case OMPRTL__kmpc_barrier: { 1884 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1885 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1886 auto *FnTy = 1887 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1888 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1889 break; 1890 } 1891 case OMPRTL__kmpc_for_static_fini: { 1892 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1893 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1894 auto *FnTy = 1895 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1896 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1897 break; 1898 } 1899 case OMPRTL__kmpc_push_num_threads: { 1900 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1901 // kmp_int32 num_threads) 1902 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1903 CGM.Int32Ty}; 1904 auto *FnTy = 1905 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1906 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1907 break; 1908 } 1909 case OMPRTL__kmpc_serialized_parallel: { 1910 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1911 // global_tid); 1912 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1913 auto *FnTy = 1914 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1915 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1916 break; 1917 } 1918 case OMPRTL__kmpc_end_serialized_parallel: { 1919 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1920 // global_tid); 1921 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1922 auto *FnTy = 1923 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1924 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1925 break; 1926 } 1927 case OMPRTL__kmpc_flush: { 1928 // Build void __kmpc_flush(ident_t *loc); 1929 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1930 auto *FnTy = 1931 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1932 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1933 break; 1934 } 1935 case OMPRTL__kmpc_master: { 1936 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1937 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1938 auto *FnTy = 1939 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1940 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 1941 break; 1942 } 1943 case OMPRTL__kmpc_end_master: { 1944 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 1945 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1946 auto *FnTy = 1947 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1948 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 1949 break; 1950 } 1951 case OMPRTL__kmpc_omp_taskyield: { 1952 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 1953 // int end_part); 1954 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1955 auto *FnTy = 1956 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1957 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 1958 break; 1959 } 1960 case OMPRTL__kmpc_single: { 1961 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 1962 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1963 auto *FnTy = 1964 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1965 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 1966 break; 1967 } 1968 case OMPRTL__kmpc_end_single: { 1969 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 1970 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1971 auto *FnTy = 1972 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1973 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 1974 break; 1975 } 1976 case OMPRTL__kmpc_omp_task_alloc: { 1977 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 1978 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1979 // kmp_routine_entry_t *task_entry); 1980 assert(KmpRoutineEntryPtrTy != nullptr && 1981 "Type kmp_routine_entry_t must be created."); 1982 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1983 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 1984 // Return void * and then cast to particular kmp_task_t type. 1985 auto *FnTy = 1986 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 1987 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 1988 break; 1989 } 1990 case OMPRTL__kmpc_omp_target_task_alloc: { 1991 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 1992 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1993 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 1994 assert(KmpRoutineEntryPtrTy != nullptr && 1995 "Type kmp_routine_entry_t must be created."); 1996 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1997 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 1998 CGM.Int64Ty}; 1999 // Return void * and then cast to particular kmp_task_t type. 2000 auto *FnTy = 2001 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2002 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2003 break; 2004 } 2005 case OMPRTL__kmpc_omp_task: { 2006 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2007 // *new_task); 2008 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2009 CGM.VoidPtrTy}; 2010 auto *FnTy = 2011 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2012 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2013 break; 2014 } 2015 case OMPRTL__kmpc_copyprivate: { 2016 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2017 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2018 // kmp_int32 didit); 2019 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2020 auto *CpyFnTy = 2021 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2022 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2023 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2024 CGM.Int32Ty}; 2025 auto *FnTy = 2026 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2027 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2028 break; 2029 } 2030 case OMPRTL__kmpc_reduce: { 2031 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2032 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2033 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2034 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2035 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2036 /*isVarArg=*/false); 2037 llvm::Type *TypeParams[] = { 2038 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2039 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2040 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2041 auto *FnTy = 2042 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2043 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2044 break; 2045 } 2046 case OMPRTL__kmpc_reduce_nowait: { 2047 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2048 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2049 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2050 // *lck); 2051 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2052 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2053 /*isVarArg=*/false); 2054 llvm::Type *TypeParams[] = { 2055 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2056 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2057 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2058 auto *FnTy = 2059 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2060 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2061 break; 2062 } 2063 case OMPRTL__kmpc_end_reduce: { 2064 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2065 // kmp_critical_name *lck); 2066 llvm::Type *TypeParams[] = { 2067 getIdentTyPointerTy(), CGM.Int32Ty, 2068 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2069 auto *FnTy = 2070 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2071 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2072 break; 2073 } 2074 case OMPRTL__kmpc_end_reduce_nowait: { 2075 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2076 // kmp_critical_name *lck); 2077 llvm::Type *TypeParams[] = { 2078 getIdentTyPointerTy(), CGM.Int32Ty, 2079 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2080 auto *FnTy = 2081 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2082 RTLFn = 2083 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2084 break; 2085 } 2086 case OMPRTL__kmpc_omp_task_begin_if0: { 2087 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2088 // *new_task); 2089 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2090 CGM.VoidPtrTy}; 2091 auto *FnTy = 2092 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2093 RTLFn = 2094 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2095 break; 2096 } 2097 case OMPRTL__kmpc_omp_task_complete_if0: { 2098 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2099 // *new_task); 2100 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2101 CGM.VoidPtrTy}; 2102 auto *FnTy = 2103 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2104 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2105 /*Name=*/"__kmpc_omp_task_complete_if0"); 2106 break; 2107 } 2108 case OMPRTL__kmpc_ordered: { 2109 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2110 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2111 auto *FnTy = 2112 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2113 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2114 break; 2115 } 2116 case OMPRTL__kmpc_end_ordered: { 2117 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2118 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2119 auto *FnTy = 2120 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2121 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2122 break; 2123 } 2124 case OMPRTL__kmpc_omp_taskwait: { 2125 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2126 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2127 auto *FnTy = 2128 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2129 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2130 break; 2131 } 2132 case OMPRTL__kmpc_taskgroup: { 2133 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2134 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2135 auto *FnTy = 2136 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2137 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2138 break; 2139 } 2140 case OMPRTL__kmpc_end_taskgroup: { 2141 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2142 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2143 auto *FnTy = 2144 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2145 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2146 break; 2147 } 2148 case OMPRTL__kmpc_push_proc_bind: { 2149 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2150 // int proc_bind) 2151 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2152 auto *FnTy = 2153 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2154 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2155 break; 2156 } 2157 case OMPRTL__kmpc_omp_task_with_deps: { 2158 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2159 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2160 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2161 llvm::Type *TypeParams[] = { 2162 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2163 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2164 auto *FnTy = 2165 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2166 RTLFn = 2167 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2168 break; 2169 } 2170 case OMPRTL__kmpc_omp_wait_deps: { 2171 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2172 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2173 // kmp_depend_info_t *noalias_dep_list); 2174 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2175 CGM.Int32Ty, CGM.VoidPtrTy, 2176 CGM.Int32Ty, CGM.VoidPtrTy}; 2177 auto *FnTy = 2178 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2179 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2180 break; 2181 } 2182 case OMPRTL__kmpc_cancellationpoint: { 2183 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2184 // global_tid, kmp_int32 cncl_kind) 2185 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2186 auto *FnTy = 2187 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2188 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2189 break; 2190 } 2191 case OMPRTL__kmpc_cancel: { 2192 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2193 // kmp_int32 cncl_kind) 2194 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2195 auto *FnTy = 2196 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2197 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2198 break; 2199 } 2200 case OMPRTL__kmpc_push_num_teams: { 2201 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2202 // kmp_int32 num_teams, kmp_int32 num_threads) 2203 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2204 CGM.Int32Ty}; 2205 auto *FnTy = 2206 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2207 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2208 break; 2209 } 2210 case OMPRTL__kmpc_fork_teams: { 2211 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2212 // microtask, ...); 2213 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2214 getKmpc_MicroPointerTy()}; 2215 auto *FnTy = 2216 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2217 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2218 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2219 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2220 llvm::LLVMContext &Ctx = F->getContext(); 2221 llvm::MDBuilder MDB(Ctx); 2222 // Annotate the callback behavior of the __kmpc_fork_teams: 2223 // - The callback callee is argument number 2 (microtask). 2224 // - The first two arguments of the callback callee are unknown (-1). 2225 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2226 // callback callee. 2227 F->addMetadata( 2228 llvm::LLVMContext::MD_callback, 2229 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2230 2, {-1, -1}, 2231 /* VarArgsArePassed */ true)})); 2232 } 2233 } 2234 break; 2235 } 2236 case OMPRTL__kmpc_taskloop: { 2237 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2238 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2239 // sched, kmp_uint64 grainsize, void *task_dup); 2240 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2241 CGM.IntTy, 2242 CGM.VoidPtrTy, 2243 CGM.IntTy, 2244 CGM.Int64Ty->getPointerTo(), 2245 CGM.Int64Ty->getPointerTo(), 2246 CGM.Int64Ty, 2247 CGM.IntTy, 2248 CGM.IntTy, 2249 CGM.Int64Ty, 2250 CGM.VoidPtrTy}; 2251 auto *FnTy = 2252 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2253 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2254 break; 2255 } 2256 case OMPRTL__kmpc_doacross_init: { 2257 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2258 // num_dims, struct kmp_dim *dims); 2259 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2260 CGM.Int32Ty, 2261 CGM.Int32Ty, 2262 CGM.VoidPtrTy}; 2263 auto *FnTy = 2264 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2265 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2266 break; 2267 } 2268 case OMPRTL__kmpc_doacross_fini: { 2269 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2270 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2271 auto *FnTy = 2272 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2273 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2274 break; 2275 } 2276 case OMPRTL__kmpc_doacross_post: { 2277 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2278 // *vec); 2279 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2280 CGM.Int64Ty->getPointerTo()}; 2281 auto *FnTy = 2282 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2283 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2284 break; 2285 } 2286 case OMPRTL__kmpc_doacross_wait: { 2287 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2288 // *vec); 2289 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2290 CGM.Int64Ty->getPointerTo()}; 2291 auto *FnTy = 2292 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2293 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2294 break; 2295 } 2296 case OMPRTL__kmpc_task_reduction_init: { 2297 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2298 // *data); 2299 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2300 auto *FnTy = 2301 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2302 RTLFn = 2303 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2304 break; 2305 } 2306 case OMPRTL__kmpc_task_reduction_get_th_data: { 2307 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2308 // *d); 2309 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2310 auto *FnTy = 2311 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2312 RTLFn = CGM.CreateRuntimeFunction( 2313 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2314 break; 2315 } 2316 case OMPRTL__kmpc_alloc: { 2317 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2318 // al); omp_allocator_handle_t type is void *. 2319 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2320 auto *FnTy = 2321 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2322 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2323 break; 2324 } 2325 case OMPRTL__kmpc_free: { 2326 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2327 // al); omp_allocator_handle_t type is void *. 2328 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2329 auto *FnTy = 2330 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2331 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2332 break; 2333 } 2334 case OMPRTL__kmpc_push_target_tripcount: { 2335 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2336 // size); 2337 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2338 llvm::FunctionType *FnTy = 2339 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2340 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2341 break; 2342 } 2343 case OMPRTL__tgt_target: { 2344 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2345 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2346 // *arg_types); 2347 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2348 CGM.VoidPtrTy, 2349 CGM.Int32Ty, 2350 CGM.VoidPtrPtrTy, 2351 CGM.VoidPtrPtrTy, 2352 CGM.Int64Ty->getPointerTo(), 2353 CGM.Int64Ty->getPointerTo()}; 2354 auto *FnTy = 2355 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2356 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2357 break; 2358 } 2359 case OMPRTL__tgt_target_nowait: { 2360 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2361 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2362 // int64_t *arg_types); 2363 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2364 CGM.VoidPtrTy, 2365 CGM.Int32Ty, 2366 CGM.VoidPtrPtrTy, 2367 CGM.VoidPtrPtrTy, 2368 CGM.Int64Ty->getPointerTo(), 2369 CGM.Int64Ty->getPointerTo()}; 2370 auto *FnTy = 2371 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2372 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2373 break; 2374 } 2375 case OMPRTL__tgt_target_teams: { 2376 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2377 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2378 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2379 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2380 CGM.VoidPtrTy, 2381 CGM.Int32Ty, 2382 CGM.VoidPtrPtrTy, 2383 CGM.VoidPtrPtrTy, 2384 CGM.Int64Ty->getPointerTo(), 2385 CGM.Int64Ty->getPointerTo(), 2386 CGM.Int32Ty, 2387 CGM.Int32Ty}; 2388 auto *FnTy = 2389 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2390 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2391 break; 2392 } 2393 case OMPRTL__tgt_target_teams_nowait: { 2394 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2395 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2396 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2397 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2398 CGM.VoidPtrTy, 2399 CGM.Int32Ty, 2400 CGM.VoidPtrPtrTy, 2401 CGM.VoidPtrPtrTy, 2402 CGM.Int64Ty->getPointerTo(), 2403 CGM.Int64Ty->getPointerTo(), 2404 CGM.Int32Ty, 2405 CGM.Int32Ty}; 2406 auto *FnTy = 2407 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2408 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2409 break; 2410 } 2411 case OMPRTL__tgt_register_requires: { 2412 // Build void __tgt_register_requires(int64_t flags); 2413 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2414 auto *FnTy = 2415 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2416 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2417 break; 2418 } 2419 case OMPRTL__tgt_register_lib: { 2420 // Build void __tgt_register_lib(__tgt_bin_desc *desc); 2421 QualType ParamTy = 2422 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2423 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2424 auto *FnTy = 2425 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2426 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); 2427 break; 2428 } 2429 case OMPRTL__tgt_unregister_lib: { 2430 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); 2431 QualType ParamTy = 2432 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2433 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2434 auto *FnTy = 2435 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2436 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); 2437 break; 2438 } 2439 case OMPRTL__tgt_target_data_begin: { 2440 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2441 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2442 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2443 CGM.Int32Ty, 2444 CGM.VoidPtrPtrTy, 2445 CGM.VoidPtrPtrTy, 2446 CGM.Int64Ty->getPointerTo(), 2447 CGM.Int64Ty->getPointerTo()}; 2448 auto *FnTy = 2449 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2450 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2451 break; 2452 } 2453 case OMPRTL__tgt_target_data_begin_nowait: { 2454 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2455 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2456 // *arg_types); 2457 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2458 CGM.Int32Ty, 2459 CGM.VoidPtrPtrTy, 2460 CGM.VoidPtrPtrTy, 2461 CGM.Int64Ty->getPointerTo(), 2462 CGM.Int64Ty->getPointerTo()}; 2463 auto *FnTy = 2464 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2465 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2466 break; 2467 } 2468 case OMPRTL__tgt_target_data_end: { 2469 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2470 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2471 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2472 CGM.Int32Ty, 2473 CGM.VoidPtrPtrTy, 2474 CGM.VoidPtrPtrTy, 2475 CGM.Int64Ty->getPointerTo(), 2476 CGM.Int64Ty->getPointerTo()}; 2477 auto *FnTy = 2478 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2479 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2480 break; 2481 } 2482 case OMPRTL__tgt_target_data_end_nowait: { 2483 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2484 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2485 // *arg_types); 2486 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2487 CGM.Int32Ty, 2488 CGM.VoidPtrPtrTy, 2489 CGM.VoidPtrPtrTy, 2490 CGM.Int64Ty->getPointerTo(), 2491 CGM.Int64Ty->getPointerTo()}; 2492 auto *FnTy = 2493 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2494 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2495 break; 2496 } 2497 case OMPRTL__tgt_target_data_update: { 2498 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2499 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2500 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2501 CGM.Int32Ty, 2502 CGM.VoidPtrPtrTy, 2503 CGM.VoidPtrPtrTy, 2504 CGM.Int64Ty->getPointerTo(), 2505 CGM.Int64Ty->getPointerTo()}; 2506 auto *FnTy = 2507 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2508 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2509 break; 2510 } 2511 case OMPRTL__tgt_target_data_update_nowait: { 2512 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2513 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2514 // *arg_types); 2515 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2516 CGM.Int32Ty, 2517 CGM.VoidPtrPtrTy, 2518 CGM.VoidPtrPtrTy, 2519 CGM.Int64Ty->getPointerTo(), 2520 CGM.Int64Ty->getPointerTo()}; 2521 auto *FnTy = 2522 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2523 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2524 break; 2525 } 2526 case OMPRTL__tgt_mapper_num_components: { 2527 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2528 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2529 auto *FnTy = 2530 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2531 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2532 break; 2533 } 2534 case OMPRTL__tgt_push_mapper_component: { 2535 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2536 // *base, void *begin, int64_t size, int64_t type); 2537 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2538 CGM.Int64Ty, CGM.Int64Ty}; 2539 auto *FnTy = 2540 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2541 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2542 break; 2543 } 2544 } 2545 assert(RTLFn && "Unable to find OpenMP runtime function"); 2546 return RTLFn; 2547 } 2548 2549 llvm::FunctionCallee 2550 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2551 assert((IVSize == 32 || IVSize == 64) && 2552 "IV size is not compatible with the omp runtime"); 2553 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2554 : "__kmpc_for_static_init_4u") 2555 : (IVSigned ? "__kmpc_for_static_init_8" 2556 : "__kmpc_for_static_init_8u"); 2557 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2558 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2559 llvm::Type *TypeParams[] = { 2560 getIdentTyPointerTy(), // loc 2561 CGM.Int32Ty, // tid 2562 CGM.Int32Ty, // schedtype 2563 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2564 PtrTy, // p_lower 2565 PtrTy, // p_upper 2566 PtrTy, // p_stride 2567 ITy, // incr 2568 ITy // chunk 2569 }; 2570 auto *FnTy = 2571 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2572 return CGM.CreateRuntimeFunction(FnTy, Name); 2573 } 2574 2575 llvm::FunctionCallee 2576 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2577 assert((IVSize == 32 || IVSize == 64) && 2578 "IV size is not compatible with the omp runtime"); 2579 StringRef Name = 2580 IVSize == 32 2581 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2582 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2583 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2584 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2585 CGM.Int32Ty, // tid 2586 CGM.Int32Ty, // schedtype 2587 ITy, // lower 2588 ITy, // upper 2589 ITy, // stride 2590 ITy // chunk 2591 }; 2592 auto *FnTy = 2593 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2594 return CGM.CreateRuntimeFunction(FnTy, Name); 2595 } 2596 2597 llvm::FunctionCallee 2598 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2599 assert((IVSize == 32 || IVSize == 64) && 2600 "IV size is not compatible with the omp runtime"); 2601 StringRef Name = 2602 IVSize == 32 2603 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2604 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2605 llvm::Type *TypeParams[] = { 2606 getIdentTyPointerTy(), // loc 2607 CGM.Int32Ty, // tid 2608 }; 2609 auto *FnTy = 2610 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2611 return CGM.CreateRuntimeFunction(FnTy, Name); 2612 } 2613 2614 llvm::FunctionCallee 2615 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2616 assert((IVSize == 32 || IVSize == 64) && 2617 "IV size is not compatible with the omp runtime"); 2618 StringRef Name = 2619 IVSize == 32 2620 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2621 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2622 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2623 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2624 llvm::Type *TypeParams[] = { 2625 getIdentTyPointerTy(), // loc 2626 CGM.Int32Ty, // tid 2627 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2628 PtrTy, // p_lower 2629 PtrTy, // p_upper 2630 PtrTy // p_stride 2631 }; 2632 auto *FnTy = 2633 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2634 return CGM.CreateRuntimeFunction(FnTy, Name); 2635 } 2636 2637 /// Obtain information that uniquely identifies a target entry. This 2638 /// consists of the file and device IDs as well as line number associated with 2639 /// the relevant entry source location. 2640 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2641 unsigned &DeviceID, unsigned &FileID, 2642 unsigned &LineNum) { 2643 SourceManager &SM = C.getSourceManager(); 2644 2645 // The loc should be always valid and have a file ID (the user cannot use 2646 // #pragma directives in macros) 2647 2648 assert(Loc.isValid() && "Source location is expected to be always valid."); 2649 2650 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2651 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2652 2653 llvm::sys::fs::UniqueID ID; 2654 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2655 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2656 << PLoc.getFilename() << EC.message(); 2657 2658 DeviceID = ID.getDevice(); 2659 FileID = ID.getFile(); 2660 LineNum = PLoc.getLine(); 2661 } 2662 2663 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2664 if (CGM.getLangOpts().OpenMPSimd) 2665 return Address::invalid(); 2666 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2667 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2668 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2669 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2670 HasRequiresUnifiedSharedMemory))) { 2671 SmallString<64> PtrName; 2672 { 2673 llvm::raw_svector_ostream OS(PtrName); 2674 OS << CGM.getMangledName(GlobalDecl(VD)); 2675 if (!VD->isExternallyVisible()) { 2676 unsigned DeviceID, FileID, Line; 2677 getTargetEntryUniqueInfo(CGM.getContext(), 2678 VD->getCanonicalDecl()->getBeginLoc(), 2679 DeviceID, FileID, Line); 2680 OS << llvm::format("_%x", FileID); 2681 } 2682 OS << "_decl_tgt_ref_ptr"; 2683 } 2684 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2685 if (!Ptr) { 2686 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2687 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2688 PtrName); 2689 2690 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2691 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2692 2693 if (!CGM.getLangOpts().OpenMPIsDevice) 2694 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2695 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2696 } 2697 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2698 } 2699 return Address::invalid(); 2700 } 2701 2702 llvm::Constant * 2703 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2704 assert(!CGM.getLangOpts().OpenMPUseTLS || 2705 !CGM.getContext().getTargetInfo().isTLSSupported()); 2706 // Lookup the entry, lazily creating it if necessary. 2707 std::string Suffix = getName({"cache", ""}); 2708 return getOrCreateInternalVariable( 2709 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2710 } 2711 2712 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2713 const VarDecl *VD, 2714 Address VDAddr, 2715 SourceLocation Loc) { 2716 if (CGM.getLangOpts().OpenMPUseTLS && 2717 CGM.getContext().getTargetInfo().isTLSSupported()) 2718 return VDAddr; 2719 2720 llvm::Type *VarTy = VDAddr.getElementType(); 2721 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2722 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2723 CGM.Int8PtrTy), 2724 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2725 getOrCreateThreadPrivateCache(VD)}; 2726 return Address(CGF.EmitRuntimeCall( 2727 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2728 VDAddr.getAlignment()); 2729 } 2730 2731 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2732 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2733 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2734 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2735 // library. 2736 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2737 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2738 OMPLoc); 2739 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2740 // to register constructor/destructor for variable. 2741 llvm::Value *Args[] = { 2742 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2743 Ctor, CopyCtor, Dtor}; 2744 CGF.EmitRuntimeCall( 2745 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2746 } 2747 2748 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2749 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2750 bool PerformInit, CodeGenFunction *CGF) { 2751 if (CGM.getLangOpts().OpenMPUseTLS && 2752 CGM.getContext().getTargetInfo().isTLSSupported()) 2753 return nullptr; 2754 2755 VD = VD->getDefinition(CGM.getContext()); 2756 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2757 QualType ASTTy = VD->getType(); 2758 2759 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2760 const Expr *Init = VD->getAnyInitializer(); 2761 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2762 // Generate function that re-emits the declaration's initializer into the 2763 // threadprivate copy of the variable VD 2764 CodeGenFunction CtorCGF(CGM); 2765 FunctionArgList Args; 2766 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2767 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2768 ImplicitParamDecl::Other); 2769 Args.push_back(&Dst); 2770 2771 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2772 CGM.getContext().VoidPtrTy, Args); 2773 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2774 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2775 llvm::Function *Fn = 2776 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2777 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2778 Args, Loc, Loc); 2779 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2780 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2781 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2782 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2783 Arg = CtorCGF.Builder.CreateElementBitCast( 2784 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2785 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2786 /*IsInitializer=*/true); 2787 ArgVal = CtorCGF.EmitLoadOfScalar( 2788 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2789 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2790 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2791 CtorCGF.FinishFunction(); 2792 Ctor = Fn; 2793 } 2794 if (VD->getType().isDestructedType() != QualType::DK_none) { 2795 // Generate function that emits destructor call for the threadprivate copy 2796 // of the variable VD 2797 CodeGenFunction DtorCGF(CGM); 2798 FunctionArgList Args; 2799 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2800 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2801 ImplicitParamDecl::Other); 2802 Args.push_back(&Dst); 2803 2804 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2805 CGM.getContext().VoidTy, Args); 2806 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2807 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2808 llvm::Function *Fn = 2809 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2810 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2811 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2812 Loc, Loc); 2813 // Create a scope with an artificial location for the body of this function. 2814 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2815 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2816 DtorCGF.GetAddrOfLocalVar(&Dst), 2817 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2818 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2819 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2820 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2821 DtorCGF.FinishFunction(); 2822 Dtor = Fn; 2823 } 2824 // Do not emit init function if it is not required. 2825 if (!Ctor && !Dtor) 2826 return nullptr; 2827 2828 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2829 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2830 /*isVarArg=*/false) 2831 ->getPointerTo(); 2832 // Copying constructor for the threadprivate variable. 2833 // Must be NULL - reserved by runtime, but currently it requires that this 2834 // parameter is always NULL. Otherwise it fires assertion. 2835 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2836 if (Ctor == nullptr) { 2837 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2838 /*isVarArg=*/false) 2839 ->getPointerTo(); 2840 Ctor = llvm::Constant::getNullValue(CtorTy); 2841 } 2842 if (Dtor == nullptr) { 2843 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2844 /*isVarArg=*/false) 2845 ->getPointerTo(); 2846 Dtor = llvm::Constant::getNullValue(DtorTy); 2847 } 2848 if (!CGF) { 2849 auto *InitFunctionTy = 2850 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2851 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2852 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2853 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2854 CodeGenFunction InitCGF(CGM); 2855 FunctionArgList ArgList; 2856 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2857 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2858 Loc, Loc); 2859 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2860 InitCGF.FinishFunction(); 2861 return InitFunction; 2862 } 2863 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2864 } 2865 return nullptr; 2866 } 2867 2868 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2869 llvm::GlobalVariable *Addr, 2870 bool PerformInit) { 2871 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2872 !CGM.getLangOpts().OpenMPIsDevice) 2873 return false; 2874 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2875 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2876 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2877 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2878 HasRequiresUnifiedSharedMemory)) 2879 return CGM.getLangOpts().OpenMPIsDevice; 2880 VD = VD->getDefinition(CGM.getContext()); 2881 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2882 return CGM.getLangOpts().OpenMPIsDevice; 2883 2884 QualType ASTTy = VD->getType(); 2885 2886 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2887 // Produce the unique prefix to identify the new target regions. We use 2888 // the source location of the variable declaration which we know to not 2889 // conflict with any target region. 2890 unsigned DeviceID; 2891 unsigned FileID; 2892 unsigned Line; 2893 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2894 SmallString<128> Buffer, Out; 2895 { 2896 llvm::raw_svector_ostream OS(Buffer); 2897 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2898 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2899 } 2900 2901 const Expr *Init = VD->getAnyInitializer(); 2902 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2903 llvm::Constant *Ctor; 2904 llvm::Constant *ID; 2905 if (CGM.getLangOpts().OpenMPIsDevice) { 2906 // Generate function that re-emits the declaration's initializer into 2907 // the threadprivate copy of the variable VD 2908 CodeGenFunction CtorCGF(CGM); 2909 2910 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2911 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2912 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2913 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2914 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2915 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2916 FunctionArgList(), Loc, Loc); 2917 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2918 CtorCGF.EmitAnyExprToMem(Init, 2919 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2920 Init->getType().getQualifiers(), 2921 /*IsInitializer=*/true); 2922 CtorCGF.FinishFunction(); 2923 Ctor = Fn; 2924 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2925 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2926 } else { 2927 Ctor = new llvm::GlobalVariable( 2928 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2929 llvm::GlobalValue::PrivateLinkage, 2930 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2931 ID = Ctor; 2932 } 2933 2934 // Register the information for the entry associated with the constructor. 2935 Out.clear(); 2936 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2937 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2938 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2939 } 2940 if (VD->getType().isDestructedType() != QualType::DK_none) { 2941 llvm::Constant *Dtor; 2942 llvm::Constant *ID; 2943 if (CGM.getLangOpts().OpenMPIsDevice) { 2944 // Generate function that emits destructor call for the threadprivate 2945 // copy of the variable VD 2946 CodeGenFunction DtorCGF(CGM); 2947 2948 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2949 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2950 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2951 FTy, Twine(Buffer, "_dtor"), FI, Loc); 2952 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2953 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2954 FunctionArgList(), Loc, Loc); 2955 // Create a scope with an artificial location for the body of this 2956 // function. 2957 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2958 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 2959 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2960 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2961 DtorCGF.FinishFunction(); 2962 Dtor = Fn; 2963 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2964 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 2965 } else { 2966 Dtor = new llvm::GlobalVariable( 2967 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2968 llvm::GlobalValue::PrivateLinkage, 2969 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 2970 ID = Dtor; 2971 } 2972 // Register the information for the entry associated with the destructor. 2973 Out.clear(); 2974 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2975 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 2976 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 2977 } 2978 return CGM.getLangOpts().OpenMPIsDevice; 2979 } 2980 2981 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2982 QualType VarType, 2983 StringRef Name) { 2984 std::string Suffix = getName({"artificial", ""}); 2985 std::string CacheSuffix = getName({"cache", ""}); 2986 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2987 llvm::Value *GAddr = 2988 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 2989 llvm::Value *Args[] = { 2990 emitUpdateLocation(CGF, SourceLocation()), 2991 getThreadID(CGF, SourceLocation()), 2992 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 2993 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 2994 /*isSigned=*/false), 2995 getOrCreateInternalVariable( 2996 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 2997 return Address( 2998 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2999 CGF.EmitRuntimeCall( 3000 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3001 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3002 CGM.getPointerAlign()); 3003 } 3004 3005 void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, 3006 const RegionCodeGenTy &ThenGen, 3007 const RegionCodeGenTy &ElseGen) { 3008 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3009 3010 // If the condition constant folds and can be elided, try to avoid emitting 3011 // the condition and the dead arm of the if/else. 3012 bool CondConstant; 3013 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3014 if (CondConstant) 3015 ThenGen(CGF); 3016 else 3017 ElseGen(CGF); 3018 return; 3019 } 3020 3021 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3022 // emit the conditional branch. 3023 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3024 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3025 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3026 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3027 3028 // Emit the 'then' code. 3029 CGF.EmitBlock(ThenBlock); 3030 ThenGen(CGF); 3031 CGF.EmitBranch(ContBlock); 3032 // Emit the 'else' code if present. 3033 // There is no need to emit line number for unconditional branch. 3034 (void)ApplyDebugLocation::CreateEmpty(CGF); 3035 CGF.EmitBlock(ElseBlock); 3036 ElseGen(CGF); 3037 // There is no need to emit line number for unconditional branch. 3038 (void)ApplyDebugLocation::CreateEmpty(CGF); 3039 CGF.EmitBranch(ContBlock); 3040 // Emit the continuation block for code after the if. 3041 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3042 } 3043 3044 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3045 llvm::Function *OutlinedFn, 3046 ArrayRef<llvm::Value *> CapturedVars, 3047 const Expr *IfCond) { 3048 if (!CGF.HaveInsertPoint()) 3049 return; 3050 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3051 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3052 PrePostActionTy &) { 3053 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3054 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3055 llvm::Value *Args[] = { 3056 RTLoc, 3057 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3058 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3059 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3060 RealArgs.append(std::begin(Args), std::end(Args)); 3061 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3062 3063 llvm::FunctionCallee RTLFn = 3064 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3065 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3066 }; 3067 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3068 PrePostActionTy &) { 3069 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3070 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3071 // Build calls: 3072 // __kmpc_serialized_parallel(&Loc, GTid); 3073 llvm::Value *Args[] = {RTLoc, ThreadID}; 3074 CGF.EmitRuntimeCall( 3075 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3076 3077 // OutlinedFn(>id, &zero, CapturedStruct); 3078 Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3079 /*Name*/ ".zero.addr"); 3080 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); 3081 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3082 // ThreadId for serialized parallels is 0. 3083 OutlinedFnArgs.push_back(ZeroAddr.getPointer()); 3084 OutlinedFnArgs.push_back(ZeroAddr.getPointer()); 3085 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3086 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3087 3088 // __kmpc_end_serialized_parallel(&Loc, GTid); 3089 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3090 CGF.EmitRuntimeCall( 3091 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3092 EndArgs); 3093 }; 3094 if (IfCond) { 3095 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 3096 } else { 3097 RegionCodeGenTy ThenRCG(ThenGen); 3098 ThenRCG(CGF); 3099 } 3100 } 3101 3102 // If we're inside an (outlined) parallel region, use the region info's 3103 // thread-ID variable (it is passed in a first argument of the outlined function 3104 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3105 // regular serial code region, get thread ID by calling kmp_int32 3106 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3107 // return the address of that temp. 3108 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3109 SourceLocation Loc) { 3110 if (auto *OMPRegionInfo = 3111 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3112 if (OMPRegionInfo->getThreadIDVariable()) 3113 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); 3114 3115 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3116 QualType Int32Ty = 3117 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3118 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3119 CGF.EmitStoreOfScalar(ThreadID, 3120 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3121 3122 return ThreadIDTemp; 3123 } 3124 3125 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3126 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3127 SmallString<256> Buffer; 3128 llvm::raw_svector_ostream Out(Buffer); 3129 Out << Name; 3130 StringRef RuntimeName = Out.str(); 3131 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3132 if (Elem.second) { 3133 assert(Elem.second->getType()->getPointerElementType() == Ty && 3134 "OMP internal variable has different type than requested"); 3135 return &*Elem.second; 3136 } 3137 3138 return Elem.second = new llvm::GlobalVariable( 3139 CGM.getModule(), Ty, /*IsConstant*/ false, 3140 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3141 Elem.first(), /*InsertBefore=*/nullptr, 3142 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3143 } 3144 3145 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3146 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3147 std::string Name = getName({Prefix, "var"}); 3148 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3149 } 3150 3151 namespace { 3152 /// Common pre(post)-action for different OpenMP constructs. 3153 class CommonActionTy final : public PrePostActionTy { 3154 llvm::FunctionCallee EnterCallee; 3155 ArrayRef<llvm::Value *> EnterArgs; 3156 llvm::FunctionCallee ExitCallee; 3157 ArrayRef<llvm::Value *> ExitArgs; 3158 bool Conditional; 3159 llvm::BasicBlock *ContBlock = nullptr; 3160 3161 public: 3162 CommonActionTy(llvm::FunctionCallee EnterCallee, 3163 ArrayRef<llvm::Value *> EnterArgs, 3164 llvm::FunctionCallee ExitCallee, 3165 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3166 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3167 ExitArgs(ExitArgs), Conditional(Conditional) {} 3168 void Enter(CodeGenFunction &CGF) override { 3169 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3170 if (Conditional) { 3171 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3172 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3173 ContBlock = CGF.createBasicBlock("omp_if.end"); 3174 // Generate the branch (If-stmt) 3175 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3176 CGF.EmitBlock(ThenBlock); 3177 } 3178 } 3179 void Done(CodeGenFunction &CGF) { 3180 // Emit the rest of blocks/branches 3181 CGF.EmitBranch(ContBlock); 3182 CGF.EmitBlock(ContBlock, true); 3183 } 3184 void Exit(CodeGenFunction &CGF) override { 3185 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3186 } 3187 }; 3188 } // anonymous namespace 3189 3190 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3191 StringRef CriticalName, 3192 const RegionCodeGenTy &CriticalOpGen, 3193 SourceLocation Loc, const Expr *Hint) { 3194 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3195 // CriticalOpGen(); 3196 // __kmpc_end_critical(ident_t *, gtid, Lock); 3197 // Prepare arguments and build a call to __kmpc_critical 3198 if (!CGF.HaveInsertPoint()) 3199 return; 3200 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3201 getCriticalRegionLock(CriticalName)}; 3202 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3203 std::end(Args)); 3204 if (Hint) { 3205 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3206 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3207 } 3208 CommonActionTy Action( 3209 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3210 : OMPRTL__kmpc_critical), 3211 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3212 CriticalOpGen.setAction(Action); 3213 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3214 } 3215 3216 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3217 const RegionCodeGenTy &MasterOpGen, 3218 SourceLocation Loc) { 3219 if (!CGF.HaveInsertPoint()) 3220 return; 3221 // if(__kmpc_master(ident_t *, gtid)) { 3222 // MasterOpGen(); 3223 // __kmpc_end_master(ident_t *, gtid); 3224 // } 3225 // Prepare arguments and build a call to __kmpc_master 3226 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3227 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3228 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3229 /*Conditional=*/true); 3230 MasterOpGen.setAction(Action); 3231 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3232 Action.Done(CGF); 3233 } 3234 3235 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3236 SourceLocation Loc) { 3237 if (!CGF.HaveInsertPoint()) 3238 return; 3239 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3240 llvm::Value *Args[] = { 3241 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3242 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3243 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 3244 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3245 Region->emitUntiedSwitch(CGF); 3246 } 3247 3248 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3249 const RegionCodeGenTy &TaskgroupOpGen, 3250 SourceLocation Loc) { 3251 if (!CGF.HaveInsertPoint()) 3252 return; 3253 // __kmpc_taskgroup(ident_t *, gtid); 3254 // TaskgroupOpGen(); 3255 // __kmpc_end_taskgroup(ident_t *, gtid); 3256 // Prepare arguments and build a call to __kmpc_taskgroup 3257 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3258 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3259 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3260 Args); 3261 TaskgroupOpGen.setAction(Action); 3262 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3263 } 3264 3265 /// Given an array of pointers to variables, project the address of a 3266 /// given variable. 3267 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3268 unsigned Index, const VarDecl *Var) { 3269 // Pull out the pointer to the variable. 3270 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3271 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3272 3273 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3274 Addr = CGF.Builder.CreateElementBitCast( 3275 Addr, CGF.ConvertTypeForMem(Var->getType())); 3276 return Addr; 3277 } 3278 3279 static llvm::Value *emitCopyprivateCopyFunction( 3280 CodeGenModule &CGM, llvm::Type *ArgsType, 3281 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3282 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3283 SourceLocation Loc) { 3284 ASTContext &C = CGM.getContext(); 3285 // void copy_func(void *LHSArg, void *RHSArg); 3286 FunctionArgList Args; 3287 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3288 ImplicitParamDecl::Other); 3289 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3290 ImplicitParamDecl::Other); 3291 Args.push_back(&LHSArg); 3292 Args.push_back(&RHSArg); 3293 const auto &CGFI = 3294 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3295 std::string Name = 3296 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3297 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3298 llvm::GlobalValue::InternalLinkage, Name, 3299 &CGM.getModule()); 3300 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3301 Fn->setDoesNotRecurse(); 3302 CodeGenFunction CGF(CGM); 3303 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3304 // Dest = (void*[n])(LHSArg); 3305 // Src = (void*[n])(RHSArg); 3306 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3307 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3308 ArgsType), CGF.getPointerAlign()); 3309 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3310 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3311 ArgsType), CGF.getPointerAlign()); 3312 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3313 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3314 // ... 3315 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3316 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3317 const auto *DestVar = 3318 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3319 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3320 3321 const auto *SrcVar = 3322 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3323 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3324 3325 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3326 QualType Type = VD->getType(); 3327 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3328 } 3329 CGF.FinishFunction(); 3330 return Fn; 3331 } 3332 3333 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3334 const RegionCodeGenTy &SingleOpGen, 3335 SourceLocation Loc, 3336 ArrayRef<const Expr *> CopyprivateVars, 3337 ArrayRef<const Expr *> SrcExprs, 3338 ArrayRef<const Expr *> DstExprs, 3339 ArrayRef<const Expr *> AssignmentOps) { 3340 if (!CGF.HaveInsertPoint()) 3341 return; 3342 assert(CopyprivateVars.size() == SrcExprs.size() && 3343 CopyprivateVars.size() == DstExprs.size() && 3344 CopyprivateVars.size() == AssignmentOps.size()); 3345 ASTContext &C = CGM.getContext(); 3346 // int32 did_it = 0; 3347 // if(__kmpc_single(ident_t *, gtid)) { 3348 // SingleOpGen(); 3349 // __kmpc_end_single(ident_t *, gtid); 3350 // did_it = 1; 3351 // } 3352 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3353 // <copy_func>, did_it); 3354 3355 Address DidIt = Address::invalid(); 3356 if (!CopyprivateVars.empty()) { 3357 // int32 did_it = 0; 3358 QualType KmpInt32Ty = 3359 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3360 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3361 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3362 } 3363 // Prepare arguments and build a call to __kmpc_single 3364 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3365 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3366 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3367 /*Conditional=*/true); 3368 SingleOpGen.setAction(Action); 3369 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3370 if (DidIt.isValid()) { 3371 // did_it = 1; 3372 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3373 } 3374 Action.Done(CGF); 3375 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3376 // <copy_func>, did_it); 3377 if (DidIt.isValid()) { 3378 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3379 QualType CopyprivateArrayTy = C.getConstantArrayType( 3380 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3381 /*IndexTypeQuals=*/0); 3382 // Create a list of all private variables for copyprivate. 3383 Address CopyprivateList = 3384 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3385 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3386 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3387 CGF.Builder.CreateStore( 3388 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3389 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy), 3390 Elem); 3391 } 3392 // Build function that copies private values from single region to all other 3393 // threads in the corresponding parallel region. 3394 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3395 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3396 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3397 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3398 Address CL = 3399 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3400 CGF.VoidPtrTy); 3401 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3402 llvm::Value *Args[] = { 3403 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3404 getThreadID(CGF, Loc), // i32 <gtid> 3405 BufSize, // size_t <buf_size> 3406 CL.getPointer(), // void *<copyprivate list> 3407 CpyFn, // void (*) (void *, void *) <copy_func> 3408 DidItVal // i32 did_it 3409 }; 3410 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3411 } 3412 } 3413 3414 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3415 const RegionCodeGenTy &OrderedOpGen, 3416 SourceLocation Loc, bool IsThreads) { 3417 if (!CGF.HaveInsertPoint()) 3418 return; 3419 // __kmpc_ordered(ident_t *, gtid); 3420 // OrderedOpGen(); 3421 // __kmpc_end_ordered(ident_t *, gtid); 3422 // Prepare arguments and build a call to __kmpc_ordered 3423 if (IsThreads) { 3424 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3425 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3426 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3427 Args); 3428 OrderedOpGen.setAction(Action); 3429 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3430 return; 3431 } 3432 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3433 } 3434 3435 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3436 unsigned Flags; 3437 if (Kind == OMPD_for) 3438 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3439 else if (Kind == OMPD_sections) 3440 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3441 else if (Kind == OMPD_single) 3442 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3443 else if (Kind == OMPD_barrier) 3444 Flags = OMP_IDENT_BARRIER_EXPL; 3445 else 3446 Flags = OMP_IDENT_BARRIER_IMPL; 3447 return Flags; 3448 } 3449 3450 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3451 CodeGenFunction &CGF, const OMPLoopDirective &S, 3452 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3453 // Check if the loop directive is actually a doacross loop directive. In this 3454 // case choose static, 1 schedule. 3455 if (llvm::any_of( 3456 S.getClausesOfKind<OMPOrderedClause>(), 3457 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3458 ScheduleKind = OMPC_SCHEDULE_static; 3459 // Chunk size is 1 in this case. 3460 llvm::APInt ChunkSize(32, 1); 3461 ChunkExpr = IntegerLiteral::Create( 3462 CGF.getContext(), ChunkSize, 3463 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3464 SourceLocation()); 3465 } 3466 } 3467 3468 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3469 OpenMPDirectiveKind Kind, bool EmitChecks, 3470 bool ForceSimpleCall) { 3471 if (!CGF.HaveInsertPoint()) 3472 return; 3473 // Build call __kmpc_cancel_barrier(loc, thread_id); 3474 // Build call __kmpc_barrier(loc, thread_id); 3475 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3476 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3477 // thread_id); 3478 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3479 getThreadID(CGF, Loc)}; 3480 if (auto *OMPRegionInfo = 3481 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 3482 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3483 llvm::Value *Result = CGF.EmitRuntimeCall( 3484 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3485 if (EmitChecks) { 3486 // if (__kmpc_cancel_barrier()) { 3487 // exit from construct; 3488 // } 3489 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3490 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3491 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3492 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3493 CGF.EmitBlock(ExitBB); 3494 // exit from construct; 3495 CodeGenFunction::JumpDest CancelDestination = 3496 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3497 CGF.EmitBranchThroughCleanup(CancelDestination); 3498 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3499 } 3500 return; 3501 } 3502 } 3503 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3504 } 3505 3506 /// Map the OpenMP loop schedule to the runtime enumeration. 3507 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3508 bool Chunked, bool Ordered) { 3509 switch (ScheduleKind) { 3510 case OMPC_SCHEDULE_static: 3511 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3512 : (Ordered ? OMP_ord_static : OMP_sch_static); 3513 case OMPC_SCHEDULE_dynamic: 3514 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3515 case OMPC_SCHEDULE_guided: 3516 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3517 case OMPC_SCHEDULE_runtime: 3518 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3519 case OMPC_SCHEDULE_auto: 3520 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3521 case OMPC_SCHEDULE_unknown: 3522 assert(!Chunked && "chunk was specified but schedule kind not known"); 3523 return Ordered ? OMP_ord_static : OMP_sch_static; 3524 } 3525 llvm_unreachable("Unexpected runtime schedule"); 3526 } 3527 3528 /// Map the OpenMP distribute schedule to the runtime enumeration. 3529 static OpenMPSchedType 3530 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3531 // only static is allowed for dist_schedule 3532 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3533 } 3534 3535 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3536 bool Chunked) const { 3537 OpenMPSchedType Schedule = 3538 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3539 return Schedule == OMP_sch_static; 3540 } 3541 3542 bool CGOpenMPRuntime::isStaticNonchunked( 3543 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3544 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3545 return Schedule == OMP_dist_sch_static; 3546 } 3547 3548 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3549 bool Chunked) const { 3550 OpenMPSchedType Schedule = 3551 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3552 return Schedule == OMP_sch_static_chunked; 3553 } 3554 3555 bool CGOpenMPRuntime::isStaticChunked( 3556 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3557 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3558 return Schedule == OMP_dist_sch_static_chunked; 3559 } 3560 3561 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3562 OpenMPSchedType Schedule = 3563 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3564 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3565 return Schedule != OMP_sch_static; 3566 } 3567 3568 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3569 OpenMPScheduleClauseModifier M1, 3570 OpenMPScheduleClauseModifier M2) { 3571 int Modifier = 0; 3572 switch (M1) { 3573 case OMPC_SCHEDULE_MODIFIER_monotonic: 3574 Modifier = OMP_sch_modifier_monotonic; 3575 break; 3576 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3577 Modifier = OMP_sch_modifier_nonmonotonic; 3578 break; 3579 case OMPC_SCHEDULE_MODIFIER_simd: 3580 if (Schedule == OMP_sch_static_chunked) 3581 Schedule = OMP_sch_static_balanced_chunked; 3582 break; 3583 case OMPC_SCHEDULE_MODIFIER_last: 3584 case OMPC_SCHEDULE_MODIFIER_unknown: 3585 break; 3586 } 3587 switch (M2) { 3588 case OMPC_SCHEDULE_MODIFIER_monotonic: 3589 Modifier = OMP_sch_modifier_monotonic; 3590 break; 3591 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3592 Modifier = OMP_sch_modifier_nonmonotonic; 3593 break; 3594 case OMPC_SCHEDULE_MODIFIER_simd: 3595 if (Schedule == OMP_sch_static_chunked) 3596 Schedule = OMP_sch_static_balanced_chunked; 3597 break; 3598 case OMPC_SCHEDULE_MODIFIER_last: 3599 case OMPC_SCHEDULE_MODIFIER_unknown: 3600 break; 3601 } 3602 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3603 // If the static schedule kind is specified or if the ordered clause is 3604 // specified, and if the nonmonotonic modifier is not specified, the effect is 3605 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3606 // modifier is specified, the effect is as if the nonmonotonic modifier is 3607 // specified. 3608 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3609 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3610 Schedule == OMP_sch_static_balanced_chunked || 3611 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static)) 3612 Modifier = OMP_sch_modifier_nonmonotonic; 3613 } 3614 return Schedule | Modifier; 3615 } 3616 3617 void CGOpenMPRuntime::emitForDispatchInit( 3618 CodeGenFunction &CGF, SourceLocation Loc, 3619 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3620 bool Ordered, const DispatchRTInput &DispatchValues) { 3621 if (!CGF.HaveInsertPoint()) 3622 return; 3623 OpenMPSchedType Schedule = getRuntimeSchedule( 3624 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3625 assert(Ordered || 3626 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3627 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3628 Schedule != OMP_sch_static_balanced_chunked)); 3629 // Call __kmpc_dispatch_init( 3630 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3631 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3632 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3633 3634 // If the Chunk was not specified in the clause - use default value 1. 3635 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3636 : CGF.Builder.getIntN(IVSize, 1); 3637 llvm::Value *Args[] = { 3638 emitUpdateLocation(CGF, Loc), 3639 getThreadID(CGF, Loc), 3640 CGF.Builder.getInt32(addMonoNonMonoModifier( 3641 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3642 DispatchValues.LB, // Lower 3643 DispatchValues.UB, // Upper 3644 CGF.Builder.getIntN(IVSize, 1), // Stride 3645 Chunk // Chunk 3646 }; 3647 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3648 } 3649 3650 static void emitForStaticInitCall( 3651 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3652 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3653 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3654 const CGOpenMPRuntime::StaticRTInput &Values) { 3655 if (!CGF.HaveInsertPoint()) 3656 return; 3657 3658 assert(!Values.Ordered); 3659 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3660 Schedule == OMP_sch_static_balanced_chunked || 3661 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3662 Schedule == OMP_dist_sch_static || 3663 Schedule == OMP_dist_sch_static_chunked); 3664 3665 // Call __kmpc_for_static_init( 3666 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3667 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3668 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3669 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3670 llvm::Value *Chunk = Values.Chunk; 3671 if (Chunk == nullptr) { 3672 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3673 Schedule == OMP_dist_sch_static) && 3674 "expected static non-chunked schedule"); 3675 // If the Chunk was not specified in the clause - use default value 1. 3676 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3677 } else { 3678 assert((Schedule == OMP_sch_static_chunked || 3679 Schedule == OMP_sch_static_balanced_chunked || 3680 Schedule == OMP_ord_static_chunked || 3681 Schedule == OMP_dist_sch_static_chunked) && 3682 "expected static chunked schedule"); 3683 } 3684 llvm::Value *Args[] = { 3685 UpdateLocation, 3686 ThreadId, 3687 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3688 M2)), // Schedule type 3689 Values.IL.getPointer(), // &isLastIter 3690 Values.LB.getPointer(), // &LB 3691 Values.UB.getPointer(), // &UB 3692 Values.ST.getPointer(), // &Stride 3693 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3694 Chunk // Chunk 3695 }; 3696 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3697 } 3698 3699 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3700 SourceLocation Loc, 3701 OpenMPDirectiveKind DKind, 3702 const OpenMPScheduleTy &ScheduleKind, 3703 const StaticRTInput &Values) { 3704 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3705 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3706 assert(isOpenMPWorksharingDirective(DKind) && 3707 "Expected loop-based or sections-based directive."); 3708 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3709 isOpenMPLoopDirective(DKind) 3710 ? OMP_IDENT_WORK_LOOP 3711 : OMP_IDENT_WORK_SECTIONS); 3712 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3713 llvm::FunctionCallee StaticInitFunction = 3714 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3715 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3716 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3717 } 3718 3719 void CGOpenMPRuntime::emitDistributeStaticInit( 3720 CodeGenFunction &CGF, SourceLocation Loc, 3721 OpenMPDistScheduleClauseKind SchedKind, 3722 const CGOpenMPRuntime::StaticRTInput &Values) { 3723 OpenMPSchedType ScheduleNum = 3724 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3725 llvm::Value *UpdatedLocation = 3726 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3727 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3728 llvm::FunctionCallee StaticInitFunction = 3729 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3730 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3731 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3732 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3733 } 3734 3735 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3736 SourceLocation Loc, 3737 OpenMPDirectiveKind DKind) { 3738 if (!CGF.HaveInsertPoint()) 3739 return; 3740 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3741 llvm::Value *Args[] = { 3742 emitUpdateLocation(CGF, Loc, 3743 isOpenMPDistributeDirective(DKind) 3744 ? OMP_IDENT_WORK_DISTRIBUTE 3745 : isOpenMPLoopDirective(DKind) 3746 ? OMP_IDENT_WORK_LOOP 3747 : OMP_IDENT_WORK_SECTIONS), 3748 getThreadID(CGF, Loc)}; 3749 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3750 Args); 3751 } 3752 3753 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3754 SourceLocation Loc, 3755 unsigned IVSize, 3756 bool IVSigned) { 3757 if (!CGF.HaveInsertPoint()) 3758 return; 3759 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3760 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3761 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3762 } 3763 3764 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3765 SourceLocation Loc, unsigned IVSize, 3766 bool IVSigned, Address IL, 3767 Address LB, Address UB, 3768 Address ST) { 3769 // Call __kmpc_dispatch_next( 3770 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3771 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3772 // kmp_int[32|64] *p_stride); 3773 llvm::Value *Args[] = { 3774 emitUpdateLocation(CGF, Loc), 3775 getThreadID(CGF, Loc), 3776 IL.getPointer(), // &isLastIter 3777 LB.getPointer(), // &Lower 3778 UB.getPointer(), // &Upper 3779 ST.getPointer() // &Stride 3780 }; 3781 llvm::Value *Call = 3782 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3783 return CGF.EmitScalarConversion( 3784 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3785 CGF.getContext().BoolTy, Loc); 3786 } 3787 3788 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3789 llvm::Value *NumThreads, 3790 SourceLocation Loc) { 3791 if (!CGF.HaveInsertPoint()) 3792 return; 3793 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3794 llvm::Value *Args[] = { 3795 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3796 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3797 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3798 Args); 3799 } 3800 3801 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3802 OpenMPProcBindClauseKind ProcBind, 3803 SourceLocation Loc) { 3804 if (!CGF.HaveInsertPoint()) 3805 return; 3806 // Constants for proc bind value accepted by the runtime. 3807 enum ProcBindTy { 3808 ProcBindFalse = 0, 3809 ProcBindTrue, 3810 ProcBindMaster, 3811 ProcBindClose, 3812 ProcBindSpread, 3813 ProcBindIntel, 3814 ProcBindDefault 3815 } RuntimeProcBind; 3816 switch (ProcBind) { 3817 case OMPC_PROC_BIND_master: 3818 RuntimeProcBind = ProcBindMaster; 3819 break; 3820 case OMPC_PROC_BIND_close: 3821 RuntimeProcBind = ProcBindClose; 3822 break; 3823 case OMPC_PROC_BIND_spread: 3824 RuntimeProcBind = ProcBindSpread; 3825 break; 3826 case OMPC_PROC_BIND_unknown: 3827 llvm_unreachable("Unsupported proc_bind value."); 3828 } 3829 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3830 llvm::Value *Args[] = { 3831 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3832 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; 3833 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3834 } 3835 3836 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3837 SourceLocation Loc) { 3838 if (!CGF.HaveInsertPoint()) 3839 return; 3840 // Build call void __kmpc_flush(ident_t *loc) 3841 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3842 emitUpdateLocation(CGF, Loc)); 3843 } 3844 3845 namespace { 3846 /// Indexes of fields for type kmp_task_t. 3847 enum KmpTaskTFields { 3848 /// List of shared variables. 3849 KmpTaskTShareds, 3850 /// Task routine. 3851 KmpTaskTRoutine, 3852 /// Partition id for the untied tasks. 3853 KmpTaskTPartId, 3854 /// Function with call of destructors for private variables. 3855 Data1, 3856 /// Task priority. 3857 Data2, 3858 /// (Taskloops only) Lower bound. 3859 KmpTaskTLowerBound, 3860 /// (Taskloops only) Upper bound. 3861 KmpTaskTUpperBound, 3862 /// (Taskloops only) Stride. 3863 KmpTaskTStride, 3864 /// (Taskloops only) Is last iteration flag. 3865 KmpTaskTLastIter, 3866 /// (Taskloops only) Reduction data. 3867 KmpTaskTReductions, 3868 }; 3869 } // anonymous namespace 3870 3871 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3872 return OffloadEntriesTargetRegion.empty() && 3873 OffloadEntriesDeviceGlobalVar.empty(); 3874 } 3875 3876 /// Initialize target region entry. 3877 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3878 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3879 StringRef ParentName, unsigned LineNum, 3880 unsigned Order) { 3881 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3882 "only required for the device " 3883 "code generation."); 3884 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3885 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3886 OMPTargetRegionEntryTargetRegion); 3887 ++OffloadingEntriesNum; 3888 } 3889 3890 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3891 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3892 StringRef ParentName, unsigned LineNum, 3893 llvm::Constant *Addr, llvm::Constant *ID, 3894 OMPTargetRegionEntryKind Flags) { 3895 // If we are emitting code for a target, the entry is already initialized, 3896 // only has to be registered. 3897 if (CGM.getLangOpts().OpenMPIsDevice) { 3898 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3899 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3900 DiagnosticsEngine::Error, 3901 "Unable to find target region on line '%0' in the device code."); 3902 CGM.getDiags().Report(DiagID) << LineNum; 3903 return; 3904 } 3905 auto &Entry = 3906 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3907 assert(Entry.isValid() && "Entry not initialized!"); 3908 Entry.setAddress(Addr); 3909 Entry.setID(ID); 3910 Entry.setFlags(Flags); 3911 } else { 3912 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3913 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3914 ++OffloadingEntriesNum; 3915 } 3916 } 3917 3918 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3919 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3920 unsigned LineNum) const { 3921 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3922 if (PerDevice == OffloadEntriesTargetRegion.end()) 3923 return false; 3924 auto PerFile = PerDevice->second.find(FileID); 3925 if (PerFile == PerDevice->second.end()) 3926 return false; 3927 auto PerParentName = PerFile->second.find(ParentName); 3928 if (PerParentName == PerFile->second.end()) 3929 return false; 3930 auto PerLine = PerParentName->second.find(LineNum); 3931 if (PerLine == PerParentName->second.end()) 3932 return false; 3933 // Fail if this entry is already registered. 3934 if (PerLine->second.getAddress() || PerLine->second.getID()) 3935 return false; 3936 return true; 3937 } 3938 3939 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3940 const OffloadTargetRegionEntryInfoActTy &Action) { 3941 // Scan all target region entries and perform the provided action. 3942 for (const auto &D : OffloadEntriesTargetRegion) 3943 for (const auto &F : D.second) 3944 for (const auto &P : F.second) 3945 for (const auto &L : P.second) 3946 Action(D.first, F.first, P.first(), L.first, L.second); 3947 } 3948 3949 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3950 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3951 OMPTargetGlobalVarEntryKind Flags, 3952 unsigned Order) { 3953 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3954 "only required for the device " 3955 "code generation."); 3956 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3957 ++OffloadingEntriesNum; 3958 } 3959 3960 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3961 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3962 CharUnits VarSize, 3963 OMPTargetGlobalVarEntryKind Flags, 3964 llvm::GlobalValue::LinkageTypes Linkage) { 3965 if (CGM.getLangOpts().OpenMPIsDevice) { 3966 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3967 assert(Entry.isValid() && Entry.getFlags() == Flags && 3968 "Entry not initialized!"); 3969 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3970 "Resetting with the new address."); 3971 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3972 if (Entry.getVarSize().isZero()) { 3973 Entry.setVarSize(VarSize); 3974 Entry.setLinkage(Linkage); 3975 } 3976 return; 3977 } 3978 Entry.setVarSize(VarSize); 3979 Entry.setLinkage(Linkage); 3980 Entry.setAddress(Addr); 3981 } else { 3982 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3983 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3984 assert(Entry.isValid() && Entry.getFlags() == Flags && 3985 "Entry not initialized!"); 3986 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3987 "Resetting with the new address."); 3988 if (Entry.getVarSize().isZero()) { 3989 Entry.setVarSize(VarSize); 3990 Entry.setLinkage(Linkage); 3991 } 3992 return; 3993 } 3994 OffloadEntriesDeviceGlobalVar.try_emplace( 3995 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 3996 ++OffloadingEntriesNum; 3997 } 3998 } 3999 4000 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4001 actOnDeviceGlobalVarEntriesInfo( 4002 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4003 // Scan all target region entries and perform the provided action. 4004 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4005 Action(E.getKey(), E.getValue()); 4006 } 4007 4008 llvm::Function * 4009 CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() { 4010 // If we don't have entries or if we are emitting code for the device, we 4011 // don't need to do anything. 4012 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty()) 4013 return nullptr; 4014 4015 llvm::Module &M = CGM.getModule(); 4016 ASTContext &C = CGM.getContext(); 4017 4018 // Get list of devices we care about 4019 const std::vector<llvm::Triple> &Devices = CGM.getLangOpts().OMPTargetTriples; 4020 4021 // We should be creating an offloading descriptor only if there are devices 4022 // specified. 4023 assert(!Devices.empty() && "No OpenMP offloading devices??"); 4024 4025 // Create the external variables that will point to the begin and end of the 4026 // host entries section. These will be defined by the linker. 4027 llvm::Type *OffloadEntryTy = 4028 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()); 4029 auto *HostEntriesBegin = new llvm::GlobalVariable( 4030 M, OffloadEntryTy, /*isConstant=*/true, 4031 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr, 4032 "__start_omp_offloading_entries"); 4033 HostEntriesBegin->setVisibility(llvm::GlobalValue::HiddenVisibility); 4034 auto *HostEntriesEnd = new llvm::GlobalVariable( 4035 M, OffloadEntryTy, /*isConstant=*/true, 4036 llvm::GlobalValue::ExternalLinkage, 4037 /*Initializer=*/nullptr, "__stop_omp_offloading_entries"); 4038 HostEntriesEnd->setVisibility(llvm::GlobalValue::HiddenVisibility); 4039 4040 // Create all device images 4041 auto *DeviceImageTy = cast<llvm::StructType>( 4042 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy())); 4043 ConstantInitBuilder DeviceImagesBuilder(CGM); 4044 ConstantArrayBuilder DeviceImagesEntries = 4045 DeviceImagesBuilder.beginArray(DeviceImageTy); 4046 4047 for (const llvm::Triple &Device : Devices) { 4048 StringRef T = Device.getTriple(); 4049 std::string BeginName = getName({"omp_offloading", "img_start", ""}); 4050 auto *ImgBegin = new llvm::GlobalVariable( 4051 M, CGM.Int8Ty, /*isConstant=*/true, 4052 llvm::GlobalValue::ExternalWeakLinkage, 4053 /*Initializer=*/nullptr, Twine(BeginName).concat(T)); 4054 std::string EndName = getName({"omp_offloading", "img_end", ""}); 4055 auto *ImgEnd = new llvm::GlobalVariable( 4056 M, CGM.Int8Ty, /*isConstant=*/true, 4057 llvm::GlobalValue::ExternalWeakLinkage, 4058 /*Initializer=*/nullptr, Twine(EndName).concat(T)); 4059 4060 llvm::Constant *Data[] = {ImgBegin, ImgEnd, HostEntriesBegin, 4061 HostEntriesEnd}; 4062 createConstantGlobalStructAndAddToParent(CGM, getTgtDeviceImageQTy(), Data, 4063 DeviceImagesEntries); 4064 } 4065 4066 // Create device images global array. 4067 std::string ImagesName = getName({"omp_offloading", "device_images"}); 4068 llvm::GlobalVariable *DeviceImages = 4069 DeviceImagesEntries.finishAndCreateGlobal(ImagesName, 4070 CGM.getPointerAlign(), 4071 /*isConstant=*/true); 4072 DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4073 4074 // This is a Zero array to be used in the creation of the constant expressions 4075 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty), 4076 llvm::Constant::getNullValue(CGM.Int32Ty)}; 4077 4078 // Create the target region descriptor. 4079 llvm::Constant *Data[] = { 4080 llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()), 4081 llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(), 4082 DeviceImages, Index), 4083 HostEntriesBegin, HostEntriesEnd}; 4084 std::string Descriptor = getName({"omp_offloading", "descriptor"}); 4085 llvm::GlobalVariable *Desc = createGlobalStruct( 4086 CGM, getTgtBinaryDescriptorQTy(), /*IsConstant=*/true, Data, Descriptor); 4087 4088 // Emit code to register or unregister the descriptor at execution 4089 // startup or closing, respectively. 4090 4091 llvm::Function *UnRegFn; 4092 { 4093 FunctionArgList Args; 4094 ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other); 4095 Args.push_back(&DummyPtr); 4096 4097 CodeGenFunction CGF(CGM); 4098 // Disable debug info for global (de-)initializer because they are not part 4099 // of some particular construct. 4100 CGF.disableDebugInfo(); 4101 const auto &FI = 4102 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4103 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 4104 std::string UnregName = getName({"omp_offloading", "descriptor_unreg"}); 4105 UnRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, UnregName, FI); 4106 CGF.StartFunction(GlobalDecl(), C.VoidTy, UnRegFn, FI, Args); 4107 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib), 4108 Desc); 4109 CGF.FinishFunction(); 4110 } 4111 llvm::Function *RegFn; 4112 { 4113 CodeGenFunction CGF(CGM); 4114 // Disable debug info for global (de-)initializer because they are not part 4115 // of some particular construct. 4116 CGF.disableDebugInfo(); 4117 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 4118 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 4119 4120 // Encode offload target triples into the registration function name. It 4121 // will serve as a comdat key for the registration/unregistration code for 4122 // this particular combination of offloading targets. 4123 SmallVector<StringRef, 4U> RegFnNameParts(Devices.size() + 2U); 4124 RegFnNameParts[0] = "omp_offloading"; 4125 RegFnNameParts[1] = "descriptor_reg"; 4126 llvm::transform(Devices, std::next(RegFnNameParts.begin(), 2), 4127 [](const llvm::Triple &T) -> const std::string& { 4128 return T.getTriple(); 4129 }); 4130 llvm::sort(std::next(RegFnNameParts.begin(), 2), RegFnNameParts.end()); 4131 std::string Descriptor = getName(RegFnNameParts); 4132 RegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, Descriptor, FI); 4133 CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList()); 4134 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc); 4135 // Create a variable to drive the registration and unregistration of the 4136 // descriptor, so we can reuse the logic that emits Ctors and Dtors. 4137 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), 4138 SourceLocation(), nullptr, C.CharTy, 4139 ImplicitParamDecl::Other); 4140 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc); 4141 CGF.FinishFunction(); 4142 } 4143 if (CGM.supportsCOMDAT()) { 4144 // It is sufficient to call registration function only once, so create a 4145 // COMDAT group for registration/unregistration functions and associated 4146 // data. That would reduce startup time and code size. Registration 4147 // function serves as a COMDAT group key. 4148 llvm::Comdat *ComdatKey = M.getOrInsertComdat(RegFn->getName()); 4149 RegFn->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage); 4150 RegFn->setVisibility(llvm::GlobalValue::HiddenVisibility); 4151 RegFn->setComdat(ComdatKey); 4152 UnRegFn->setComdat(ComdatKey); 4153 DeviceImages->setComdat(ComdatKey); 4154 Desc->setComdat(ComdatKey); 4155 } 4156 return RegFn; 4157 } 4158 4159 void CGOpenMPRuntime::createOffloadEntry( 4160 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4161 llvm::GlobalValue::LinkageTypes Linkage) { 4162 StringRef Name = Addr->getName(); 4163 llvm::Module &M = CGM.getModule(); 4164 llvm::LLVMContext &C = M.getContext(); 4165 4166 // Create constant string with the name. 4167 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4168 4169 std::string StringName = getName({"omp_offloading", "entry_name"}); 4170 auto *Str = new llvm::GlobalVariable( 4171 M, StrPtrInit->getType(), /*isConstant=*/true, 4172 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4173 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4174 4175 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4176 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4177 llvm::ConstantInt::get(CGM.SizeTy, Size), 4178 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4179 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4180 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4181 llvm::GlobalVariable *Entry = createGlobalStruct( 4182 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4183 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4184 4185 // The entry has to be created in the section the linker expects it to be. 4186 Entry->setSection("omp_offloading_entries"); 4187 } 4188 4189 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4190 // Emit the offloading entries and metadata so that the device codegen side 4191 // can easily figure out what to emit. The produced metadata looks like 4192 // this: 4193 // 4194 // !omp_offload.info = !{!1, ...} 4195 // 4196 // Right now we only generate metadata for function that contain target 4197 // regions. 4198 4199 // If we do not have entries, we don't need to do anything. 4200 if (OffloadEntriesInfoManager.empty()) 4201 return; 4202 4203 llvm::Module &M = CGM.getModule(); 4204 llvm::LLVMContext &C = M.getContext(); 4205 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4206 SourceLocation, StringRef>, 4207 16> 4208 OrderedEntries(OffloadEntriesInfoManager.size()); 4209 llvm::SmallVector<StringRef, 16> ParentFunctions( 4210 OffloadEntriesInfoManager.size()); 4211 4212 // Auxiliary methods to create metadata values and strings. 4213 auto &&GetMDInt = [this](unsigned V) { 4214 return llvm::ConstantAsMetadata::get( 4215 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4216 }; 4217 4218 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4219 4220 // Create the offloading info metadata node. 4221 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4222 4223 // Create function that emits metadata for each target region entry; 4224 auto &&TargetRegionMetadataEmitter = 4225 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4226 &GetMDString]( 4227 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4228 unsigned Line, 4229 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4230 // Generate metadata for target regions. Each entry of this metadata 4231 // contains: 4232 // - Entry 0 -> Kind of this type of metadata (0). 4233 // - Entry 1 -> Device ID of the file where the entry was identified. 4234 // - Entry 2 -> File ID of the file where the entry was identified. 4235 // - Entry 3 -> Mangled name of the function where the entry was 4236 // identified. 4237 // - Entry 4 -> Line in the file where the entry was identified. 4238 // - Entry 5 -> Order the entry was created. 4239 // The first element of the metadata node is the kind. 4240 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4241 GetMDInt(FileID), GetMDString(ParentName), 4242 GetMDInt(Line), GetMDInt(E.getOrder())}; 4243 4244 SourceLocation Loc; 4245 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4246 E = CGM.getContext().getSourceManager().fileinfo_end(); 4247 I != E; ++I) { 4248 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4249 I->getFirst()->getUniqueID().getFile() == FileID) { 4250 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4251 I->getFirst(), Line, 1); 4252 break; 4253 } 4254 } 4255 // Save this entry in the right position of the ordered entries array. 4256 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4257 ParentFunctions[E.getOrder()] = ParentName; 4258 4259 // Add metadata to the named metadata node. 4260 MD->addOperand(llvm::MDNode::get(C, Ops)); 4261 }; 4262 4263 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4264 TargetRegionMetadataEmitter); 4265 4266 // Create function that emits metadata for each device global variable entry; 4267 auto &&DeviceGlobalVarMetadataEmitter = 4268 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4269 MD](StringRef MangledName, 4270 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4271 &E) { 4272 // Generate metadata for global variables. Each entry of this metadata 4273 // contains: 4274 // - Entry 0 -> Kind of this type of metadata (1). 4275 // - Entry 1 -> Mangled name of the variable. 4276 // - Entry 2 -> Declare target kind. 4277 // - Entry 3 -> Order the entry was created. 4278 // The first element of the metadata node is the kind. 4279 llvm::Metadata *Ops[] = { 4280 GetMDInt(E.getKind()), GetMDString(MangledName), 4281 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4282 4283 // Save this entry in the right position of the ordered entries array. 4284 OrderedEntries[E.getOrder()] = 4285 std::make_tuple(&E, SourceLocation(), MangledName); 4286 4287 // Add metadata to the named metadata node. 4288 MD->addOperand(llvm::MDNode::get(C, Ops)); 4289 }; 4290 4291 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4292 DeviceGlobalVarMetadataEmitter); 4293 4294 for (const auto &E : OrderedEntries) { 4295 assert(std::get<0>(E) && "All ordered entries must exist!"); 4296 if (const auto *CE = 4297 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4298 std::get<0>(E))) { 4299 if (!CE->getID() || !CE->getAddress()) { 4300 // Do not blame the entry if the parent funtion is not emitted. 4301 StringRef FnName = ParentFunctions[CE->getOrder()]; 4302 if (!CGM.GetGlobalValue(FnName)) 4303 continue; 4304 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4305 DiagnosticsEngine::Error, 4306 "Offloading entry for target region in %0 is incorrect: either the " 4307 "address or the ID is invalid."); 4308 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4309 continue; 4310 } 4311 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4312 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4313 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4314 OffloadEntryInfoDeviceGlobalVar>( 4315 std::get<0>(E))) { 4316 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4317 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4318 CE->getFlags()); 4319 switch (Flags) { 4320 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4321 if (CGM.getLangOpts().OpenMPIsDevice && 4322 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4323 continue; 4324 if (!CE->getAddress()) { 4325 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4326 DiagnosticsEngine::Error, "Offloading entry for declare target " 4327 "variable %0 is incorrect: the " 4328 "address is invalid."); 4329 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4330 continue; 4331 } 4332 // The vaiable has no definition - no need to add the entry. 4333 if (CE->getVarSize().isZero()) 4334 continue; 4335 break; 4336 } 4337 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4338 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4339 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4340 "Declaret target link address is set."); 4341 if (CGM.getLangOpts().OpenMPIsDevice) 4342 continue; 4343 if (!CE->getAddress()) { 4344 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4345 DiagnosticsEngine::Error, 4346 "Offloading entry for declare target variable is incorrect: the " 4347 "address is invalid."); 4348 CGM.getDiags().Report(DiagID); 4349 continue; 4350 } 4351 break; 4352 } 4353 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4354 CE->getVarSize().getQuantity(), Flags, 4355 CE->getLinkage()); 4356 } else { 4357 llvm_unreachable("Unsupported entry kind."); 4358 } 4359 } 4360 } 4361 4362 /// Loads all the offload entries information from the host IR 4363 /// metadata. 4364 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4365 // If we are in target mode, load the metadata from the host IR. This code has 4366 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4367 4368 if (!CGM.getLangOpts().OpenMPIsDevice) 4369 return; 4370 4371 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4372 return; 4373 4374 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4375 if (auto EC = Buf.getError()) { 4376 CGM.getDiags().Report(diag::err_cannot_open_file) 4377 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4378 return; 4379 } 4380 4381 llvm::LLVMContext C; 4382 auto ME = expectedToErrorOrAndEmitErrors( 4383 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4384 4385 if (auto EC = ME.getError()) { 4386 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4387 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4388 CGM.getDiags().Report(DiagID) 4389 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4390 return; 4391 } 4392 4393 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4394 if (!MD) 4395 return; 4396 4397 for (llvm::MDNode *MN : MD->operands()) { 4398 auto &&GetMDInt = [MN](unsigned Idx) { 4399 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4400 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4401 }; 4402 4403 auto &&GetMDString = [MN](unsigned Idx) { 4404 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4405 return V->getString(); 4406 }; 4407 4408 switch (GetMDInt(0)) { 4409 default: 4410 llvm_unreachable("Unexpected metadata!"); 4411 break; 4412 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4413 OffloadingEntryInfoTargetRegion: 4414 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4415 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4416 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4417 /*Order=*/GetMDInt(5)); 4418 break; 4419 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4420 OffloadingEntryInfoDeviceGlobalVar: 4421 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4422 /*MangledName=*/GetMDString(1), 4423 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4424 /*Flags=*/GetMDInt(2)), 4425 /*Order=*/GetMDInt(3)); 4426 break; 4427 } 4428 } 4429 } 4430 4431 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4432 if (!KmpRoutineEntryPtrTy) { 4433 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4434 ASTContext &C = CGM.getContext(); 4435 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4436 FunctionProtoType::ExtProtoInfo EPI; 4437 KmpRoutineEntryPtrQTy = C.getPointerType( 4438 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4439 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4440 } 4441 } 4442 4443 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4444 // Make sure the type of the entry is already created. This is the type we 4445 // have to create: 4446 // struct __tgt_offload_entry{ 4447 // void *addr; // Pointer to the offload entry info. 4448 // // (function or global) 4449 // char *name; // Name of the function or global. 4450 // size_t size; // Size of the entry info (0 if it a function). 4451 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4452 // int32_t reserved; // Reserved, to use by the runtime library. 4453 // }; 4454 if (TgtOffloadEntryQTy.isNull()) { 4455 ASTContext &C = CGM.getContext(); 4456 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4457 RD->startDefinition(); 4458 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4459 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4460 addFieldToRecordDecl(C, RD, C.getSizeType()); 4461 addFieldToRecordDecl( 4462 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4463 addFieldToRecordDecl( 4464 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4465 RD->completeDefinition(); 4466 RD->addAttr(PackedAttr::CreateImplicit(C)); 4467 TgtOffloadEntryQTy = C.getRecordType(RD); 4468 } 4469 return TgtOffloadEntryQTy; 4470 } 4471 4472 QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { 4473 // These are the types we need to build: 4474 // struct __tgt_device_image{ 4475 // void *ImageStart; // Pointer to the target code start. 4476 // void *ImageEnd; // Pointer to the target code end. 4477 // // We also add the host entries to the device image, as it may be useful 4478 // // for the target runtime to have access to that information. 4479 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all 4480 // // the entries. 4481 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4482 // // entries (non inclusive). 4483 // }; 4484 if (TgtDeviceImageQTy.isNull()) { 4485 ASTContext &C = CGM.getContext(); 4486 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image"); 4487 RD->startDefinition(); 4488 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4489 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4490 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4491 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4492 RD->completeDefinition(); 4493 TgtDeviceImageQTy = C.getRecordType(RD); 4494 } 4495 return TgtDeviceImageQTy; 4496 } 4497 4498 QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { 4499 // struct __tgt_bin_desc{ 4500 // int32_t NumDevices; // Number of devices supported. 4501 // __tgt_device_image *DeviceImages; // Arrays of device images 4502 // // (one per device). 4503 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the 4504 // // entries. 4505 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4506 // // entries (non inclusive). 4507 // }; 4508 if (TgtBinaryDescriptorQTy.isNull()) { 4509 ASTContext &C = CGM.getContext(); 4510 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc"); 4511 RD->startDefinition(); 4512 addFieldToRecordDecl( 4513 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4514 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); 4515 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4516 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4517 RD->completeDefinition(); 4518 TgtBinaryDescriptorQTy = C.getRecordType(RD); 4519 } 4520 return TgtBinaryDescriptorQTy; 4521 } 4522 4523 namespace { 4524 struct PrivateHelpersTy { 4525 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4526 const VarDecl *PrivateElemInit) 4527 : Original(Original), PrivateCopy(PrivateCopy), 4528 PrivateElemInit(PrivateElemInit) {} 4529 const VarDecl *Original; 4530 const VarDecl *PrivateCopy; 4531 const VarDecl *PrivateElemInit; 4532 }; 4533 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4534 } // anonymous namespace 4535 4536 static RecordDecl * 4537 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4538 if (!Privates.empty()) { 4539 ASTContext &C = CGM.getContext(); 4540 // Build struct .kmp_privates_t. { 4541 // /* private vars */ 4542 // }; 4543 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4544 RD->startDefinition(); 4545 for (const auto &Pair : Privates) { 4546 const VarDecl *VD = Pair.second.Original; 4547 QualType Type = VD->getType().getNonReferenceType(); 4548 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4549 if (VD->hasAttrs()) { 4550 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4551 E(VD->getAttrs().end()); 4552 I != E; ++I) 4553 FD->addAttr(*I); 4554 } 4555 } 4556 RD->completeDefinition(); 4557 return RD; 4558 } 4559 return nullptr; 4560 } 4561 4562 static RecordDecl * 4563 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4564 QualType KmpInt32Ty, 4565 QualType KmpRoutineEntryPointerQTy) { 4566 ASTContext &C = CGM.getContext(); 4567 // Build struct kmp_task_t { 4568 // void * shareds; 4569 // kmp_routine_entry_t routine; 4570 // kmp_int32 part_id; 4571 // kmp_cmplrdata_t data1; 4572 // kmp_cmplrdata_t data2; 4573 // For taskloops additional fields: 4574 // kmp_uint64 lb; 4575 // kmp_uint64 ub; 4576 // kmp_int64 st; 4577 // kmp_int32 liter; 4578 // void * reductions; 4579 // }; 4580 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4581 UD->startDefinition(); 4582 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4583 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4584 UD->completeDefinition(); 4585 QualType KmpCmplrdataTy = C.getRecordType(UD); 4586 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4587 RD->startDefinition(); 4588 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4589 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4590 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4591 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4592 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4593 if (isOpenMPTaskLoopDirective(Kind)) { 4594 QualType KmpUInt64Ty = 4595 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4596 QualType KmpInt64Ty = 4597 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4598 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4599 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4600 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4601 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4602 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4603 } 4604 RD->completeDefinition(); 4605 return RD; 4606 } 4607 4608 static RecordDecl * 4609 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4610 ArrayRef<PrivateDataTy> Privates) { 4611 ASTContext &C = CGM.getContext(); 4612 // Build struct kmp_task_t_with_privates { 4613 // kmp_task_t task_data; 4614 // .kmp_privates_t. privates; 4615 // }; 4616 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4617 RD->startDefinition(); 4618 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4619 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4620 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4621 RD->completeDefinition(); 4622 return RD; 4623 } 4624 4625 /// Emit a proxy function which accepts kmp_task_t as the second 4626 /// argument. 4627 /// \code 4628 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4629 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4630 /// For taskloops: 4631 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4632 /// tt->reductions, tt->shareds); 4633 /// return 0; 4634 /// } 4635 /// \endcode 4636 static llvm::Function * 4637 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4638 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4639 QualType KmpTaskTWithPrivatesPtrQTy, 4640 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4641 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4642 llvm::Value *TaskPrivatesMap) { 4643 ASTContext &C = CGM.getContext(); 4644 FunctionArgList Args; 4645 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4646 ImplicitParamDecl::Other); 4647 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4648 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4649 ImplicitParamDecl::Other); 4650 Args.push_back(&GtidArg); 4651 Args.push_back(&TaskTypeArg); 4652 const auto &TaskEntryFnInfo = 4653 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4654 llvm::FunctionType *TaskEntryTy = 4655 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4656 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4657 auto *TaskEntry = llvm::Function::Create( 4658 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4659 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4660 TaskEntry->setDoesNotRecurse(); 4661 CodeGenFunction CGF(CGM); 4662 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4663 Loc, Loc); 4664 4665 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4666 // tt, 4667 // For taskloops: 4668 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4669 // tt->task_data.shareds); 4670 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4671 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4672 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4673 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4674 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4675 const auto *KmpTaskTWithPrivatesQTyRD = 4676 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4677 LValue Base = 4678 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4679 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4680 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4681 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4682 llvm::Value *PartidParam = PartIdLVal.getPointer(); 4683 4684 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4685 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4686 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4687 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4688 CGF.ConvertTypeForMem(SharedsPtrTy)); 4689 4690 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4691 llvm::Value *PrivatesParam; 4692 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4693 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4694 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4695 PrivatesLVal.getPointer(), CGF.VoidPtrTy); 4696 } else { 4697 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4698 } 4699 4700 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4701 TaskPrivatesMap, 4702 CGF.Builder 4703 .CreatePointerBitCastOrAddrSpaceCast( 4704 TDBase.getAddress(), CGF.VoidPtrTy) 4705 .getPointer()}; 4706 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4707 std::end(CommonArgs)); 4708 if (isOpenMPTaskLoopDirective(Kind)) { 4709 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4710 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4711 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4712 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4713 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4714 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4715 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4716 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4717 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4718 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4719 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4720 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4721 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4722 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4723 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4724 CallArgs.push_back(LBParam); 4725 CallArgs.push_back(UBParam); 4726 CallArgs.push_back(StParam); 4727 CallArgs.push_back(LIParam); 4728 CallArgs.push_back(RParam); 4729 } 4730 CallArgs.push_back(SharedsParam); 4731 4732 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4733 CallArgs); 4734 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4735 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4736 CGF.FinishFunction(); 4737 return TaskEntry; 4738 } 4739 4740 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4741 SourceLocation Loc, 4742 QualType KmpInt32Ty, 4743 QualType KmpTaskTWithPrivatesPtrQTy, 4744 QualType KmpTaskTWithPrivatesQTy) { 4745 ASTContext &C = CGM.getContext(); 4746 FunctionArgList Args; 4747 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4748 ImplicitParamDecl::Other); 4749 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4750 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4751 ImplicitParamDecl::Other); 4752 Args.push_back(&GtidArg); 4753 Args.push_back(&TaskTypeArg); 4754 const auto &DestructorFnInfo = 4755 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4756 llvm::FunctionType *DestructorFnTy = 4757 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4758 std::string Name = 4759 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4760 auto *DestructorFn = 4761 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4762 Name, &CGM.getModule()); 4763 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4764 DestructorFnInfo); 4765 DestructorFn->setDoesNotRecurse(); 4766 CodeGenFunction CGF(CGM); 4767 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4768 Args, Loc, Loc); 4769 4770 LValue Base = CGF.EmitLoadOfPointerLValue( 4771 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4772 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4773 const auto *KmpTaskTWithPrivatesQTyRD = 4774 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4775 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4776 Base = CGF.EmitLValueForField(Base, *FI); 4777 for (const auto *Field : 4778 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4779 if (QualType::DestructionKind DtorKind = 4780 Field->getType().isDestructedType()) { 4781 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4782 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType()); 4783 } 4784 } 4785 CGF.FinishFunction(); 4786 return DestructorFn; 4787 } 4788 4789 /// Emit a privates mapping function for correct handling of private and 4790 /// firstprivate variables. 4791 /// \code 4792 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4793 /// **noalias priv1,..., <tyn> **noalias privn) { 4794 /// *priv1 = &.privates.priv1; 4795 /// ...; 4796 /// *privn = &.privates.privn; 4797 /// } 4798 /// \endcode 4799 static llvm::Value * 4800 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4801 ArrayRef<const Expr *> PrivateVars, 4802 ArrayRef<const Expr *> FirstprivateVars, 4803 ArrayRef<const Expr *> LastprivateVars, 4804 QualType PrivatesQTy, 4805 ArrayRef<PrivateDataTy> Privates) { 4806 ASTContext &C = CGM.getContext(); 4807 FunctionArgList Args; 4808 ImplicitParamDecl TaskPrivatesArg( 4809 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4810 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4811 ImplicitParamDecl::Other); 4812 Args.push_back(&TaskPrivatesArg); 4813 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4814 unsigned Counter = 1; 4815 for (const Expr *E : PrivateVars) { 4816 Args.push_back(ImplicitParamDecl::Create( 4817 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4818 C.getPointerType(C.getPointerType(E->getType())) 4819 .withConst() 4820 .withRestrict(), 4821 ImplicitParamDecl::Other)); 4822 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4823 PrivateVarsPos[VD] = Counter; 4824 ++Counter; 4825 } 4826 for (const Expr *E : FirstprivateVars) { 4827 Args.push_back(ImplicitParamDecl::Create( 4828 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4829 C.getPointerType(C.getPointerType(E->getType())) 4830 .withConst() 4831 .withRestrict(), 4832 ImplicitParamDecl::Other)); 4833 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4834 PrivateVarsPos[VD] = Counter; 4835 ++Counter; 4836 } 4837 for (const Expr *E : LastprivateVars) { 4838 Args.push_back(ImplicitParamDecl::Create( 4839 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4840 C.getPointerType(C.getPointerType(E->getType())) 4841 .withConst() 4842 .withRestrict(), 4843 ImplicitParamDecl::Other)); 4844 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4845 PrivateVarsPos[VD] = Counter; 4846 ++Counter; 4847 } 4848 const auto &TaskPrivatesMapFnInfo = 4849 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4850 llvm::FunctionType *TaskPrivatesMapTy = 4851 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4852 std::string Name = 4853 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4854 auto *TaskPrivatesMap = llvm::Function::Create( 4855 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4856 &CGM.getModule()); 4857 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4858 TaskPrivatesMapFnInfo); 4859 if (CGM.getLangOpts().Optimize) { 4860 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4861 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4862 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4863 } 4864 CodeGenFunction CGF(CGM); 4865 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4866 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4867 4868 // *privi = &.privates.privi; 4869 LValue Base = CGF.EmitLoadOfPointerLValue( 4870 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4871 TaskPrivatesArg.getType()->castAs<PointerType>()); 4872 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4873 Counter = 0; 4874 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4875 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4876 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4877 LValue RefLVal = 4878 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4879 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4880 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>()); 4881 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal); 4882 ++Counter; 4883 } 4884 CGF.FinishFunction(); 4885 return TaskPrivatesMap; 4886 } 4887 4888 /// Emit initialization for private variables in task-based directives. 4889 static void emitPrivatesInit(CodeGenFunction &CGF, 4890 const OMPExecutableDirective &D, 4891 Address KmpTaskSharedsPtr, LValue TDBase, 4892 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4893 QualType SharedsTy, QualType SharedsPtrTy, 4894 const OMPTaskDataTy &Data, 4895 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4896 ASTContext &C = CGF.getContext(); 4897 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4898 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4899 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4900 ? OMPD_taskloop 4901 : OMPD_task; 4902 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4903 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4904 LValue SrcBase; 4905 bool IsTargetTask = 4906 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4907 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4908 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4909 // PointersArray and SizesArray. The original variables for these arrays are 4910 // not captured and we get their addresses explicitly. 4911 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4912 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4913 SrcBase = CGF.MakeAddrLValue( 4914 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4915 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4916 SharedsTy); 4917 } 4918 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4919 for (const PrivateDataTy &Pair : Privates) { 4920 const VarDecl *VD = Pair.second.PrivateCopy; 4921 const Expr *Init = VD->getAnyInitializer(); 4922 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4923 !CGF.isTrivialInitializer(Init)))) { 4924 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4925 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4926 const VarDecl *OriginalVD = Pair.second.Original; 4927 // Check if the variable is the target-based BasePointersArray, 4928 // PointersArray or SizesArray. 4929 LValue SharedRefLValue; 4930 QualType Type = PrivateLValue.getType(); 4931 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4932 if (IsTargetTask && !SharedField) { 4933 assert(isa<ImplicitParamDecl>(OriginalVD) && 4934 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4935 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4936 ->getNumParams() == 0 && 4937 isa<TranslationUnitDecl>( 4938 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4939 ->getDeclContext()) && 4940 "Expected artificial target data variable."); 4941 SharedRefLValue = 4942 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4943 } else { 4944 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4945 SharedRefLValue = CGF.MakeAddrLValue( 4946 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)), 4947 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4948 SharedRefLValue.getTBAAInfo()); 4949 } 4950 if (Type->isArrayType()) { 4951 // Initialize firstprivate array. 4952 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4953 // Perform simple memcpy. 4954 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4955 } else { 4956 // Initialize firstprivate array using element-by-element 4957 // initialization. 4958 CGF.EmitOMPAggregateAssign( 4959 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type, 4960 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4961 Address SrcElement) { 4962 // Clean up any temporaries needed by the initialization. 4963 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4964 InitScope.addPrivate( 4965 Elem, [SrcElement]() -> Address { return SrcElement; }); 4966 (void)InitScope.Privatize(); 4967 // Emit initialization for single element. 4968 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4969 CGF, &CapturesInfo); 4970 CGF.EmitAnyExprToMem(Init, DestElement, 4971 Init->getType().getQualifiers(), 4972 /*IsInitializer=*/false); 4973 }); 4974 } 4975 } else { 4976 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4977 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address { 4978 return SharedRefLValue.getAddress(); 4979 }); 4980 (void)InitScope.Privatize(); 4981 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4982 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4983 /*capturedByInit=*/false); 4984 } 4985 } else { 4986 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4987 } 4988 } 4989 ++FI; 4990 } 4991 } 4992 4993 /// Check if duplication function is required for taskloops. 4994 static bool checkInitIsRequired(CodeGenFunction &CGF, 4995 ArrayRef<PrivateDataTy> Privates) { 4996 bool InitRequired = false; 4997 for (const PrivateDataTy &Pair : Privates) { 4998 const VarDecl *VD = Pair.second.PrivateCopy; 4999 const Expr *Init = VD->getAnyInitializer(); 5000 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 5001 !CGF.isTrivialInitializer(Init)); 5002 if (InitRequired) 5003 break; 5004 } 5005 return InitRequired; 5006 } 5007 5008 5009 /// Emit task_dup function (for initialization of 5010 /// private/firstprivate/lastprivate vars and last_iter flag) 5011 /// \code 5012 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 5013 /// lastpriv) { 5014 /// // setup lastprivate flag 5015 /// task_dst->last = lastpriv; 5016 /// // could be constructor calls here... 5017 /// } 5018 /// \endcode 5019 static llvm::Value * 5020 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 5021 const OMPExecutableDirective &D, 5022 QualType KmpTaskTWithPrivatesPtrQTy, 5023 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 5024 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 5025 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 5026 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 5027 ASTContext &C = CGM.getContext(); 5028 FunctionArgList Args; 5029 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 5030 KmpTaskTWithPrivatesPtrQTy, 5031 ImplicitParamDecl::Other); 5032 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 5033 KmpTaskTWithPrivatesPtrQTy, 5034 ImplicitParamDecl::Other); 5035 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 5036 ImplicitParamDecl::Other); 5037 Args.push_back(&DstArg); 5038 Args.push_back(&SrcArg); 5039 Args.push_back(&LastprivArg); 5040 const auto &TaskDupFnInfo = 5041 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5042 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 5043 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 5044 auto *TaskDup = llvm::Function::Create( 5045 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 5046 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 5047 TaskDup->setDoesNotRecurse(); 5048 CodeGenFunction CGF(CGM); 5049 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 5050 Loc); 5051 5052 LValue TDBase = CGF.EmitLoadOfPointerLValue( 5053 CGF.GetAddrOfLocalVar(&DstArg), 5054 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 5055 // task_dst->liter = lastpriv; 5056 if (WithLastIter) { 5057 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 5058 LValue Base = CGF.EmitLValueForField( 5059 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5060 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 5061 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 5062 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 5063 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 5064 } 5065 5066 // Emit initial values for private copies (if any). 5067 assert(!Privates.empty()); 5068 Address KmpTaskSharedsPtr = Address::invalid(); 5069 if (!Data.FirstprivateVars.empty()) { 5070 LValue TDBase = CGF.EmitLoadOfPointerLValue( 5071 CGF.GetAddrOfLocalVar(&SrcArg), 5072 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 5073 LValue Base = CGF.EmitLValueForField( 5074 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5075 KmpTaskSharedsPtr = Address( 5076 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 5077 Base, *std::next(KmpTaskTQTyRD->field_begin(), 5078 KmpTaskTShareds)), 5079 Loc), 5080 CGF.getNaturalTypeAlignment(SharedsTy)); 5081 } 5082 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 5083 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 5084 CGF.FinishFunction(); 5085 return TaskDup; 5086 } 5087 5088 /// Checks if destructor function is required to be generated. 5089 /// \return true if cleanups are required, false otherwise. 5090 static bool 5091 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 5092 bool NeedsCleanup = false; 5093 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 5094 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 5095 for (const FieldDecl *FD : PrivateRD->fields()) { 5096 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 5097 if (NeedsCleanup) 5098 break; 5099 } 5100 return NeedsCleanup; 5101 } 5102 5103 CGOpenMPRuntime::TaskResultTy 5104 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 5105 const OMPExecutableDirective &D, 5106 llvm::Function *TaskFunction, QualType SharedsTy, 5107 Address Shareds, const OMPTaskDataTy &Data) { 5108 ASTContext &C = CGM.getContext(); 5109 llvm::SmallVector<PrivateDataTy, 4> Privates; 5110 // Aggregate privates and sort them by the alignment. 5111 auto I = Data.PrivateCopies.begin(); 5112 for (const Expr *E : Data.PrivateVars) { 5113 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5114 Privates.emplace_back( 5115 C.getDeclAlign(VD), 5116 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5117 /*PrivateElemInit=*/nullptr)); 5118 ++I; 5119 } 5120 I = Data.FirstprivateCopies.begin(); 5121 auto IElemInitRef = Data.FirstprivateInits.begin(); 5122 for (const Expr *E : Data.FirstprivateVars) { 5123 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5124 Privates.emplace_back( 5125 C.getDeclAlign(VD), 5126 PrivateHelpersTy( 5127 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5128 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 5129 ++I; 5130 ++IElemInitRef; 5131 } 5132 I = Data.LastprivateCopies.begin(); 5133 for (const Expr *E : Data.LastprivateVars) { 5134 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5135 Privates.emplace_back( 5136 C.getDeclAlign(VD), 5137 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5138 /*PrivateElemInit=*/nullptr)); 5139 ++I; 5140 } 5141 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 5142 return L.first > R.first; 5143 }); 5144 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 5145 // Build type kmp_routine_entry_t (if not built yet). 5146 emitKmpRoutineEntryT(KmpInt32Ty); 5147 // Build type kmp_task_t (if not built yet). 5148 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 5149 if (SavedKmpTaskloopTQTy.isNull()) { 5150 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5151 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5152 } 5153 KmpTaskTQTy = SavedKmpTaskloopTQTy; 5154 } else { 5155 assert((D.getDirectiveKind() == OMPD_task || 5156 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 5157 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5158 "Expected taskloop, task or target directive"); 5159 if (SavedKmpTaskTQTy.isNull()) { 5160 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5161 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5162 } 5163 KmpTaskTQTy = SavedKmpTaskTQTy; 5164 } 5165 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5166 // Build particular struct kmp_task_t for the given task. 5167 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5168 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5169 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5170 QualType KmpTaskTWithPrivatesPtrQTy = 5171 C.getPointerType(KmpTaskTWithPrivatesQTy); 5172 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5173 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5174 KmpTaskTWithPrivatesTy->getPointerTo(); 5175 llvm::Value *KmpTaskTWithPrivatesTySize = 5176 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5177 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5178 5179 // Emit initial values for private copies (if any). 5180 llvm::Value *TaskPrivatesMap = nullptr; 5181 llvm::Type *TaskPrivatesMapTy = 5182 std::next(TaskFunction->arg_begin(), 3)->getType(); 5183 if (!Privates.empty()) { 5184 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5185 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5186 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5187 FI->getType(), Privates); 5188 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5189 TaskPrivatesMap, TaskPrivatesMapTy); 5190 } else { 5191 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5192 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5193 } 5194 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5195 // kmp_task_t *tt); 5196 llvm::Function *TaskEntry = emitProxyTaskFunction( 5197 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5198 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5199 TaskPrivatesMap); 5200 5201 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5202 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5203 // kmp_routine_entry_t *task_entry); 5204 // Task flags. Format is taken from 5205 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5206 // description of kmp_tasking_flags struct. 5207 enum { 5208 TiedFlag = 0x1, 5209 FinalFlag = 0x2, 5210 DestructorsFlag = 0x8, 5211 PriorityFlag = 0x20 5212 }; 5213 unsigned Flags = Data.Tied ? TiedFlag : 0; 5214 bool NeedsCleanup = false; 5215 if (!Privates.empty()) { 5216 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5217 if (NeedsCleanup) 5218 Flags = Flags | DestructorsFlag; 5219 } 5220 if (Data.Priority.getInt()) 5221 Flags = Flags | PriorityFlag; 5222 llvm::Value *TaskFlags = 5223 Data.Final.getPointer() 5224 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5225 CGF.Builder.getInt32(FinalFlag), 5226 CGF.Builder.getInt32(/*C=*/0)) 5227 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5228 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5229 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5230 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5231 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5232 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5233 TaskEntry, KmpRoutineEntryPtrTy)}; 5234 llvm::Value *NewTask; 5235 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5236 // Check if we have any device clause associated with the directive. 5237 const Expr *Device = nullptr; 5238 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5239 Device = C->getDevice(); 5240 // Emit device ID if any otherwise use default value. 5241 llvm::Value *DeviceID; 5242 if (Device) 5243 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5244 CGF.Int64Ty, /*isSigned=*/true); 5245 else 5246 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5247 AllocArgs.push_back(DeviceID); 5248 NewTask = CGF.EmitRuntimeCall( 5249 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5250 } else { 5251 NewTask = CGF.EmitRuntimeCall( 5252 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5253 } 5254 llvm::Value *NewTaskNewTaskTTy = 5255 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5256 NewTask, KmpTaskTWithPrivatesPtrTy); 5257 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5258 KmpTaskTWithPrivatesQTy); 5259 LValue TDBase = 5260 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5261 // Fill the data in the resulting kmp_task_t record. 5262 // Copy shareds if there are any. 5263 Address KmpTaskSharedsPtr = Address::invalid(); 5264 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5265 KmpTaskSharedsPtr = 5266 Address(CGF.EmitLoadOfScalar( 5267 CGF.EmitLValueForField( 5268 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5269 KmpTaskTShareds)), 5270 Loc), 5271 CGF.getNaturalTypeAlignment(SharedsTy)); 5272 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5273 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5274 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5275 } 5276 // Emit initial values for private copies (if any). 5277 TaskResultTy Result; 5278 if (!Privates.empty()) { 5279 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5280 SharedsTy, SharedsPtrTy, Data, Privates, 5281 /*ForDup=*/false); 5282 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5283 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5284 Result.TaskDupFn = emitTaskDupFunction( 5285 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5286 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5287 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5288 } 5289 } 5290 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5291 enum { Priority = 0, Destructors = 1 }; 5292 // Provide pointer to function with destructors for privates. 5293 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5294 const RecordDecl *KmpCmplrdataUD = 5295 (*FI)->getType()->getAsUnionType()->getDecl(); 5296 if (NeedsCleanup) { 5297 llvm::Value *DestructorFn = emitDestructorsFunction( 5298 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5299 KmpTaskTWithPrivatesQTy); 5300 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5301 LValue DestructorsLV = CGF.EmitLValueForField( 5302 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5303 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5304 DestructorFn, KmpRoutineEntryPtrTy), 5305 DestructorsLV); 5306 } 5307 // Set priority. 5308 if (Data.Priority.getInt()) { 5309 LValue Data2LV = CGF.EmitLValueForField( 5310 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5311 LValue PriorityLV = CGF.EmitLValueForField( 5312 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5313 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5314 } 5315 Result.NewTask = NewTask; 5316 Result.TaskEntry = TaskEntry; 5317 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5318 Result.TDBase = TDBase; 5319 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5320 return Result; 5321 } 5322 5323 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5324 const OMPExecutableDirective &D, 5325 llvm::Function *TaskFunction, 5326 QualType SharedsTy, Address Shareds, 5327 const Expr *IfCond, 5328 const OMPTaskDataTy &Data) { 5329 if (!CGF.HaveInsertPoint()) 5330 return; 5331 5332 TaskResultTy Result = 5333 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5334 llvm::Value *NewTask = Result.NewTask; 5335 llvm::Function *TaskEntry = Result.TaskEntry; 5336 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5337 LValue TDBase = Result.TDBase; 5338 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5339 ASTContext &C = CGM.getContext(); 5340 // Process list of dependences. 5341 Address DependenciesArray = Address::invalid(); 5342 unsigned NumDependencies = Data.Dependences.size(); 5343 if (NumDependencies) { 5344 // Dependence kind for RTL. 5345 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 }; 5346 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5347 RecordDecl *KmpDependInfoRD; 5348 QualType FlagsTy = 5349 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5350 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5351 if (KmpDependInfoTy.isNull()) { 5352 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5353 KmpDependInfoRD->startDefinition(); 5354 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5355 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5356 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5357 KmpDependInfoRD->completeDefinition(); 5358 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5359 } else { 5360 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5361 } 5362 // Define type kmp_depend_info[<Dependences.size()>]; 5363 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5364 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5365 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5366 // kmp_depend_info[<Dependences.size()>] deps; 5367 DependenciesArray = 5368 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5369 for (unsigned I = 0; I < NumDependencies; ++I) { 5370 const Expr *E = Data.Dependences[I].second; 5371 LValue Addr = CGF.EmitLValue(E); 5372 llvm::Value *Size; 5373 QualType Ty = E->getType(); 5374 if (const auto *ASE = 5375 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5376 LValue UpAddrLVal = 5377 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5378 llvm::Value *UpAddr = 5379 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1); 5380 llvm::Value *LowIntPtr = 5381 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy); 5382 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5383 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5384 } else { 5385 Size = CGF.getTypeSize(Ty); 5386 } 5387 LValue Base = CGF.MakeAddrLValue( 5388 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I), 5389 KmpDependInfoTy); 5390 // deps[i].base_addr = &<Dependences[i].second>; 5391 LValue BaseAddrLVal = CGF.EmitLValueForField( 5392 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5393 CGF.EmitStoreOfScalar( 5394 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy), 5395 BaseAddrLVal); 5396 // deps[i].len = sizeof(<Dependences[i].second>); 5397 LValue LenLVal = CGF.EmitLValueForField( 5398 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5399 CGF.EmitStoreOfScalar(Size, LenLVal); 5400 // deps[i].flags = <Dependences[i].first>; 5401 RTLDependenceKindTy DepKind; 5402 switch (Data.Dependences[I].first) { 5403 case OMPC_DEPEND_in: 5404 DepKind = DepIn; 5405 break; 5406 // Out and InOut dependencies must use the same code. 5407 case OMPC_DEPEND_out: 5408 case OMPC_DEPEND_inout: 5409 DepKind = DepInOut; 5410 break; 5411 case OMPC_DEPEND_mutexinoutset: 5412 DepKind = DepMutexInOutSet; 5413 break; 5414 case OMPC_DEPEND_source: 5415 case OMPC_DEPEND_sink: 5416 case OMPC_DEPEND_unknown: 5417 llvm_unreachable("Unknown task dependence type"); 5418 } 5419 LValue FlagsLVal = CGF.EmitLValueForField( 5420 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5421 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5422 FlagsLVal); 5423 } 5424 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5425 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); 5426 } 5427 5428 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5429 // libcall. 5430 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5431 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5432 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5433 // list is not empty 5434 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5435 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5436 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5437 llvm::Value *DepTaskArgs[7]; 5438 if (NumDependencies) { 5439 DepTaskArgs[0] = UpLoc; 5440 DepTaskArgs[1] = ThreadID; 5441 DepTaskArgs[2] = NewTask; 5442 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 5443 DepTaskArgs[4] = DependenciesArray.getPointer(); 5444 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5445 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5446 } 5447 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 5448 &TaskArgs, 5449 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5450 if (!Data.Tied) { 5451 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5452 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5453 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5454 } 5455 if (NumDependencies) { 5456 CGF.EmitRuntimeCall( 5457 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5458 } else { 5459 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5460 TaskArgs); 5461 } 5462 // Check if parent region is untied and build return for untied task; 5463 if (auto *Region = 5464 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5465 Region->emitUntiedSwitch(CGF); 5466 }; 5467 5468 llvm::Value *DepWaitTaskArgs[6]; 5469 if (NumDependencies) { 5470 DepWaitTaskArgs[0] = UpLoc; 5471 DepWaitTaskArgs[1] = ThreadID; 5472 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 5473 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5474 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5475 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5476 } 5477 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5478 NumDependencies, &DepWaitTaskArgs, 5479 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5480 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5481 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5482 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5483 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5484 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5485 // is specified. 5486 if (NumDependencies) 5487 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5488 DepWaitTaskArgs); 5489 // Call proxy_task_entry(gtid, new_task); 5490 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5491 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5492 Action.Enter(CGF); 5493 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5494 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5495 OutlinedFnArgs); 5496 }; 5497 5498 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5499 // kmp_task_t *new_task); 5500 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5501 // kmp_task_t *new_task); 5502 RegionCodeGenTy RCG(CodeGen); 5503 CommonActionTy Action( 5504 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5505 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5506 RCG.setAction(Action); 5507 RCG(CGF); 5508 }; 5509 5510 if (IfCond) { 5511 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5512 } else { 5513 RegionCodeGenTy ThenRCG(ThenCodeGen); 5514 ThenRCG(CGF); 5515 } 5516 } 5517 5518 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5519 const OMPLoopDirective &D, 5520 llvm::Function *TaskFunction, 5521 QualType SharedsTy, Address Shareds, 5522 const Expr *IfCond, 5523 const OMPTaskDataTy &Data) { 5524 if (!CGF.HaveInsertPoint()) 5525 return; 5526 TaskResultTy Result = 5527 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5528 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5529 // libcall. 5530 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5531 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5532 // sched, kmp_uint64 grainsize, void *task_dup); 5533 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5534 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5535 llvm::Value *IfVal; 5536 if (IfCond) { 5537 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5538 /*isSigned=*/true); 5539 } else { 5540 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5541 } 5542 5543 LValue LBLVal = CGF.EmitLValueForField( 5544 Result.TDBase, 5545 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5546 const auto *LBVar = 5547 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5548 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(), 5549 /*IsInitializer=*/true); 5550 LValue UBLVal = CGF.EmitLValueForField( 5551 Result.TDBase, 5552 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5553 const auto *UBVar = 5554 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5555 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(), 5556 /*IsInitializer=*/true); 5557 LValue StLVal = CGF.EmitLValueForField( 5558 Result.TDBase, 5559 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5560 const auto *StVar = 5561 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5562 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(), 5563 /*IsInitializer=*/true); 5564 // Store reductions address. 5565 LValue RedLVal = CGF.EmitLValueForField( 5566 Result.TDBase, 5567 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5568 if (Data.Reductions) { 5569 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5570 } else { 5571 CGF.EmitNullInitialization(RedLVal.getAddress(), 5572 CGF.getContext().VoidPtrTy); 5573 } 5574 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5575 llvm::Value *TaskArgs[] = { 5576 UpLoc, 5577 ThreadID, 5578 Result.NewTask, 5579 IfVal, 5580 LBLVal.getPointer(), 5581 UBLVal.getPointer(), 5582 CGF.EmitLoadOfScalar(StLVal, Loc), 5583 llvm::ConstantInt::getSigned( 5584 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5585 llvm::ConstantInt::getSigned( 5586 CGF.IntTy, Data.Schedule.getPointer() 5587 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5588 : NoSchedule), 5589 Data.Schedule.getPointer() 5590 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5591 /*isSigned=*/false) 5592 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5593 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5594 Result.TaskDupFn, CGF.VoidPtrTy) 5595 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5596 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5597 } 5598 5599 /// Emit reduction operation for each element of array (required for 5600 /// array sections) LHS op = RHS. 5601 /// \param Type Type of array. 5602 /// \param LHSVar Variable on the left side of the reduction operation 5603 /// (references element of array in original variable). 5604 /// \param RHSVar Variable on the right side of the reduction operation 5605 /// (references element of array in original variable). 5606 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5607 /// RHSVar. 5608 static void EmitOMPAggregateReduction( 5609 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5610 const VarDecl *RHSVar, 5611 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5612 const Expr *, const Expr *)> &RedOpGen, 5613 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5614 const Expr *UpExpr = nullptr) { 5615 // Perform element-by-element initialization. 5616 QualType ElementTy; 5617 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5618 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5619 5620 // Drill down to the base element type on both arrays. 5621 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5622 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5623 5624 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5625 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5626 // Cast from pointer to array type to pointer to single element. 5627 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5628 // The basic structure here is a while-do loop. 5629 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5630 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5631 llvm::Value *IsEmpty = 5632 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5633 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5634 5635 // Enter the loop body, making that address the current address. 5636 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5637 CGF.EmitBlock(BodyBB); 5638 5639 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5640 5641 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5642 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5643 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5644 Address RHSElementCurrent = 5645 Address(RHSElementPHI, 5646 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5647 5648 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5649 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5650 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5651 Address LHSElementCurrent = 5652 Address(LHSElementPHI, 5653 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5654 5655 // Emit copy. 5656 CodeGenFunction::OMPPrivateScope Scope(CGF); 5657 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5658 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5659 Scope.Privatize(); 5660 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5661 Scope.ForceCleanup(); 5662 5663 // Shift the address forward by one element. 5664 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5665 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5666 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5667 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5668 // Check whether we've reached the end. 5669 llvm::Value *Done = 5670 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5671 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5672 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5673 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5674 5675 // Done. 5676 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5677 } 5678 5679 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5680 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5681 /// UDR combiner function. 5682 static void emitReductionCombiner(CodeGenFunction &CGF, 5683 const Expr *ReductionOp) { 5684 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5685 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5686 if (const auto *DRE = 5687 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5688 if (const auto *DRD = 5689 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5690 std::pair<llvm::Function *, llvm::Function *> Reduction = 5691 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5692 RValue Func = RValue::get(Reduction.first); 5693 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5694 CGF.EmitIgnoredExpr(ReductionOp); 5695 return; 5696 } 5697 CGF.EmitIgnoredExpr(ReductionOp); 5698 } 5699 5700 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5701 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5702 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5703 ArrayRef<const Expr *> ReductionOps) { 5704 ASTContext &C = CGM.getContext(); 5705 5706 // void reduction_func(void *LHSArg, void *RHSArg); 5707 FunctionArgList Args; 5708 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5709 ImplicitParamDecl::Other); 5710 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5711 ImplicitParamDecl::Other); 5712 Args.push_back(&LHSArg); 5713 Args.push_back(&RHSArg); 5714 const auto &CGFI = 5715 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5716 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5717 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5718 llvm::GlobalValue::InternalLinkage, Name, 5719 &CGM.getModule()); 5720 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5721 Fn->setDoesNotRecurse(); 5722 CodeGenFunction CGF(CGM); 5723 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5724 5725 // Dst = (void*[n])(LHSArg); 5726 // Src = (void*[n])(RHSArg); 5727 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5728 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5729 ArgsType), CGF.getPointerAlign()); 5730 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5731 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5732 ArgsType), CGF.getPointerAlign()); 5733 5734 // ... 5735 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5736 // ... 5737 CodeGenFunction::OMPPrivateScope Scope(CGF); 5738 auto IPriv = Privates.begin(); 5739 unsigned Idx = 0; 5740 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5741 const auto *RHSVar = 5742 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5743 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5744 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5745 }); 5746 const auto *LHSVar = 5747 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5748 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5749 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5750 }); 5751 QualType PrivTy = (*IPriv)->getType(); 5752 if (PrivTy->isVariablyModifiedType()) { 5753 // Get array size and emit VLA type. 5754 ++Idx; 5755 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5756 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5757 const VariableArrayType *VLA = 5758 CGF.getContext().getAsVariableArrayType(PrivTy); 5759 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5760 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5761 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5762 CGF.EmitVariablyModifiedType(PrivTy); 5763 } 5764 } 5765 Scope.Privatize(); 5766 IPriv = Privates.begin(); 5767 auto ILHS = LHSExprs.begin(); 5768 auto IRHS = RHSExprs.begin(); 5769 for (const Expr *E : ReductionOps) { 5770 if ((*IPriv)->getType()->isArrayType()) { 5771 // Emit reduction for array section. 5772 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5773 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5774 EmitOMPAggregateReduction( 5775 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5776 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5777 emitReductionCombiner(CGF, E); 5778 }); 5779 } else { 5780 // Emit reduction for array subscript or single variable. 5781 emitReductionCombiner(CGF, E); 5782 } 5783 ++IPriv; 5784 ++ILHS; 5785 ++IRHS; 5786 } 5787 Scope.ForceCleanup(); 5788 CGF.FinishFunction(); 5789 return Fn; 5790 } 5791 5792 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5793 const Expr *ReductionOp, 5794 const Expr *PrivateRef, 5795 const DeclRefExpr *LHS, 5796 const DeclRefExpr *RHS) { 5797 if (PrivateRef->getType()->isArrayType()) { 5798 // Emit reduction for array section. 5799 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5800 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5801 EmitOMPAggregateReduction( 5802 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5803 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5804 emitReductionCombiner(CGF, ReductionOp); 5805 }); 5806 } else { 5807 // Emit reduction for array subscript or single variable. 5808 emitReductionCombiner(CGF, ReductionOp); 5809 } 5810 } 5811 5812 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5813 ArrayRef<const Expr *> Privates, 5814 ArrayRef<const Expr *> LHSExprs, 5815 ArrayRef<const Expr *> RHSExprs, 5816 ArrayRef<const Expr *> ReductionOps, 5817 ReductionOptionsTy Options) { 5818 if (!CGF.HaveInsertPoint()) 5819 return; 5820 5821 bool WithNowait = Options.WithNowait; 5822 bool SimpleReduction = Options.SimpleReduction; 5823 5824 // Next code should be emitted for reduction: 5825 // 5826 // static kmp_critical_name lock = { 0 }; 5827 // 5828 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5829 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5830 // ... 5831 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5832 // *(Type<n>-1*)rhs[<n>-1]); 5833 // } 5834 // 5835 // ... 5836 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5837 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5838 // RedList, reduce_func, &<lock>)) { 5839 // case 1: 5840 // ... 5841 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5842 // ... 5843 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5844 // break; 5845 // case 2: 5846 // ... 5847 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5848 // ... 5849 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5850 // break; 5851 // default:; 5852 // } 5853 // 5854 // if SimpleReduction is true, only the next code is generated: 5855 // ... 5856 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5857 // ... 5858 5859 ASTContext &C = CGM.getContext(); 5860 5861 if (SimpleReduction) { 5862 CodeGenFunction::RunCleanupsScope Scope(CGF); 5863 auto IPriv = Privates.begin(); 5864 auto ILHS = LHSExprs.begin(); 5865 auto IRHS = RHSExprs.begin(); 5866 for (const Expr *E : ReductionOps) { 5867 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5868 cast<DeclRefExpr>(*IRHS)); 5869 ++IPriv; 5870 ++ILHS; 5871 ++IRHS; 5872 } 5873 return; 5874 } 5875 5876 // 1. Build a list of reduction variables. 5877 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5878 auto Size = RHSExprs.size(); 5879 for (const Expr *E : Privates) { 5880 if (E->getType()->isVariablyModifiedType()) 5881 // Reserve place for array size. 5882 ++Size; 5883 } 5884 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5885 QualType ReductionArrayTy = 5886 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5887 /*IndexTypeQuals=*/0); 5888 Address ReductionList = 5889 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5890 auto IPriv = Privates.begin(); 5891 unsigned Idx = 0; 5892 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5893 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5894 CGF.Builder.CreateStore( 5895 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5896 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy), 5897 Elem); 5898 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5899 // Store array size. 5900 ++Idx; 5901 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5902 llvm::Value *Size = CGF.Builder.CreateIntCast( 5903 CGF.getVLASize( 5904 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5905 .NumElts, 5906 CGF.SizeTy, /*isSigned=*/false); 5907 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5908 Elem); 5909 } 5910 } 5911 5912 // 2. Emit reduce_func(). 5913 llvm::Function *ReductionFn = emitReductionFunction( 5914 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5915 LHSExprs, RHSExprs, ReductionOps); 5916 5917 // 3. Create static kmp_critical_name lock = { 0 }; 5918 std::string Name = getName({"reduction"}); 5919 llvm::Value *Lock = getCriticalRegionLock(Name); 5920 5921 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5922 // RedList, reduce_func, &<lock>); 5923 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5924 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5925 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5926 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5927 ReductionList.getPointer(), CGF.VoidPtrTy); 5928 llvm::Value *Args[] = { 5929 IdentTLoc, // ident_t *<loc> 5930 ThreadId, // i32 <gtid> 5931 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5932 ReductionArrayTySize, // size_type sizeof(RedList) 5933 RL, // void *RedList 5934 ReductionFn, // void (*) (void *, void *) <reduce_func> 5935 Lock // kmp_critical_name *&<lock> 5936 }; 5937 llvm::Value *Res = CGF.EmitRuntimeCall( 5938 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 5939 : OMPRTL__kmpc_reduce), 5940 Args); 5941 5942 // 5. Build switch(res) 5943 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5944 llvm::SwitchInst *SwInst = 5945 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5946 5947 // 6. Build case 1: 5948 // ... 5949 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5950 // ... 5951 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5952 // break; 5953 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5954 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5955 CGF.EmitBlock(Case1BB); 5956 5957 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5958 llvm::Value *EndArgs[] = { 5959 IdentTLoc, // ident_t *<loc> 5960 ThreadId, // i32 <gtid> 5961 Lock // kmp_critical_name *&<lock> 5962 }; 5963 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5964 CodeGenFunction &CGF, PrePostActionTy &Action) { 5965 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5966 auto IPriv = Privates.begin(); 5967 auto ILHS = LHSExprs.begin(); 5968 auto IRHS = RHSExprs.begin(); 5969 for (const Expr *E : ReductionOps) { 5970 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5971 cast<DeclRefExpr>(*IRHS)); 5972 ++IPriv; 5973 ++ILHS; 5974 ++IRHS; 5975 } 5976 }; 5977 RegionCodeGenTy RCG(CodeGen); 5978 CommonActionTy Action( 5979 nullptr, llvm::None, 5980 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 5981 : OMPRTL__kmpc_end_reduce), 5982 EndArgs); 5983 RCG.setAction(Action); 5984 RCG(CGF); 5985 5986 CGF.EmitBranch(DefaultBB); 5987 5988 // 7. Build case 2: 5989 // ... 5990 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5991 // ... 5992 // break; 5993 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5994 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5995 CGF.EmitBlock(Case2BB); 5996 5997 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5998 CodeGenFunction &CGF, PrePostActionTy &Action) { 5999 auto ILHS = LHSExprs.begin(); 6000 auto IRHS = RHSExprs.begin(); 6001 auto IPriv = Privates.begin(); 6002 for (const Expr *E : ReductionOps) { 6003 const Expr *XExpr = nullptr; 6004 const Expr *EExpr = nullptr; 6005 const Expr *UpExpr = nullptr; 6006 BinaryOperatorKind BO = BO_Comma; 6007 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 6008 if (BO->getOpcode() == BO_Assign) { 6009 XExpr = BO->getLHS(); 6010 UpExpr = BO->getRHS(); 6011 } 6012 } 6013 // Try to emit update expression as a simple atomic. 6014 const Expr *RHSExpr = UpExpr; 6015 if (RHSExpr) { 6016 // Analyze RHS part of the whole expression. 6017 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 6018 RHSExpr->IgnoreParenImpCasts())) { 6019 // If this is a conditional operator, analyze its condition for 6020 // min/max reduction operator. 6021 RHSExpr = ACO->getCond(); 6022 } 6023 if (const auto *BORHS = 6024 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 6025 EExpr = BORHS->getRHS(); 6026 BO = BORHS->getOpcode(); 6027 } 6028 } 6029 if (XExpr) { 6030 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 6031 auto &&AtomicRedGen = [BO, VD, 6032 Loc](CodeGenFunction &CGF, const Expr *XExpr, 6033 const Expr *EExpr, const Expr *UpExpr) { 6034 LValue X = CGF.EmitLValue(XExpr); 6035 RValue E; 6036 if (EExpr) 6037 E = CGF.EmitAnyExpr(EExpr); 6038 CGF.EmitOMPAtomicSimpleUpdateExpr( 6039 X, E, BO, /*IsXLHSInRHSPart=*/true, 6040 llvm::AtomicOrdering::Monotonic, Loc, 6041 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 6042 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6043 PrivateScope.addPrivate( 6044 VD, [&CGF, VD, XRValue, Loc]() { 6045 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 6046 CGF.emitOMPSimpleStore( 6047 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 6048 VD->getType().getNonReferenceType(), Loc); 6049 return LHSTemp; 6050 }); 6051 (void)PrivateScope.Privatize(); 6052 return CGF.EmitAnyExpr(UpExpr); 6053 }); 6054 }; 6055 if ((*IPriv)->getType()->isArrayType()) { 6056 // Emit atomic reduction for array section. 6057 const auto *RHSVar = 6058 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 6059 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 6060 AtomicRedGen, XExpr, EExpr, UpExpr); 6061 } else { 6062 // Emit atomic reduction for array subscript or single variable. 6063 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 6064 } 6065 } else { 6066 // Emit as a critical region. 6067 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 6068 const Expr *, const Expr *) { 6069 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6070 std::string Name = RT.getName({"atomic_reduction"}); 6071 RT.emitCriticalRegion( 6072 CGF, Name, 6073 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 6074 Action.Enter(CGF); 6075 emitReductionCombiner(CGF, E); 6076 }, 6077 Loc); 6078 }; 6079 if ((*IPriv)->getType()->isArrayType()) { 6080 const auto *LHSVar = 6081 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 6082 const auto *RHSVar = 6083 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 6084 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 6085 CritRedGen); 6086 } else { 6087 CritRedGen(CGF, nullptr, nullptr, nullptr); 6088 } 6089 } 6090 ++ILHS; 6091 ++IRHS; 6092 ++IPriv; 6093 } 6094 }; 6095 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 6096 if (!WithNowait) { 6097 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 6098 llvm::Value *EndArgs[] = { 6099 IdentTLoc, // ident_t *<loc> 6100 ThreadId, // i32 <gtid> 6101 Lock // kmp_critical_name *&<lock> 6102 }; 6103 CommonActionTy Action(nullptr, llvm::None, 6104 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 6105 EndArgs); 6106 AtomicRCG.setAction(Action); 6107 AtomicRCG(CGF); 6108 } else { 6109 AtomicRCG(CGF); 6110 } 6111 6112 CGF.EmitBranch(DefaultBB); 6113 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 6114 } 6115 6116 /// Generates unique name for artificial threadprivate variables. 6117 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 6118 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 6119 const Expr *Ref) { 6120 SmallString<256> Buffer; 6121 llvm::raw_svector_ostream Out(Buffer); 6122 const clang::DeclRefExpr *DE; 6123 const VarDecl *D = ::getBaseDecl(Ref, DE); 6124 if (!D) 6125 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 6126 D = D->getCanonicalDecl(); 6127 std::string Name = CGM.getOpenMPRuntime().getName( 6128 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 6129 Out << Prefix << Name << "_" 6130 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 6131 return Out.str(); 6132 } 6133 6134 /// Emits reduction initializer function: 6135 /// \code 6136 /// void @.red_init(void* %arg) { 6137 /// %0 = bitcast void* %arg to <type>* 6138 /// store <type> <init>, <type>* %0 6139 /// ret void 6140 /// } 6141 /// \endcode 6142 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 6143 SourceLocation Loc, 6144 ReductionCodeGen &RCG, unsigned N) { 6145 ASTContext &C = CGM.getContext(); 6146 FunctionArgList Args; 6147 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6148 ImplicitParamDecl::Other); 6149 Args.emplace_back(&Param); 6150 const auto &FnInfo = 6151 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6152 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6153 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6154 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6155 Name, &CGM.getModule()); 6156 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6157 Fn->setDoesNotRecurse(); 6158 CodeGenFunction CGF(CGM); 6159 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6160 Address PrivateAddr = CGF.EmitLoadOfPointer( 6161 CGF.GetAddrOfLocalVar(&Param), 6162 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6163 llvm::Value *Size = nullptr; 6164 // If the size of the reduction item is non-constant, load it from global 6165 // threadprivate variable. 6166 if (RCG.getSizes(N).second) { 6167 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6168 CGF, CGM.getContext().getSizeType(), 6169 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6170 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6171 CGM.getContext().getSizeType(), Loc); 6172 } 6173 RCG.emitAggregateType(CGF, N, Size); 6174 LValue SharedLVal; 6175 // If initializer uses initializer from declare reduction construct, emit a 6176 // pointer to the address of the original reduction item (reuired by reduction 6177 // initializer) 6178 if (RCG.usesReductionInitializer(N)) { 6179 Address SharedAddr = 6180 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6181 CGF, CGM.getContext().VoidPtrTy, 6182 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6183 SharedAddr = CGF.EmitLoadOfPointer( 6184 SharedAddr, 6185 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6186 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6187 } else { 6188 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6189 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6190 CGM.getContext().VoidPtrTy); 6191 } 6192 // Emit the initializer: 6193 // %0 = bitcast void* %arg to <type>* 6194 // store <type> <init>, <type>* %0 6195 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6196 [](CodeGenFunction &) { return false; }); 6197 CGF.FinishFunction(); 6198 return Fn; 6199 } 6200 6201 /// Emits reduction combiner function: 6202 /// \code 6203 /// void @.red_comb(void* %arg0, void* %arg1) { 6204 /// %lhs = bitcast void* %arg0 to <type>* 6205 /// %rhs = bitcast void* %arg1 to <type>* 6206 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6207 /// store <type> %2, <type>* %lhs 6208 /// ret void 6209 /// } 6210 /// \endcode 6211 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6212 SourceLocation Loc, 6213 ReductionCodeGen &RCG, unsigned N, 6214 const Expr *ReductionOp, 6215 const Expr *LHS, const Expr *RHS, 6216 const Expr *PrivateRef) { 6217 ASTContext &C = CGM.getContext(); 6218 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6219 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6220 FunctionArgList Args; 6221 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6222 C.VoidPtrTy, ImplicitParamDecl::Other); 6223 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6224 ImplicitParamDecl::Other); 6225 Args.emplace_back(&ParamInOut); 6226 Args.emplace_back(&ParamIn); 6227 const auto &FnInfo = 6228 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6229 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6230 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6231 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6232 Name, &CGM.getModule()); 6233 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6234 Fn->setDoesNotRecurse(); 6235 CodeGenFunction CGF(CGM); 6236 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6237 llvm::Value *Size = nullptr; 6238 // If the size of the reduction item is non-constant, load it from global 6239 // threadprivate variable. 6240 if (RCG.getSizes(N).second) { 6241 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6242 CGF, CGM.getContext().getSizeType(), 6243 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6244 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6245 CGM.getContext().getSizeType(), Loc); 6246 } 6247 RCG.emitAggregateType(CGF, N, Size); 6248 // Remap lhs and rhs variables to the addresses of the function arguments. 6249 // %lhs = bitcast void* %arg0 to <type>* 6250 // %rhs = bitcast void* %arg1 to <type>* 6251 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6252 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6253 // Pull out the pointer to the variable. 6254 Address PtrAddr = CGF.EmitLoadOfPointer( 6255 CGF.GetAddrOfLocalVar(&ParamInOut), 6256 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6257 return CGF.Builder.CreateElementBitCast( 6258 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6259 }); 6260 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6261 // Pull out the pointer to the variable. 6262 Address PtrAddr = CGF.EmitLoadOfPointer( 6263 CGF.GetAddrOfLocalVar(&ParamIn), 6264 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6265 return CGF.Builder.CreateElementBitCast( 6266 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6267 }); 6268 PrivateScope.Privatize(); 6269 // Emit the combiner body: 6270 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6271 // store <type> %2, <type>* %lhs 6272 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6273 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6274 cast<DeclRefExpr>(RHS)); 6275 CGF.FinishFunction(); 6276 return Fn; 6277 } 6278 6279 /// Emits reduction finalizer function: 6280 /// \code 6281 /// void @.red_fini(void* %arg) { 6282 /// %0 = bitcast void* %arg to <type>* 6283 /// <destroy>(<type>* %0) 6284 /// ret void 6285 /// } 6286 /// \endcode 6287 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6288 SourceLocation Loc, 6289 ReductionCodeGen &RCG, unsigned N) { 6290 if (!RCG.needCleanups(N)) 6291 return nullptr; 6292 ASTContext &C = CGM.getContext(); 6293 FunctionArgList Args; 6294 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6295 ImplicitParamDecl::Other); 6296 Args.emplace_back(&Param); 6297 const auto &FnInfo = 6298 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6299 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6300 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6301 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6302 Name, &CGM.getModule()); 6303 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6304 Fn->setDoesNotRecurse(); 6305 CodeGenFunction CGF(CGM); 6306 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6307 Address PrivateAddr = CGF.EmitLoadOfPointer( 6308 CGF.GetAddrOfLocalVar(&Param), 6309 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6310 llvm::Value *Size = nullptr; 6311 // If the size of the reduction item is non-constant, load it from global 6312 // threadprivate variable. 6313 if (RCG.getSizes(N).second) { 6314 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6315 CGF, CGM.getContext().getSizeType(), 6316 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6317 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6318 CGM.getContext().getSizeType(), Loc); 6319 } 6320 RCG.emitAggregateType(CGF, N, Size); 6321 // Emit the finalizer body: 6322 // <destroy>(<type>* %0) 6323 RCG.emitCleanups(CGF, N, PrivateAddr); 6324 CGF.FinishFunction(); 6325 return Fn; 6326 } 6327 6328 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6329 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6330 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6331 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6332 return nullptr; 6333 6334 // Build typedef struct: 6335 // kmp_task_red_input { 6336 // void *reduce_shar; // shared reduction item 6337 // size_t reduce_size; // size of data item 6338 // void *reduce_init; // data initialization routine 6339 // void *reduce_fini; // data finalization routine 6340 // void *reduce_comb; // data combiner routine 6341 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6342 // } kmp_task_red_input_t; 6343 ASTContext &C = CGM.getContext(); 6344 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6345 RD->startDefinition(); 6346 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6347 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6348 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6349 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6350 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6351 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6352 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6353 RD->completeDefinition(); 6354 QualType RDType = C.getRecordType(RD); 6355 unsigned Size = Data.ReductionVars.size(); 6356 llvm::APInt ArraySize(/*numBits=*/64, Size); 6357 QualType ArrayRDType = C.getConstantArrayType( 6358 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6359 // kmp_task_red_input_t .rd_input.[Size]; 6360 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6361 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6362 Data.ReductionOps); 6363 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6364 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6365 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6366 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6367 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6368 TaskRedInput.getPointer(), Idxs, 6369 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6370 ".rd_input.gep."); 6371 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6372 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6373 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6374 RCG.emitSharedLValue(CGF, Cnt); 6375 llvm::Value *CastedShared = 6376 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer()); 6377 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6378 RCG.emitAggregateType(CGF, Cnt); 6379 llvm::Value *SizeValInChars; 6380 llvm::Value *SizeVal; 6381 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6382 // We use delayed creation/initialization for VLAs, array sections and 6383 // custom reduction initializations. It is required because runtime does not 6384 // provide the way to pass the sizes of VLAs/array sections to 6385 // initializer/combiner/finalizer functions and does not pass the pointer to 6386 // original reduction item to the initializer. Instead threadprivate global 6387 // variables are used to store these values and use them in the functions. 6388 bool DelayedCreation = !!SizeVal; 6389 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6390 /*isSigned=*/false); 6391 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6392 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6393 // ElemLVal.reduce_init = init; 6394 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6395 llvm::Value *InitAddr = 6396 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6397 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6398 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6399 // ElemLVal.reduce_fini = fini; 6400 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6401 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6402 llvm::Value *FiniAddr = Fini 6403 ? CGF.EmitCastToVoidPtr(Fini) 6404 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6405 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6406 // ElemLVal.reduce_comb = comb; 6407 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6408 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6409 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6410 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6411 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6412 // ElemLVal.flags = 0; 6413 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6414 if (DelayedCreation) { 6415 CGF.EmitStoreOfScalar( 6416 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6417 FlagsLVal); 6418 } else 6419 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType()); 6420 } 6421 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6422 // *data); 6423 llvm::Value *Args[] = { 6424 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6425 /*isSigned=*/true), 6426 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6427 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6428 CGM.VoidPtrTy)}; 6429 return CGF.EmitRuntimeCall( 6430 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6431 } 6432 6433 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6434 SourceLocation Loc, 6435 ReductionCodeGen &RCG, 6436 unsigned N) { 6437 auto Sizes = RCG.getSizes(N); 6438 // Emit threadprivate global variable if the type is non-constant 6439 // (Sizes.second = nullptr). 6440 if (Sizes.second) { 6441 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6442 /*isSigned=*/false); 6443 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6444 CGF, CGM.getContext().getSizeType(), 6445 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6446 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6447 } 6448 // Store address of the original reduction item if custom initializer is used. 6449 if (RCG.usesReductionInitializer(N)) { 6450 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6451 CGF, CGM.getContext().VoidPtrTy, 6452 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6453 CGF.Builder.CreateStore( 6454 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6455 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy), 6456 SharedAddr, /*IsVolatile=*/false); 6457 } 6458 } 6459 6460 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6461 SourceLocation Loc, 6462 llvm::Value *ReductionsPtr, 6463 LValue SharedLVal) { 6464 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6465 // *d); 6466 llvm::Value *Args[] = { 6467 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6468 /*isSigned=*/true), 6469 ReductionsPtr, 6470 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(), 6471 CGM.VoidPtrTy)}; 6472 return Address( 6473 CGF.EmitRuntimeCall( 6474 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6475 SharedLVal.getAlignment()); 6476 } 6477 6478 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6479 SourceLocation Loc) { 6480 if (!CGF.HaveInsertPoint()) 6481 return; 6482 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6483 // global_tid); 6484 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6485 // Ignore return result until untied tasks are supported. 6486 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6487 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6488 Region->emitUntiedSwitch(CGF); 6489 } 6490 6491 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6492 OpenMPDirectiveKind InnerKind, 6493 const RegionCodeGenTy &CodeGen, 6494 bool HasCancel) { 6495 if (!CGF.HaveInsertPoint()) 6496 return; 6497 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6498 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6499 } 6500 6501 namespace { 6502 enum RTCancelKind { 6503 CancelNoreq = 0, 6504 CancelParallel = 1, 6505 CancelLoop = 2, 6506 CancelSections = 3, 6507 CancelTaskgroup = 4 6508 }; 6509 } // anonymous namespace 6510 6511 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6512 RTCancelKind CancelKind = CancelNoreq; 6513 if (CancelRegion == OMPD_parallel) 6514 CancelKind = CancelParallel; 6515 else if (CancelRegion == OMPD_for) 6516 CancelKind = CancelLoop; 6517 else if (CancelRegion == OMPD_sections) 6518 CancelKind = CancelSections; 6519 else { 6520 assert(CancelRegion == OMPD_taskgroup); 6521 CancelKind = CancelTaskgroup; 6522 } 6523 return CancelKind; 6524 } 6525 6526 void CGOpenMPRuntime::emitCancellationPointCall( 6527 CodeGenFunction &CGF, SourceLocation Loc, 6528 OpenMPDirectiveKind CancelRegion) { 6529 if (!CGF.HaveInsertPoint()) 6530 return; 6531 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6532 // global_tid, kmp_int32 cncl_kind); 6533 if (auto *OMPRegionInfo = 6534 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6535 // For 'cancellation point taskgroup', the task region info may not have a 6536 // cancel. This may instead happen in another adjacent task. 6537 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6538 llvm::Value *Args[] = { 6539 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6540 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6541 // Ignore return result until untied tasks are supported. 6542 llvm::Value *Result = CGF.EmitRuntimeCall( 6543 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6544 // if (__kmpc_cancellationpoint()) { 6545 // exit from construct; 6546 // } 6547 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6548 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6549 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6550 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6551 CGF.EmitBlock(ExitBB); 6552 // exit from construct; 6553 CodeGenFunction::JumpDest CancelDest = 6554 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6555 CGF.EmitBranchThroughCleanup(CancelDest); 6556 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6557 } 6558 } 6559 } 6560 6561 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6562 const Expr *IfCond, 6563 OpenMPDirectiveKind CancelRegion) { 6564 if (!CGF.HaveInsertPoint()) 6565 return; 6566 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6567 // kmp_int32 cncl_kind); 6568 if (auto *OMPRegionInfo = 6569 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6570 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6571 PrePostActionTy &) { 6572 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6573 llvm::Value *Args[] = { 6574 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6575 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6576 // Ignore return result until untied tasks are supported. 6577 llvm::Value *Result = CGF.EmitRuntimeCall( 6578 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6579 // if (__kmpc_cancel()) { 6580 // exit from construct; 6581 // } 6582 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6583 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6584 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6585 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6586 CGF.EmitBlock(ExitBB); 6587 // exit from construct; 6588 CodeGenFunction::JumpDest CancelDest = 6589 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6590 CGF.EmitBranchThroughCleanup(CancelDest); 6591 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6592 }; 6593 if (IfCond) { 6594 emitOMPIfClause(CGF, IfCond, ThenGen, 6595 [](CodeGenFunction &, PrePostActionTy &) {}); 6596 } else { 6597 RegionCodeGenTy ThenRCG(ThenGen); 6598 ThenRCG(CGF); 6599 } 6600 } 6601 } 6602 6603 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6604 const OMPExecutableDirective &D, StringRef ParentName, 6605 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6606 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6607 assert(!ParentName.empty() && "Invalid target region parent name!"); 6608 HasEmittedTargetRegion = true; 6609 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6610 IsOffloadEntry, CodeGen); 6611 } 6612 6613 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6614 const OMPExecutableDirective &D, StringRef ParentName, 6615 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6616 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6617 // Create a unique name for the entry function using the source location 6618 // information of the current target region. The name will be something like: 6619 // 6620 // __omp_offloading_DD_FFFF_PP_lBB 6621 // 6622 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6623 // mangled name of the function that encloses the target region and BB is the 6624 // line number of the target region. 6625 6626 unsigned DeviceID; 6627 unsigned FileID; 6628 unsigned Line; 6629 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6630 Line); 6631 SmallString<64> EntryFnName; 6632 { 6633 llvm::raw_svector_ostream OS(EntryFnName); 6634 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6635 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6636 } 6637 6638 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6639 6640 CodeGenFunction CGF(CGM, true); 6641 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6642 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6643 6644 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 6645 6646 // If this target outline function is not an offload entry, we don't need to 6647 // register it. 6648 if (!IsOffloadEntry) 6649 return; 6650 6651 // The target region ID is used by the runtime library to identify the current 6652 // target region, so it only has to be unique and not necessarily point to 6653 // anything. It could be the pointer to the outlined function that implements 6654 // the target region, but we aren't using that so that the compiler doesn't 6655 // need to keep that, and could therefore inline the host function if proven 6656 // worthwhile during optimization. In the other hand, if emitting code for the 6657 // device, the ID has to be the function address so that it can retrieved from 6658 // the offloading entry and launched by the runtime library. We also mark the 6659 // outlined function to have external linkage in case we are emitting code for 6660 // the device, because these functions will be entry points to the device. 6661 6662 if (CGM.getLangOpts().OpenMPIsDevice) { 6663 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6664 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6665 OutlinedFn->setDSOLocal(false); 6666 } else { 6667 std::string Name = getName({EntryFnName, "region_id"}); 6668 OutlinedFnID = new llvm::GlobalVariable( 6669 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6670 llvm::GlobalValue::WeakAnyLinkage, 6671 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6672 } 6673 6674 // Register the information for the entry associated with this target region. 6675 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6676 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6677 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6678 } 6679 6680 /// Checks if the expression is constant or does not have non-trivial function 6681 /// calls. 6682 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6683 // We can skip constant expressions. 6684 // We can skip expressions with trivial calls or simple expressions. 6685 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6686 !E->hasNonTrivialCall(Ctx)) && 6687 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6688 } 6689 6690 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6691 const Stmt *Body) { 6692 const Stmt *Child = Body->IgnoreContainers(); 6693 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6694 Child = nullptr; 6695 for (const Stmt *S : C->body()) { 6696 if (const auto *E = dyn_cast<Expr>(S)) { 6697 if (isTrivial(Ctx, E)) 6698 continue; 6699 } 6700 // Some of the statements can be ignored. 6701 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6702 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6703 continue; 6704 // Analyze declarations. 6705 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6706 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6707 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6708 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6709 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6710 isa<UsingDirectiveDecl>(D) || 6711 isa<OMPDeclareReductionDecl>(D) || 6712 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6713 return true; 6714 const auto *VD = dyn_cast<VarDecl>(D); 6715 if (!VD) 6716 return false; 6717 return VD->isConstexpr() || 6718 ((VD->getType().isTrivialType(Ctx) || 6719 VD->getType()->isReferenceType()) && 6720 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6721 })) 6722 continue; 6723 } 6724 // Found multiple children - cannot get the one child only. 6725 if (Child) 6726 return nullptr; 6727 Child = S; 6728 } 6729 if (Child) 6730 Child = Child->IgnoreContainers(); 6731 } 6732 return Child; 6733 } 6734 6735 /// Emit the number of teams for a target directive. Inspect the num_teams 6736 /// clause associated with a teams construct combined or closely nested 6737 /// with the target directive. 6738 /// 6739 /// Emit a team of size one for directives such as 'target parallel' that 6740 /// have no associated teams construct. 6741 /// 6742 /// Otherwise, return nullptr. 6743 static llvm::Value * 6744 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6745 const OMPExecutableDirective &D) { 6746 assert(!CGF.getLangOpts().OpenMPIsDevice && 6747 "Clauses associated with the teams directive expected to be emitted " 6748 "only for the host!"); 6749 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6750 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6751 "Expected target-based executable directive."); 6752 CGBuilderTy &Bld = CGF.Builder; 6753 switch (DirectiveKind) { 6754 case OMPD_target: { 6755 const auto *CS = D.getInnermostCapturedStmt(); 6756 const auto *Body = 6757 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6758 const Stmt *ChildStmt = 6759 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6760 if (const auto *NestedDir = 6761 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6762 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6763 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6764 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6765 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6766 const Expr *NumTeams = 6767 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6768 llvm::Value *NumTeamsVal = 6769 CGF.EmitScalarExpr(NumTeams, 6770 /*IgnoreResultAssign*/ true); 6771 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6772 /*isSigned=*/true); 6773 } 6774 return Bld.getInt32(0); 6775 } 6776 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6777 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6778 return Bld.getInt32(1); 6779 return Bld.getInt32(0); 6780 } 6781 return nullptr; 6782 } 6783 case OMPD_target_teams: 6784 case OMPD_target_teams_distribute: 6785 case OMPD_target_teams_distribute_simd: 6786 case OMPD_target_teams_distribute_parallel_for: 6787 case OMPD_target_teams_distribute_parallel_for_simd: { 6788 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6789 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6790 const Expr *NumTeams = 6791 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6792 llvm::Value *NumTeamsVal = 6793 CGF.EmitScalarExpr(NumTeams, 6794 /*IgnoreResultAssign*/ true); 6795 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6796 /*isSigned=*/true); 6797 } 6798 return Bld.getInt32(0); 6799 } 6800 case OMPD_target_parallel: 6801 case OMPD_target_parallel_for: 6802 case OMPD_target_parallel_for_simd: 6803 case OMPD_target_simd: 6804 return Bld.getInt32(1); 6805 case OMPD_parallel: 6806 case OMPD_for: 6807 case OMPD_parallel_for: 6808 case OMPD_parallel_sections: 6809 case OMPD_for_simd: 6810 case OMPD_parallel_for_simd: 6811 case OMPD_cancel: 6812 case OMPD_cancellation_point: 6813 case OMPD_ordered: 6814 case OMPD_threadprivate: 6815 case OMPD_allocate: 6816 case OMPD_task: 6817 case OMPD_simd: 6818 case OMPD_sections: 6819 case OMPD_section: 6820 case OMPD_single: 6821 case OMPD_master: 6822 case OMPD_critical: 6823 case OMPD_taskyield: 6824 case OMPD_barrier: 6825 case OMPD_taskwait: 6826 case OMPD_taskgroup: 6827 case OMPD_atomic: 6828 case OMPD_flush: 6829 case OMPD_teams: 6830 case OMPD_target_data: 6831 case OMPD_target_exit_data: 6832 case OMPD_target_enter_data: 6833 case OMPD_distribute: 6834 case OMPD_distribute_simd: 6835 case OMPD_distribute_parallel_for: 6836 case OMPD_distribute_parallel_for_simd: 6837 case OMPD_teams_distribute: 6838 case OMPD_teams_distribute_simd: 6839 case OMPD_teams_distribute_parallel_for: 6840 case OMPD_teams_distribute_parallel_for_simd: 6841 case OMPD_target_update: 6842 case OMPD_declare_simd: 6843 case OMPD_declare_variant: 6844 case OMPD_declare_target: 6845 case OMPD_end_declare_target: 6846 case OMPD_declare_reduction: 6847 case OMPD_declare_mapper: 6848 case OMPD_taskloop: 6849 case OMPD_taskloop_simd: 6850 case OMPD_requires: 6851 case OMPD_unknown: 6852 break; 6853 } 6854 llvm_unreachable("Unexpected directive kind."); 6855 } 6856 6857 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6858 llvm::Value *DefaultThreadLimitVal) { 6859 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6860 CGF.getContext(), CS->getCapturedStmt()); 6861 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6862 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6863 llvm::Value *NumThreads = nullptr; 6864 llvm::Value *CondVal = nullptr; 6865 // Handle if clause. If if clause present, the number of threads is 6866 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6867 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6868 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6869 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6870 const OMPIfClause *IfClause = nullptr; 6871 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6872 if (C->getNameModifier() == OMPD_unknown || 6873 C->getNameModifier() == OMPD_parallel) { 6874 IfClause = C; 6875 break; 6876 } 6877 } 6878 if (IfClause) { 6879 const Expr *Cond = IfClause->getCondition(); 6880 bool Result; 6881 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6882 if (!Result) 6883 return CGF.Builder.getInt32(1); 6884 } else { 6885 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6886 if (const auto *PreInit = 6887 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6888 for (const auto *I : PreInit->decls()) { 6889 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6890 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6891 } else { 6892 CodeGenFunction::AutoVarEmission Emission = 6893 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6894 CGF.EmitAutoVarCleanups(Emission); 6895 } 6896 } 6897 } 6898 CondVal = CGF.EvaluateExprAsBool(Cond); 6899 } 6900 } 6901 } 6902 // Check the value of num_threads clause iff if clause was not specified 6903 // or is not evaluated to false. 6904 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6905 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6906 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6907 const auto *NumThreadsClause = 6908 Dir->getSingleClause<OMPNumThreadsClause>(); 6909 CodeGenFunction::LexicalScope Scope( 6910 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6911 if (const auto *PreInit = 6912 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6913 for (const auto *I : PreInit->decls()) { 6914 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6915 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6916 } else { 6917 CodeGenFunction::AutoVarEmission Emission = 6918 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6919 CGF.EmitAutoVarCleanups(Emission); 6920 } 6921 } 6922 } 6923 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6924 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6925 /*isSigned=*/false); 6926 if (DefaultThreadLimitVal) 6927 NumThreads = CGF.Builder.CreateSelect( 6928 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6929 DefaultThreadLimitVal, NumThreads); 6930 } else { 6931 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6932 : CGF.Builder.getInt32(0); 6933 } 6934 // Process condition of the if clause. 6935 if (CondVal) { 6936 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6937 CGF.Builder.getInt32(1)); 6938 } 6939 return NumThreads; 6940 } 6941 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6942 return CGF.Builder.getInt32(1); 6943 return DefaultThreadLimitVal; 6944 } 6945 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6946 : CGF.Builder.getInt32(0); 6947 } 6948 6949 /// Emit the number of threads for a target directive. Inspect the 6950 /// thread_limit clause associated with a teams construct combined or closely 6951 /// nested with the target directive. 6952 /// 6953 /// Emit the num_threads clause for directives such as 'target parallel' that 6954 /// have no associated teams construct. 6955 /// 6956 /// Otherwise, return nullptr. 6957 static llvm::Value * 6958 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6959 const OMPExecutableDirective &D) { 6960 assert(!CGF.getLangOpts().OpenMPIsDevice && 6961 "Clauses associated with the teams directive expected to be emitted " 6962 "only for the host!"); 6963 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6964 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6965 "Expected target-based executable directive."); 6966 CGBuilderTy &Bld = CGF.Builder; 6967 llvm::Value *ThreadLimitVal = nullptr; 6968 llvm::Value *NumThreadsVal = nullptr; 6969 switch (DirectiveKind) { 6970 case OMPD_target: { 6971 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6972 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6973 return NumThreads; 6974 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6975 CGF.getContext(), CS->getCapturedStmt()); 6976 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6977 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6978 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6979 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6980 const auto *ThreadLimitClause = 6981 Dir->getSingleClause<OMPThreadLimitClause>(); 6982 CodeGenFunction::LexicalScope Scope( 6983 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6984 if (const auto *PreInit = 6985 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6986 for (const auto *I : PreInit->decls()) { 6987 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6988 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6989 } else { 6990 CodeGenFunction::AutoVarEmission Emission = 6991 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6992 CGF.EmitAutoVarCleanups(Emission); 6993 } 6994 } 6995 } 6996 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6997 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6998 ThreadLimitVal = 6999 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7000 } 7001 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 7002 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 7003 CS = Dir->getInnermostCapturedStmt(); 7004 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7005 CGF.getContext(), CS->getCapturedStmt()); 7006 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 7007 } 7008 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 7009 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 7010 CS = Dir->getInnermostCapturedStmt(); 7011 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7012 return NumThreads; 7013 } 7014 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 7015 return Bld.getInt32(1); 7016 } 7017 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7018 } 7019 case OMPD_target_teams: { 7020 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7021 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7022 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7023 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7024 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7025 ThreadLimitVal = 7026 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7027 } 7028 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7029 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7030 return NumThreads; 7031 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7032 CGF.getContext(), CS->getCapturedStmt()); 7033 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7034 if (Dir->getDirectiveKind() == OMPD_distribute) { 7035 CS = Dir->getInnermostCapturedStmt(); 7036 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7037 return NumThreads; 7038 } 7039 } 7040 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7041 } 7042 case OMPD_target_teams_distribute: 7043 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7044 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7045 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7046 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7047 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7048 ThreadLimitVal = 7049 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7050 } 7051 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 7052 case OMPD_target_parallel: 7053 case OMPD_target_parallel_for: 7054 case OMPD_target_parallel_for_simd: 7055 case OMPD_target_teams_distribute_parallel_for: 7056 case OMPD_target_teams_distribute_parallel_for_simd: { 7057 llvm::Value *CondVal = nullptr; 7058 // Handle if clause. If if clause present, the number of threads is 7059 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 7060 if (D.hasClausesOfKind<OMPIfClause>()) { 7061 const OMPIfClause *IfClause = nullptr; 7062 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 7063 if (C->getNameModifier() == OMPD_unknown || 7064 C->getNameModifier() == OMPD_parallel) { 7065 IfClause = C; 7066 break; 7067 } 7068 } 7069 if (IfClause) { 7070 const Expr *Cond = IfClause->getCondition(); 7071 bool Result; 7072 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 7073 if (!Result) 7074 return Bld.getInt32(1); 7075 } else { 7076 CodeGenFunction::RunCleanupsScope Scope(CGF); 7077 CondVal = CGF.EvaluateExprAsBool(Cond); 7078 } 7079 } 7080 } 7081 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7082 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7083 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7084 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7085 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7086 ThreadLimitVal = 7087 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7088 } 7089 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 7090 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 7091 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 7092 llvm::Value *NumThreads = CGF.EmitScalarExpr( 7093 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 7094 NumThreadsVal = 7095 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 7096 ThreadLimitVal = ThreadLimitVal 7097 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 7098 ThreadLimitVal), 7099 NumThreadsVal, ThreadLimitVal) 7100 : NumThreadsVal; 7101 } 7102 if (!ThreadLimitVal) 7103 ThreadLimitVal = Bld.getInt32(0); 7104 if (CondVal) 7105 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 7106 return ThreadLimitVal; 7107 } 7108 case OMPD_target_teams_distribute_simd: 7109 case OMPD_target_simd: 7110 return Bld.getInt32(1); 7111 case OMPD_parallel: 7112 case OMPD_for: 7113 case OMPD_parallel_for: 7114 case OMPD_parallel_sections: 7115 case OMPD_for_simd: 7116 case OMPD_parallel_for_simd: 7117 case OMPD_cancel: 7118 case OMPD_cancellation_point: 7119 case OMPD_ordered: 7120 case OMPD_threadprivate: 7121 case OMPD_allocate: 7122 case OMPD_task: 7123 case OMPD_simd: 7124 case OMPD_sections: 7125 case OMPD_section: 7126 case OMPD_single: 7127 case OMPD_master: 7128 case OMPD_critical: 7129 case OMPD_taskyield: 7130 case OMPD_barrier: 7131 case OMPD_taskwait: 7132 case OMPD_taskgroup: 7133 case OMPD_atomic: 7134 case OMPD_flush: 7135 case OMPD_teams: 7136 case OMPD_target_data: 7137 case OMPD_target_exit_data: 7138 case OMPD_target_enter_data: 7139 case OMPD_distribute: 7140 case OMPD_distribute_simd: 7141 case OMPD_distribute_parallel_for: 7142 case OMPD_distribute_parallel_for_simd: 7143 case OMPD_teams_distribute: 7144 case OMPD_teams_distribute_simd: 7145 case OMPD_teams_distribute_parallel_for: 7146 case OMPD_teams_distribute_parallel_for_simd: 7147 case OMPD_target_update: 7148 case OMPD_declare_simd: 7149 case OMPD_declare_variant: 7150 case OMPD_declare_target: 7151 case OMPD_end_declare_target: 7152 case OMPD_declare_reduction: 7153 case OMPD_declare_mapper: 7154 case OMPD_taskloop: 7155 case OMPD_taskloop_simd: 7156 case OMPD_requires: 7157 case OMPD_unknown: 7158 break; 7159 } 7160 llvm_unreachable("Unsupported directive kind."); 7161 } 7162 7163 namespace { 7164 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7165 7166 // Utility to handle information from clauses associated with a given 7167 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7168 // It provides a convenient interface to obtain the information and generate 7169 // code for that information. 7170 class MappableExprsHandler { 7171 public: 7172 /// Values for bit flags used to specify the mapping type for 7173 /// offloading. 7174 enum OpenMPOffloadMappingFlags : uint64_t { 7175 /// No flags 7176 OMP_MAP_NONE = 0x0, 7177 /// Allocate memory on the device and move data from host to device. 7178 OMP_MAP_TO = 0x01, 7179 /// Allocate memory on the device and move data from device to host. 7180 OMP_MAP_FROM = 0x02, 7181 /// Always perform the requested mapping action on the element, even 7182 /// if it was already mapped before. 7183 OMP_MAP_ALWAYS = 0x04, 7184 /// Delete the element from the device environment, ignoring the 7185 /// current reference count associated with the element. 7186 OMP_MAP_DELETE = 0x08, 7187 /// The element being mapped is a pointer-pointee pair; both the 7188 /// pointer and the pointee should be mapped. 7189 OMP_MAP_PTR_AND_OBJ = 0x10, 7190 /// This flags signals that the base address of an entry should be 7191 /// passed to the target kernel as an argument. 7192 OMP_MAP_TARGET_PARAM = 0x20, 7193 /// Signal that the runtime library has to return the device pointer 7194 /// in the current position for the data being mapped. Used when we have the 7195 /// use_device_ptr clause. 7196 OMP_MAP_RETURN_PARAM = 0x40, 7197 /// This flag signals that the reference being passed is a pointer to 7198 /// private data. 7199 OMP_MAP_PRIVATE = 0x80, 7200 /// Pass the element to the device by value. 7201 OMP_MAP_LITERAL = 0x100, 7202 /// Implicit map 7203 OMP_MAP_IMPLICIT = 0x200, 7204 /// Close is a hint to the runtime to allocate memory close to 7205 /// the target device. 7206 OMP_MAP_CLOSE = 0x400, 7207 /// The 16 MSBs of the flags indicate whether the entry is member of some 7208 /// struct/class. 7209 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7210 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7211 }; 7212 7213 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7214 static unsigned getFlagMemberOffset() { 7215 unsigned Offset = 0; 7216 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7217 Remain = Remain >> 1) 7218 Offset++; 7219 return Offset; 7220 } 7221 7222 /// Class that associates information with a base pointer to be passed to the 7223 /// runtime library. 7224 class BasePointerInfo { 7225 /// The base pointer. 7226 llvm::Value *Ptr = nullptr; 7227 /// The base declaration that refers to this device pointer, or null if 7228 /// there is none. 7229 const ValueDecl *DevPtrDecl = nullptr; 7230 7231 public: 7232 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7233 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7234 llvm::Value *operator*() const { return Ptr; } 7235 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7236 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7237 }; 7238 7239 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7240 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7241 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7242 7243 /// Map between a struct and the its lowest & highest elements which have been 7244 /// mapped. 7245 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7246 /// HE(FieldIndex, Pointer)} 7247 struct StructRangeInfoTy { 7248 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7249 0, Address::invalid()}; 7250 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7251 0, Address::invalid()}; 7252 Address Base = Address::invalid(); 7253 }; 7254 7255 private: 7256 /// Kind that defines how a device pointer has to be returned. 7257 struct MapInfo { 7258 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7259 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7260 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7261 bool ReturnDevicePointer = false; 7262 bool IsImplicit = false; 7263 7264 MapInfo() = default; 7265 MapInfo( 7266 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7267 OpenMPMapClauseKind MapType, 7268 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7269 bool ReturnDevicePointer, bool IsImplicit) 7270 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7271 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7272 }; 7273 7274 /// If use_device_ptr is used on a pointer which is a struct member and there 7275 /// is no map information about it, then emission of that entry is deferred 7276 /// until the whole struct has been processed. 7277 struct DeferredDevicePtrEntryTy { 7278 const Expr *IE = nullptr; 7279 const ValueDecl *VD = nullptr; 7280 7281 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7282 : IE(IE), VD(VD) {} 7283 }; 7284 7285 /// The target directive from where the mappable clauses were extracted. It 7286 /// is either a executable directive or a user-defined mapper directive. 7287 llvm::PointerUnion<const OMPExecutableDirective *, 7288 const OMPDeclareMapperDecl *> 7289 CurDir; 7290 7291 /// Function the directive is being generated for. 7292 CodeGenFunction &CGF; 7293 7294 /// Set of all first private variables in the current directive. 7295 /// bool data is set to true if the variable is implicitly marked as 7296 /// firstprivate, false otherwise. 7297 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7298 7299 /// Map between device pointer declarations and their expression components. 7300 /// The key value for declarations in 'this' is null. 7301 llvm::DenseMap< 7302 const ValueDecl *, 7303 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7304 DevPointersMap; 7305 7306 llvm::Value *getExprTypeSize(const Expr *E) const { 7307 QualType ExprTy = E->getType().getCanonicalType(); 7308 7309 // Reference types are ignored for mapping purposes. 7310 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7311 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7312 7313 // Given that an array section is considered a built-in type, we need to 7314 // do the calculation based on the length of the section instead of relying 7315 // on CGF.getTypeSize(E->getType()). 7316 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7317 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7318 OAE->getBase()->IgnoreParenImpCasts()) 7319 .getCanonicalType(); 7320 7321 // If there is no length associated with the expression and lower bound is 7322 // not specified too, that means we are using the whole length of the 7323 // base. 7324 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7325 !OAE->getLowerBound()) 7326 return CGF.getTypeSize(BaseTy); 7327 7328 llvm::Value *ElemSize; 7329 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7330 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7331 } else { 7332 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7333 assert(ATy && "Expecting array type if not a pointer type."); 7334 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7335 } 7336 7337 // If we don't have a length at this point, that is because we have an 7338 // array section with a single element. 7339 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7340 return ElemSize; 7341 7342 if (const Expr *LenExpr = OAE->getLength()) { 7343 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7344 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7345 CGF.getContext().getSizeType(), 7346 LenExpr->getExprLoc()); 7347 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7348 } 7349 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7350 OAE->getLowerBound() && "expected array_section[lb:]."); 7351 // Size = sizetype - lb * elemtype; 7352 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7353 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7354 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7355 CGF.getContext().getSizeType(), 7356 OAE->getLowerBound()->getExprLoc()); 7357 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7358 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7359 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7360 LengthVal = CGF.Builder.CreateSelect( 7361 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7362 return LengthVal; 7363 } 7364 return CGF.getTypeSize(ExprTy); 7365 } 7366 7367 /// Return the corresponding bits for a given map clause modifier. Add 7368 /// a flag marking the map as a pointer if requested. Add a flag marking the 7369 /// map as the first one of a series of maps that relate to the same map 7370 /// expression. 7371 OpenMPOffloadMappingFlags getMapTypeBits( 7372 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7373 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7374 OpenMPOffloadMappingFlags Bits = 7375 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7376 switch (MapType) { 7377 case OMPC_MAP_alloc: 7378 case OMPC_MAP_release: 7379 // alloc and release is the default behavior in the runtime library, i.e. 7380 // if we don't pass any bits alloc/release that is what the runtime is 7381 // going to do. Therefore, we don't need to signal anything for these two 7382 // type modifiers. 7383 break; 7384 case OMPC_MAP_to: 7385 Bits |= OMP_MAP_TO; 7386 break; 7387 case OMPC_MAP_from: 7388 Bits |= OMP_MAP_FROM; 7389 break; 7390 case OMPC_MAP_tofrom: 7391 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7392 break; 7393 case OMPC_MAP_delete: 7394 Bits |= OMP_MAP_DELETE; 7395 break; 7396 case OMPC_MAP_unknown: 7397 llvm_unreachable("Unexpected map type!"); 7398 } 7399 if (AddPtrFlag) 7400 Bits |= OMP_MAP_PTR_AND_OBJ; 7401 if (AddIsTargetParamFlag) 7402 Bits |= OMP_MAP_TARGET_PARAM; 7403 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7404 != MapModifiers.end()) 7405 Bits |= OMP_MAP_ALWAYS; 7406 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7407 != MapModifiers.end()) 7408 Bits |= OMP_MAP_CLOSE; 7409 return Bits; 7410 } 7411 7412 /// Return true if the provided expression is a final array section. A 7413 /// final array section, is one whose length can't be proved to be one. 7414 bool isFinalArraySectionExpression(const Expr *E) const { 7415 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7416 7417 // It is not an array section and therefore not a unity-size one. 7418 if (!OASE) 7419 return false; 7420 7421 // An array section with no colon always refer to a single element. 7422 if (OASE->getColonLoc().isInvalid()) 7423 return false; 7424 7425 const Expr *Length = OASE->getLength(); 7426 7427 // If we don't have a length we have to check if the array has size 1 7428 // for this dimension. Also, we should always expect a length if the 7429 // base type is pointer. 7430 if (!Length) { 7431 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7432 OASE->getBase()->IgnoreParenImpCasts()) 7433 .getCanonicalType(); 7434 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7435 return ATy->getSize().getSExtValue() != 1; 7436 // If we don't have a constant dimension length, we have to consider 7437 // the current section as having any size, so it is not necessarily 7438 // unitary. If it happen to be unity size, that's user fault. 7439 return true; 7440 } 7441 7442 // Check if the length evaluates to 1. 7443 Expr::EvalResult Result; 7444 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7445 return true; // Can have more that size 1. 7446 7447 llvm::APSInt ConstLength = Result.Val.getInt(); 7448 return ConstLength.getSExtValue() != 1; 7449 } 7450 7451 /// Generate the base pointers, section pointers, sizes and map type 7452 /// bits for the provided map type, map modifier, and expression components. 7453 /// \a IsFirstComponent should be set to true if the provided set of 7454 /// components is the first associated with a capture. 7455 void generateInfoForComponentList( 7456 OpenMPMapClauseKind MapType, 7457 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7458 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7459 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7460 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7461 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7462 bool IsImplicit, 7463 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7464 OverlappedElements = llvm::None) const { 7465 // The following summarizes what has to be generated for each map and the 7466 // types below. The generated information is expressed in this order: 7467 // base pointer, section pointer, size, flags 7468 // (to add to the ones that come from the map type and modifier). 7469 // 7470 // double d; 7471 // int i[100]; 7472 // float *p; 7473 // 7474 // struct S1 { 7475 // int i; 7476 // float f[50]; 7477 // } 7478 // struct S2 { 7479 // int i; 7480 // float f[50]; 7481 // S1 s; 7482 // double *p; 7483 // struct S2 *ps; 7484 // } 7485 // S2 s; 7486 // S2 *ps; 7487 // 7488 // map(d) 7489 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7490 // 7491 // map(i) 7492 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7493 // 7494 // map(i[1:23]) 7495 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7496 // 7497 // map(p) 7498 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7499 // 7500 // map(p[1:24]) 7501 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7502 // 7503 // map(s) 7504 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7505 // 7506 // map(s.i) 7507 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7508 // 7509 // map(s.s.f) 7510 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7511 // 7512 // map(s.p) 7513 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7514 // 7515 // map(to: s.p[:22]) 7516 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7517 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7518 // &(s.p), &(s.p[0]), 22*sizeof(double), 7519 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7520 // (*) alloc space for struct members, only this is a target parameter 7521 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7522 // optimizes this entry out, same in the examples below) 7523 // (***) map the pointee (map: to) 7524 // 7525 // map(s.ps) 7526 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7527 // 7528 // map(from: s.ps->s.i) 7529 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7530 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7531 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7532 // 7533 // map(to: s.ps->ps) 7534 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7535 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7536 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7537 // 7538 // map(s.ps->ps->ps) 7539 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7540 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7541 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7542 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7543 // 7544 // map(to: s.ps->ps->s.f[:22]) 7545 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7546 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7547 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7548 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7549 // 7550 // map(ps) 7551 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7552 // 7553 // map(ps->i) 7554 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7555 // 7556 // map(ps->s.f) 7557 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7558 // 7559 // map(from: ps->p) 7560 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7561 // 7562 // map(to: ps->p[:22]) 7563 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7564 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7565 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7566 // 7567 // map(ps->ps) 7568 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7569 // 7570 // map(from: ps->ps->s.i) 7571 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7572 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7573 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7574 // 7575 // map(from: ps->ps->ps) 7576 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7577 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7578 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7579 // 7580 // map(ps->ps->ps->ps) 7581 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7582 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7583 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7584 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7585 // 7586 // map(to: ps->ps->ps->s.f[:22]) 7587 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7588 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7589 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7590 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7591 // 7592 // map(to: s.f[:22]) map(from: s.p[:33]) 7593 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7594 // sizeof(double*) (**), TARGET_PARAM 7595 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7596 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7597 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7598 // (*) allocate contiguous space needed to fit all mapped members even if 7599 // we allocate space for members not mapped (in this example, 7600 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7601 // them as well because they fall between &s.f[0] and &s.p) 7602 // 7603 // map(from: s.f[:22]) map(to: ps->p[:33]) 7604 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7605 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7606 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7607 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7608 // (*) the struct this entry pertains to is the 2nd element in the list of 7609 // arguments, hence MEMBER_OF(2) 7610 // 7611 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7612 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7613 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7614 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7615 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7616 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7617 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7618 // (*) the struct this entry pertains to is the 4th element in the list 7619 // of arguments, hence MEMBER_OF(4) 7620 7621 // Track if the map information being generated is the first for a capture. 7622 bool IsCaptureFirstInfo = IsFirstComponentList; 7623 // When the variable is on a declare target link or in a to clause with 7624 // unified memory, a reference is needed to hold the host/device address 7625 // of the variable. 7626 bool RequiresReference = false; 7627 7628 // Scan the components from the base to the complete expression. 7629 auto CI = Components.rbegin(); 7630 auto CE = Components.rend(); 7631 auto I = CI; 7632 7633 // Track if the map information being generated is the first for a list of 7634 // components. 7635 bool IsExpressionFirstInfo = true; 7636 Address BP = Address::invalid(); 7637 const Expr *AssocExpr = I->getAssociatedExpression(); 7638 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7639 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7640 7641 if (isa<MemberExpr>(AssocExpr)) { 7642 // The base is the 'this' pointer. The content of the pointer is going 7643 // to be the base of the field being mapped. 7644 BP = CGF.LoadCXXThisAddress(); 7645 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7646 (OASE && 7647 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7648 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); 7649 } else { 7650 // The base is the reference to the variable. 7651 // BP = &Var. 7652 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); 7653 if (const auto *VD = 7654 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7655 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7656 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7657 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7658 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7659 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7660 RequiresReference = true; 7661 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7662 } 7663 } 7664 } 7665 7666 // If the variable is a pointer and is being dereferenced (i.e. is not 7667 // the last component), the base has to be the pointer itself, not its 7668 // reference. References are ignored for mapping purposes. 7669 QualType Ty = 7670 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7671 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7672 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7673 7674 // We do not need to generate individual map information for the 7675 // pointer, it can be associated with the combined storage. 7676 ++I; 7677 } 7678 } 7679 7680 // Track whether a component of the list should be marked as MEMBER_OF some 7681 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7682 // in a component list should be marked as MEMBER_OF, all subsequent entries 7683 // do not belong to the base struct. E.g. 7684 // struct S2 s; 7685 // s.ps->ps->ps->f[:] 7686 // (1) (2) (3) (4) 7687 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7688 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7689 // is the pointee of ps(2) which is not member of struct s, so it should not 7690 // be marked as such (it is still PTR_AND_OBJ). 7691 // The variable is initialized to false so that PTR_AND_OBJ entries which 7692 // are not struct members are not considered (e.g. array of pointers to 7693 // data). 7694 bool ShouldBeMemberOf = false; 7695 7696 // Variable keeping track of whether or not we have encountered a component 7697 // in the component list which is a member expression. Useful when we have a 7698 // pointer or a final array section, in which case it is the previous 7699 // component in the list which tells us whether we have a member expression. 7700 // E.g. X.f[:] 7701 // While processing the final array section "[:]" it is "f" which tells us 7702 // whether we are dealing with a member of a declared struct. 7703 const MemberExpr *EncounteredME = nullptr; 7704 7705 for (; I != CE; ++I) { 7706 // If the current component is member of a struct (parent struct) mark it. 7707 if (!EncounteredME) { 7708 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7709 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7710 // as MEMBER_OF the parent struct. 7711 if (EncounteredME) 7712 ShouldBeMemberOf = true; 7713 } 7714 7715 auto Next = std::next(I); 7716 7717 // We need to generate the addresses and sizes if this is the last 7718 // component, if the component is a pointer or if it is an array section 7719 // whose length can't be proved to be one. If this is a pointer, it 7720 // becomes the base address for the following components. 7721 7722 // A final array section, is one whose length can't be proved to be one. 7723 bool IsFinalArraySection = 7724 isFinalArraySectionExpression(I->getAssociatedExpression()); 7725 7726 // Get information on whether the element is a pointer. Have to do a 7727 // special treatment for array sections given that they are built-in 7728 // types. 7729 const auto *OASE = 7730 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7731 bool IsPointer = 7732 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7733 .getCanonicalType() 7734 ->isAnyPointerType()) || 7735 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7736 7737 if (Next == CE || IsPointer || IsFinalArraySection) { 7738 // If this is not the last component, we expect the pointer to be 7739 // associated with an array expression or member expression. 7740 assert((Next == CE || 7741 isa<MemberExpr>(Next->getAssociatedExpression()) || 7742 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7743 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 7744 "Unexpected expression"); 7745 7746 Address LB = 7747 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress(); 7748 7749 // If this component is a pointer inside the base struct then we don't 7750 // need to create any entry for it - it will be combined with the object 7751 // it is pointing to into a single PTR_AND_OBJ entry. 7752 bool IsMemberPointer = 7753 IsPointer && EncounteredME && 7754 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7755 EncounteredME); 7756 if (!OverlappedElements.empty()) { 7757 // Handle base element with the info for overlapped elements. 7758 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7759 assert(Next == CE && 7760 "Expected last element for the overlapped elements."); 7761 assert(!IsPointer && 7762 "Unexpected base element with the pointer type."); 7763 // Mark the whole struct as the struct that requires allocation on the 7764 // device. 7765 PartialStruct.LowestElem = {0, LB}; 7766 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7767 I->getAssociatedExpression()->getType()); 7768 Address HB = CGF.Builder.CreateConstGEP( 7769 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7770 CGF.VoidPtrTy), 7771 TypeSize.getQuantity() - 1); 7772 PartialStruct.HighestElem = { 7773 std::numeric_limits<decltype( 7774 PartialStruct.HighestElem.first)>::max(), 7775 HB}; 7776 PartialStruct.Base = BP; 7777 // Emit data for non-overlapped data. 7778 OpenMPOffloadMappingFlags Flags = 7779 OMP_MAP_MEMBER_OF | 7780 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7781 /*AddPtrFlag=*/false, 7782 /*AddIsTargetParamFlag=*/false); 7783 LB = BP; 7784 llvm::Value *Size = nullptr; 7785 // Do bitcopy of all non-overlapped structure elements. 7786 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7787 Component : OverlappedElements) { 7788 Address ComponentLB = Address::invalid(); 7789 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7790 Component) { 7791 if (MC.getAssociatedDeclaration()) { 7792 ComponentLB = 7793 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7794 .getAddress(); 7795 Size = CGF.Builder.CreatePtrDiff( 7796 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7797 CGF.EmitCastToVoidPtr(LB.getPointer())); 7798 break; 7799 } 7800 } 7801 BasePointers.push_back(BP.getPointer()); 7802 Pointers.push_back(LB.getPointer()); 7803 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7804 /*isSigned=*/true)); 7805 Types.push_back(Flags); 7806 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7807 } 7808 BasePointers.push_back(BP.getPointer()); 7809 Pointers.push_back(LB.getPointer()); 7810 Size = CGF.Builder.CreatePtrDiff( 7811 CGF.EmitCastToVoidPtr( 7812 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7813 CGF.EmitCastToVoidPtr(LB.getPointer())); 7814 Sizes.push_back( 7815 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7816 Types.push_back(Flags); 7817 break; 7818 } 7819 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7820 if (!IsMemberPointer) { 7821 BasePointers.push_back(BP.getPointer()); 7822 Pointers.push_back(LB.getPointer()); 7823 Sizes.push_back( 7824 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7825 7826 // We need to add a pointer flag for each map that comes from the 7827 // same expression except for the first one. We also need to signal 7828 // this map is the first one that relates with the current capture 7829 // (there is a set of entries for each capture). 7830 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7831 MapType, MapModifiers, IsImplicit, 7832 !IsExpressionFirstInfo || RequiresReference, 7833 IsCaptureFirstInfo && !RequiresReference); 7834 7835 if (!IsExpressionFirstInfo) { 7836 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7837 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7838 if (IsPointer) 7839 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7840 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7841 7842 if (ShouldBeMemberOf) { 7843 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7844 // should be later updated with the correct value of MEMBER_OF. 7845 Flags |= OMP_MAP_MEMBER_OF; 7846 // From now on, all subsequent PTR_AND_OBJ entries should not be 7847 // marked as MEMBER_OF. 7848 ShouldBeMemberOf = false; 7849 } 7850 } 7851 7852 Types.push_back(Flags); 7853 } 7854 7855 // If we have encountered a member expression so far, keep track of the 7856 // mapped member. If the parent is "*this", then the value declaration 7857 // is nullptr. 7858 if (EncounteredME) { 7859 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl()); 7860 unsigned FieldIndex = FD->getFieldIndex(); 7861 7862 // Update info about the lowest and highest elements for this struct 7863 if (!PartialStruct.Base.isValid()) { 7864 PartialStruct.LowestElem = {FieldIndex, LB}; 7865 PartialStruct.HighestElem = {FieldIndex, LB}; 7866 PartialStruct.Base = BP; 7867 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7868 PartialStruct.LowestElem = {FieldIndex, LB}; 7869 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7870 PartialStruct.HighestElem = {FieldIndex, LB}; 7871 } 7872 } 7873 7874 // If we have a final array section, we are done with this expression. 7875 if (IsFinalArraySection) 7876 break; 7877 7878 // The pointer becomes the base for the next element. 7879 if (Next != CE) 7880 BP = LB; 7881 7882 IsExpressionFirstInfo = false; 7883 IsCaptureFirstInfo = false; 7884 } 7885 } 7886 } 7887 7888 /// Return the adjusted map modifiers if the declaration a capture refers to 7889 /// appears in a first-private clause. This is expected to be used only with 7890 /// directives that start with 'target'. 7891 MappableExprsHandler::OpenMPOffloadMappingFlags 7892 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7893 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7894 7895 // A first private variable captured by reference will use only the 7896 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7897 // declaration is known as first-private in this handler. 7898 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7899 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7900 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7901 return MappableExprsHandler::OMP_MAP_ALWAYS | 7902 MappableExprsHandler::OMP_MAP_TO; 7903 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7904 return MappableExprsHandler::OMP_MAP_TO | 7905 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7906 return MappableExprsHandler::OMP_MAP_PRIVATE | 7907 MappableExprsHandler::OMP_MAP_TO; 7908 } 7909 return MappableExprsHandler::OMP_MAP_TO | 7910 MappableExprsHandler::OMP_MAP_FROM; 7911 } 7912 7913 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7914 // Rotate by getFlagMemberOffset() bits. 7915 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7916 << getFlagMemberOffset()); 7917 } 7918 7919 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7920 OpenMPOffloadMappingFlags MemberOfFlag) { 7921 // If the entry is PTR_AND_OBJ but has not been marked with the special 7922 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7923 // marked as MEMBER_OF. 7924 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7925 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7926 return; 7927 7928 // Reset the placeholder value to prepare the flag for the assignment of the 7929 // proper MEMBER_OF value. 7930 Flags &= ~OMP_MAP_MEMBER_OF; 7931 Flags |= MemberOfFlag; 7932 } 7933 7934 void getPlainLayout(const CXXRecordDecl *RD, 7935 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7936 bool AsBase) const { 7937 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7938 7939 llvm::StructType *St = 7940 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7941 7942 unsigned NumElements = St->getNumElements(); 7943 llvm::SmallVector< 7944 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7945 RecordLayout(NumElements); 7946 7947 // Fill bases. 7948 for (const auto &I : RD->bases()) { 7949 if (I.isVirtual()) 7950 continue; 7951 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7952 // Ignore empty bases. 7953 if (Base->isEmpty() || CGF.getContext() 7954 .getASTRecordLayout(Base) 7955 .getNonVirtualSize() 7956 .isZero()) 7957 continue; 7958 7959 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7960 RecordLayout[FieldIndex] = Base; 7961 } 7962 // Fill in virtual bases. 7963 for (const auto &I : RD->vbases()) { 7964 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7965 // Ignore empty bases. 7966 if (Base->isEmpty()) 7967 continue; 7968 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7969 if (RecordLayout[FieldIndex]) 7970 continue; 7971 RecordLayout[FieldIndex] = Base; 7972 } 7973 // Fill in all the fields. 7974 assert(!RD->isUnion() && "Unexpected union."); 7975 for (const auto *Field : RD->fields()) { 7976 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7977 // will fill in later.) 7978 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 7979 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7980 RecordLayout[FieldIndex] = Field; 7981 } 7982 } 7983 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7984 &Data : RecordLayout) { 7985 if (Data.isNull()) 7986 continue; 7987 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7988 getPlainLayout(Base, Layout, /*AsBase=*/true); 7989 else 7990 Layout.push_back(Data.get<const FieldDecl *>()); 7991 } 7992 } 7993 7994 public: 7995 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7996 : CurDir(&Dir), CGF(CGF) { 7997 // Extract firstprivate clause information. 7998 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7999 for (const auto *D : C->varlists()) 8000 FirstPrivateDecls.try_emplace( 8001 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 8002 // Extract device pointer clause information. 8003 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 8004 for (auto L : C->component_lists()) 8005 DevPointersMap[L.first].push_back(L.second); 8006 } 8007 8008 /// Constructor for the declare mapper directive. 8009 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 8010 : CurDir(&Dir), CGF(CGF) {} 8011 8012 /// Generate code for the combined entry if we have a partially mapped struct 8013 /// and take care of the mapping flags of the arguments corresponding to 8014 /// individual struct members. 8015 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 8016 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8017 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 8018 const StructRangeInfoTy &PartialStruct) const { 8019 // Base is the base of the struct 8020 BasePointers.push_back(PartialStruct.Base.getPointer()); 8021 // Pointer is the address of the lowest element 8022 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 8023 Pointers.push_back(LB); 8024 // Size is (addr of {highest+1} element) - (addr of lowest element) 8025 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 8026 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 8027 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 8028 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 8029 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 8030 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 8031 /*isSigned=*/false); 8032 Sizes.push_back(Size); 8033 // Map type is always TARGET_PARAM 8034 Types.push_back(OMP_MAP_TARGET_PARAM); 8035 // Remove TARGET_PARAM flag from the first element 8036 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 8037 8038 // All other current entries will be MEMBER_OF the combined entry 8039 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8040 // 0xFFFF in the MEMBER_OF field). 8041 OpenMPOffloadMappingFlags MemberOfFlag = 8042 getMemberOfFlag(BasePointers.size() - 1); 8043 for (auto &M : CurTypes) 8044 setCorrectMemberOfFlag(M, MemberOfFlag); 8045 } 8046 8047 /// Generate all the base pointers, section pointers, sizes and map 8048 /// types for the extracted mappable expressions. Also, for each item that 8049 /// relates with a device pointer, a pair of the relevant declaration and 8050 /// index where it occurs is appended to the device pointers info array. 8051 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 8052 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8053 MapFlagsArrayTy &Types) const { 8054 // We have to process the component lists that relate with the same 8055 // declaration in a single chunk so that we can generate the map flags 8056 // correctly. Therefore, we organize all lists in a map. 8057 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8058 8059 // Helper function to fill the information map for the different supported 8060 // clauses. 8061 auto &&InfoGen = [&Info]( 8062 const ValueDecl *D, 8063 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8064 OpenMPMapClauseKind MapType, 8065 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8066 bool ReturnDevicePointer, bool IsImplicit) { 8067 const ValueDecl *VD = 8068 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8069 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8070 IsImplicit); 8071 }; 8072 8073 assert(CurDir.is<const OMPExecutableDirective *>() && 8074 "Expect a executable directive"); 8075 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8076 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 8077 for (const auto &L : C->component_lists()) { 8078 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 8079 /*ReturnDevicePointer=*/false, C->isImplicit()); 8080 } 8081 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 8082 for (const auto &L : C->component_lists()) { 8083 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 8084 /*ReturnDevicePointer=*/false, C->isImplicit()); 8085 } 8086 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 8087 for (const auto &L : C->component_lists()) { 8088 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 8089 /*ReturnDevicePointer=*/false, C->isImplicit()); 8090 } 8091 8092 // Look at the use_device_ptr clause information and mark the existing map 8093 // entries as such. If there is no map information for an entry in the 8094 // use_device_ptr list, we create one with map type 'alloc' and zero size 8095 // section. It is the user fault if that was not mapped before. If there is 8096 // no map information and the pointer is a struct member, then we defer the 8097 // emission of that entry until the whole struct has been processed. 8098 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 8099 DeferredInfo; 8100 8101 for (const auto *C : 8102 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 8103 for (const auto &L : C->component_lists()) { 8104 assert(!L.second.empty() && "Not expecting empty list of components!"); 8105 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 8106 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8107 const Expr *IE = L.second.back().getAssociatedExpression(); 8108 // If the first component is a member expression, we have to look into 8109 // 'this', which maps to null in the map of map information. Otherwise 8110 // look directly for the information. 8111 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8112 8113 // We potentially have map information for this declaration already. 8114 // Look for the first set of components that refer to it. 8115 if (It != Info.end()) { 8116 auto CI = std::find_if( 8117 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 8118 return MI.Components.back().getAssociatedDeclaration() == VD; 8119 }); 8120 // If we found a map entry, signal that the pointer has to be returned 8121 // and move on to the next declaration. 8122 if (CI != It->second.end()) { 8123 CI->ReturnDevicePointer = true; 8124 continue; 8125 } 8126 } 8127 8128 // We didn't find any match in our map information - generate a zero 8129 // size array section - if the pointer is a struct member we defer this 8130 // action until the whole struct has been processed. 8131 if (isa<MemberExpr>(IE)) { 8132 // Insert the pointer into Info to be processed by 8133 // generateInfoForComponentList. Because it is a member pointer 8134 // without a pointee, no entry will be generated for it, therefore 8135 // we need to generate one after the whole struct has been processed. 8136 // Nonetheless, generateInfoForComponentList must be called to take 8137 // the pointer into account for the calculation of the range of the 8138 // partial struct. 8139 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 8140 /*ReturnDevicePointer=*/false, C->isImplicit()); 8141 DeferredInfo[nullptr].emplace_back(IE, VD); 8142 } else { 8143 llvm::Value *Ptr = 8144 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8145 BasePointers.emplace_back(Ptr, VD); 8146 Pointers.push_back(Ptr); 8147 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8148 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8149 } 8150 } 8151 } 8152 8153 for (const auto &M : Info) { 8154 // We need to know when we generate information for the first component 8155 // associated with a capture, because the mapping flags depend on it. 8156 bool IsFirstComponentList = true; 8157 8158 // Temporary versions of arrays 8159 MapBaseValuesArrayTy CurBasePointers; 8160 MapValuesArrayTy CurPointers; 8161 MapValuesArrayTy CurSizes; 8162 MapFlagsArrayTy CurTypes; 8163 StructRangeInfoTy PartialStruct; 8164 8165 for (const MapInfo &L : M.second) { 8166 assert(!L.Components.empty() && 8167 "Not expecting declaration with no component lists."); 8168 8169 // Remember the current base pointer index. 8170 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8171 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8172 CurBasePointers, CurPointers, CurSizes, 8173 CurTypes, PartialStruct, 8174 IsFirstComponentList, L.IsImplicit); 8175 8176 // If this entry relates with a device pointer, set the relevant 8177 // declaration and add the 'return pointer' flag. 8178 if (L.ReturnDevicePointer) { 8179 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8180 "Unexpected number of mapped base pointers."); 8181 8182 const ValueDecl *RelevantVD = 8183 L.Components.back().getAssociatedDeclaration(); 8184 assert(RelevantVD && 8185 "No relevant declaration related with device pointer??"); 8186 8187 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8188 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8189 } 8190 IsFirstComponentList = false; 8191 } 8192 8193 // Append any pending zero-length pointers which are struct members and 8194 // used with use_device_ptr. 8195 auto CI = DeferredInfo.find(M.first); 8196 if (CI != DeferredInfo.end()) { 8197 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8198 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(); 8199 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8200 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8201 CurBasePointers.emplace_back(BasePtr, L.VD); 8202 CurPointers.push_back(Ptr); 8203 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8204 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8205 // value MEMBER_OF=FFFF so that the entry is later updated with the 8206 // correct value of MEMBER_OF. 8207 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8208 OMP_MAP_MEMBER_OF); 8209 } 8210 } 8211 8212 // If there is an entry in PartialStruct it means we have a struct with 8213 // individual members mapped. Emit an extra combined entry. 8214 if (PartialStruct.Base.isValid()) 8215 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8216 PartialStruct); 8217 8218 // We need to append the results of this capture to what we already have. 8219 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8220 Pointers.append(CurPointers.begin(), CurPointers.end()); 8221 Sizes.append(CurSizes.begin(), CurSizes.end()); 8222 Types.append(CurTypes.begin(), CurTypes.end()); 8223 } 8224 } 8225 8226 /// Generate all the base pointers, section pointers, sizes and map types for 8227 /// the extracted map clauses of user-defined mapper. 8228 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8229 MapValuesArrayTy &Pointers, 8230 MapValuesArrayTy &Sizes, 8231 MapFlagsArrayTy &Types) const { 8232 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8233 "Expect a declare mapper directive"); 8234 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8235 // We have to process the component lists that relate with the same 8236 // declaration in a single chunk so that we can generate the map flags 8237 // correctly. Therefore, we organize all lists in a map. 8238 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8239 8240 // Helper function to fill the information map for the different supported 8241 // clauses. 8242 auto &&InfoGen = [&Info]( 8243 const ValueDecl *D, 8244 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8245 OpenMPMapClauseKind MapType, 8246 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8247 bool ReturnDevicePointer, bool IsImplicit) { 8248 const ValueDecl *VD = 8249 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8250 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8251 IsImplicit); 8252 }; 8253 8254 for (const auto *C : CurMapperDir->clauselists()) { 8255 const auto *MC = cast<OMPMapClause>(C); 8256 for (const auto &L : MC->component_lists()) { 8257 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8258 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8259 } 8260 } 8261 8262 for (const auto &M : Info) { 8263 // We need to know when we generate information for the first component 8264 // associated with a capture, because the mapping flags depend on it. 8265 bool IsFirstComponentList = true; 8266 8267 // Temporary versions of arrays 8268 MapBaseValuesArrayTy CurBasePointers; 8269 MapValuesArrayTy CurPointers; 8270 MapValuesArrayTy CurSizes; 8271 MapFlagsArrayTy CurTypes; 8272 StructRangeInfoTy PartialStruct; 8273 8274 for (const MapInfo &L : M.second) { 8275 assert(!L.Components.empty() && 8276 "Not expecting declaration with no component lists."); 8277 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8278 CurBasePointers, CurPointers, CurSizes, 8279 CurTypes, PartialStruct, 8280 IsFirstComponentList, L.IsImplicit); 8281 IsFirstComponentList = false; 8282 } 8283 8284 // If there is an entry in PartialStruct it means we have a struct with 8285 // individual members mapped. Emit an extra combined entry. 8286 if (PartialStruct.Base.isValid()) 8287 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8288 PartialStruct); 8289 8290 // We need to append the results of this capture to what we already have. 8291 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8292 Pointers.append(CurPointers.begin(), CurPointers.end()); 8293 Sizes.append(CurSizes.begin(), CurSizes.end()); 8294 Types.append(CurTypes.begin(), CurTypes.end()); 8295 } 8296 } 8297 8298 /// Emit capture info for lambdas for variables captured by reference. 8299 void generateInfoForLambdaCaptures( 8300 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8301 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8302 MapFlagsArrayTy &Types, 8303 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8304 const auto *RD = VD->getType() 8305 .getCanonicalType() 8306 .getNonReferenceType() 8307 ->getAsCXXRecordDecl(); 8308 if (!RD || !RD->isLambda()) 8309 return; 8310 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8311 LValue VDLVal = CGF.MakeAddrLValue( 8312 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8313 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8314 FieldDecl *ThisCapture = nullptr; 8315 RD->getCaptureFields(Captures, ThisCapture); 8316 if (ThisCapture) { 8317 LValue ThisLVal = 8318 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8319 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8320 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer()); 8321 BasePointers.push_back(ThisLVal.getPointer()); 8322 Pointers.push_back(ThisLValVal.getPointer()); 8323 Sizes.push_back( 8324 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8325 CGF.Int64Ty, /*isSigned=*/true)); 8326 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8327 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8328 } 8329 for (const LambdaCapture &LC : RD->captures()) { 8330 if (!LC.capturesVariable()) 8331 continue; 8332 const VarDecl *VD = LC.getCapturedVar(); 8333 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8334 continue; 8335 auto It = Captures.find(VD); 8336 assert(It != Captures.end() && "Found lambda capture without field."); 8337 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8338 if (LC.getCaptureKind() == LCK_ByRef) { 8339 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8340 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer()); 8341 BasePointers.push_back(VarLVal.getPointer()); 8342 Pointers.push_back(VarLValVal.getPointer()); 8343 Sizes.push_back(CGF.Builder.CreateIntCast( 8344 CGF.getTypeSize( 8345 VD->getType().getCanonicalType().getNonReferenceType()), 8346 CGF.Int64Ty, /*isSigned=*/true)); 8347 } else { 8348 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8349 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer()); 8350 BasePointers.push_back(VarLVal.getPointer()); 8351 Pointers.push_back(VarRVal.getScalarVal()); 8352 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8353 } 8354 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8355 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8356 } 8357 } 8358 8359 /// Set correct indices for lambdas captures. 8360 void adjustMemberOfForLambdaCaptures( 8361 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8362 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8363 MapFlagsArrayTy &Types) const { 8364 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8365 // Set correct member_of idx for all implicit lambda captures. 8366 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8367 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8368 continue; 8369 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8370 assert(BasePtr && "Unable to find base lambda address."); 8371 int TgtIdx = -1; 8372 for (unsigned J = I; J > 0; --J) { 8373 unsigned Idx = J - 1; 8374 if (Pointers[Idx] != BasePtr) 8375 continue; 8376 TgtIdx = Idx; 8377 break; 8378 } 8379 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8380 // All other current entries will be MEMBER_OF the combined entry 8381 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8382 // 0xFFFF in the MEMBER_OF field). 8383 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8384 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8385 } 8386 } 8387 8388 /// Generate the base pointers, section pointers, sizes and map types 8389 /// associated to a given capture. 8390 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8391 llvm::Value *Arg, 8392 MapBaseValuesArrayTy &BasePointers, 8393 MapValuesArrayTy &Pointers, 8394 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8395 StructRangeInfoTy &PartialStruct) const { 8396 assert(!Cap->capturesVariableArrayType() && 8397 "Not expecting to generate map info for a variable array type!"); 8398 8399 // We need to know when we generating information for the first component 8400 const ValueDecl *VD = Cap->capturesThis() 8401 ? nullptr 8402 : Cap->getCapturedVar()->getCanonicalDecl(); 8403 8404 // If this declaration appears in a is_device_ptr clause we just have to 8405 // pass the pointer by value. If it is a reference to a declaration, we just 8406 // pass its value. 8407 if (DevPointersMap.count(VD)) { 8408 BasePointers.emplace_back(Arg, VD); 8409 Pointers.push_back(Arg); 8410 Sizes.push_back( 8411 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8412 CGF.Int64Ty, /*isSigned=*/true)); 8413 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8414 return; 8415 } 8416 8417 using MapData = 8418 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8419 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8420 SmallVector<MapData, 4> DeclComponentLists; 8421 assert(CurDir.is<const OMPExecutableDirective *>() && 8422 "Expect a executable directive"); 8423 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8424 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8425 for (const auto &L : C->decl_component_lists(VD)) { 8426 assert(L.first == VD && 8427 "We got information for the wrong declaration??"); 8428 assert(!L.second.empty() && 8429 "Not expecting declaration with no component lists."); 8430 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8431 C->getMapTypeModifiers(), 8432 C->isImplicit()); 8433 } 8434 } 8435 8436 // Find overlapping elements (including the offset from the base element). 8437 llvm::SmallDenseMap< 8438 const MapData *, 8439 llvm::SmallVector< 8440 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8441 4> 8442 OverlappedData; 8443 size_t Count = 0; 8444 for (const MapData &L : DeclComponentLists) { 8445 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8446 OpenMPMapClauseKind MapType; 8447 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8448 bool IsImplicit; 8449 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8450 ++Count; 8451 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8452 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8453 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8454 auto CI = Components.rbegin(); 8455 auto CE = Components.rend(); 8456 auto SI = Components1.rbegin(); 8457 auto SE = Components1.rend(); 8458 for (; CI != CE && SI != SE; ++CI, ++SI) { 8459 if (CI->getAssociatedExpression()->getStmtClass() != 8460 SI->getAssociatedExpression()->getStmtClass()) 8461 break; 8462 // Are we dealing with different variables/fields? 8463 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8464 break; 8465 } 8466 // Found overlapping if, at least for one component, reached the head of 8467 // the components list. 8468 if (CI == CE || SI == SE) { 8469 assert((CI != CE || SI != SE) && 8470 "Unexpected full match of the mapping components."); 8471 const MapData &BaseData = CI == CE ? L : L1; 8472 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8473 SI == SE ? Components : Components1; 8474 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8475 OverlappedElements.getSecond().push_back(SubData); 8476 } 8477 } 8478 } 8479 // Sort the overlapped elements for each item. 8480 llvm::SmallVector<const FieldDecl *, 4> Layout; 8481 if (!OverlappedData.empty()) { 8482 if (const auto *CRD = 8483 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8484 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8485 else { 8486 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8487 Layout.append(RD->field_begin(), RD->field_end()); 8488 } 8489 } 8490 for (auto &Pair : OverlappedData) { 8491 llvm::sort( 8492 Pair.getSecond(), 8493 [&Layout]( 8494 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8495 OMPClauseMappableExprCommon::MappableExprComponentListRef 8496 Second) { 8497 auto CI = First.rbegin(); 8498 auto CE = First.rend(); 8499 auto SI = Second.rbegin(); 8500 auto SE = Second.rend(); 8501 for (; CI != CE && SI != SE; ++CI, ++SI) { 8502 if (CI->getAssociatedExpression()->getStmtClass() != 8503 SI->getAssociatedExpression()->getStmtClass()) 8504 break; 8505 // Are we dealing with different variables/fields? 8506 if (CI->getAssociatedDeclaration() != 8507 SI->getAssociatedDeclaration()) 8508 break; 8509 } 8510 8511 // Lists contain the same elements. 8512 if (CI == CE && SI == SE) 8513 return false; 8514 8515 // List with less elements is less than list with more elements. 8516 if (CI == CE || SI == SE) 8517 return CI == CE; 8518 8519 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8520 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8521 if (FD1->getParent() == FD2->getParent()) 8522 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8523 const auto It = 8524 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8525 return FD == FD1 || FD == FD2; 8526 }); 8527 return *It == FD1; 8528 }); 8529 } 8530 8531 // Associated with a capture, because the mapping flags depend on it. 8532 // Go through all of the elements with the overlapped elements. 8533 for (const auto &Pair : OverlappedData) { 8534 const MapData &L = *Pair.getFirst(); 8535 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8536 OpenMPMapClauseKind MapType; 8537 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8538 bool IsImplicit; 8539 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8540 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8541 OverlappedComponents = Pair.getSecond(); 8542 bool IsFirstComponentList = true; 8543 generateInfoForComponentList(MapType, MapModifiers, Components, 8544 BasePointers, Pointers, Sizes, Types, 8545 PartialStruct, IsFirstComponentList, 8546 IsImplicit, OverlappedComponents); 8547 } 8548 // Go through other elements without overlapped elements. 8549 bool IsFirstComponentList = OverlappedData.empty(); 8550 for (const MapData &L : DeclComponentLists) { 8551 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8552 OpenMPMapClauseKind MapType; 8553 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8554 bool IsImplicit; 8555 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8556 auto It = OverlappedData.find(&L); 8557 if (It == OverlappedData.end()) 8558 generateInfoForComponentList(MapType, MapModifiers, Components, 8559 BasePointers, Pointers, Sizes, Types, 8560 PartialStruct, IsFirstComponentList, 8561 IsImplicit); 8562 IsFirstComponentList = false; 8563 } 8564 } 8565 8566 /// Generate the base pointers, section pointers, sizes and map types 8567 /// associated with the declare target link variables. 8568 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8569 MapValuesArrayTy &Pointers, 8570 MapValuesArrayTy &Sizes, 8571 MapFlagsArrayTy &Types) const { 8572 assert(CurDir.is<const OMPExecutableDirective *>() && 8573 "Expect a executable directive"); 8574 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8575 // Map other list items in the map clause which are not captured variables 8576 // but "declare target link" global variables. 8577 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8578 for (const auto &L : C->component_lists()) { 8579 if (!L.first) 8580 continue; 8581 const auto *VD = dyn_cast<VarDecl>(L.first); 8582 if (!VD) 8583 continue; 8584 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8585 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8586 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8587 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8588 continue; 8589 StructRangeInfoTy PartialStruct; 8590 generateInfoForComponentList( 8591 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8592 Pointers, Sizes, Types, PartialStruct, 8593 /*IsFirstComponentList=*/true, C->isImplicit()); 8594 assert(!PartialStruct.Base.isValid() && 8595 "No partial structs for declare target link expected."); 8596 } 8597 } 8598 } 8599 8600 /// Generate the default map information for a given capture \a CI, 8601 /// record field declaration \a RI and captured value \a CV. 8602 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8603 const FieldDecl &RI, llvm::Value *CV, 8604 MapBaseValuesArrayTy &CurBasePointers, 8605 MapValuesArrayTy &CurPointers, 8606 MapValuesArrayTy &CurSizes, 8607 MapFlagsArrayTy &CurMapTypes) const { 8608 bool IsImplicit = true; 8609 // Do the default mapping. 8610 if (CI.capturesThis()) { 8611 CurBasePointers.push_back(CV); 8612 CurPointers.push_back(CV); 8613 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8614 CurSizes.push_back( 8615 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8616 CGF.Int64Ty, /*isSigned=*/true)); 8617 // Default map type. 8618 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8619 } else if (CI.capturesVariableByCopy()) { 8620 CurBasePointers.push_back(CV); 8621 CurPointers.push_back(CV); 8622 if (!RI.getType()->isAnyPointerType()) { 8623 // We have to signal to the runtime captures passed by value that are 8624 // not pointers. 8625 CurMapTypes.push_back(OMP_MAP_LITERAL); 8626 CurSizes.push_back(CGF.Builder.CreateIntCast( 8627 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8628 } else { 8629 // Pointers are implicitly mapped with a zero size and no flags 8630 // (other than first map that is added for all implicit maps). 8631 CurMapTypes.push_back(OMP_MAP_NONE); 8632 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8633 } 8634 const VarDecl *VD = CI.getCapturedVar(); 8635 auto I = FirstPrivateDecls.find(VD); 8636 if (I != FirstPrivateDecls.end()) 8637 IsImplicit = I->getSecond(); 8638 } else { 8639 assert(CI.capturesVariable() && "Expected captured reference."); 8640 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8641 QualType ElementType = PtrTy->getPointeeType(); 8642 CurSizes.push_back(CGF.Builder.CreateIntCast( 8643 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8644 // The default map type for a scalar/complex type is 'to' because by 8645 // default the value doesn't have to be retrieved. For an aggregate 8646 // type, the default is 'tofrom'. 8647 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8648 const VarDecl *VD = CI.getCapturedVar(); 8649 auto I = FirstPrivateDecls.find(VD); 8650 if (I != FirstPrivateDecls.end() && 8651 VD->getType().isConstant(CGF.getContext())) { 8652 llvm::Constant *Addr = 8653 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8654 // Copy the value of the original variable to the new global copy. 8655 CGF.Builder.CreateMemCpy( 8656 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(), 8657 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8658 CurSizes.back(), /*IsVolatile=*/false); 8659 // Use new global variable as the base pointers. 8660 CurBasePointers.push_back(Addr); 8661 CurPointers.push_back(Addr); 8662 } else { 8663 CurBasePointers.push_back(CV); 8664 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8665 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8666 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8667 AlignmentSource::Decl)); 8668 CurPointers.push_back(PtrAddr.getPointer()); 8669 } else { 8670 CurPointers.push_back(CV); 8671 } 8672 } 8673 if (I != FirstPrivateDecls.end()) 8674 IsImplicit = I->getSecond(); 8675 } 8676 // Every default map produces a single argument which is a target parameter. 8677 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8678 8679 // Add flag stating this is an implicit map. 8680 if (IsImplicit) 8681 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8682 } 8683 }; 8684 } // anonymous namespace 8685 8686 /// Emit the arrays used to pass the captures and map information to the 8687 /// offloading runtime library. If there is no map or capture information, 8688 /// return nullptr by reference. 8689 static void 8690 emitOffloadingArrays(CodeGenFunction &CGF, 8691 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8692 MappableExprsHandler::MapValuesArrayTy &Pointers, 8693 MappableExprsHandler::MapValuesArrayTy &Sizes, 8694 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8695 CGOpenMPRuntime::TargetDataInfo &Info) { 8696 CodeGenModule &CGM = CGF.CGM; 8697 ASTContext &Ctx = CGF.getContext(); 8698 8699 // Reset the array information. 8700 Info.clearArrayInfo(); 8701 Info.NumberOfPtrs = BasePointers.size(); 8702 8703 if (Info.NumberOfPtrs) { 8704 // Detect if we have any capture size requiring runtime evaluation of the 8705 // size so that a constant array could be eventually used. 8706 bool hasRuntimeEvaluationCaptureSize = false; 8707 for (llvm::Value *S : Sizes) 8708 if (!isa<llvm::Constant>(S)) { 8709 hasRuntimeEvaluationCaptureSize = true; 8710 break; 8711 } 8712 8713 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8714 QualType PointerArrayType = Ctx.getConstantArrayType( 8715 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8716 /*IndexTypeQuals=*/0); 8717 8718 Info.BasePointersArray = 8719 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8720 Info.PointersArray = 8721 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8722 8723 // If we don't have any VLA types or other types that require runtime 8724 // evaluation, we can use a constant array for the map sizes, otherwise we 8725 // need to fill up the arrays as we do for the pointers. 8726 QualType Int64Ty = 8727 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8728 if (hasRuntimeEvaluationCaptureSize) { 8729 QualType SizeArrayType = Ctx.getConstantArrayType( 8730 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8731 /*IndexTypeQuals=*/0); 8732 Info.SizesArray = 8733 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8734 } else { 8735 // We expect all the sizes to be constant, so we collect them to create 8736 // a constant array. 8737 SmallVector<llvm::Constant *, 16> ConstSizes; 8738 for (llvm::Value *S : Sizes) 8739 ConstSizes.push_back(cast<llvm::Constant>(S)); 8740 8741 auto *SizesArrayInit = llvm::ConstantArray::get( 8742 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8743 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8744 auto *SizesArrayGbl = new llvm::GlobalVariable( 8745 CGM.getModule(), SizesArrayInit->getType(), 8746 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8747 SizesArrayInit, Name); 8748 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8749 Info.SizesArray = SizesArrayGbl; 8750 } 8751 8752 // The map types are always constant so we don't need to generate code to 8753 // fill arrays. Instead, we create an array constant. 8754 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8755 llvm::copy(MapTypes, Mapping.begin()); 8756 llvm::Constant *MapTypesArrayInit = 8757 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8758 std::string MaptypesName = 8759 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8760 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8761 CGM.getModule(), MapTypesArrayInit->getType(), 8762 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8763 MapTypesArrayInit, MaptypesName); 8764 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8765 Info.MapTypesArray = MapTypesArrayGbl; 8766 8767 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8768 llvm::Value *BPVal = *BasePointers[I]; 8769 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8770 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8771 Info.BasePointersArray, 0, I); 8772 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8773 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8774 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8775 CGF.Builder.CreateStore(BPVal, BPAddr); 8776 8777 if (Info.requiresDevicePointerInfo()) 8778 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8779 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8780 8781 llvm::Value *PVal = Pointers[I]; 8782 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8783 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8784 Info.PointersArray, 0, I); 8785 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8786 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8787 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8788 CGF.Builder.CreateStore(PVal, PAddr); 8789 8790 if (hasRuntimeEvaluationCaptureSize) { 8791 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8792 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8793 Info.SizesArray, 8794 /*Idx0=*/0, 8795 /*Idx1=*/I); 8796 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8797 CGF.Builder.CreateStore( 8798 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8799 SAddr); 8800 } 8801 } 8802 } 8803 } 8804 8805 /// Emit the arguments to be passed to the runtime library based on the 8806 /// arrays of pointers, sizes and map types. 8807 static void emitOffloadingArraysArgument( 8808 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8809 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8810 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8811 CodeGenModule &CGM = CGF.CGM; 8812 if (Info.NumberOfPtrs) { 8813 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8814 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8815 Info.BasePointersArray, 8816 /*Idx0=*/0, /*Idx1=*/0); 8817 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8818 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8819 Info.PointersArray, 8820 /*Idx0=*/0, 8821 /*Idx1=*/0); 8822 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8823 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8824 /*Idx0=*/0, /*Idx1=*/0); 8825 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8826 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8827 Info.MapTypesArray, 8828 /*Idx0=*/0, 8829 /*Idx1=*/0); 8830 } else { 8831 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8832 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8833 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8834 MapTypesArrayArg = 8835 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8836 } 8837 } 8838 8839 /// Check for inner distribute directive. 8840 static const OMPExecutableDirective * 8841 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8842 const auto *CS = D.getInnermostCapturedStmt(); 8843 const auto *Body = 8844 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8845 const Stmt *ChildStmt = 8846 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8847 8848 if (const auto *NestedDir = 8849 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8850 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8851 switch (D.getDirectiveKind()) { 8852 case OMPD_target: 8853 if (isOpenMPDistributeDirective(DKind)) 8854 return NestedDir; 8855 if (DKind == OMPD_teams) { 8856 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8857 /*IgnoreCaptured=*/true); 8858 if (!Body) 8859 return nullptr; 8860 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8861 if (const auto *NND = 8862 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8863 DKind = NND->getDirectiveKind(); 8864 if (isOpenMPDistributeDirective(DKind)) 8865 return NND; 8866 } 8867 } 8868 return nullptr; 8869 case OMPD_target_teams: 8870 if (isOpenMPDistributeDirective(DKind)) 8871 return NestedDir; 8872 return nullptr; 8873 case OMPD_target_parallel: 8874 case OMPD_target_simd: 8875 case OMPD_target_parallel_for: 8876 case OMPD_target_parallel_for_simd: 8877 return nullptr; 8878 case OMPD_target_teams_distribute: 8879 case OMPD_target_teams_distribute_simd: 8880 case OMPD_target_teams_distribute_parallel_for: 8881 case OMPD_target_teams_distribute_parallel_for_simd: 8882 case OMPD_parallel: 8883 case OMPD_for: 8884 case OMPD_parallel_for: 8885 case OMPD_parallel_sections: 8886 case OMPD_for_simd: 8887 case OMPD_parallel_for_simd: 8888 case OMPD_cancel: 8889 case OMPD_cancellation_point: 8890 case OMPD_ordered: 8891 case OMPD_threadprivate: 8892 case OMPD_allocate: 8893 case OMPD_task: 8894 case OMPD_simd: 8895 case OMPD_sections: 8896 case OMPD_section: 8897 case OMPD_single: 8898 case OMPD_master: 8899 case OMPD_critical: 8900 case OMPD_taskyield: 8901 case OMPD_barrier: 8902 case OMPD_taskwait: 8903 case OMPD_taskgroup: 8904 case OMPD_atomic: 8905 case OMPD_flush: 8906 case OMPD_teams: 8907 case OMPD_target_data: 8908 case OMPD_target_exit_data: 8909 case OMPD_target_enter_data: 8910 case OMPD_distribute: 8911 case OMPD_distribute_simd: 8912 case OMPD_distribute_parallel_for: 8913 case OMPD_distribute_parallel_for_simd: 8914 case OMPD_teams_distribute: 8915 case OMPD_teams_distribute_simd: 8916 case OMPD_teams_distribute_parallel_for: 8917 case OMPD_teams_distribute_parallel_for_simd: 8918 case OMPD_target_update: 8919 case OMPD_declare_simd: 8920 case OMPD_declare_variant: 8921 case OMPD_declare_target: 8922 case OMPD_end_declare_target: 8923 case OMPD_declare_reduction: 8924 case OMPD_declare_mapper: 8925 case OMPD_taskloop: 8926 case OMPD_taskloop_simd: 8927 case OMPD_requires: 8928 case OMPD_unknown: 8929 llvm_unreachable("Unexpected directive."); 8930 } 8931 } 8932 8933 return nullptr; 8934 } 8935 8936 /// Emit the user-defined mapper function. The code generation follows the 8937 /// pattern in the example below. 8938 /// \code 8939 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 8940 /// void *base, void *begin, 8941 /// int64_t size, int64_t type) { 8942 /// // Allocate space for an array section first. 8943 /// if (size > 1 && !maptype.IsDelete) 8944 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8945 /// size*sizeof(Ty), clearToFrom(type)); 8946 /// // Map members. 8947 /// for (unsigned i = 0; i < size; i++) { 8948 /// // For each component specified by this mapper: 8949 /// for (auto c : all_components) { 8950 /// if (c.hasMapper()) 8951 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 8952 /// c.arg_type); 8953 /// else 8954 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 8955 /// c.arg_begin, c.arg_size, c.arg_type); 8956 /// } 8957 /// } 8958 /// // Delete the array section. 8959 /// if (size > 1 && maptype.IsDelete) 8960 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8961 /// size*sizeof(Ty), clearToFrom(type)); 8962 /// } 8963 /// \endcode 8964 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 8965 CodeGenFunction *CGF) { 8966 if (UDMMap.count(D) > 0) 8967 return; 8968 ASTContext &C = CGM.getContext(); 8969 QualType Ty = D->getType(); 8970 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 8971 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 8972 auto *MapperVarDecl = 8973 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 8974 SourceLocation Loc = D->getLocation(); 8975 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 8976 8977 // Prepare mapper function arguments and attributes. 8978 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8979 C.VoidPtrTy, ImplicitParamDecl::Other); 8980 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 8981 ImplicitParamDecl::Other); 8982 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8983 C.VoidPtrTy, ImplicitParamDecl::Other); 8984 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8985 ImplicitParamDecl::Other); 8986 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8987 ImplicitParamDecl::Other); 8988 FunctionArgList Args; 8989 Args.push_back(&HandleArg); 8990 Args.push_back(&BaseArg); 8991 Args.push_back(&BeginArg); 8992 Args.push_back(&SizeArg); 8993 Args.push_back(&TypeArg); 8994 const CGFunctionInfo &FnInfo = 8995 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 8996 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 8997 SmallString<64> TyStr; 8998 llvm::raw_svector_ostream Out(TyStr); 8999 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 9000 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 9001 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 9002 Name, &CGM.getModule()); 9003 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 9004 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 9005 // Start the mapper function code generation. 9006 CodeGenFunction MapperCGF(CGM); 9007 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 9008 // Compute the starting and end addreses of array elements. 9009 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 9010 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 9011 C.getPointerType(Int64Ty), Loc); 9012 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 9013 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 9014 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 9015 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 9016 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 9017 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 9018 C.getPointerType(Int64Ty), Loc); 9019 // Prepare common arguments for array initiation and deletion. 9020 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 9021 MapperCGF.GetAddrOfLocalVar(&HandleArg), 9022 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9023 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 9024 MapperCGF.GetAddrOfLocalVar(&BaseArg), 9025 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9026 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 9027 MapperCGF.GetAddrOfLocalVar(&BeginArg), 9028 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9029 9030 // Emit array initiation if this is an array section and \p MapType indicates 9031 // that memory allocation is required. 9032 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 9033 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9034 ElementSize, HeadBB, /*IsInit=*/true); 9035 9036 // Emit a for loop to iterate through SizeArg of elements and map all of them. 9037 9038 // Emit the loop header block. 9039 MapperCGF.EmitBlock(HeadBB); 9040 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 9041 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 9042 // Evaluate whether the initial condition is satisfied. 9043 llvm::Value *IsEmpty = 9044 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 9045 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 9046 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 9047 9048 // Emit the loop body block. 9049 MapperCGF.EmitBlock(BodyBB); 9050 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 9051 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 9052 PtrPHI->addIncoming(PtrBegin, EntryBB); 9053 Address PtrCurrent = 9054 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 9055 .getAlignment() 9056 .alignmentOfArrayElement(ElementSize)); 9057 // Privatize the declared variable of mapper to be the current array element. 9058 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 9059 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 9060 return MapperCGF 9061 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 9062 .getAddress(); 9063 }); 9064 (void)Scope.Privatize(); 9065 9066 // Get map clause information. Fill up the arrays with all mapped variables. 9067 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9068 MappableExprsHandler::MapValuesArrayTy Pointers; 9069 MappableExprsHandler::MapValuesArrayTy Sizes; 9070 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9071 MappableExprsHandler MEHandler(*D, MapperCGF); 9072 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 9073 9074 // Call the runtime API __tgt_mapper_num_components to get the number of 9075 // pre-existing components. 9076 llvm::Value *OffloadingArgs[] = {Handle}; 9077 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 9078 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 9079 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 9080 PreviousSize, 9081 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 9082 9083 // Fill up the runtime mapper handle for all components. 9084 for (unsigned I = 0; I < BasePointers.size(); ++I) { 9085 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 9086 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9087 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 9088 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9089 llvm::Value *CurSizeArg = Sizes[I]; 9090 9091 // Extract the MEMBER_OF field from the map type. 9092 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 9093 MapperCGF.EmitBlock(MemberBB); 9094 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 9095 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 9096 OriMapType, 9097 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 9098 llvm::BasicBlock *MemberCombineBB = 9099 MapperCGF.createBasicBlock("omp.member.combine"); 9100 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 9101 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 9102 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 9103 // Add the number of pre-existing components to the MEMBER_OF field if it 9104 // is valid. 9105 MapperCGF.EmitBlock(MemberCombineBB); 9106 llvm::Value *CombinedMember = 9107 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 9108 // Do nothing if it is not a member of previous components. 9109 MapperCGF.EmitBlock(TypeBB); 9110 llvm::PHINode *MemberMapType = 9111 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 9112 MemberMapType->addIncoming(OriMapType, MemberBB); 9113 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 9114 9115 // Combine the map type inherited from user-defined mapper with that 9116 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9117 // bits of the \a MapType, which is the input argument of the mapper 9118 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9119 // bits of MemberMapType. 9120 // [OpenMP 5.0], 1.2.6. map-type decay. 9121 // | alloc | to | from | tofrom | release | delete 9122 // ---------------------------------------------------------- 9123 // alloc | alloc | alloc | alloc | alloc | release | delete 9124 // to | alloc | to | alloc | to | release | delete 9125 // from | alloc | alloc | from | from | release | delete 9126 // tofrom | alloc | to | from | tofrom | release | delete 9127 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9128 MapType, 9129 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9130 MappableExprsHandler::OMP_MAP_FROM)); 9131 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9132 llvm::BasicBlock *AllocElseBB = 9133 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9134 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9135 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9136 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9137 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9138 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9139 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9140 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9141 MapperCGF.EmitBlock(AllocBB); 9142 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9143 MemberMapType, 9144 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9145 MappableExprsHandler::OMP_MAP_FROM))); 9146 MapperCGF.Builder.CreateBr(EndBB); 9147 MapperCGF.EmitBlock(AllocElseBB); 9148 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9149 LeftToFrom, 9150 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9151 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9152 // In case of to, clear OMP_MAP_FROM. 9153 MapperCGF.EmitBlock(ToBB); 9154 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9155 MemberMapType, 9156 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9157 MapperCGF.Builder.CreateBr(EndBB); 9158 MapperCGF.EmitBlock(ToElseBB); 9159 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9160 LeftToFrom, 9161 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9162 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9163 // In case of from, clear OMP_MAP_TO. 9164 MapperCGF.EmitBlock(FromBB); 9165 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9166 MemberMapType, 9167 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9168 // In case of tofrom, do nothing. 9169 MapperCGF.EmitBlock(EndBB); 9170 llvm::PHINode *CurMapType = 9171 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9172 CurMapType->addIncoming(AllocMapType, AllocBB); 9173 CurMapType->addIncoming(ToMapType, ToBB); 9174 CurMapType->addIncoming(FromMapType, FromBB); 9175 CurMapType->addIncoming(MemberMapType, ToElseBB); 9176 9177 // TODO: call the corresponding mapper function if a user-defined mapper is 9178 // associated with this map clause. 9179 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9180 // data structure. 9181 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9182 CurSizeArg, CurMapType}; 9183 MapperCGF.EmitRuntimeCall( 9184 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9185 OffloadingArgs); 9186 } 9187 9188 // Update the pointer to point to the next element that needs to be mapped, 9189 // and check whether we have mapped all elements. 9190 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9191 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9192 PtrPHI->addIncoming(PtrNext, BodyBB); 9193 llvm::Value *IsDone = 9194 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9195 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9196 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9197 9198 MapperCGF.EmitBlock(ExitBB); 9199 // Emit array deletion if this is an array section and \p MapType indicates 9200 // that deletion is required. 9201 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9202 ElementSize, DoneBB, /*IsInit=*/false); 9203 9204 // Emit the function exit block. 9205 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9206 MapperCGF.FinishFunction(); 9207 UDMMap.try_emplace(D, Fn); 9208 if (CGF) { 9209 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9210 Decls.second.push_back(D); 9211 } 9212 } 9213 9214 /// Emit the array initialization or deletion portion for user-defined mapper 9215 /// code generation. First, it evaluates whether an array section is mapped and 9216 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9217 /// true, and \a MapType indicates to not delete this array, array 9218 /// initialization code is generated. If \a IsInit is false, and \a MapType 9219 /// indicates to not this array, array deletion code is generated. 9220 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9221 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9222 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9223 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9224 StringRef Prefix = IsInit ? ".init" : ".del"; 9225 9226 // Evaluate if this is an array section. 9227 llvm::BasicBlock *IsDeleteBB = 9228 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete"); 9229 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix); 9230 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9231 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9232 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9233 9234 // Evaluate if we are going to delete this section. 9235 MapperCGF.EmitBlock(IsDeleteBB); 9236 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9237 MapType, 9238 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9239 llvm::Value *DeleteCond; 9240 if (IsInit) { 9241 DeleteCond = MapperCGF.Builder.CreateIsNull( 9242 DeleteBit, "omp.array" + Prefix + ".delete"); 9243 } else { 9244 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9245 DeleteBit, "omp.array" + Prefix + ".delete"); 9246 } 9247 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9248 9249 MapperCGF.EmitBlock(BodyBB); 9250 // Get the array size by multiplying element size and element number (i.e., \p 9251 // Size). 9252 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9253 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9254 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9255 // memory allocation/deletion purpose only. 9256 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9257 MapType, 9258 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9259 MappableExprsHandler::OMP_MAP_FROM))); 9260 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9261 // data structure. 9262 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9263 MapperCGF.EmitRuntimeCall( 9264 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9265 } 9266 9267 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9268 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9269 llvm::Value *DeviceID, 9270 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9271 const OMPLoopDirective &D)> 9272 SizeEmitter) { 9273 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9274 const OMPExecutableDirective *TD = &D; 9275 // Get nested teams distribute kind directive, if any. 9276 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9277 TD = getNestedDistributeDirective(CGM.getContext(), D); 9278 if (!TD) 9279 return; 9280 const auto *LD = cast<OMPLoopDirective>(TD); 9281 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9282 PrePostActionTy &) { 9283 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9284 llvm::Value *Args[] = {DeviceID, NumIterations}; 9285 CGF.EmitRuntimeCall( 9286 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9287 } 9288 }; 9289 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9290 } 9291 9292 void CGOpenMPRuntime::emitTargetCall( 9293 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9294 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9295 const Expr *Device, 9296 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9297 const OMPLoopDirective &D)> 9298 SizeEmitter) { 9299 if (!CGF.HaveInsertPoint()) 9300 return; 9301 9302 assert(OutlinedFn && "Invalid outlined function!"); 9303 9304 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9305 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9306 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9307 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9308 PrePostActionTy &) { 9309 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9310 }; 9311 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9312 9313 CodeGenFunction::OMPTargetDataInfo InputInfo; 9314 llvm::Value *MapTypesArray = nullptr; 9315 // Fill up the pointer arrays and transfer execution to the device. 9316 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9317 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9318 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9319 // On top of the arrays that were filled up, the target offloading call 9320 // takes as arguments the device id as well as the host pointer. The host 9321 // pointer is used by the runtime library to identify the current target 9322 // region, so it only has to be unique and not necessarily point to 9323 // anything. It could be the pointer to the outlined function that 9324 // implements the target region, but we aren't using that so that the 9325 // compiler doesn't need to keep that, and could therefore inline the host 9326 // function if proven worthwhile during optimization. 9327 9328 // From this point on, we need to have an ID of the target region defined. 9329 assert(OutlinedFnID && "Invalid outlined function ID!"); 9330 9331 // Emit device ID if any. 9332 llvm::Value *DeviceID; 9333 if (Device) { 9334 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9335 CGF.Int64Ty, /*isSigned=*/true); 9336 } else { 9337 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9338 } 9339 9340 // Emit the number of elements in the offloading arrays. 9341 llvm::Value *PointerNum = 9342 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9343 9344 // Return value of the runtime offloading call. 9345 llvm::Value *Return; 9346 9347 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9348 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9349 9350 // Emit tripcount for the target loop-based directive. 9351 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9352 9353 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9354 // The target region is an outlined function launched by the runtime 9355 // via calls __tgt_target() or __tgt_target_teams(). 9356 // 9357 // __tgt_target() launches a target region with one team and one thread, 9358 // executing a serial region. This master thread may in turn launch 9359 // more threads within its team upon encountering a parallel region, 9360 // however, no additional teams can be launched on the device. 9361 // 9362 // __tgt_target_teams() launches a target region with one or more teams, 9363 // each with one or more threads. This call is required for target 9364 // constructs such as: 9365 // 'target teams' 9366 // 'target' / 'teams' 9367 // 'target teams distribute parallel for' 9368 // 'target parallel' 9369 // and so on. 9370 // 9371 // Note that on the host and CPU targets, the runtime implementation of 9372 // these calls simply call the outlined function without forking threads. 9373 // The outlined functions themselves have runtime calls to 9374 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9375 // the compiler in emitTeamsCall() and emitParallelCall(). 9376 // 9377 // In contrast, on the NVPTX target, the implementation of 9378 // __tgt_target_teams() launches a GPU kernel with the requested number 9379 // of teams and threads so no additional calls to the runtime are required. 9380 if (NumTeams) { 9381 // If we have NumTeams defined this means that we have an enclosed teams 9382 // region. Therefore we also expect to have NumThreads defined. These two 9383 // values should be defined in the presence of a teams directive, 9384 // regardless of having any clauses associated. If the user is using teams 9385 // but no clauses, these two values will be the default that should be 9386 // passed to the runtime library - a 32-bit integer with the value zero. 9387 assert(NumThreads && "Thread limit expression should be available along " 9388 "with number of teams."); 9389 llvm::Value *OffloadingArgs[] = {DeviceID, 9390 OutlinedFnID, 9391 PointerNum, 9392 InputInfo.BasePointersArray.getPointer(), 9393 InputInfo.PointersArray.getPointer(), 9394 InputInfo.SizesArray.getPointer(), 9395 MapTypesArray, 9396 NumTeams, 9397 NumThreads}; 9398 Return = CGF.EmitRuntimeCall( 9399 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9400 : OMPRTL__tgt_target_teams), 9401 OffloadingArgs); 9402 } else { 9403 llvm::Value *OffloadingArgs[] = {DeviceID, 9404 OutlinedFnID, 9405 PointerNum, 9406 InputInfo.BasePointersArray.getPointer(), 9407 InputInfo.PointersArray.getPointer(), 9408 InputInfo.SizesArray.getPointer(), 9409 MapTypesArray}; 9410 Return = CGF.EmitRuntimeCall( 9411 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9412 : OMPRTL__tgt_target), 9413 OffloadingArgs); 9414 } 9415 9416 // Check the error code and execute the host version if required. 9417 llvm::BasicBlock *OffloadFailedBlock = 9418 CGF.createBasicBlock("omp_offload.failed"); 9419 llvm::BasicBlock *OffloadContBlock = 9420 CGF.createBasicBlock("omp_offload.cont"); 9421 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9422 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9423 9424 CGF.EmitBlock(OffloadFailedBlock); 9425 if (RequiresOuterTask) { 9426 CapturedVars.clear(); 9427 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9428 } 9429 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9430 CGF.EmitBranch(OffloadContBlock); 9431 9432 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9433 }; 9434 9435 // Notify that the host version must be executed. 9436 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9437 RequiresOuterTask](CodeGenFunction &CGF, 9438 PrePostActionTy &) { 9439 if (RequiresOuterTask) { 9440 CapturedVars.clear(); 9441 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9442 } 9443 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9444 }; 9445 9446 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9447 &CapturedVars, RequiresOuterTask, 9448 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9449 // Fill up the arrays with all the captured variables. 9450 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9451 MappableExprsHandler::MapValuesArrayTy Pointers; 9452 MappableExprsHandler::MapValuesArrayTy Sizes; 9453 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9454 9455 // Get mappable expression information. 9456 MappableExprsHandler MEHandler(D, CGF); 9457 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9458 9459 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9460 auto CV = CapturedVars.begin(); 9461 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9462 CE = CS.capture_end(); 9463 CI != CE; ++CI, ++RI, ++CV) { 9464 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9465 MappableExprsHandler::MapValuesArrayTy CurPointers; 9466 MappableExprsHandler::MapValuesArrayTy CurSizes; 9467 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9468 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9469 9470 // VLA sizes are passed to the outlined region by copy and do not have map 9471 // information associated. 9472 if (CI->capturesVariableArrayType()) { 9473 CurBasePointers.push_back(*CV); 9474 CurPointers.push_back(*CV); 9475 CurSizes.push_back(CGF.Builder.CreateIntCast( 9476 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9477 // Copy to the device as an argument. No need to retrieve it. 9478 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9479 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9480 MappableExprsHandler::OMP_MAP_IMPLICIT); 9481 } else { 9482 // If we have any information in the map clause, we use it, otherwise we 9483 // just do a default mapping. 9484 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9485 CurSizes, CurMapTypes, PartialStruct); 9486 if (CurBasePointers.empty()) 9487 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9488 CurPointers, CurSizes, CurMapTypes); 9489 // Generate correct mapping for variables captured by reference in 9490 // lambdas. 9491 if (CI->capturesVariable()) 9492 MEHandler.generateInfoForLambdaCaptures( 9493 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9494 CurMapTypes, LambdaPointers); 9495 } 9496 // We expect to have at least an element of information for this capture. 9497 assert(!CurBasePointers.empty() && 9498 "Non-existing map pointer for capture!"); 9499 assert(CurBasePointers.size() == CurPointers.size() && 9500 CurBasePointers.size() == CurSizes.size() && 9501 CurBasePointers.size() == CurMapTypes.size() && 9502 "Inconsistent map information sizes!"); 9503 9504 // If there is an entry in PartialStruct it means we have a struct with 9505 // individual members mapped. Emit an extra combined entry. 9506 if (PartialStruct.Base.isValid()) 9507 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9508 CurMapTypes, PartialStruct); 9509 9510 // We need to append the results of this capture to what we already have. 9511 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9512 Pointers.append(CurPointers.begin(), CurPointers.end()); 9513 Sizes.append(CurSizes.begin(), CurSizes.end()); 9514 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9515 } 9516 // Adjust MEMBER_OF flags for the lambdas captures. 9517 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9518 Pointers, MapTypes); 9519 // Map other list items in the map clause which are not captured variables 9520 // but "declare target link" global variables. 9521 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9522 MapTypes); 9523 9524 TargetDataInfo Info; 9525 // Fill up the arrays and create the arguments. 9526 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9527 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9528 Info.PointersArray, Info.SizesArray, 9529 Info.MapTypesArray, Info); 9530 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9531 InputInfo.BasePointersArray = 9532 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9533 InputInfo.PointersArray = 9534 Address(Info.PointersArray, CGM.getPointerAlign()); 9535 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9536 MapTypesArray = Info.MapTypesArray; 9537 if (RequiresOuterTask) 9538 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9539 else 9540 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9541 }; 9542 9543 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9544 CodeGenFunction &CGF, PrePostActionTy &) { 9545 if (RequiresOuterTask) { 9546 CodeGenFunction::OMPTargetDataInfo InputInfo; 9547 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9548 } else { 9549 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9550 } 9551 }; 9552 9553 // If we have a target function ID it means that we need to support 9554 // offloading, otherwise, just execute on the host. We need to execute on host 9555 // regardless of the conditional in the if clause if, e.g., the user do not 9556 // specify target triples. 9557 if (OutlinedFnID) { 9558 if (IfCond) { 9559 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9560 } else { 9561 RegionCodeGenTy ThenRCG(TargetThenGen); 9562 ThenRCG(CGF); 9563 } 9564 } else { 9565 RegionCodeGenTy ElseRCG(TargetElseGen); 9566 ElseRCG(CGF); 9567 } 9568 } 9569 9570 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9571 StringRef ParentName) { 9572 if (!S) 9573 return; 9574 9575 // Codegen OMP target directives that offload compute to the device. 9576 bool RequiresDeviceCodegen = 9577 isa<OMPExecutableDirective>(S) && 9578 isOpenMPTargetExecutionDirective( 9579 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9580 9581 if (RequiresDeviceCodegen) { 9582 const auto &E = *cast<OMPExecutableDirective>(S); 9583 unsigned DeviceID; 9584 unsigned FileID; 9585 unsigned Line; 9586 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9587 FileID, Line); 9588 9589 // Is this a target region that should not be emitted as an entry point? If 9590 // so just signal we are done with this target region. 9591 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9592 ParentName, Line)) 9593 return; 9594 9595 switch (E.getDirectiveKind()) { 9596 case OMPD_target: 9597 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9598 cast<OMPTargetDirective>(E)); 9599 break; 9600 case OMPD_target_parallel: 9601 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9602 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9603 break; 9604 case OMPD_target_teams: 9605 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9606 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9607 break; 9608 case OMPD_target_teams_distribute: 9609 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9610 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9611 break; 9612 case OMPD_target_teams_distribute_simd: 9613 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9614 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9615 break; 9616 case OMPD_target_parallel_for: 9617 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9618 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9619 break; 9620 case OMPD_target_parallel_for_simd: 9621 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9622 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9623 break; 9624 case OMPD_target_simd: 9625 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9626 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9627 break; 9628 case OMPD_target_teams_distribute_parallel_for: 9629 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9630 CGM, ParentName, 9631 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9632 break; 9633 case OMPD_target_teams_distribute_parallel_for_simd: 9634 CodeGenFunction:: 9635 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9636 CGM, ParentName, 9637 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9638 break; 9639 case OMPD_parallel: 9640 case OMPD_for: 9641 case OMPD_parallel_for: 9642 case OMPD_parallel_sections: 9643 case OMPD_for_simd: 9644 case OMPD_parallel_for_simd: 9645 case OMPD_cancel: 9646 case OMPD_cancellation_point: 9647 case OMPD_ordered: 9648 case OMPD_threadprivate: 9649 case OMPD_allocate: 9650 case OMPD_task: 9651 case OMPD_simd: 9652 case OMPD_sections: 9653 case OMPD_section: 9654 case OMPD_single: 9655 case OMPD_master: 9656 case OMPD_critical: 9657 case OMPD_taskyield: 9658 case OMPD_barrier: 9659 case OMPD_taskwait: 9660 case OMPD_taskgroup: 9661 case OMPD_atomic: 9662 case OMPD_flush: 9663 case OMPD_teams: 9664 case OMPD_target_data: 9665 case OMPD_target_exit_data: 9666 case OMPD_target_enter_data: 9667 case OMPD_distribute: 9668 case OMPD_distribute_simd: 9669 case OMPD_distribute_parallel_for: 9670 case OMPD_distribute_parallel_for_simd: 9671 case OMPD_teams_distribute: 9672 case OMPD_teams_distribute_simd: 9673 case OMPD_teams_distribute_parallel_for: 9674 case OMPD_teams_distribute_parallel_for_simd: 9675 case OMPD_target_update: 9676 case OMPD_declare_simd: 9677 case OMPD_declare_variant: 9678 case OMPD_declare_target: 9679 case OMPD_end_declare_target: 9680 case OMPD_declare_reduction: 9681 case OMPD_declare_mapper: 9682 case OMPD_taskloop: 9683 case OMPD_taskloop_simd: 9684 case OMPD_requires: 9685 case OMPD_unknown: 9686 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9687 } 9688 return; 9689 } 9690 9691 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9692 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9693 return; 9694 9695 scanForTargetRegionsFunctions( 9696 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9697 return; 9698 } 9699 9700 // If this is a lambda function, look into its body. 9701 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9702 S = L->getBody(); 9703 9704 // Keep looking for target regions recursively. 9705 for (const Stmt *II : S->children()) 9706 scanForTargetRegionsFunctions(II, ParentName); 9707 } 9708 9709 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9710 // If emitting code for the host, we do not process FD here. Instead we do 9711 // the normal code generation. 9712 if (!CGM.getLangOpts().OpenMPIsDevice) { 9713 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9714 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9715 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9716 // Do not emit device_type(nohost) functions for the host. 9717 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9718 return true; 9719 } 9720 return false; 9721 } 9722 9723 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9724 StringRef Name = CGM.getMangledName(GD); 9725 // Try to detect target regions in the function. 9726 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9727 scanForTargetRegionsFunctions(FD->getBody(), Name); 9728 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9729 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9730 // Do not emit device_type(nohost) functions for the host. 9731 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9732 return true; 9733 } 9734 9735 // Do not to emit function if it is not marked as declare target. 9736 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9737 AlreadyEmittedTargetFunctions.count(Name) == 0; 9738 } 9739 9740 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9741 if (!CGM.getLangOpts().OpenMPIsDevice) 9742 return false; 9743 9744 // Check if there are Ctors/Dtors in this declaration and look for target 9745 // regions in it. We use the complete variant to produce the kernel name 9746 // mangling. 9747 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9748 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9749 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9750 StringRef ParentName = 9751 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9752 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9753 } 9754 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9755 StringRef ParentName = 9756 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9757 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9758 } 9759 } 9760 9761 // Do not to emit variable if it is not marked as declare target. 9762 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9763 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9764 cast<VarDecl>(GD.getDecl())); 9765 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9766 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9767 HasRequiresUnifiedSharedMemory)) { 9768 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9769 return true; 9770 } 9771 return false; 9772 } 9773 9774 llvm::Constant * 9775 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9776 const VarDecl *VD) { 9777 assert(VD->getType().isConstant(CGM.getContext()) && 9778 "Expected constant variable."); 9779 StringRef VarName; 9780 llvm::Constant *Addr; 9781 llvm::GlobalValue::LinkageTypes Linkage; 9782 QualType Ty = VD->getType(); 9783 SmallString<128> Buffer; 9784 { 9785 unsigned DeviceID; 9786 unsigned FileID; 9787 unsigned Line; 9788 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9789 FileID, Line); 9790 llvm::raw_svector_ostream OS(Buffer); 9791 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9792 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9793 VarName = OS.str(); 9794 } 9795 Linkage = llvm::GlobalValue::InternalLinkage; 9796 Addr = 9797 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9798 getDefaultFirstprivateAddressSpace()); 9799 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9800 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9801 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9802 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9803 VarName, Addr, VarSize, 9804 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9805 return Addr; 9806 } 9807 9808 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9809 llvm::Constant *Addr) { 9810 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9811 !CGM.getLangOpts().OpenMPIsDevice) 9812 return; 9813 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9814 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9815 if (!Res) { 9816 if (CGM.getLangOpts().OpenMPIsDevice) { 9817 // Register non-target variables being emitted in device code (debug info 9818 // may cause this). 9819 StringRef VarName = CGM.getMangledName(VD); 9820 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9821 } 9822 return; 9823 } 9824 // Register declare target variables. 9825 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9826 StringRef VarName; 9827 CharUnits VarSize; 9828 llvm::GlobalValue::LinkageTypes Linkage; 9829 9830 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9831 !HasRequiresUnifiedSharedMemory) { 9832 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9833 VarName = CGM.getMangledName(VD); 9834 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9835 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9836 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9837 } else { 9838 VarSize = CharUnits::Zero(); 9839 } 9840 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9841 // Temp solution to prevent optimizations of the internal variables. 9842 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9843 std::string RefName = getName({VarName, "ref"}); 9844 if (!CGM.GetGlobalValue(RefName)) { 9845 llvm::Constant *AddrRef = 9846 getOrCreateInternalVariable(Addr->getType(), RefName); 9847 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9848 GVAddrRef->setConstant(/*Val=*/true); 9849 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9850 GVAddrRef->setInitializer(Addr); 9851 CGM.addCompilerUsedGlobal(GVAddrRef); 9852 } 9853 } 9854 } else { 9855 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9856 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9857 HasRequiresUnifiedSharedMemory)) && 9858 "Declare target attribute must link or to with unified memory."); 9859 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9860 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9861 else 9862 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9863 9864 if (CGM.getLangOpts().OpenMPIsDevice) { 9865 VarName = Addr->getName(); 9866 Addr = nullptr; 9867 } else { 9868 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9869 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9870 } 9871 VarSize = CGM.getPointerSize(); 9872 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9873 } 9874 9875 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9876 VarName, Addr, VarSize, Flags, Linkage); 9877 } 9878 9879 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9880 if (isa<FunctionDecl>(GD.getDecl()) || 9881 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9882 return emitTargetFunctions(GD); 9883 9884 return emitTargetGlobalVariable(GD); 9885 } 9886 9887 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9888 for (const VarDecl *VD : DeferredGlobalVariables) { 9889 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9890 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9891 if (!Res) 9892 continue; 9893 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9894 !HasRequiresUnifiedSharedMemory) { 9895 CGM.EmitGlobal(VD); 9896 } else { 9897 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 9898 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9899 HasRequiresUnifiedSharedMemory)) && 9900 "Expected link clause or to clause with unified memory."); 9901 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 9902 } 9903 } 9904 } 9905 9906 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9907 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9908 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9909 " Expected target-based directive."); 9910 } 9911 9912 void CGOpenMPRuntime::checkArchForUnifiedAddressing( 9913 const OMPRequiresDecl *D) { 9914 for (const OMPClause *Clause : D->clauselists()) { 9915 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9916 HasRequiresUnifiedSharedMemory = true; 9917 break; 9918 } 9919 } 9920 } 9921 9922 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9923 LangAS &AS) { 9924 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9925 return false; 9926 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9927 switch(A->getAllocatorType()) { 9928 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9929 // Not supported, fallback to the default mem space. 9930 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9931 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9932 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9933 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9934 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9935 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9936 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9937 AS = LangAS::Default; 9938 return true; 9939 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9940 llvm_unreachable("Expected predefined allocator for the variables with the " 9941 "static storage."); 9942 } 9943 return false; 9944 } 9945 9946 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9947 return HasRequiresUnifiedSharedMemory; 9948 } 9949 9950 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9951 CodeGenModule &CGM) 9952 : CGM(CGM) { 9953 if (CGM.getLangOpts().OpenMPIsDevice) { 9954 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9955 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9956 } 9957 } 9958 9959 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9960 if (CGM.getLangOpts().OpenMPIsDevice) 9961 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9962 } 9963 9964 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9965 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9966 return true; 9967 9968 StringRef Name = CGM.getMangledName(GD); 9969 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9970 // Do not to emit function if it is marked as declare target as it was already 9971 // emitted. 9972 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9973 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) { 9974 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name))) 9975 return !F->isDeclaration(); 9976 return false; 9977 } 9978 return true; 9979 } 9980 9981 return !AlreadyEmittedTargetFunctions.insert(Name).second; 9982 } 9983 9984 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9985 // If we don't have entries or if we are emitting code for the device, we 9986 // don't need to do anything. 9987 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9988 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9989 (OffloadEntriesInfoManager.empty() && 9990 !HasEmittedDeclareTargetRegion && 9991 !HasEmittedTargetRegion)) 9992 return nullptr; 9993 9994 // Create and register the function that handles the requires directives. 9995 ASTContext &C = CGM.getContext(); 9996 9997 llvm::Function *RequiresRegFn; 9998 { 9999 CodeGenFunction CGF(CGM); 10000 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 10001 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 10002 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 10003 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 10004 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 10005 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 10006 // TODO: check for other requires clauses. 10007 // The requires directive takes effect only when a target region is 10008 // present in the compilation unit. Otherwise it is ignored and not 10009 // passed to the runtime. This avoids the runtime from throwing an error 10010 // for mismatching requires clauses across compilation units that don't 10011 // contain at least 1 target region. 10012 assert((HasEmittedTargetRegion || 10013 HasEmittedDeclareTargetRegion || 10014 !OffloadEntriesInfoManager.empty()) && 10015 "Target or declare target region expected."); 10016 if (HasRequiresUnifiedSharedMemory) 10017 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 10018 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 10019 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 10020 CGF.FinishFunction(); 10021 } 10022 return RequiresRegFn; 10023 } 10024 10025 llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() { 10026 // If we have offloading in the current module, we need to emit the entries 10027 // now and register the offloading descriptor. 10028 createOffloadEntriesAndInfoMetadata(); 10029 10030 // Create and register the offloading binary descriptors. This is the main 10031 // entity that captures all the information about offloading in the current 10032 // compilation unit. 10033 return createOffloadingBinaryDescriptorRegistration(); 10034 } 10035 10036 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 10037 const OMPExecutableDirective &D, 10038 SourceLocation Loc, 10039 llvm::Function *OutlinedFn, 10040 ArrayRef<llvm::Value *> CapturedVars) { 10041 if (!CGF.HaveInsertPoint()) 10042 return; 10043 10044 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10045 CodeGenFunction::RunCleanupsScope Scope(CGF); 10046 10047 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 10048 llvm::Value *Args[] = { 10049 RTLoc, 10050 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 10051 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 10052 llvm::SmallVector<llvm::Value *, 16> RealArgs; 10053 RealArgs.append(std::begin(Args), std::end(Args)); 10054 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 10055 10056 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 10057 CGF.EmitRuntimeCall(RTLFn, RealArgs); 10058 } 10059 10060 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 10061 const Expr *NumTeams, 10062 const Expr *ThreadLimit, 10063 SourceLocation Loc) { 10064 if (!CGF.HaveInsertPoint()) 10065 return; 10066 10067 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10068 10069 llvm::Value *NumTeamsVal = 10070 NumTeams 10071 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 10072 CGF.CGM.Int32Ty, /* isSigned = */ true) 10073 : CGF.Builder.getInt32(0); 10074 10075 llvm::Value *ThreadLimitVal = 10076 ThreadLimit 10077 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 10078 CGF.CGM.Int32Ty, /* isSigned = */ true) 10079 : CGF.Builder.getInt32(0); 10080 10081 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 10082 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 10083 ThreadLimitVal}; 10084 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 10085 PushNumTeamsArgs); 10086 } 10087 10088 void CGOpenMPRuntime::emitTargetDataCalls( 10089 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10090 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 10091 if (!CGF.HaveInsertPoint()) 10092 return; 10093 10094 // Action used to replace the default codegen action and turn privatization 10095 // off. 10096 PrePostActionTy NoPrivAction; 10097 10098 // Generate the code for the opening of the data environment. Capture all the 10099 // arguments of the runtime call by reference because they are used in the 10100 // closing of the region. 10101 auto &&BeginThenGen = [this, &D, Device, &Info, 10102 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 10103 // Fill up the arrays with all the mapped variables. 10104 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10105 MappableExprsHandler::MapValuesArrayTy Pointers; 10106 MappableExprsHandler::MapValuesArrayTy Sizes; 10107 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10108 10109 // Get map clause information. 10110 MappableExprsHandler MCHandler(D, CGF); 10111 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10112 10113 // Fill up the arrays and create the arguments. 10114 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10115 10116 llvm::Value *BasePointersArrayArg = nullptr; 10117 llvm::Value *PointersArrayArg = nullptr; 10118 llvm::Value *SizesArrayArg = nullptr; 10119 llvm::Value *MapTypesArrayArg = nullptr; 10120 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10121 SizesArrayArg, MapTypesArrayArg, Info); 10122 10123 // Emit device ID if any. 10124 llvm::Value *DeviceID = nullptr; 10125 if (Device) { 10126 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10127 CGF.Int64Ty, /*isSigned=*/true); 10128 } else { 10129 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10130 } 10131 10132 // Emit the number of elements in the offloading arrays. 10133 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10134 10135 llvm::Value *OffloadingArgs[] = { 10136 DeviceID, PointerNum, BasePointersArrayArg, 10137 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10138 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 10139 OffloadingArgs); 10140 10141 // If device pointer privatization is required, emit the body of the region 10142 // here. It will have to be duplicated: with and without privatization. 10143 if (!Info.CaptureDeviceAddrMap.empty()) 10144 CodeGen(CGF); 10145 }; 10146 10147 // Generate code for the closing of the data region. 10148 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10149 PrePostActionTy &) { 10150 assert(Info.isValid() && "Invalid data environment closing arguments."); 10151 10152 llvm::Value *BasePointersArrayArg = nullptr; 10153 llvm::Value *PointersArrayArg = nullptr; 10154 llvm::Value *SizesArrayArg = nullptr; 10155 llvm::Value *MapTypesArrayArg = nullptr; 10156 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10157 SizesArrayArg, MapTypesArrayArg, Info); 10158 10159 // Emit device ID if any. 10160 llvm::Value *DeviceID = nullptr; 10161 if (Device) { 10162 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10163 CGF.Int64Ty, /*isSigned=*/true); 10164 } else { 10165 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10166 } 10167 10168 // Emit the number of elements in the offloading arrays. 10169 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10170 10171 llvm::Value *OffloadingArgs[] = { 10172 DeviceID, PointerNum, BasePointersArrayArg, 10173 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10174 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10175 OffloadingArgs); 10176 }; 10177 10178 // If we need device pointer privatization, we need to emit the body of the 10179 // region with no privatization in the 'else' branch of the conditional. 10180 // Otherwise, we don't have to do anything. 10181 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10182 PrePostActionTy &) { 10183 if (!Info.CaptureDeviceAddrMap.empty()) { 10184 CodeGen.setAction(NoPrivAction); 10185 CodeGen(CGF); 10186 } 10187 }; 10188 10189 // We don't have to do anything to close the region if the if clause evaluates 10190 // to false. 10191 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10192 10193 if (IfCond) { 10194 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10195 } else { 10196 RegionCodeGenTy RCG(BeginThenGen); 10197 RCG(CGF); 10198 } 10199 10200 // If we don't require privatization of device pointers, we emit the body in 10201 // between the runtime calls. This avoids duplicating the body code. 10202 if (Info.CaptureDeviceAddrMap.empty()) { 10203 CodeGen.setAction(NoPrivAction); 10204 CodeGen(CGF); 10205 } 10206 10207 if (IfCond) { 10208 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10209 } else { 10210 RegionCodeGenTy RCG(EndThenGen); 10211 RCG(CGF); 10212 } 10213 } 10214 10215 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10216 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10217 const Expr *Device) { 10218 if (!CGF.HaveInsertPoint()) 10219 return; 10220 10221 assert((isa<OMPTargetEnterDataDirective>(D) || 10222 isa<OMPTargetExitDataDirective>(D) || 10223 isa<OMPTargetUpdateDirective>(D)) && 10224 "Expecting either target enter, exit data, or update directives."); 10225 10226 CodeGenFunction::OMPTargetDataInfo InputInfo; 10227 llvm::Value *MapTypesArray = nullptr; 10228 // Generate the code for the opening of the data environment. 10229 auto &&ThenGen = [this, &D, Device, &InputInfo, 10230 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10231 // Emit device ID if any. 10232 llvm::Value *DeviceID = nullptr; 10233 if (Device) { 10234 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10235 CGF.Int64Ty, /*isSigned=*/true); 10236 } else { 10237 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10238 } 10239 10240 // Emit the number of elements in the offloading arrays. 10241 llvm::Constant *PointerNum = 10242 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10243 10244 llvm::Value *OffloadingArgs[] = {DeviceID, 10245 PointerNum, 10246 InputInfo.BasePointersArray.getPointer(), 10247 InputInfo.PointersArray.getPointer(), 10248 InputInfo.SizesArray.getPointer(), 10249 MapTypesArray}; 10250 10251 // Select the right runtime function call for each expected standalone 10252 // directive. 10253 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10254 OpenMPRTLFunction RTLFn; 10255 switch (D.getDirectiveKind()) { 10256 case OMPD_target_enter_data: 10257 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10258 : OMPRTL__tgt_target_data_begin; 10259 break; 10260 case OMPD_target_exit_data: 10261 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10262 : OMPRTL__tgt_target_data_end; 10263 break; 10264 case OMPD_target_update: 10265 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10266 : OMPRTL__tgt_target_data_update; 10267 break; 10268 case OMPD_parallel: 10269 case OMPD_for: 10270 case OMPD_parallel_for: 10271 case OMPD_parallel_sections: 10272 case OMPD_for_simd: 10273 case OMPD_parallel_for_simd: 10274 case OMPD_cancel: 10275 case OMPD_cancellation_point: 10276 case OMPD_ordered: 10277 case OMPD_threadprivate: 10278 case OMPD_allocate: 10279 case OMPD_task: 10280 case OMPD_simd: 10281 case OMPD_sections: 10282 case OMPD_section: 10283 case OMPD_single: 10284 case OMPD_master: 10285 case OMPD_critical: 10286 case OMPD_taskyield: 10287 case OMPD_barrier: 10288 case OMPD_taskwait: 10289 case OMPD_taskgroup: 10290 case OMPD_atomic: 10291 case OMPD_flush: 10292 case OMPD_teams: 10293 case OMPD_target_data: 10294 case OMPD_distribute: 10295 case OMPD_distribute_simd: 10296 case OMPD_distribute_parallel_for: 10297 case OMPD_distribute_parallel_for_simd: 10298 case OMPD_teams_distribute: 10299 case OMPD_teams_distribute_simd: 10300 case OMPD_teams_distribute_parallel_for: 10301 case OMPD_teams_distribute_parallel_for_simd: 10302 case OMPD_declare_simd: 10303 case OMPD_declare_variant: 10304 case OMPD_declare_target: 10305 case OMPD_end_declare_target: 10306 case OMPD_declare_reduction: 10307 case OMPD_declare_mapper: 10308 case OMPD_taskloop: 10309 case OMPD_taskloop_simd: 10310 case OMPD_target: 10311 case OMPD_target_simd: 10312 case OMPD_target_teams_distribute: 10313 case OMPD_target_teams_distribute_simd: 10314 case OMPD_target_teams_distribute_parallel_for: 10315 case OMPD_target_teams_distribute_parallel_for_simd: 10316 case OMPD_target_teams: 10317 case OMPD_target_parallel: 10318 case OMPD_target_parallel_for: 10319 case OMPD_target_parallel_for_simd: 10320 case OMPD_requires: 10321 case OMPD_unknown: 10322 llvm_unreachable("Unexpected standalone target data directive."); 10323 break; 10324 } 10325 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10326 }; 10327 10328 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10329 CodeGenFunction &CGF, PrePostActionTy &) { 10330 // Fill up the arrays with all the mapped variables. 10331 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10332 MappableExprsHandler::MapValuesArrayTy Pointers; 10333 MappableExprsHandler::MapValuesArrayTy Sizes; 10334 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10335 10336 // Get map clause information. 10337 MappableExprsHandler MEHandler(D, CGF); 10338 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10339 10340 TargetDataInfo Info; 10341 // Fill up the arrays and create the arguments. 10342 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10343 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10344 Info.PointersArray, Info.SizesArray, 10345 Info.MapTypesArray, Info); 10346 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10347 InputInfo.BasePointersArray = 10348 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10349 InputInfo.PointersArray = 10350 Address(Info.PointersArray, CGM.getPointerAlign()); 10351 InputInfo.SizesArray = 10352 Address(Info.SizesArray, CGM.getPointerAlign()); 10353 MapTypesArray = Info.MapTypesArray; 10354 if (D.hasClausesOfKind<OMPDependClause>()) 10355 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10356 else 10357 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10358 }; 10359 10360 if (IfCond) { 10361 emitOMPIfClause(CGF, IfCond, TargetThenGen, 10362 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10363 } else { 10364 RegionCodeGenTy ThenRCG(TargetThenGen); 10365 ThenRCG(CGF); 10366 } 10367 } 10368 10369 namespace { 10370 /// Kind of parameter in a function with 'declare simd' directive. 10371 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10372 /// Attribute set of the parameter. 10373 struct ParamAttrTy { 10374 ParamKindTy Kind = Vector; 10375 llvm::APSInt StrideOrArg; 10376 llvm::APSInt Alignment; 10377 }; 10378 } // namespace 10379 10380 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10381 ArrayRef<ParamAttrTy> ParamAttrs) { 10382 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10383 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10384 // of that clause. The VLEN value must be power of 2. 10385 // In other case the notion of the function`s "characteristic data type" (CDT) 10386 // is used to compute the vector length. 10387 // CDT is defined in the following order: 10388 // a) For non-void function, the CDT is the return type. 10389 // b) If the function has any non-uniform, non-linear parameters, then the 10390 // CDT is the type of the first such parameter. 10391 // c) If the CDT determined by a) or b) above is struct, union, or class 10392 // type which is pass-by-value (except for the type that maps to the 10393 // built-in complex data type), the characteristic data type is int. 10394 // d) If none of the above three cases is applicable, the CDT is int. 10395 // The VLEN is then determined based on the CDT and the size of vector 10396 // register of that ISA for which current vector version is generated. The 10397 // VLEN is computed using the formula below: 10398 // VLEN = sizeof(vector_register) / sizeof(CDT), 10399 // where vector register size specified in section 3.2.1 Registers and the 10400 // Stack Frame of original AMD64 ABI document. 10401 QualType RetType = FD->getReturnType(); 10402 if (RetType.isNull()) 10403 return 0; 10404 ASTContext &C = FD->getASTContext(); 10405 QualType CDT; 10406 if (!RetType.isNull() && !RetType->isVoidType()) { 10407 CDT = RetType; 10408 } else { 10409 unsigned Offset = 0; 10410 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10411 if (ParamAttrs[Offset].Kind == Vector) 10412 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10413 ++Offset; 10414 } 10415 if (CDT.isNull()) { 10416 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10417 if (ParamAttrs[I + Offset].Kind == Vector) { 10418 CDT = FD->getParamDecl(I)->getType(); 10419 break; 10420 } 10421 } 10422 } 10423 } 10424 if (CDT.isNull()) 10425 CDT = C.IntTy; 10426 CDT = CDT->getCanonicalTypeUnqualified(); 10427 if (CDT->isRecordType() || CDT->isUnionType()) 10428 CDT = C.IntTy; 10429 return C.getTypeSize(CDT); 10430 } 10431 10432 static void 10433 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10434 const llvm::APSInt &VLENVal, 10435 ArrayRef<ParamAttrTy> ParamAttrs, 10436 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10437 struct ISADataTy { 10438 char ISA; 10439 unsigned VecRegSize; 10440 }; 10441 ISADataTy ISAData[] = { 10442 { 10443 'b', 128 10444 }, // SSE 10445 { 10446 'c', 256 10447 }, // AVX 10448 { 10449 'd', 256 10450 }, // AVX2 10451 { 10452 'e', 512 10453 }, // AVX512 10454 }; 10455 llvm::SmallVector<char, 2> Masked; 10456 switch (State) { 10457 case OMPDeclareSimdDeclAttr::BS_Undefined: 10458 Masked.push_back('N'); 10459 Masked.push_back('M'); 10460 break; 10461 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10462 Masked.push_back('N'); 10463 break; 10464 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10465 Masked.push_back('M'); 10466 break; 10467 } 10468 for (char Mask : Masked) { 10469 for (const ISADataTy &Data : ISAData) { 10470 SmallString<256> Buffer; 10471 llvm::raw_svector_ostream Out(Buffer); 10472 Out << "_ZGV" << Data.ISA << Mask; 10473 if (!VLENVal) { 10474 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10475 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10476 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10477 } else { 10478 Out << VLENVal; 10479 } 10480 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10481 switch (ParamAttr.Kind){ 10482 case LinearWithVarStride: 10483 Out << 's' << ParamAttr.StrideOrArg; 10484 break; 10485 case Linear: 10486 Out << 'l'; 10487 if (!!ParamAttr.StrideOrArg) 10488 Out << ParamAttr.StrideOrArg; 10489 break; 10490 case Uniform: 10491 Out << 'u'; 10492 break; 10493 case Vector: 10494 Out << 'v'; 10495 break; 10496 } 10497 if (!!ParamAttr.Alignment) 10498 Out << 'a' << ParamAttr.Alignment; 10499 } 10500 Out << '_' << Fn->getName(); 10501 Fn->addFnAttr(Out.str()); 10502 } 10503 } 10504 } 10505 10506 // This are the Functions that are needed to mangle the name of the 10507 // vector functions generated by the compiler, according to the rules 10508 // defined in the "Vector Function ABI specifications for AArch64", 10509 // available at 10510 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10511 10512 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10513 /// 10514 /// TODO: Need to implement the behavior for reference marked with a 10515 /// var or no linear modifiers (1.b in the section). For this, we 10516 /// need to extend ParamKindTy to support the linear modifiers. 10517 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10518 QT = QT.getCanonicalType(); 10519 10520 if (QT->isVoidType()) 10521 return false; 10522 10523 if (Kind == ParamKindTy::Uniform) 10524 return false; 10525 10526 if (Kind == ParamKindTy::Linear) 10527 return false; 10528 10529 // TODO: Handle linear references with modifiers 10530 10531 if (Kind == ParamKindTy::LinearWithVarStride) 10532 return false; 10533 10534 return true; 10535 } 10536 10537 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10538 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10539 QT = QT.getCanonicalType(); 10540 unsigned Size = C.getTypeSize(QT); 10541 10542 // Only scalars and complex within 16 bytes wide set PVB to true. 10543 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10544 return false; 10545 10546 if (QT->isFloatingType()) 10547 return true; 10548 10549 if (QT->isIntegerType()) 10550 return true; 10551 10552 if (QT->isPointerType()) 10553 return true; 10554 10555 // TODO: Add support for complex types (section 3.1.2, item 2). 10556 10557 return false; 10558 } 10559 10560 /// Computes the lane size (LS) of a return type or of an input parameter, 10561 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10562 /// TODO: Add support for references, section 3.2.1, item 1. 10563 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10564 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10565 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10566 if (getAArch64PBV(PTy, C)) 10567 return C.getTypeSize(PTy); 10568 } 10569 if (getAArch64PBV(QT, C)) 10570 return C.getTypeSize(QT); 10571 10572 return C.getTypeSize(C.getUIntPtrType()); 10573 } 10574 10575 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10576 // signature of the scalar function, as defined in 3.2.2 of the 10577 // AAVFABI. 10578 static std::tuple<unsigned, unsigned, bool> 10579 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10580 QualType RetType = FD->getReturnType().getCanonicalType(); 10581 10582 ASTContext &C = FD->getASTContext(); 10583 10584 bool OutputBecomesInput = false; 10585 10586 llvm::SmallVector<unsigned, 8> Sizes; 10587 if (!RetType->isVoidType()) { 10588 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10589 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10590 OutputBecomesInput = true; 10591 } 10592 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10593 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10594 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10595 } 10596 10597 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10598 // The LS of a function parameter / return value can only be a power 10599 // of 2, starting from 8 bits, up to 128. 10600 assert(std::all_of(Sizes.begin(), Sizes.end(), 10601 [](unsigned Size) { 10602 return Size == 8 || Size == 16 || Size == 32 || 10603 Size == 64 || Size == 128; 10604 }) && 10605 "Invalid size"); 10606 10607 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10608 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10609 OutputBecomesInput); 10610 } 10611 10612 /// Mangle the parameter part of the vector function name according to 10613 /// their OpenMP classification. The mangling function is defined in 10614 /// section 3.5 of the AAVFABI. 10615 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10616 SmallString<256> Buffer; 10617 llvm::raw_svector_ostream Out(Buffer); 10618 for (const auto &ParamAttr : ParamAttrs) { 10619 switch (ParamAttr.Kind) { 10620 case LinearWithVarStride: 10621 Out << "ls" << ParamAttr.StrideOrArg; 10622 break; 10623 case Linear: 10624 Out << 'l'; 10625 // Don't print the step value if it is not present or if it is 10626 // equal to 1. 10627 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10628 Out << ParamAttr.StrideOrArg; 10629 break; 10630 case Uniform: 10631 Out << 'u'; 10632 break; 10633 case Vector: 10634 Out << 'v'; 10635 break; 10636 } 10637 10638 if (!!ParamAttr.Alignment) 10639 Out << 'a' << ParamAttr.Alignment; 10640 } 10641 10642 return Out.str(); 10643 } 10644 10645 // Function used to add the attribute. The parameter `VLEN` is 10646 // templated to allow the use of "x" when targeting scalable functions 10647 // for SVE. 10648 template <typename T> 10649 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10650 char ISA, StringRef ParSeq, 10651 StringRef MangledName, bool OutputBecomesInput, 10652 llvm::Function *Fn) { 10653 SmallString<256> Buffer; 10654 llvm::raw_svector_ostream Out(Buffer); 10655 Out << Prefix << ISA << LMask << VLEN; 10656 if (OutputBecomesInput) 10657 Out << "v"; 10658 Out << ParSeq << "_" << MangledName; 10659 Fn->addFnAttr(Out.str()); 10660 } 10661 10662 // Helper function to generate the Advanced SIMD names depending on 10663 // the value of the NDS when simdlen is not present. 10664 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10665 StringRef Prefix, char ISA, 10666 StringRef ParSeq, StringRef MangledName, 10667 bool OutputBecomesInput, 10668 llvm::Function *Fn) { 10669 switch (NDS) { 10670 case 8: 10671 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10672 OutputBecomesInput, Fn); 10673 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10674 OutputBecomesInput, Fn); 10675 break; 10676 case 16: 10677 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10678 OutputBecomesInput, Fn); 10679 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10680 OutputBecomesInput, Fn); 10681 break; 10682 case 32: 10683 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10684 OutputBecomesInput, Fn); 10685 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10686 OutputBecomesInput, Fn); 10687 break; 10688 case 64: 10689 case 128: 10690 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10691 OutputBecomesInput, Fn); 10692 break; 10693 default: 10694 llvm_unreachable("Scalar type is too wide."); 10695 } 10696 } 10697 10698 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10699 static void emitAArch64DeclareSimdFunction( 10700 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10701 ArrayRef<ParamAttrTy> ParamAttrs, 10702 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10703 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10704 10705 // Get basic data for building the vector signature. 10706 const auto Data = getNDSWDS(FD, ParamAttrs); 10707 const unsigned NDS = std::get<0>(Data); 10708 const unsigned WDS = std::get<1>(Data); 10709 const bool OutputBecomesInput = std::get<2>(Data); 10710 10711 // Check the values provided via `simdlen` by the user. 10712 // 1. A `simdlen(1)` doesn't produce vector signatures, 10713 if (UserVLEN == 1) { 10714 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10715 DiagnosticsEngine::Warning, 10716 "The clause simdlen(1) has no effect when targeting aarch64."); 10717 CGM.getDiags().Report(SLoc, DiagID); 10718 return; 10719 } 10720 10721 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10722 // Advanced SIMD output. 10723 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10724 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10725 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10726 "power of 2 when targeting Advanced SIMD."); 10727 CGM.getDiags().Report(SLoc, DiagID); 10728 return; 10729 } 10730 10731 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10732 // limits. 10733 if (ISA == 's' && UserVLEN != 0) { 10734 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10735 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10736 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10737 "lanes in the architectural constraints " 10738 "for SVE (min is 128-bit, max is " 10739 "2048-bit, by steps of 128-bit)"); 10740 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10741 return; 10742 } 10743 } 10744 10745 // Sort out parameter sequence. 10746 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10747 StringRef Prefix = "_ZGV"; 10748 // Generate simdlen from user input (if any). 10749 if (UserVLEN) { 10750 if (ISA == 's') { 10751 // SVE generates only a masked function. 10752 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10753 OutputBecomesInput, Fn); 10754 } else { 10755 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10756 // Advanced SIMD generates one or two functions, depending on 10757 // the `[not]inbranch` clause. 10758 switch (State) { 10759 case OMPDeclareSimdDeclAttr::BS_Undefined: 10760 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10761 OutputBecomesInput, Fn); 10762 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10763 OutputBecomesInput, Fn); 10764 break; 10765 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10766 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10767 OutputBecomesInput, Fn); 10768 break; 10769 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10770 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10771 OutputBecomesInput, Fn); 10772 break; 10773 } 10774 } 10775 } else { 10776 // If no user simdlen is provided, follow the AAVFABI rules for 10777 // generating the vector length. 10778 if (ISA == 's') { 10779 // SVE, section 3.4.1, item 1. 10780 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10781 OutputBecomesInput, Fn); 10782 } else { 10783 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10784 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10785 // two vector names depending on the use of the clause 10786 // `[not]inbranch`. 10787 switch (State) { 10788 case OMPDeclareSimdDeclAttr::BS_Undefined: 10789 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10790 OutputBecomesInput, Fn); 10791 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10792 OutputBecomesInput, Fn); 10793 break; 10794 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10795 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10796 OutputBecomesInput, Fn); 10797 break; 10798 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10799 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10800 OutputBecomesInput, Fn); 10801 break; 10802 } 10803 } 10804 } 10805 } 10806 10807 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10808 llvm::Function *Fn) { 10809 ASTContext &C = CGM.getContext(); 10810 FD = FD->getMostRecentDecl(); 10811 // Map params to their positions in function decl. 10812 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10813 if (isa<CXXMethodDecl>(FD)) 10814 ParamPositions.try_emplace(FD, 0); 10815 unsigned ParamPos = ParamPositions.size(); 10816 for (const ParmVarDecl *P : FD->parameters()) { 10817 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10818 ++ParamPos; 10819 } 10820 while (FD) { 10821 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10822 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10823 // Mark uniform parameters. 10824 for (const Expr *E : Attr->uniforms()) { 10825 E = E->IgnoreParenImpCasts(); 10826 unsigned Pos; 10827 if (isa<CXXThisExpr>(E)) { 10828 Pos = ParamPositions[FD]; 10829 } else { 10830 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10831 ->getCanonicalDecl(); 10832 Pos = ParamPositions[PVD]; 10833 } 10834 ParamAttrs[Pos].Kind = Uniform; 10835 } 10836 // Get alignment info. 10837 auto NI = Attr->alignments_begin(); 10838 for (const Expr *E : Attr->aligneds()) { 10839 E = E->IgnoreParenImpCasts(); 10840 unsigned Pos; 10841 QualType ParmTy; 10842 if (isa<CXXThisExpr>(E)) { 10843 Pos = ParamPositions[FD]; 10844 ParmTy = E->getType(); 10845 } else { 10846 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10847 ->getCanonicalDecl(); 10848 Pos = ParamPositions[PVD]; 10849 ParmTy = PVD->getType(); 10850 } 10851 ParamAttrs[Pos].Alignment = 10852 (*NI) 10853 ? (*NI)->EvaluateKnownConstInt(C) 10854 : llvm::APSInt::getUnsigned( 10855 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10856 .getQuantity()); 10857 ++NI; 10858 } 10859 // Mark linear parameters. 10860 auto SI = Attr->steps_begin(); 10861 auto MI = Attr->modifiers_begin(); 10862 for (const Expr *E : Attr->linears()) { 10863 E = E->IgnoreParenImpCasts(); 10864 unsigned Pos; 10865 if (isa<CXXThisExpr>(E)) { 10866 Pos = ParamPositions[FD]; 10867 } else { 10868 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10869 ->getCanonicalDecl(); 10870 Pos = ParamPositions[PVD]; 10871 } 10872 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10873 ParamAttr.Kind = Linear; 10874 if (*SI) { 10875 Expr::EvalResult Result; 10876 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10877 if (const auto *DRE = 10878 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10879 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10880 ParamAttr.Kind = LinearWithVarStride; 10881 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10882 ParamPositions[StridePVD->getCanonicalDecl()]); 10883 } 10884 } 10885 } else { 10886 ParamAttr.StrideOrArg = Result.Val.getInt(); 10887 } 10888 } 10889 ++SI; 10890 ++MI; 10891 } 10892 llvm::APSInt VLENVal; 10893 SourceLocation ExprLoc; 10894 const Expr *VLENExpr = Attr->getSimdlen(); 10895 if (VLENExpr) { 10896 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10897 ExprLoc = VLENExpr->getExprLoc(); 10898 } 10899 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10900 if (CGM.getTriple().getArch() == llvm::Triple::x86 || 10901 CGM.getTriple().getArch() == llvm::Triple::x86_64) { 10902 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10903 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10904 unsigned VLEN = VLENVal.getExtValue(); 10905 StringRef MangledName = Fn->getName(); 10906 if (CGM.getTarget().hasFeature("sve")) 10907 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10908 MangledName, 's', 128, Fn, ExprLoc); 10909 if (CGM.getTarget().hasFeature("neon")) 10910 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10911 MangledName, 'n', 128, Fn, ExprLoc); 10912 } 10913 } 10914 FD = FD->getPreviousDecl(); 10915 } 10916 } 10917 10918 namespace { 10919 /// Cleanup action for doacross support. 10920 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10921 public: 10922 static const int DoacrossFinArgs = 2; 10923 10924 private: 10925 llvm::FunctionCallee RTLFn; 10926 llvm::Value *Args[DoacrossFinArgs]; 10927 10928 public: 10929 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10930 ArrayRef<llvm::Value *> CallArgs) 10931 : RTLFn(RTLFn) { 10932 assert(CallArgs.size() == DoacrossFinArgs); 10933 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10934 } 10935 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10936 if (!CGF.HaveInsertPoint()) 10937 return; 10938 CGF.EmitRuntimeCall(RTLFn, Args); 10939 } 10940 }; 10941 } // namespace 10942 10943 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10944 const OMPLoopDirective &D, 10945 ArrayRef<Expr *> NumIterations) { 10946 if (!CGF.HaveInsertPoint()) 10947 return; 10948 10949 ASTContext &C = CGM.getContext(); 10950 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10951 RecordDecl *RD; 10952 if (KmpDimTy.isNull()) { 10953 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10954 // kmp_int64 lo; // lower 10955 // kmp_int64 up; // upper 10956 // kmp_int64 st; // stride 10957 // }; 10958 RD = C.buildImplicitRecord("kmp_dim"); 10959 RD->startDefinition(); 10960 addFieldToRecordDecl(C, RD, Int64Ty); 10961 addFieldToRecordDecl(C, RD, Int64Ty); 10962 addFieldToRecordDecl(C, RD, Int64Ty); 10963 RD->completeDefinition(); 10964 KmpDimTy = C.getRecordType(RD); 10965 } else { 10966 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10967 } 10968 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10969 QualType ArrayTy = 10970 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 10971 10972 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10973 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10974 enum { LowerFD = 0, UpperFD, StrideFD }; 10975 // Fill dims with data. 10976 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10977 LValue DimsLVal = CGF.MakeAddrLValue( 10978 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10979 // dims.upper = num_iterations; 10980 LValue UpperLVal = CGF.EmitLValueForField( 10981 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10982 llvm::Value *NumIterVal = 10983 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 10984 D.getNumIterations()->getType(), Int64Ty, 10985 D.getNumIterations()->getExprLoc()); 10986 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10987 // dims.stride = 1; 10988 LValue StrideLVal = CGF.EmitLValueForField( 10989 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10990 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10991 StrideLVal); 10992 } 10993 10994 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10995 // kmp_int32 num_dims, struct kmp_dim * dims); 10996 llvm::Value *Args[] = { 10997 emitUpdateLocation(CGF, D.getBeginLoc()), 10998 getThreadID(CGF, D.getBeginLoc()), 10999 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 11000 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11001 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 11002 CGM.VoidPtrTy)}; 11003 11004 llvm::FunctionCallee RTLFn = 11005 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 11006 CGF.EmitRuntimeCall(RTLFn, Args); 11007 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 11008 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 11009 llvm::FunctionCallee FiniRTLFn = 11010 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 11011 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11012 llvm::makeArrayRef(FiniArgs)); 11013 } 11014 11015 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11016 const OMPDependClause *C) { 11017 QualType Int64Ty = 11018 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 11019 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 11020 QualType ArrayTy = CGM.getContext().getConstantArrayType( 11021 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 11022 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 11023 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 11024 const Expr *CounterVal = C->getLoopData(I); 11025 assert(CounterVal); 11026 llvm::Value *CntVal = CGF.EmitScalarConversion( 11027 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 11028 CounterVal->getExprLoc()); 11029 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 11030 /*Volatile=*/false, Int64Ty); 11031 } 11032 llvm::Value *Args[] = { 11033 emitUpdateLocation(CGF, C->getBeginLoc()), 11034 getThreadID(CGF, C->getBeginLoc()), 11035 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 11036 llvm::FunctionCallee RTLFn; 11037 if (C->getDependencyKind() == OMPC_DEPEND_source) { 11038 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 11039 } else { 11040 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 11041 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 11042 } 11043 CGF.EmitRuntimeCall(RTLFn, Args); 11044 } 11045 11046 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 11047 llvm::FunctionCallee Callee, 11048 ArrayRef<llvm::Value *> Args) const { 11049 assert(Loc.isValid() && "Outlined function call location must be valid."); 11050 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 11051 11052 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 11053 if (Fn->doesNotThrow()) { 11054 CGF.EmitNounwindRuntimeCall(Fn, Args); 11055 return; 11056 } 11057 } 11058 CGF.EmitRuntimeCall(Callee, Args); 11059 } 11060 11061 void CGOpenMPRuntime::emitOutlinedFunctionCall( 11062 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 11063 ArrayRef<llvm::Value *> Args) const { 11064 emitCall(CGF, Loc, OutlinedFn, Args); 11065 } 11066 11067 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 11068 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 11069 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 11070 HasEmittedDeclareTargetRegion = true; 11071 } 11072 11073 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 11074 const VarDecl *NativeParam, 11075 const VarDecl *TargetParam) const { 11076 return CGF.GetAddrOfLocalVar(NativeParam); 11077 } 11078 11079 namespace { 11080 /// Cleanup action for allocate support. 11081 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 11082 public: 11083 static const int CleanupArgs = 3; 11084 11085 private: 11086 llvm::FunctionCallee RTLFn; 11087 llvm::Value *Args[CleanupArgs]; 11088 11089 public: 11090 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 11091 ArrayRef<llvm::Value *> CallArgs) 11092 : RTLFn(RTLFn) { 11093 assert(CallArgs.size() == CleanupArgs && 11094 "Size of arguments does not match."); 11095 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11096 } 11097 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11098 if (!CGF.HaveInsertPoint()) 11099 return; 11100 CGF.EmitRuntimeCall(RTLFn, Args); 11101 } 11102 }; 11103 } // namespace 11104 11105 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 11106 const VarDecl *VD) { 11107 if (!VD) 11108 return Address::invalid(); 11109 const VarDecl *CVD = VD->getCanonicalDecl(); 11110 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 11111 return Address::invalid(); 11112 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 11113 // Use the default allocation. 11114 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 11115 !AA->getAllocator()) 11116 return Address::invalid(); 11117 llvm::Value *Size; 11118 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11119 if (CVD->getType()->isVariablyModifiedType()) { 11120 Size = CGF.getTypeSize(CVD->getType()); 11121 // Align the size: ((size + align - 1) / align) * align 11122 Size = CGF.Builder.CreateNUWAdd( 11123 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11124 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11125 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11126 } else { 11127 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 11128 Size = CGM.getSize(Sz.alignTo(Align)); 11129 } 11130 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11131 assert(AA->getAllocator() && 11132 "Expected allocator expression for non-default allocator."); 11133 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11134 // According to the standard, the original allocator type is a enum (integer). 11135 // Convert to pointer type, if required. 11136 if (Allocator->getType()->isIntegerTy()) 11137 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11138 else if (Allocator->getType()->isPointerTy()) 11139 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11140 CGM.VoidPtrTy); 11141 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11142 11143 llvm::Value *Addr = 11144 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11145 CVD->getName() + ".void.addr"); 11146 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11147 Allocator}; 11148 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11149 11150 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11151 llvm::makeArrayRef(FiniArgs)); 11152 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11153 Addr, 11154 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11155 CVD->getName() + ".addr"); 11156 return Address(Addr, Align); 11157 } 11158 11159 /// Checks current context and returns true if it matches the context selector. 11160 template <OMPDeclareVariantAttr::CtxSelectorSetType CtxSet, 11161 OMPDeclareVariantAttr::CtxSelectorType Ctx> 11162 static bool checkContext(const OMPDeclareVariantAttr *A) { 11163 assert(CtxSet != OMPDeclareVariantAttr::CtxSetUnknown && 11164 Ctx != OMPDeclareVariantAttr::CtxUnknown && 11165 "Unknown context selector or context selector set."); 11166 return false; 11167 } 11168 11169 /// Checks for implementation={vendor(<vendor>)} context selector. 11170 /// \returns true iff <vendor>="llvm", false otherwise. 11171 template <> 11172 bool checkContext<OMPDeclareVariantAttr::CtxSetImplementation, 11173 OMPDeclareVariantAttr::CtxVendor>( 11174 const OMPDeclareVariantAttr *A) { 11175 return !A->getImplVendor().compare("llvm"); 11176 } 11177 11178 static bool greaterCtxScore(ASTContext &Ctx, const Expr *LHS, const Expr *RHS) { 11179 // If both scores are unknown, choose the very first one. 11180 if (!LHS && !RHS) 11181 return true; 11182 // If only one is known, return this one. 11183 if (LHS && !RHS) 11184 return true; 11185 if (!LHS && RHS) 11186 return false; 11187 llvm::APSInt LHSVal = LHS->EvaluateKnownConstInt(Ctx); 11188 llvm::APSInt RHSVal = RHS->EvaluateKnownConstInt(Ctx); 11189 return llvm::APSInt::compareValues(LHSVal, RHSVal) <= 0; 11190 } 11191 11192 namespace { 11193 /// Comparator for the priority queue for context selector. 11194 class OMPDeclareVariantAttrComparer 11195 : public std::greater<const OMPDeclareVariantAttr *> { 11196 private: 11197 ASTContext &Ctx; 11198 11199 public: 11200 OMPDeclareVariantAttrComparer(ASTContext &Ctx) : Ctx(Ctx) {} 11201 bool operator()(const OMPDeclareVariantAttr *LHS, 11202 const OMPDeclareVariantAttr *RHS) const { 11203 const Expr *LHSExpr = nullptr; 11204 const Expr *RHSExpr = nullptr; 11205 if (LHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified) 11206 LHSExpr = LHS->getScore(); 11207 if (RHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified) 11208 RHSExpr = RHS->getScore(); 11209 return greaterCtxScore(Ctx, LHSExpr, RHSExpr); 11210 } 11211 }; 11212 } // anonymous namespace 11213 11214 /// Finds the variant function that matches current context with its context 11215 /// selector. 11216 static const FunctionDecl *getDeclareVariantFunction(ASTContext &Ctx, 11217 const FunctionDecl *FD) { 11218 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) 11219 return FD; 11220 // Iterate through all DeclareVariant attributes and check context selectors. 11221 auto &&Comparer = [&Ctx](const OMPDeclareVariantAttr *LHS, 11222 const OMPDeclareVariantAttr *RHS) { 11223 const Expr *LHSExpr = nullptr; 11224 const Expr *RHSExpr = nullptr; 11225 if (LHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified) 11226 LHSExpr = LHS->getScore(); 11227 if (RHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified) 11228 RHSExpr = RHS->getScore(); 11229 return greaterCtxScore(Ctx, LHSExpr, RHSExpr); 11230 }; 11231 const OMPDeclareVariantAttr *TopMostAttr = nullptr; 11232 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { 11233 const OMPDeclareVariantAttr *SelectedAttr = nullptr; 11234 switch (A->getCtxSelectorSet()) { 11235 case OMPDeclareVariantAttr::CtxSetImplementation: 11236 switch (A->getCtxSelector()) { 11237 case OMPDeclareVariantAttr::CtxVendor: 11238 if (checkContext<OMPDeclareVariantAttr::CtxSetImplementation, 11239 OMPDeclareVariantAttr::CtxVendor>(A)) 11240 SelectedAttr = A; 11241 break; 11242 case OMPDeclareVariantAttr::CtxUnknown: 11243 llvm_unreachable( 11244 "Unknown context selector in implementation selector set."); 11245 } 11246 break; 11247 case OMPDeclareVariantAttr::CtxSetUnknown: 11248 llvm_unreachable("Unknown context selector set."); 11249 } 11250 // If the attribute matches the context, find the attribute with the highest 11251 // score. 11252 if (SelectedAttr && (!TopMostAttr || Comparer(TopMostAttr, SelectedAttr))) 11253 TopMostAttr = SelectedAttr; 11254 } 11255 if (!TopMostAttr) 11256 return FD; 11257 return cast<FunctionDecl>( 11258 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) 11259 ->getDecl()); 11260 } 11261 11262 bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { 11263 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11264 // If the original function is defined already, use its definition. 11265 StringRef MangledName = CGM.getMangledName(GD); 11266 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); 11267 if (Orig && !Orig->isDeclaration()) 11268 return false; 11269 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM.getContext(), D); 11270 // Emit original function if it does not have declare variant attribute or the 11271 // context does not match. 11272 if (NewFD == D) 11273 return false; 11274 GlobalDecl NewGD = GD.getWithDecl(NewFD); 11275 if (tryEmitAlias(CGM, NewGD, GD, Orig, IsForDefinition)) { 11276 DeferredVariantFunction.erase(D); 11277 return true; 11278 } 11279 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD))); 11280 return true; 11281 } 11282 11283 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11284 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11285 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11286 llvm_unreachable("Not supported in SIMD-only mode"); 11287 } 11288 11289 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11290 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11291 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11292 llvm_unreachable("Not supported in SIMD-only mode"); 11293 } 11294 11295 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11296 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11297 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11298 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11299 bool Tied, unsigned &NumberOfParts) { 11300 llvm_unreachable("Not supported in SIMD-only mode"); 11301 } 11302 11303 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11304 SourceLocation Loc, 11305 llvm::Function *OutlinedFn, 11306 ArrayRef<llvm::Value *> CapturedVars, 11307 const Expr *IfCond) { 11308 llvm_unreachable("Not supported in SIMD-only mode"); 11309 } 11310 11311 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11312 CodeGenFunction &CGF, StringRef CriticalName, 11313 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11314 const Expr *Hint) { 11315 llvm_unreachable("Not supported in SIMD-only mode"); 11316 } 11317 11318 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11319 const RegionCodeGenTy &MasterOpGen, 11320 SourceLocation Loc) { 11321 llvm_unreachable("Not supported in SIMD-only mode"); 11322 } 11323 11324 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11325 SourceLocation Loc) { 11326 llvm_unreachable("Not supported in SIMD-only mode"); 11327 } 11328 11329 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11330 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11331 SourceLocation Loc) { 11332 llvm_unreachable("Not supported in SIMD-only mode"); 11333 } 11334 11335 void CGOpenMPSIMDRuntime::emitSingleRegion( 11336 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11337 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11338 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11339 ArrayRef<const Expr *> AssignmentOps) { 11340 llvm_unreachable("Not supported in SIMD-only mode"); 11341 } 11342 11343 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11344 const RegionCodeGenTy &OrderedOpGen, 11345 SourceLocation Loc, 11346 bool IsThreads) { 11347 llvm_unreachable("Not supported in SIMD-only mode"); 11348 } 11349 11350 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11351 SourceLocation Loc, 11352 OpenMPDirectiveKind Kind, 11353 bool EmitChecks, 11354 bool ForceSimpleCall) { 11355 llvm_unreachable("Not supported in SIMD-only mode"); 11356 } 11357 11358 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11359 CodeGenFunction &CGF, SourceLocation Loc, 11360 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11361 bool Ordered, const DispatchRTInput &DispatchValues) { 11362 llvm_unreachable("Not supported in SIMD-only mode"); 11363 } 11364 11365 void CGOpenMPSIMDRuntime::emitForStaticInit( 11366 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11367 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11368 llvm_unreachable("Not supported in SIMD-only mode"); 11369 } 11370 11371 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11372 CodeGenFunction &CGF, SourceLocation Loc, 11373 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11374 llvm_unreachable("Not supported in SIMD-only mode"); 11375 } 11376 11377 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11378 SourceLocation Loc, 11379 unsigned IVSize, 11380 bool IVSigned) { 11381 llvm_unreachable("Not supported in SIMD-only mode"); 11382 } 11383 11384 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11385 SourceLocation Loc, 11386 OpenMPDirectiveKind DKind) { 11387 llvm_unreachable("Not supported in SIMD-only mode"); 11388 } 11389 11390 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11391 SourceLocation Loc, 11392 unsigned IVSize, bool IVSigned, 11393 Address IL, Address LB, 11394 Address UB, Address ST) { 11395 llvm_unreachable("Not supported in SIMD-only mode"); 11396 } 11397 11398 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11399 llvm::Value *NumThreads, 11400 SourceLocation Loc) { 11401 llvm_unreachable("Not supported in SIMD-only mode"); 11402 } 11403 11404 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11405 OpenMPProcBindClauseKind ProcBind, 11406 SourceLocation Loc) { 11407 llvm_unreachable("Not supported in SIMD-only mode"); 11408 } 11409 11410 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11411 const VarDecl *VD, 11412 Address VDAddr, 11413 SourceLocation Loc) { 11414 llvm_unreachable("Not supported in SIMD-only mode"); 11415 } 11416 11417 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11418 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11419 CodeGenFunction *CGF) { 11420 llvm_unreachable("Not supported in SIMD-only mode"); 11421 } 11422 11423 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11424 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11425 llvm_unreachable("Not supported in SIMD-only mode"); 11426 } 11427 11428 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11429 ArrayRef<const Expr *> Vars, 11430 SourceLocation Loc) { 11431 llvm_unreachable("Not supported in SIMD-only mode"); 11432 } 11433 11434 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11435 const OMPExecutableDirective &D, 11436 llvm::Function *TaskFunction, 11437 QualType SharedsTy, Address Shareds, 11438 const Expr *IfCond, 11439 const OMPTaskDataTy &Data) { 11440 llvm_unreachable("Not supported in SIMD-only mode"); 11441 } 11442 11443 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11444 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11445 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11446 const Expr *IfCond, const OMPTaskDataTy &Data) { 11447 llvm_unreachable("Not supported in SIMD-only mode"); 11448 } 11449 11450 void CGOpenMPSIMDRuntime::emitReduction( 11451 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 11452 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 11453 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 11454 assert(Options.SimpleReduction && "Only simple reduction is expected."); 11455 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 11456 ReductionOps, Options); 11457 } 11458 11459 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 11460 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 11461 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 11462 llvm_unreachable("Not supported in SIMD-only mode"); 11463 } 11464 11465 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 11466 SourceLocation Loc, 11467 ReductionCodeGen &RCG, 11468 unsigned N) { 11469 llvm_unreachable("Not supported in SIMD-only mode"); 11470 } 11471 11472 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 11473 SourceLocation Loc, 11474 llvm::Value *ReductionsPtr, 11475 LValue SharedLVal) { 11476 llvm_unreachable("Not supported in SIMD-only mode"); 11477 } 11478 11479 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 11480 SourceLocation Loc) { 11481 llvm_unreachable("Not supported in SIMD-only mode"); 11482 } 11483 11484 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 11485 CodeGenFunction &CGF, SourceLocation Loc, 11486 OpenMPDirectiveKind CancelRegion) { 11487 llvm_unreachable("Not supported in SIMD-only mode"); 11488 } 11489 11490 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 11491 SourceLocation Loc, const Expr *IfCond, 11492 OpenMPDirectiveKind CancelRegion) { 11493 llvm_unreachable("Not supported in SIMD-only mode"); 11494 } 11495 11496 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 11497 const OMPExecutableDirective &D, StringRef ParentName, 11498 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 11499 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 11500 llvm_unreachable("Not supported in SIMD-only mode"); 11501 } 11502 11503 void CGOpenMPSIMDRuntime::emitTargetCall( 11504 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11505 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 11506 const Expr *Device, 11507 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 11508 const OMPLoopDirective &D)> 11509 SizeEmitter) { 11510 llvm_unreachable("Not supported in SIMD-only mode"); 11511 } 11512 11513 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 11514 llvm_unreachable("Not supported in SIMD-only mode"); 11515 } 11516 11517 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 11518 llvm_unreachable("Not supported in SIMD-only mode"); 11519 } 11520 11521 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 11522 return false; 11523 } 11524 11525 llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() { 11526 return nullptr; 11527 } 11528 11529 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 11530 const OMPExecutableDirective &D, 11531 SourceLocation Loc, 11532 llvm::Function *OutlinedFn, 11533 ArrayRef<llvm::Value *> CapturedVars) { 11534 llvm_unreachable("Not supported in SIMD-only mode"); 11535 } 11536 11537 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11538 const Expr *NumTeams, 11539 const Expr *ThreadLimit, 11540 SourceLocation Loc) { 11541 llvm_unreachable("Not supported in SIMD-only mode"); 11542 } 11543 11544 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 11545 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11546 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11547 llvm_unreachable("Not supported in SIMD-only mode"); 11548 } 11549 11550 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 11551 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11552 const Expr *Device) { 11553 llvm_unreachable("Not supported in SIMD-only mode"); 11554 } 11555 11556 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11557 const OMPLoopDirective &D, 11558 ArrayRef<Expr *> NumIterations) { 11559 llvm_unreachable("Not supported in SIMD-only mode"); 11560 } 11561 11562 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11563 const OMPDependClause *C) { 11564 llvm_unreachable("Not supported in SIMD-only mode"); 11565 } 11566 11567 const VarDecl * 11568 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 11569 const VarDecl *NativeParam) const { 11570 llvm_unreachable("Not supported in SIMD-only mode"); 11571 } 11572 11573 Address 11574 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 11575 const VarDecl *NativeParam, 11576 const VarDecl *TargetParam) const { 11577 llvm_unreachable("Not supported in SIMD-only mode"); 11578 } 11579