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 "CGOpenMPRuntime.h" 14 #include "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/AST/Attr.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/OpenMPClause.h" 21 #include "clang/AST/StmtOpenMP.h" 22 #include "clang/AST/StmtVisitor.h" 23 #include "clang/Basic/BitmaskEnum.h" 24 #include "clang/Basic/OpenMPKinds.h" 25 #include "clang/CodeGen/ConstantInitBuilder.h" 26 #include "llvm/ADT/ArrayRef.h" 27 #include "llvm/ADT/SetOperations.h" 28 #include "llvm/ADT/StringExtras.h" 29 #include "llvm/Bitcode/BitcodeReader.h" 30 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" 31 #include "llvm/IR/DerivedTypes.h" 32 #include "llvm/IR/GlobalValue.h" 33 #include "llvm/IR/Value.h" 34 #include "llvm/Support/AtomicOrdering.h" 35 #include "llvm/Support/Format.h" 36 #include "llvm/Support/raw_ostream.h" 37 #include <cassert> 38 39 using namespace clang; 40 using namespace CodeGen; 41 using namespace llvm::omp; 42 43 namespace { 44 /// Base class for handling code generation inside OpenMP regions. 45 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 46 public: 47 /// Kinds of OpenMP regions used in codegen. 48 enum CGOpenMPRegionKind { 49 /// Region with outlined function for standalone 'parallel' 50 /// directive. 51 ParallelOutlinedRegion, 52 /// Region with outlined function for standalone 'task' directive. 53 TaskOutlinedRegion, 54 /// Region for constructs that do not require function outlining, 55 /// like 'for', 'sections', 'atomic' etc. directives. 56 InlinedRegion, 57 /// Region with outlined function for standalone 'target' directive. 58 TargetRegion, 59 }; 60 61 CGOpenMPRegionInfo(const CapturedStmt &CS, 62 const CGOpenMPRegionKind RegionKind, 63 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 64 bool HasCancel) 65 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 66 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 67 68 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 69 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 70 bool HasCancel) 71 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 72 Kind(Kind), HasCancel(HasCancel) {} 73 74 /// Get a variable or parameter for storing global thread id 75 /// inside OpenMP construct. 76 virtual const VarDecl *getThreadIDVariable() const = 0; 77 78 /// Emit the captured statement body. 79 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 80 81 /// Get an LValue for the current ThreadID variable. 82 /// \return LValue for thread id variable. This LValue always has type int32*. 83 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 84 85 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 86 87 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 88 89 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 90 91 bool hasCancel() const { return HasCancel; } 92 93 static bool classof(const CGCapturedStmtInfo *Info) { 94 return Info->getKind() == CR_OpenMP; 95 } 96 97 ~CGOpenMPRegionInfo() override = default; 98 99 protected: 100 CGOpenMPRegionKind RegionKind; 101 RegionCodeGenTy CodeGen; 102 OpenMPDirectiveKind Kind; 103 bool HasCancel; 104 }; 105 106 /// API for captured statement code generation in OpenMP constructs. 107 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 108 public: 109 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 110 const RegionCodeGenTy &CodeGen, 111 OpenMPDirectiveKind Kind, bool HasCancel, 112 StringRef HelperName) 113 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 114 HasCancel), 115 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 116 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 117 } 118 119 /// Get a variable or parameter for storing global thread id 120 /// inside OpenMP construct. 121 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 122 123 /// Get the name of the capture helper. 124 StringRef getHelperName() const override { return HelperName; } 125 126 static bool classof(const CGCapturedStmtInfo *Info) { 127 return CGOpenMPRegionInfo::classof(Info) && 128 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 129 ParallelOutlinedRegion; 130 } 131 132 private: 133 /// A variable or parameter storing global thread id for OpenMP 134 /// constructs. 135 const VarDecl *ThreadIDVar; 136 StringRef HelperName; 137 }; 138 139 /// API for captured statement code generation in OpenMP constructs. 140 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 141 public: 142 class UntiedTaskActionTy final : public PrePostActionTy { 143 bool Untied; 144 const VarDecl *PartIDVar; 145 const RegionCodeGenTy UntiedCodeGen; 146 llvm::SwitchInst *UntiedSwitch = nullptr; 147 148 public: 149 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 150 const RegionCodeGenTy &UntiedCodeGen) 151 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 152 void Enter(CodeGenFunction &CGF) override { 153 if (Untied) { 154 // Emit task switching point. 155 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 156 CGF.GetAddrOfLocalVar(PartIDVar), 157 PartIDVar->getType()->castAs<PointerType>()); 158 llvm::Value *Res = 159 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 160 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 161 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 162 CGF.EmitBlock(DoneBB); 163 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 164 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 165 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 166 CGF.Builder.GetInsertBlock()); 167 emitUntiedSwitch(CGF); 168 } 169 } 170 void emitUntiedSwitch(CodeGenFunction &CGF) const { 171 if (Untied) { 172 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 173 CGF.GetAddrOfLocalVar(PartIDVar), 174 PartIDVar->getType()->castAs<PointerType>()); 175 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 176 PartIdLVal); 177 UntiedCodeGen(CGF); 178 CodeGenFunction::JumpDest CurPoint = 179 CGF.getJumpDestInCurrentScope(".untied.next."); 180 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 181 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 182 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 183 CGF.Builder.GetInsertBlock()); 184 CGF.EmitBranchThroughCleanup(CurPoint); 185 CGF.EmitBlock(CurPoint.getBlock()); 186 } 187 } 188 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 189 }; 190 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 191 const VarDecl *ThreadIDVar, 192 const RegionCodeGenTy &CodeGen, 193 OpenMPDirectiveKind Kind, bool HasCancel, 194 const UntiedTaskActionTy &Action) 195 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 196 ThreadIDVar(ThreadIDVar), Action(Action) { 197 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 198 } 199 200 /// Get a variable or parameter for storing global thread id 201 /// inside OpenMP construct. 202 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 203 204 /// Get an LValue for the current ThreadID variable. 205 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 206 207 /// Get the name of the capture helper. 208 StringRef getHelperName() const override { return ".omp_outlined."; } 209 210 void emitUntiedSwitch(CodeGenFunction &CGF) override { 211 Action.emitUntiedSwitch(CGF); 212 } 213 214 static bool classof(const CGCapturedStmtInfo *Info) { 215 return CGOpenMPRegionInfo::classof(Info) && 216 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 217 TaskOutlinedRegion; 218 } 219 220 private: 221 /// A variable or parameter storing global thread id for OpenMP 222 /// constructs. 223 const VarDecl *ThreadIDVar; 224 /// Action for emitting code for untied tasks. 225 const UntiedTaskActionTy &Action; 226 }; 227 228 /// API for inlined captured statement code generation in OpenMP 229 /// constructs. 230 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 231 public: 232 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 233 const RegionCodeGenTy &CodeGen, 234 OpenMPDirectiveKind Kind, bool HasCancel) 235 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 236 OldCSI(OldCSI), 237 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 238 239 // Retrieve the value of the context parameter. 240 llvm::Value *getContextValue() const override { 241 if (OuterRegionInfo) 242 return OuterRegionInfo->getContextValue(); 243 llvm_unreachable("No context value for inlined OpenMP region"); 244 } 245 246 void setContextValue(llvm::Value *V) override { 247 if (OuterRegionInfo) { 248 OuterRegionInfo->setContextValue(V); 249 return; 250 } 251 llvm_unreachable("No context value for inlined OpenMP region"); 252 } 253 254 /// Lookup the captured field decl for a variable. 255 const FieldDecl *lookup(const VarDecl *VD) const override { 256 if (OuterRegionInfo) 257 return OuterRegionInfo->lookup(VD); 258 // If there is no outer outlined region,no need to lookup in a list of 259 // captured variables, we can use the original one. 260 return nullptr; 261 } 262 263 FieldDecl *getThisFieldDecl() const override { 264 if (OuterRegionInfo) 265 return OuterRegionInfo->getThisFieldDecl(); 266 return nullptr; 267 } 268 269 /// Get a variable or parameter for storing global thread id 270 /// inside OpenMP construct. 271 const VarDecl *getThreadIDVariable() const override { 272 if (OuterRegionInfo) 273 return OuterRegionInfo->getThreadIDVariable(); 274 return nullptr; 275 } 276 277 /// Get an LValue for the current ThreadID variable. 278 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 279 if (OuterRegionInfo) 280 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 281 llvm_unreachable("No LValue for inlined OpenMP construct"); 282 } 283 284 /// Get the name of the capture helper. 285 StringRef getHelperName() const override { 286 if (auto *OuterRegionInfo = getOldCSI()) 287 return OuterRegionInfo->getHelperName(); 288 llvm_unreachable("No helper name for inlined OpenMP construct"); 289 } 290 291 void emitUntiedSwitch(CodeGenFunction &CGF) override { 292 if (OuterRegionInfo) 293 OuterRegionInfo->emitUntiedSwitch(CGF); 294 } 295 296 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 297 298 static bool classof(const CGCapturedStmtInfo *Info) { 299 return CGOpenMPRegionInfo::classof(Info) && 300 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 301 } 302 303 ~CGOpenMPInlinedRegionInfo() override = default; 304 305 private: 306 /// CodeGen info about outer OpenMP region. 307 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 308 CGOpenMPRegionInfo *OuterRegionInfo; 309 }; 310 311 /// API for captured statement code generation in OpenMP target 312 /// constructs. For this captures, implicit parameters are used instead of the 313 /// captured fields. The name of the target region has to be unique in a given 314 /// application so it is provided by the client, because only the client has 315 /// the information to generate that. 316 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 317 public: 318 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 319 const RegionCodeGenTy &CodeGen, StringRef HelperName) 320 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 321 /*HasCancel=*/false), 322 HelperName(HelperName) {} 323 324 /// This is unused for target regions because each starts executing 325 /// with a single thread. 326 const VarDecl *getThreadIDVariable() const override { return nullptr; } 327 328 /// Get the name of the capture helper. 329 StringRef getHelperName() const override { return HelperName; } 330 331 static bool classof(const CGCapturedStmtInfo *Info) { 332 return CGOpenMPRegionInfo::classof(Info) && 333 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 334 } 335 336 private: 337 StringRef HelperName; 338 }; 339 340 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 341 llvm_unreachable("No codegen for expressions"); 342 } 343 /// API for generation of expressions captured in a innermost OpenMP 344 /// region. 345 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 346 public: 347 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 348 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 349 OMPD_unknown, 350 /*HasCancel=*/false), 351 PrivScope(CGF) { 352 // Make sure the globals captured in the provided statement are local by 353 // using the privatization logic. We assume the same variable is not 354 // captured more than once. 355 for (const auto &C : CS.captures()) { 356 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 357 continue; 358 359 const VarDecl *VD = C.getCapturedVar(); 360 if (VD->isLocalVarDeclOrParm()) 361 continue; 362 363 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 364 /*RefersToEnclosingVariableOrCapture=*/false, 365 VD->getType().getNonReferenceType(), VK_LValue, 366 C.getLocation()); 367 PrivScope.addPrivate( 368 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 369 } 370 (void)PrivScope.Privatize(); 371 } 372 373 /// Lookup the captured field decl for a variable. 374 const FieldDecl *lookup(const VarDecl *VD) const override { 375 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 376 return FD; 377 return nullptr; 378 } 379 380 /// Emit the captured statement body. 381 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 382 llvm_unreachable("No body for expressions"); 383 } 384 385 /// Get a variable or parameter for storing global thread id 386 /// inside OpenMP construct. 387 const VarDecl *getThreadIDVariable() const override { 388 llvm_unreachable("No thread id for expressions"); 389 } 390 391 /// Get the name of the capture helper. 392 StringRef getHelperName() const override { 393 llvm_unreachable("No helper name for expressions"); 394 } 395 396 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 397 398 private: 399 /// Private scope to capture global variables. 400 CodeGenFunction::OMPPrivateScope PrivScope; 401 }; 402 403 /// RAII for emitting code of OpenMP constructs. 404 class InlinedOpenMPRegionRAII { 405 CodeGenFunction &CGF; 406 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 407 FieldDecl *LambdaThisCaptureField = nullptr; 408 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 409 410 public: 411 /// Constructs region for combined constructs. 412 /// \param CodeGen Code generation sequence for combined directives. Includes 413 /// a list of functions used for code generation of implicitly inlined 414 /// regions. 415 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 416 OpenMPDirectiveKind Kind, bool HasCancel) 417 : CGF(CGF) { 418 // Start emission for the construct. 419 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 420 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 421 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 422 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 423 CGF.LambdaThisCaptureField = nullptr; 424 BlockInfo = CGF.BlockInfo; 425 CGF.BlockInfo = nullptr; 426 } 427 428 ~InlinedOpenMPRegionRAII() { 429 // Restore original CapturedStmtInfo only if we're done with code emission. 430 auto *OldCSI = 431 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 432 delete CGF.CapturedStmtInfo; 433 CGF.CapturedStmtInfo = OldCSI; 434 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 435 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 436 CGF.BlockInfo = BlockInfo; 437 } 438 }; 439 440 /// Values for bit flags used in the ident_t to describe the fields. 441 /// All enumeric elements are named and described in accordance with the code 442 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 443 enum OpenMPLocationFlags : unsigned { 444 /// Use trampoline for internal microtask. 445 OMP_IDENT_IMD = 0x01, 446 /// Use c-style ident structure. 447 OMP_IDENT_KMPC = 0x02, 448 /// Atomic reduction option for kmpc_reduce. 449 OMP_ATOMIC_REDUCE = 0x10, 450 /// Explicit 'barrier' directive. 451 OMP_IDENT_BARRIER_EXPL = 0x20, 452 /// Implicit barrier in code. 453 OMP_IDENT_BARRIER_IMPL = 0x40, 454 /// Implicit barrier in 'for' directive. 455 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 456 /// Implicit barrier in 'sections' directive. 457 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 458 /// Implicit barrier in 'single' directive. 459 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 460 /// Call of __kmp_for_static_init for static loop. 461 OMP_IDENT_WORK_LOOP = 0x200, 462 /// Call of __kmp_for_static_init for sections. 463 OMP_IDENT_WORK_SECTIONS = 0x400, 464 /// Call of __kmp_for_static_init for distribute. 465 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 466 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 467 }; 468 469 namespace { 470 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 471 /// Values for bit flags for marking which requires clauses have been used. 472 enum OpenMPOffloadingRequiresDirFlags : int64_t { 473 /// flag undefined. 474 OMP_REQ_UNDEFINED = 0x000, 475 /// no requires clause present. 476 OMP_REQ_NONE = 0x001, 477 /// reverse_offload clause. 478 OMP_REQ_REVERSE_OFFLOAD = 0x002, 479 /// unified_address clause. 480 OMP_REQ_UNIFIED_ADDRESS = 0x004, 481 /// unified_shared_memory clause. 482 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 483 /// dynamic_allocators clause. 484 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 485 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 486 }; 487 488 enum OpenMPOffloadingReservedDeviceIDs { 489 /// Device ID if the device was not defined, runtime should get it 490 /// from environment variables in the spec. 491 OMP_DEVICEID_UNDEF = -1, 492 }; 493 } // anonymous namespace 494 495 /// Describes ident structure that describes a source location. 496 /// All descriptions are taken from 497 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 498 /// Original structure: 499 /// typedef struct ident { 500 /// kmp_int32 reserved_1; /**< might be used in Fortran; 501 /// see above */ 502 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 503 /// KMP_IDENT_KMPC identifies this union 504 /// member */ 505 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 506 /// see above */ 507 ///#if USE_ITT_BUILD 508 /// /* but currently used for storing 509 /// region-specific ITT */ 510 /// /* contextual information. */ 511 ///#endif /* USE_ITT_BUILD */ 512 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 513 /// C++ */ 514 /// char const *psource; /**< String describing the source location. 515 /// The string is composed of semi-colon separated 516 // fields which describe the source file, 517 /// the function and a pair of line numbers that 518 /// delimit the construct. 519 /// */ 520 /// } ident_t; 521 enum IdentFieldIndex { 522 /// might be used in Fortran 523 IdentField_Reserved_1, 524 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 525 IdentField_Flags, 526 /// Not really used in Fortran any more 527 IdentField_Reserved_2, 528 /// Source[4] in Fortran, do not use for C++ 529 IdentField_Reserved_3, 530 /// String describing the source location. The string is composed of 531 /// semi-colon separated fields which describe the source file, the function 532 /// and a pair of line numbers that delimit the construct. 533 IdentField_PSource 534 }; 535 536 /// Schedule types for 'omp for' loops (these enumerators are taken from 537 /// the enum sched_type in kmp.h). 538 enum OpenMPSchedType { 539 /// Lower bound for default (unordered) versions. 540 OMP_sch_lower = 32, 541 OMP_sch_static_chunked = 33, 542 OMP_sch_static = 34, 543 OMP_sch_dynamic_chunked = 35, 544 OMP_sch_guided_chunked = 36, 545 OMP_sch_runtime = 37, 546 OMP_sch_auto = 38, 547 /// static with chunk adjustment (e.g., simd) 548 OMP_sch_static_balanced_chunked = 45, 549 /// Lower bound for 'ordered' versions. 550 OMP_ord_lower = 64, 551 OMP_ord_static_chunked = 65, 552 OMP_ord_static = 66, 553 OMP_ord_dynamic_chunked = 67, 554 OMP_ord_guided_chunked = 68, 555 OMP_ord_runtime = 69, 556 OMP_ord_auto = 70, 557 OMP_sch_default = OMP_sch_static, 558 /// dist_schedule types 559 OMP_dist_sch_static_chunked = 91, 560 OMP_dist_sch_static = 92, 561 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 562 /// Set if the monotonic schedule modifier was present. 563 OMP_sch_modifier_monotonic = (1 << 29), 564 /// Set if the nonmonotonic schedule modifier was present. 565 OMP_sch_modifier_nonmonotonic = (1 << 30), 566 }; 567 568 enum OpenMPRTLFunction { 569 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 570 /// kmpc_micro microtask, ...); 571 OMPRTL__kmpc_fork_call, 572 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 573 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 574 OMPRTL__kmpc_threadprivate_cached, 575 /// Call to void __kmpc_threadprivate_register( ident_t *, 576 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 577 OMPRTL__kmpc_threadprivate_register, 578 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 579 OMPRTL__kmpc_global_thread_num, 580 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 581 // kmp_critical_name *crit); 582 OMPRTL__kmpc_critical, 583 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 584 // global_tid, kmp_critical_name *crit, uintptr_t hint); 585 OMPRTL__kmpc_critical_with_hint, 586 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 587 // kmp_critical_name *crit); 588 OMPRTL__kmpc_end_critical, 589 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 590 // global_tid); 591 OMPRTL__kmpc_cancel_barrier, 592 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 593 OMPRTL__kmpc_barrier, 594 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 595 OMPRTL__kmpc_for_static_fini, 596 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 597 // global_tid); 598 OMPRTL__kmpc_serialized_parallel, 599 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 600 // global_tid); 601 OMPRTL__kmpc_end_serialized_parallel, 602 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 603 // kmp_int32 num_threads); 604 OMPRTL__kmpc_push_num_threads, 605 // Call to void __kmpc_flush(ident_t *loc); 606 OMPRTL__kmpc_flush, 607 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 608 OMPRTL__kmpc_master, 609 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 610 OMPRTL__kmpc_end_master, 611 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 612 // int end_part); 613 OMPRTL__kmpc_omp_taskyield, 614 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 615 OMPRTL__kmpc_single, 616 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 617 OMPRTL__kmpc_end_single, 618 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 619 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 620 // kmp_routine_entry_t *task_entry); 621 OMPRTL__kmpc_omp_task_alloc, 622 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 623 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 624 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 625 // kmp_int64 device_id); 626 OMPRTL__kmpc_omp_target_task_alloc, 627 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 628 // new_task); 629 OMPRTL__kmpc_omp_task, 630 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 631 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 632 // kmp_int32 didit); 633 OMPRTL__kmpc_copyprivate, 634 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 635 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 636 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 637 OMPRTL__kmpc_reduce, 638 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 639 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 640 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 641 // *lck); 642 OMPRTL__kmpc_reduce_nowait, 643 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 644 // kmp_critical_name *lck); 645 OMPRTL__kmpc_end_reduce, 646 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 647 // kmp_critical_name *lck); 648 OMPRTL__kmpc_end_reduce_nowait, 649 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 650 // kmp_task_t * new_task); 651 OMPRTL__kmpc_omp_task_begin_if0, 652 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 653 // kmp_task_t * new_task); 654 OMPRTL__kmpc_omp_task_complete_if0, 655 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 656 OMPRTL__kmpc_ordered, 657 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 658 OMPRTL__kmpc_end_ordered, 659 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 660 // global_tid); 661 OMPRTL__kmpc_omp_taskwait, 662 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 663 OMPRTL__kmpc_taskgroup, 664 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 665 OMPRTL__kmpc_end_taskgroup, 666 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 667 // int proc_bind); 668 OMPRTL__kmpc_push_proc_bind, 669 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 670 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 671 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 672 OMPRTL__kmpc_omp_task_with_deps, 673 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 674 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 675 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 676 OMPRTL__kmpc_omp_wait_deps, 677 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 678 // global_tid, kmp_int32 cncl_kind); 679 OMPRTL__kmpc_cancellationpoint, 680 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 681 // kmp_int32 cncl_kind); 682 OMPRTL__kmpc_cancel, 683 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 684 // kmp_int32 num_teams, kmp_int32 thread_limit); 685 OMPRTL__kmpc_push_num_teams, 686 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 687 // microtask, ...); 688 OMPRTL__kmpc_fork_teams, 689 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 690 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 691 // sched, kmp_uint64 grainsize, void *task_dup); 692 OMPRTL__kmpc_taskloop, 693 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 694 // num_dims, struct kmp_dim *dims); 695 OMPRTL__kmpc_doacross_init, 696 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 697 OMPRTL__kmpc_doacross_fini, 698 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 699 // *vec); 700 OMPRTL__kmpc_doacross_post, 701 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 702 // *vec); 703 OMPRTL__kmpc_doacross_wait, 704 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 705 // *data); 706 OMPRTL__kmpc_task_reduction_init, 707 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 708 // *d); 709 OMPRTL__kmpc_task_reduction_get_th_data, 710 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 711 OMPRTL__kmpc_alloc, 712 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 713 OMPRTL__kmpc_free, 714 715 // 716 // Offloading related calls 717 // 718 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 719 // size); 720 OMPRTL__kmpc_push_target_tripcount, 721 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 722 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 723 // *arg_types); 724 OMPRTL__tgt_target, 725 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 726 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 727 // *arg_types); 728 OMPRTL__tgt_target_nowait, 729 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 730 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 731 // *arg_types, int32_t num_teams, int32_t thread_limit); 732 OMPRTL__tgt_target_teams, 733 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 734 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 735 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 736 OMPRTL__tgt_target_teams_nowait, 737 // Call to void __tgt_register_requires(int64_t flags); 738 OMPRTL__tgt_register_requires, 739 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 740 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 741 OMPRTL__tgt_target_data_begin, 742 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 743 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 744 // *arg_types); 745 OMPRTL__tgt_target_data_begin_nowait, 746 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 747 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 748 OMPRTL__tgt_target_data_end, 749 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 750 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 751 // *arg_types); 752 OMPRTL__tgt_target_data_end_nowait, 753 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 754 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 755 OMPRTL__tgt_target_data_update, 756 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 757 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 758 // *arg_types); 759 OMPRTL__tgt_target_data_update_nowait, 760 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 761 OMPRTL__tgt_mapper_num_components, 762 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 763 // *base, void *begin, int64_t size, int64_t type); 764 OMPRTL__tgt_push_mapper_component, 765 }; 766 767 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 768 /// region. 769 class CleanupTy final : public EHScopeStack::Cleanup { 770 PrePostActionTy *Action; 771 772 public: 773 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 774 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 775 if (!CGF.HaveInsertPoint()) 776 return; 777 Action->Exit(CGF); 778 } 779 }; 780 781 } // anonymous namespace 782 783 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 784 CodeGenFunction::RunCleanupsScope Scope(CGF); 785 if (PrePostAction) { 786 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 787 Callback(CodeGen, CGF, *PrePostAction); 788 } else { 789 PrePostActionTy Action; 790 Callback(CodeGen, CGF, Action); 791 } 792 } 793 794 /// Check if the combiner is a call to UDR combiner and if it is so return the 795 /// UDR decl used for reduction. 796 static const OMPDeclareReductionDecl * 797 getReductionInit(const Expr *ReductionOp) { 798 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 799 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 800 if (const auto *DRE = 801 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 802 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 803 return DRD; 804 return nullptr; 805 } 806 807 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 808 const OMPDeclareReductionDecl *DRD, 809 const Expr *InitOp, 810 Address Private, Address Original, 811 QualType Ty) { 812 if (DRD->getInitializer()) { 813 std::pair<llvm::Function *, llvm::Function *> Reduction = 814 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 815 const auto *CE = cast<CallExpr>(InitOp); 816 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 817 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 818 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 819 const auto *LHSDRE = 820 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 821 const auto *RHSDRE = 822 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 823 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 824 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 825 [=]() { return Private; }); 826 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 827 [=]() { return Original; }); 828 (void)PrivateScope.Privatize(); 829 RValue Func = RValue::get(Reduction.second); 830 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 831 CGF.EmitIgnoredExpr(InitOp); 832 } else { 833 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 834 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 835 auto *GV = new llvm::GlobalVariable( 836 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 837 llvm::GlobalValue::PrivateLinkage, Init, Name); 838 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 839 RValue InitRVal; 840 switch (CGF.getEvaluationKind(Ty)) { 841 case TEK_Scalar: 842 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 843 break; 844 case TEK_Complex: 845 InitRVal = 846 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 847 break; 848 case TEK_Aggregate: 849 InitRVal = RValue::getAggregate(LV.getAddress(CGF)); 850 break; 851 } 852 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 853 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 854 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 855 /*IsInitializer=*/false); 856 } 857 } 858 859 /// Emit initialization of arrays of complex types. 860 /// \param DestAddr Address of the array. 861 /// \param Type Type of array. 862 /// \param Init Initial expression of array. 863 /// \param SrcAddr Address of the original array. 864 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 865 QualType Type, bool EmitDeclareReductionInit, 866 const Expr *Init, 867 const OMPDeclareReductionDecl *DRD, 868 Address SrcAddr = Address::invalid()) { 869 // Perform element-by-element initialization. 870 QualType ElementTy; 871 872 // Drill down to the base element type on both arrays. 873 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 874 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 875 DestAddr = 876 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 877 if (DRD) 878 SrcAddr = 879 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 880 881 llvm::Value *SrcBegin = nullptr; 882 if (DRD) 883 SrcBegin = SrcAddr.getPointer(); 884 llvm::Value *DestBegin = DestAddr.getPointer(); 885 // Cast from pointer to array type to pointer to single element. 886 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 887 // The basic structure here is a while-do loop. 888 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 889 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 890 llvm::Value *IsEmpty = 891 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 892 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 893 894 // Enter the loop body, making that address the current address. 895 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 896 CGF.EmitBlock(BodyBB); 897 898 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 899 900 llvm::PHINode *SrcElementPHI = nullptr; 901 Address SrcElementCurrent = Address::invalid(); 902 if (DRD) { 903 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 904 "omp.arraycpy.srcElementPast"); 905 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 906 SrcElementCurrent = 907 Address(SrcElementPHI, 908 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 909 } 910 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 911 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 912 DestElementPHI->addIncoming(DestBegin, EntryBB); 913 Address DestElementCurrent = 914 Address(DestElementPHI, 915 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 916 917 // Emit copy. 918 { 919 CodeGenFunction::RunCleanupsScope InitScope(CGF); 920 if (EmitDeclareReductionInit) { 921 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 922 SrcElementCurrent, ElementTy); 923 } else 924 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 925 /*IsInitializer=*/false); 926 } 927 928 if (DRD) { 929 // Shift the address forward by one element. 930 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 931 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 932 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 933 } 934 935 // Shift the address forward by one element. 936 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 937 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 938 // Check whether we've reached the end. 939 llvm::Value *Done = 940 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 941 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 942 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 943 944 // Done. 945 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 946 } 947 948 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 949 return CGF.EmitOMPSharedLValue(E); 950 } 951 952 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 953 const Expr *E) { 954 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 955 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 956 return LValue(); 957 } 958 959 void ReductionCodeGen::emitAggregateInitialization( 960 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 961 const OMPDeclareReductionDecl *DRD) { 962 // Emit VarDecl with copy init for arrays. 963 // Get the address of the original variable captured in current 964 // captured region. 965 const auto *PrivateVD = 966 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 967 bool EmitDeclareReductionInit = 968 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 969 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 970 EmitDeclareReductionInit, 971 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 972 : PrivateVD->getInit(), 973 DRD, SharedLVal.getAddress(CGF)); 974 } 975 976 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 977 ArrayRef<const Expr *> Privates, 978 ArrayRef<const Expr *> ReductionOps) { 979 ClausesData.reserve(Shareds.size()); 980 SharedAddresses.reserve(Shareds.size()); 981 Sizes.reserve(Shareds.size()); 982 BaseDecls.reserve(Shareds.size()); 983 auto IPriv = Privates.begin(); 984 auto IRed = ReductionOps.begin(); 985 for (const Expr *Ref : Shareds) { 986 ClausesData.emplace_back(Ref, *IPriv, *IRed); 987 std::advance(IPriv, 1); 988 std::advance(IRed, 1); 989 } 990 } 991 992 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 993 assert(SharedAddresses.size() == N && 994 "Number of generated lvalues must be exactly N."); 995 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 996 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 997 SharedAddresses.emplace_back(First, Second); 998 } 999 1000 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 1001 const auto *PrivateVD = 1002 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1003 QualType PrivateType = PrivateVD->getType(); 1004 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1005 if (!PrivateType->isVariablyModifiedType()) { 1006 Sizes.emplace_back( 1007 CGF.getTypeSize( 1008 SharedAddresses[N].first.getType().getNonReferenceType()), 1009 nullptr); 1010 return; 1011 } 1012 llvm::Value *Size; 1013 llvm::Value *SizeInChars; 1014 auto *ElemType = cast<llvm::PointerType>( 1015 SharedAddresses[N].first.getPointer(CGF)->getType()) 1016 ->getElementType(); 1017 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1018 if (AsArraySection) { 1019 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF), 1020 SharedAddresses[N].first.getPointer(CGF)); 1021 Size = CGF.Builder.CreateNUWAdd( 1022 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1023 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1024 } else { 1025 SizeInChars = CGF.getTypeSize( 1026 SharedAddresses[N].first.getType().getNonReferenceType()); 1027 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1028 } 1029 Sizes.emplace_back(SizeInChars, Size); 1030 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1031 CGF, 1032 cast<OpaqueValueExpr>( 1033 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1034 RValue::get(Size)); 1035 CGF.EmitVariablyModifiedType(PrivateType); 1036 } 1037 1038 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1039 llvm::Value *Size) { 1040 const auto *PrivateVD = 1041 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1042 QualType PrivateType = PrivateVD->getType(); 1043 if (!PrivateType->isVariablyModifiedType()) { 1044 assert(!Size && !Sizes[N].second && 1045 "Size should be nullptr for non-variably modified reduction " 1046 "items."); 1047 return; 1048 } 1049 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1050 CGF, 1051 cast<OpaqueValueExpr>( 1052 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1053 RValue::get(Size)); 1054 CGF.EmitVariablyModifiedType(PrivateType); 1055 } 1056 1057 void ReductionCodeGen::emitInitialization( 1058 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1059 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1060 assert(SharedAddresses.size() > N && "No variable was generated"); 1061 const auto *PrivateVD = 1062 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1063 const OMPDeclareReductionDecl *DRD = 1064 getReductionInit(ClausesData[N].ReductionOp); 1065 QualType PrivateType = PrivateVD->getType(); 1066 PrivateAddr = CGF.Builder.CreateElementBitCast( 1067 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1068 QualType SharedType = SharedAddresses[N].first.getType(); 1069 SharedLVal = CGF.MakeAddrLValue( 1070 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 1071 CGF.ConvertTypeForMem(SharedType)), 1072 SharedType, SharedAddresses[N].first.getBaseInfo(), 1073 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1074 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1075 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1076 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1077 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1078 PrivateAddr, SharedLVal.getAddress(CGF), 1079 SharedLVal.getType()); 1080 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1081 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1082 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1083 PrivateVD->getType().getQualifiers(), 1084 /*IsInitializer=*/false); 1085 } 1086 } 1087 1088 bool ReductionCodeGen::needCleanups(unsigned N) { 1089 const auto *PrivateVD = 1090 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1091 QualType PrivateType = PrivateVD->getType(); 1092 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1093 return DTorKind != QualType::DK_none; 1094 } 1095 1096 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1097 Address PrivateAddr) { 1098 const auto *PrivateVD = 1099 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1100 QualType PrivateType = PrivateVD->getType(); 1101 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1102 if (needCleanups(N)) { 1103 PrivateAddr = CGF.Builder.CreateElementBitCast( 1104 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1105 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1106 } 1107 } 1108 1109 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1110 LValue BaseLV) { 1111 BaseTy = BaseTy.getNonReferenceType(); 1112 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1113 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1114 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1115 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 1116 } else { 1117 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 1118 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1119 } 1120 BaseTy = BaseTy->getPointeeType(); 1121 } 1122 return CGF.MakeAddrLValue( 1123 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 1124 CGF.ConvertTypeForMem(ElTy)), 1125 BaseLV.getType(), BaseLV.getBaseInfo(), 1126 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1127 } 1128 1129 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1130 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1131 llvm::Value *Addr) { 1132 Address Tmp = Address::invalid(); 1133 Address TopTmp = Address::invalid(); 1134 Address MostTopTmp = Address::invalid(); 1135 BaseTy = BaseTy.getNonReferenceType(); 1136 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1137 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1138 Tmp = CGF.CreateMemTemp(BaseTy); 1139 if (TopTmp.isValid()) 1140 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1141 else 1142 MostTopTmp = Tmp; 1143 TopTmp = Tmp; 1144 BaseTy = BaseTy->getPointeeType(); 1145 } 1146 llvm::Type *Ty = BaseLVType; 1147 if (Tmp.isValid()) 1148 Ty = Tmp.getElementType(); 1149 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1150 if (Tmp.isValid()) { 1151 CGF.Builder.CreateStore(Addr, Tmp); 1152 return MostTopTmp; 1153 } 1154 return Address(Addr, BaseLVAlignment); 1155 } 1156 1157 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1158 const VarDecl *OrigVD = nullptr; 1159 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1160 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1161 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1162 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1163 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1164 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1165 DE = cast<DeclRefExpr>(Base); 1166 OrigVD = cast<VarDecl>(DE->getDecl()); 1167 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1168 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1169 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1170 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1171 DE = cast<DeclRefExpr>(Base); 1172 OrigVD = cast<VarDecl>(DE->getDecl()); 1173 } 1174 return OrigVD; 1175 } 1176 1177 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1178 Address PrivateAddr) { 1179 const DeclRefExpr *DE; 1180 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1181 BaseDecls.emplace_back(OrigVD); 1182 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1183 LValue BaseLValue = 1184 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1185 OriginalBaseLValue); 1186 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1187 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1188 llvm::Value *PrivatePointer = 1189 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1190 PrivateAddr.getPointer(), 1191 SharedAddresses[N].first.getAddress(CGF).getType()); 1192 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1193 return castToBase(CGF, OrigVD->getType(), 1194 SharedAddresses[N].first.getType(), 1195 OriginalBaseLValue.getAddress(CGF).getType(), 1196 OriginalBaseLValue.getAlignment(), Ptr); 1197 } 1198 BaseDecls.emplace_back( 1199 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1200 return PrivateAddr; 1201 } 1202 1203 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1204 const OMPDeclareReductionDecl *DRD = 1205 getReductionInit(ClausesData[N].ReductionOp); 1206 return DRD && DRD->getInitializer(); 1207 } 1208 1209 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1210 return CGF.EmitLoadOfPointerLValue( 1211 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1212 getThreadIDVariable()->getType()->castAs<PointerType>()); 1213 } 1214 1215 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1216 if (!CGF.HaveInsertPoint()) 1217 return; 1218 // 1.2.2 OpenMP Language Terminology 1219 // Structured block - An executable statement with a single entry at the 1220 // top and a single exit at the bottom. 1221 // The point of exit cannot be a branch out of the structured block. 1222 // longjmp() and throw() must not violate the entry/exit criteria. 1223 CGF.EHStack.pushTerminate(); 1224 CodeGen(CGF); 1225 CGF.EHStack.popTerminate(); 1226 } 1227 1228 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1229 CodeGenFunction &CGF) { 1230 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1231 getThreadIDVariable()->getType(), 1232 AlignmentSource::Decl); 1233 } 1234 1235 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1236 QualType FieldTy) { 1237 auto *Field = FieldDecl::Create( 1238 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1239 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1240 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1241 Field->setAccess(AS_public); 1242 DC->addDecl(Field); 1243 return Field; 1244 } 1245 1246 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1247 StringRef Separator) 1248 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1249 OffloadEntriesInfoManager(CGM) { 1250 ASTContext &C = CGM.getContext(); 1251 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1252 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1253 RD->startDefinition(); 1254 // reserved_1 1255 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1256 // flags 1257 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1258 // reserved_2 1259 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1260 // reserved_3 1261 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1262 // psource 1263 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1264 RD->completeDefinition(); 1265 IdentQTy = C.getRecordType(RD); 1266 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1267 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1268 1269 loadOffloadInfoMetadata(); 1270 } 1271 1272 bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD, 1273 const GlobalDecl &OldGD, 1274 llvm::GlobalValue *OrigAddr, 1275 bool IsForDefinition) { 1276 // Emit at least a definition for the aliasee if the the address of the 1277 // original function is requested. 1278 if (IsForDefinition || OrigAddr) 1279 (void)CGM.GetAddrOfGlobal(NewGD); 1280 StringRef NewMangledName = CGM.getMangledName(NewGD); 1281 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName); 1282 if (Addr && !Addr->isDeclaration()) { 1283 const auto *D = cast<FunctionDecl>(OldGD.getDecl()); 1284 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(NewGD); 1285 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI); 1286 1287 // Create a reference to the named value. This ensures that it is emitted 1288 // if a deferred decl. 1289 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD); 1290 1291 // Create the new alias itself, but don't set a name yet. 1292 auto *GA = 1293 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule()); 1294 1295 if (OrigAddr) { 1296 assert(OrigAddr->isDeclaration() && "Expected declaration"); 1297 1298 GA->takeName(OrigAddr); 1299 OrigAddr->replaceAllUsesWith( 1300 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType())); 1301 OrigAddr->eraseFromParent(); 1302 } else { 1303 GA->setName(CGM.getMangledName(OldGD)); 1304 } 1305 1306 // Set attributes which are particular to an alias; this is a 1307 // specialization of the attributes which may be set on a global function. 1308 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || 1309 D->isWeakImported()) 1310 GA->setLinkage(llvm::Function::WeakAnyLinkage); 1311 1312 CGM.SetCommonAttributes(OldGD, GA); 1313 return true; 1314 } 1315 return false; 1316 } 1317 1318 void CGOpenMPRuntime::clear() { 1319 InternalVars.clear(); 1320 // Clean non-target variable declarations possibly used only in debug info. 1321 for (const auto &Data : EmittedNonTargetVariables) { 1322 if (!Data.getValue().pointsToAliveValue()) 1323 continue; 1324 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1325 if (!GV) 1326 continue; 1327 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1328 continue; 1329 GV->eraseFromParent(); 1330 } 1331 // Emit aliases for the deferred aliasees. 1332 for (const auto &Pair : DeferredVariantFunction) { 1333 StringRef MangledName = CGM.getMangledName(Pair.second.second); 1334 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName); 1335 // If not able to emit alias, just emit original declaration. 1336 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr, 1337 /*IsForDefinition=*/false); 1338 } 1339 } 1340 1341 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1342 SmallString<128> Buffer; 1343 llvm::raw_svector_ostream OS(Buffer); 1344 StringRef Sep = FirstSeparator; 1345 for (StringRef Part : Parts) { 1346 OS << Sep << Part; 1347 Sep = Separator; 1348 } 1349 return std::string(OS.str()); 1350 } 1351 1352 static llvm::Function * 1353 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1354 const Expr *CombinerInitializer, const VarDecl *In, 1355 const VarDecl *Out, bool IsCombiner) { 1356 // void .omp_combiner.(Ty *in, Ty *out); 1357 ASTContext &C = CGM.getContext(); 1358 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1359 FunctionArgList Args; 1360 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1361 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1362 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1363 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1364 Args.push_back(&OmpOutParm); 1365 Args.push_back(&OmpInParm); 1366 const CGFunctionInfo &FnInfo = 1367 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1368 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1369 std::string Name = CGM.getOpenMPRuntime().getName( 1370 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1371 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1372 Name, &CGM.getModule()); 1373 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1374 if (CGM.getLangOpts().Optimize) { 1375 Fn->removeFnAttr(llvm::Attribute::NoInline); 1376 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1377 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1378 } 1379 CodeGenFunction CGF(CGM); 1380 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1381 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1382 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1383 Out->getLocation()); 1384 CodeGenFunction::OMPPrivateScope Scope(CGF); 1385 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1386 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1387 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1388 .getAddress(CGF); 1389 }); 1390 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1391 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1392 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1393 .getAddress(CGF); 1394 }); 1395 (void)Scope.Privatize(); 1396 if (!IsCombiner && Out->hasInit() && 1397 !CGF.isTrivialInitializer(Out->getInit())) { 1398 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1399 Out->getType().getQualifiers(), 1400 /*IsInitializer=*/true); 1401 } 1402 if (CombinerInitializer) 1403 CGF.EmitIgnoredExpr(CombinerInitializer); 1404 Scope.ForceCleanup(); 1405 CGF.FinishFunction(); 1406 return Fn; 1407 } 1408 1409 void CGOpenMPRuntime::emitUserDefinedReduction( 1410 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1411 if (UDRMap.count(D) > 0) 1412 return; 1413 llvm::Function *Combiner = emitCombinerOrInitializer( 1414 CGM, D->getType(), D->getCombiner(), 1415 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1416 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1417 /*IsCombiner=*/true); 1418 llvm::Function *Initializer = nullptr; 1419 if (const Expr *Init = D->getInitializer()) { 1420 Initializer = emitCombinerOrInitializer( 1421 CGM, D->getType(), 1422 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1423 : nullptr, 1424 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1425 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1426 /*IsCombiner=*/false); 1427 } 1428 UDRMap.try_emplace(D, Combiner, Initializer); 1429 if (CGF) { 1430 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1431 Decls.second.push_back(D); 1432 } 1433 } 1434 1435 std::pair<llvm::Function *, llvm::Function *> 1436 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1437 auto I = UDRMap.find(D); 1438 if (I != UDRMap.end()) 1439 return I->second; 1440 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1441 return UDRMap.lookup(D); 1442 } 1443 1444 namespace { 1445 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1446 // Builder if one is present. 1447 struct PushAndPopStackRAII { 1448 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1449 bool HasCancel) 1450 : OMPBuilder(OMPBuilder) { 1451 if (!OMPBuilder) 1452 return; 1453 1454 // The following callback is the crucial part of clangs cleanup process. 1455 // 1456 // NOTE: 1457 // Once the OpenMPIRBuilder is used to create parallel regions (and 1458 // similar), the cancellation destination (Dest below) is determined via 1459 // IP. That means if we have variables to finalize we split the block at IP, 1460 // use the new block (=BB) as destination to build a JumpDest (via 1461 // getJumpDestInCurrentScope(BB)) which then is fed to 1462 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1463 // to push & pop an FinalizationInfo object. 1464 // The FiniCB will still be needed but at the point where the 1465 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1466 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1467 assert(IP.getBlock()->end() == IP.getPoint() && 1468 "Clang CG should cause non-terminated block!"); 1469 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1470 CGF.Builder.restoreIP(IP); 1471 CodeGenFunction::JumpDest Dest = 1472 CGF.getOMPCancelDestination(OMPD_parallel); 1473 CGF.EmitBranchThroughCleanup(Dest); 1474 }; 1475 1476 // TODO: Remove this once we emit parallel regions through the 1477 // OpenMPIRBuilder as it can do this setup internally. 1478 llvm::OpenMPIRBuilder::FinalizationInfo FI( 1479 {FiniCB, OMPD_parallel, HasCancel}); 1480 OMPBuilder->pushFinalizationCB(std::move(FI)); 1481 } 1482 ~PushAndPopStackRAII() { 1483 if (OMPBuilder) 1484 OMPBuilder->popFinalizationCB(); 1485 } 1486 llvm::OpenMPIRBuilder *OMPBuilder; 1487 }; 1488 } // namespace 1489 1490 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1491 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1492 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1493 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1494 assert(ThreadIDVar->getType()->isPointerType() && 1495 "thread id variable must be of type kmp_int32 *"); 1496 CodeGenFunction CGF(CGM, true); 1497 bool HasCancel = false; 1498 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1499 HasCancel = OPD->hasCancel(); 1500 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1501 HasCancel = OPSD->hasCancel(); 1502 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1503 HasCancel = OPFD->hasCancel(); 1504 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1505 HasCancel = OPFD->hasCancel(); 1506 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1507 HasCancel = OPFD->hasCancel(); 1508 else if (const auto *OPFD = 1509 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1510 HasCancel = OPFD->hasCancel(); 1511 else if (const auto *OPFD = 1512 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1513 HasCancel = OPFD->hasCancel(); 1514 1515 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1516 // parallel region to make cancellation barriers work properly. 1517 llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder(); 1518 PushAndPopStackRAII PSR(OMPBuilder, CGF, HasCancel); 1519 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1520 HasCancel, OutlinedHelperName); 1521 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1522 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1523 } 1524 1525 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1526 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1527 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1528 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1529 return emitParallelOrTeamsOutlinedFunction( 1530 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1531 } 1532 1533 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1534 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1535 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1536 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1537 return emitParallelOrTeamsOutlinedFunction( 1538 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1539 } 1540 1541 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1542 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1543 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1544 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1545 bool Tied, unsigned &NumberOfParts) { 1546 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1547 PrePostActionTy &) { 1548 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1549 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1550 llvm::Value *TaskArgs[] = { 1551 UpLoc, ThreadID, 1552 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1553 TaskTVar->getType()->castAs<PointerType>()) 1554 .getPointer(CGF)}; 1555 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1556 }; 1557 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1558 UntiedCodeGen); 1559 CodeGen.setAction(Action); 1560 assert(!ThreadIDVar->getType()->isPointerType() && 1561 "thread id variable must be of type kmp_int32 for tasks"); 1562 const OpenMPDirectiveKind Region = 1563 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1564 : OMPD_task; 1565 const CapturedStmt *CS = D.getCapturedStmt(Region); 1566 bool HasCancel = false; 1567 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D)) 1568 HasCancel = TD->hasCancel(); 1569 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D)) 1570 HasCancel = TD->hasCancel(); 1571 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D)) 1572 HasCancel = TD->hasCancel(); 1573 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D)) 1574 HasCancel = TD->hasCancel(); 1575 1576 CodeGenFunction CGF(CGM, true); 1577 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1578 InnermostKind, HasCancel, Action); 1579 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1580 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1581 if (!Tied) 1582 NumberOfParts = Action.getNumberOfParts(); 1583 return Res; 1584 } 1585 1586 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1587 const RecordDecl *RD, const CGRecordLayout &RL, 1588 ArrayRef<llvm::Constant *> Data) { 1589 llvm::StructType *StructTy = RL.getLLVMType(); 1590 unsigned PrevIdx = 0; 1591 ConstantInitBuilder CIBuilder(CGM); 1592 auto DI = Data.begin(); 1593 for (const FieldDecl *FD : RD->fields()) { 1594 unsigned Idx = RL.getLLVMFieldNo(FD); 1595 // Fill the alignment. 1596 for (unsigned I = PrevIdx; I < Idx; ++I) 1597 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1598 PrevIdx = Idx + 1; 1599 Fields.add(*DI); 1600 ++DI; 1601 } 1602 } 1603 1604 template <class... As> 1605 static llvm::GlobalVariable * 1606 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1607 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1608 As &&... Args) { 1609 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1610 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1611 ConstantInitBuilder CIBuilder(CGM); 1612 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1613 buildStructValue(Fields, CGM, RD, RL, Data); 1614 return Fields.finishAndCreateGlobal( 1615 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1616 std::forward<As>(Args)...); 1617 } 1618 1619 template <typename T> 1620 static void 1621 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1622 ArrayRef<llvm::Constant *> Data, 1623 T &Parent) { 1624 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1625 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1626 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1627 buildStructValue(Fields, CGM, RD, RL, Data); 1628 Fields.finishAndAddTo(Parent); 1629 } 1630 1631 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1632 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1633 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1634 FlagsTy FlagsKey(Flags, Reserved2Flags); 1635 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1636 if (!Entry) { 1637 if (!DefaultOpenMPPSource) { 1638 // Initialize default location for psource field of ident_t structure of 1639 // all ident_t objects. Format is ";file;function;line;column;;". 1640 // Taken from 1641 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1642 DefaultOpenMPPSource = 1643 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1644 DefaultOpenMPPSource = 1645 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1646 } 1647 1648 llvm::Constant *Data[] = { 1649 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1650 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1651 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1652 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1653 llvm::GlobalValue *DefaultOpenMPLocation = 1654 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1655 llvm::GlobalValue::PrivateLinkage); 1656 DefaultOpenMPLocation->setUnnamedAddr( 1657 llvm::GlobalValue::UnnamedAddr::Global); 1658 1659 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1660 } 1661 return Address(Entry, Align); 1662 } 1663 1664 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1665 bool AtCurrentPoint) { 1666 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1667 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1668 1669 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1670 if (AtCurrentPoint) { 1671 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1672 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1673 } else { 1674 Elem.second.ServiceInsertPt = 1675 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1676 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1677 } 1678 } 1679 1680 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1681 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1682 if (Elem.second.ServiceInsertPt) { 1683 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1684 Elem.second.ServiceInsertPt = nullptr; 1685 Ptr->eraseFromParent(); 1686 } 1687 } 1688 1689 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1690 SourceLocation Loc, 1691 unsigned Flags) { 1692 Flags |= OMP_IDENT_KMPC; 1693 // If no debug info is generated - return global default location. 1694 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1695 Loc.isInvalid()) 1696 return getOrCreateDefaultLocation(Flags).getPointer(); 1697 1698 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1699 1700 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1701 Address LocValue = Address::invalid(); 1702 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1703 if (I != OpenMPLocThreadIDMap.end()) 1704 LocValue = Address(I->second.DebugLoc, Align); 1705 1706 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1707 // GetOpenMPThreadID was called before this routine. 1708 if (!LocValue.isValid()) { 1709 // Generate "ident_t .kmpc_loc.addr;" 1710 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1711 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1712 Elem.second.DebugLoc = AI.getPointer(); 1713 LocValue = AI; 1714 1715 if (!Elem.second.ServiceInsertPt) 1716 setLocThreadIdInsertPt(CGF); 1717 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1718 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1719 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1720 CGF.getTypeSize(IdentQTy)); 1721 } 1722 1723 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1724 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1725 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1726 LValue PSource = 1727 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1728 1729 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1730 if (OMPDebugLoc == nullptr) { 1731 SmallString<128> Buffer2; 1732 llvm::raw_svector_ostream OS2(Buffer2); 1733 // Build debug location 1734 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1735 OS2 << ";" << PLoc.getFilename() << ";"; 1736 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1737 OS2 << FD->getQualifiedNameAsString(); 1738 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1739 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1740 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1741 } 1742 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1743 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1744 1745 // Our callers always pass this to a runtime function, so for 1746 // convenience, go ahead and return a naked pointer. 1747 return LocValue.getPointer(); 1748 } 1749 1750 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1751 SourceLocation Loc) { 1752 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1753 1754 llvm::Value *ThreadID = nullptr; 1755 // Check whether we've already cached a load of the thread id in this 1756 // function. 1757 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1758 if (I != OpenMPLocThreadIDMap.end()) { 1759 ThreadID = I->second.ThreadID; 1760 if (ThreadID != nullptr) 1761 return ThreadID; 1762 } 1763 // If exceptions are enabled, do not use parameter to avoid possible crash. 1764 if (auto *OMPRegionInfo = 1765 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1766 if (OMPRegionInfo->getThreadIDVariable()) { 1767 // Check if this an outlined function with thread id passed as argument. 1768 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1769 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1770 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1771 !CGF.getLangOpts().CXXExceptions || 1772 CGF.Builder.GetInsertBlock() == TopBlock || 1773 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1774 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1775 TopBlock || 1776 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1777 CGF.Builder.GetInsertBlock()) { 1778 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1779 // If value loaded in entry block, cache it and use it everywhere in 1780 // function. 1781 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1782 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1783 Elem.second.ThreadID = ThreadID; 1784 } 1785 return ThreadID; 1786 } 1787 } 1788 } 1789 1790 // This is not an outlined function region - need to call __kmpc_int32 1791 // kmpc_global_thread_num(ident_t *loc). 1792 // Generate thread id value and cache this value for use across the 1793 // function. 1794 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1795 if (!Elem.second.ServiceInsertPt) 1796 setLocThreadIdInsertPt(CGF); 1797 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1798 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1799 llvm::CallInst *Call = CGF.Builder.CreateCall( 1800 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1801 emitUpdateLocation(CGF, Loc)); 1802 Call->setCallingConv(CGF.getRuntimeCC()); 1803 Elem.second.ThreadID = Call; 1804 return Call; 1805 } 1806 1807 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1808 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1809 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1810 clearLocThreadIdInsertPt(CGF); 1811 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1812 } 1813 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1814 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1815 UDRMap.erase(D); 1816 FunctionUDRMap.erase(CGF.CurFn); 1817 } 1818 auto I = FunctionUDMMap.find(CGF.CurFn); 1819 if (I != FunctionUDMMap.end()) { 1820 for(const auto *D : I->second) 1821 UDMMap.erase(D); 1822 FunctionUDMMap.erase(I); 1823 } 1824 LastprivateConditionalToTypes.erase(CGF.CurFn); 1825 } 1826 1827 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1828 return IdentTy->getPointerTo(); 1829 } 1830 1831 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1832 if (!Kmpc_MicroTy) { 1833 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1834 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1835 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1836 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1837 } 1838 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1839 } 1840 1841 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1842 llvm::FunctionCallee RTLFn = nullptr; 1843 switch (static_cast<OpenMPRTLFunction>(Function)) { 1844 case OMPRTL__kmpc_fork_call: { 1845 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1846 // microtask, ...); 1847 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1848 getKmpc_MicroPointerTy()}; 1849 auto *FnTy = 1850 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1851 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1852 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1853 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1854 llvm::LLVMContext &Ctx = F->getContext(); 1855 llvm::MDBuilder MDB(Ctx); 1856 // Annotate the callback behavior of the __kmpc_fork_call: 1857 // - The callback callee is argument number 2 (microtask). 1858 // - The first two arguments of the callback callee are unknown (-1). 1859 // - All variadic arguments to the __kmpc_fork_call are passed to the 1860 // callback callee. 1861 F->addMetadata( 1862 llvm::LLVMContext::MD_callback, 1863 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1864 2, {-1, -1}, 1865 /* VarArgsArePassed */ true)})); 1866 } 1867 } 1868 break; 1869 } 1870 case OMPRTL__kmpc_global_thread_num: { 1871 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1872 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1873 auto *FnTy = 1874 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1875 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1876 break; 1877 } 1878 case OMPRTL__kmpc_threadprivate_cached: { 1879 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1880 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1881 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1882 CGM.VoidPtrTy, CGM.SizeTy, 1883 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1884 auto *FnTy = 1885 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1886 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1887 break; 1888 } 1889 case OMPRTL__kmpc_critical: { 1890 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1891 // kmp_critical_name *crit); 1892 llvm::Type *TypeParams[] = { 1893 getIdentTyPointerTy(), CGM.Int32Ty, 1894 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1895 auto *FnTy = 1896 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1897 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1898 break; 1899 } 1900 case OMPRTL__kmpc_critical_with_hint: { 1901 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1902 // kmp_critical_name *crit, uintptr_t hint); 1903 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1904 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1905 CGM.IntPtrTy}; 1906 auto *FnTy = 1907 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1908 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1909 break; 1910 } 1911 case OMPRTL__kmpc_threadprivate_register: { 1912 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1913 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1914 // typedef void *(*kmpc_ctor)(void *); 1915 auto *KmpcCtorTy = 1916 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1917 /*isVarArg*/ false)->getPointerTo(); 1918 // typedef void *(*kmpc_cctor)(void *, void *); 1919 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1920 auto *KmpcCopyCtorTy = 1921 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1922 /*isVarArg*/ false) 1923 ->getPointerTo(); 1924 // typedef void (*kmpc_dtor)(void *); 1925 auto *KmpcDtorTy = 1926 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1927 ->getPointerTo(); 1928 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1929 KmpcCopyCtorTy, KmpcDtorTy}; 1930 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1931 /*isVarArg*/ false); 1932 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1933 break; 1934 } 1935 case OMPRTL__kmpc_end_critical: { 1936 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1937 // kmp_critical_name *crit); 1938 llvm::Type *TypeParams[] = { 1939 getIdentTyPointerTy(), CGM.Int32Ty, 1940 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1941 auto *FnTy = 1942 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1943 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1944 break; 1945 } 1946 case OMPRTL__kmpc_cancel_barrier: { 1947 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1948 // global_tid); 1949 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1950 auto *FnTy = 1951 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1952 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1953 break; 1954 } 1955 case OMPRTL__kmpc_barrier: { 1956 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1957 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1958 auto *FnTy = 1959 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1960 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1961 break; 1962 } 1963 case OMPRTL__kmpc_for_static_fini: { 1964 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1965 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1966 auto *FnTy = 1967 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1968 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1969 break; 1970 } 1971 case OMPRTL__kmpc_push_num_threads: { 1972 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1973 // kmp_int32 num_threads) 1974 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1975 CGM.Int32Ty}; 1976 auto *FnTy = 1977 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1978 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1979 break; 1980 } 1981 case OMPRTL__kmpc_serialized_parallel: { 1982 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1983 // global_tid); 1984 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1985 auto *FnTy = 1986 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1987 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1988 break; 1989 } 1990 case OMPRTL__kmpc_end_serialized_parallel: { 1991 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1992 // global_tid); 1993 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1994 auto *FnTy = 1995 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1996 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1997 break; 1998 } 1999 case OMPRTL__kmpc_flush: { 2000 // Build void __kmpc_flush(ident_t *loc); 2001 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 2002 auto *FnTy = 2003 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2004 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 2005 break; 2006 } 2007 case OMPRTL__kmpc_master: { 2008 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 2009 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2010 auto *FnTy = 2011 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2012 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 2013 break; 2014 } 2015 case OMPRTL__kmpc_end_master: { 2016 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 2017 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2018 auto *FnTy = 2019 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2020 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 2021 break; 2022 } 2023 case OMPRTL__kmpc_omp_taskyield: { 2024 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 2025 // int end_part); 2026 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2027 auto *FnTy = 2028 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2029 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 2030 break; 2031 } 2032 case OMPRTL__kmpc_single: { 2033 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 2034 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2035 auto *FnTy = 2036 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2037 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 2038 break; 2039 } 2040 case OMPRTL__kmpc_end_single: { 2041 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 2042 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2043 auto *FnTy = 2044 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2045 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 2046 break; 2047 } 2048 case OMPRTL__kmpc_omp_task_alloc: { 2049 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 2050 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2051 // kmp_routine_entry_t *task_entry); 2052 assert(KmpRoutineEntryPtrTy != nullptr && 2053 "Type kmp_routine_entry_t must be created."); 2054 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2055 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 2056 // Return void * and then cast to particular kmp_task_t type. 2057 auto *FnTy = 2058 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2059 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 2060 break; 2061 } 2062 case OMPRTL__kmpc_omp_target_task_alloc: { 2063 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 2064 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2065 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 2066 assert(KmpRoutineEntryPtrTy != nullptr && 2067 "Type kmp_routine_entry_t must be created."); 2068 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2069 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 2070 CGM.Int64Ty}; 2071 // Return void * and then cast to particular kmp_task_t type. 2072 auto *FnTy = 2073 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2074 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2075 break; 2076 } 2077 case OMPRTL__kmpc_omp_task: { 2078 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2079 // *new_task); 2080 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2081 CGM.VoidPtrTy}; 2082 auto *FnTy = 2083 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2084 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2085 break; 2086 } 2087 case OMPRTL__kmpc_copyprivate: { 2088 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2089 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2090 // kmp_int32 didit); 2091 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2092 auto *CpyFnTy = 2093 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2094 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2095 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2096 CGM.Int32Ty}; 2097 auto *FnTy = 2098 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2099 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2100 break; 2101 } 2102 case OMPRTL__kmpc_reduce: { 2103 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2104 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2105 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2106 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2107 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2108 /*isVarArg=*/false); 2109 llvm::Type *TypeParams[] = { 2110 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2111 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2112 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2113 auto *FnTy = 2114 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2115 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2116 break; 2117 } 2118 case OMPRTL__kmpc_reduce_nowait: { 2119 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2120 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2121 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2122 // *lck); 2123 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2124 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2125 /*isVarArg=*/false); 2126 llvm::Type *TypeParams[] = { 2127 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2128 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2129 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2130 auto *FnTy = 2131 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2132 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2133 break; 2134 } 2135 case OMPRTL__kmpc_end_reduce: { 2136 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2137 // kmp_critical_name *lck); 2138 llvm::Type *TypeParams[] = { 2139 getIdentTyPointerTy(), CGM.Int32Ty, 2140 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2141 auto *FnTy = 2142 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2143 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2144 break; 2145 } 2146 case OMPRTL__kmpc_end_reduce_nowait: { 2147 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2148 // kmp_critical_name *lck); 2149 llvm::Type *TypeParams[] = { 2150 getIdentTyPointerTy(), CGM.Int32Ty, 2151 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2152 auto *FnTy = 2153 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2154 RTLFn = 2155 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2156 break; 2157 } 2158 case OMPRTL__kmpc_omp_task_begin_if0: { 2159 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2160 // *new_task); 2161 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2162 CGM.VoidPtrTy}; 2163 auto *FnTy = 2164 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2165 RTLFn = 2166 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2167 break; 2168 } 2169 case OMPRTL__kmpc_omp_task_complete_if0: { 2170 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2171 // *new_task); 2172 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2173 CGM.VoidPtrTy}; 2174 auto *FnTy = 2175 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2176 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2177 /*Name=*/"__kmpc_omp_task_complete_if0"); 2178 break; 2179 } 2180 case OMPRTL__kmpc_ordered: { 2181 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2182 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2183 auto *FnTy = 2184 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2185 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2186 break; 2187 } 2188 case OMPRTL__kmpc_end_ordered: { 2189 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2190 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2191 auto *FnTy = 2192 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2193 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2194 break; 2195 } 2196 case OMPRTL__kmpc_omp_taskwait: { 2197 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2198 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2199 auto *FnTy = 2200 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2201 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2202 break; 2203 } 2204 case OMPRTL__kmpc_taskgroup: { 2205 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2206 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2207 auto *FnTy = 2208 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2209 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2210 break; 2211 } 2212 case OMPRTL__kmpc_end_taskgroup: { 2213 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2214 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2215 auto *FnTy = 2216 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2217 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2218 break; 2219 } 2220 case OMPRTL__kmpc_push_proc_bind: { 2221 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2222 // int proc_bind) 2223 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2224 auto *FnTy = 2225 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2226 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2227 break; 2228 } 2229 case OMPRTL__kmpc_omp_task_with_deps: { 2230 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2231 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2232 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2233 llvm::Type *TypeParams[] = { 2234 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2235 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2236 auto *FnTy = 2237 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2238 RTLFn = 2239 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2240 break; 2241 } 2242 case OMPRTL__kmpc_omp_wait_deps: { 2243 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2244 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2245 // kmp_depend_info_t *noalias_dep_list); 2246 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2247 CGM.Int32Ty, CGM.VoidPtrTy, 2248 CGM.Int32Ty, CGM.VoidPtrTy}; 2249 auto *FnTy = 2250 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2251 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2252 break; 2253 } 2254 case OMPRTL__kmpc_cancellationpoint: { 2255 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2256 // global_tid, kmp_int32 cncl_kind) 2257 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2258 auto *FnTy = 2259 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2260 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2261 break; 2262 } 2263 case OMPRTL__kmpc_cancel: { 2264 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2265 // kmp_int32 cncl_kind) 2266 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2267 auto *FnTy = 2268 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2269 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2270 break; 2271 } 2272 case OMPRTL__kmpc_push_num_teams: { 2273 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2274 // kmp_int32 num_teams, kmp_int32 num_threads) 2275 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2276 CGM.Int32Ty}; 2277 auto *FnTy = 2278 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2279 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2280 break; 2281 } 2282 case OMPRTL__kmpc_fork_teams: { 2283 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2284 // microtask, ...); 2285 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2286 getKmpc_MicroPointerTy()}; 2287 auto *FnTy = 2288 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2289 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2290 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2291 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2292 llvm::LLVMContext &Ctx = F->getContext(); 2293 llvm::MDBuilder MDB(Ctx); 2294 // Annotate the callback behavior of the __kmpc_fork_teams: 2295 // - The callback callee is argument number 2 (microtask). 2296 // - The first two arguments of the callback callee are unknown (-1). 2297 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2298 // callback callee. 2299 F->addMetadata( 2300 llvm::LLVMContext::MD_callback, 2301 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2302 2, {-1, -1}, 2303 /* VarArgsArePassed */ true)})); 2304 } 2305 } 2306 break; 2307 } 2308 case OMPRTL__kmpc_taskloop: { 2309 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2310 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2311 // sched, kmp_uint64 grainsize, void *task_dup); 2312 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2313 CGM.IntTy, 2314 CGM.VoidPtrTy, 2315 CGM.IntTy, 2316 CGM.Int64Ty->getPointerTo(), 2317 CGM.Int64Ty->getPointerTo(), 2318 CGM.Int64Ty, 2319 CGM.IntTy, 2320 CGM.IntTy, 2321 CGM.Int64Ty, 2322 CGM.VoidPtrTy}; 2323 auto *FnTy = 2324 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2325 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2326 break; 2327 } 2328 case OMPRTL__kmpc_doacross_init: { 2329 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2330 // num_dims, struct kmp_dim *dims); 2331 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2332 CGM.Int32Ty, 2333 CGM.Int32Ty, 2334 CGM.VoidPtrTy}; 2335 auto *FnTy = 2336 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2337 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2338 break; 2339 } 2340 case OMPRTL__kmpc_doacross_fini: { 2341 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2342 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2343 auto *FnTy = 2344 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2345 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2346 break; 2347 } 2348 case OMPRTL__kmpc_doacross_post: { 2349 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2350 // *vec); 2351 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2352 CGM.Int64Ty->getPointerTo()}; 2353 auto *FnTy = 2354 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2355 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2356 break; 2357 } 2358 case OMPRTL__kmpc_doacross_wait: { 2359 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2360 // *vec); 2361 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2362 CGM.Int64Ty->getPointerTo()}; 2363 auto *FnTy = 2364 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2365 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2366 break; 2367 } 2368 case OMPRTL__kmpc_task_reduction_init: { 2369 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2370 // *data); 2371 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2372 auto *FnTy = 2373 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2374 RTLFn = 2375 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2376 break; 2377 } 2378 case OMPRTL__kmpc_task_reduction_get_th_data: { 2379 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2380 // *d); 2381 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2382 auto *FnTy = 2383 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2384 RTLFn = CGM.CreateRuntimeFunction( 2385 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2386 break; 2387 } 2388 case OMPRTL__kmpc_alloc: { 2389 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2390 // al); omp_allocator_handle_t type is void *. 2391 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2392 auto *FnTy = 2393 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2394 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2395 break; 2396 } 2397 case OMPRTL__kmpc_free: { 2398 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2399 // al); omp_allocator_handle_t type is void *. 2400 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2401 auto *FnTy = 2402 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2403 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2404 break; 2405 } 2406 case OMPRTL__kmpc_push_target_tripcount: { 2407 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2408 // size); 2409 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2410 llvm::FunctionType *FnTy = 2411 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2412 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2413 break; 2414 } 2415 case OMPRTL__tgt_target: { 2416 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2417 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2418 // *arg_types); 2419 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2420 CGM.VoidPtrTy, 2421 CGM.Int32Ty, 2422 CGM.VoidPtrPtrTy, 2423 CGM.VoidPtrPtrTy, 2424 CGM.Int64Ty->getPointerTo(), 2425 CGM.Int64Ty->getPointerTo()}; 2426 auto *FnTy = 2427 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2428 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2429 break; 2430 } 2431 case OMPRTL__tgt_target_nowait: { 2432 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2433 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2434 // int64_t *arg_types); 2435 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2436 CGM.VoidPtrTy, 2437 CGM.Int32Ty, 2438 CGM.VoidPtrPtrTy, 2439 CGM.VoidPtrPtrTy, 2440 CGM.Int64Ty->getPointerTo(), 2441 CGM.Int64Ty->getPointerTo()}; 2442 auto *FnTy = 2443 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2444 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2445 break; 2446 } 2447 case OMPRTL__tgt_target_teams: { 2448 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2449 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2450 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2451 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2452 CGM.VoidPtrTy, 2453 CGM.Int32Ty, 2454 CGM.VoidPtrPtrTy, 2455 CGM.VoidPtrPtrTy, 2456 CGM.Int64Ty->getPointerTo(), 2457 CGM.Int64Ty->getPointerTo(), 2458 CGM.Int32Ty, 2459 CGM.Int32Ty}; 2460 auto *FnTy = 2461 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2462 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2463 break; 2464 } 2465 case OMPRTL__tgt_target_teams_nowait: { 2466 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2467 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2468 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2469 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2470 CGM.VoidPtrTy, 2471 CGM.Int32Ty, 2472 CGM.VoidPtrPtrTy, 2473 CGM.VoidPtrPtrTy, 2474 CGM.Int64Ty->getPointerTo(), 2475 CGM.Int64Ty->getPointerTo(), 2476 CGM.Int32Ty, 2477 CGM.Int32Ty}; 2478 auto *FnTy = 2479 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2480 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2481 break; 2482 } 2483 case OMPRTL__tgt_register_requires: { 2484 // Build void __tgt_register_requires(int64_t flags); 2485 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2486 auto *FnTy = 2487 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2488 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2489 break; 2490 } 2491 case OMPRTL__tgt_target_data_begin: { 2492 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2493 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2494 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2495 CGM.Int32Ty, 2496 CGM.VoidPtrPtrTy, 2497 CGM.VoidPtrPtrTy, 2498 CGM.Int64Ty->getPointerTo(), 2499 CGM.Int64Ty->getPointerTo()}; 2500 auto *FnTy = 2501 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2502 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2503 break; 2504 } 2505 case OMPRTL__tgt_target_data_begin_nowait: { 2506 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2507 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2508 // *arg_types); 2509 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2510 CGM.Int32Ty, 2511 CGM.VoidPtrPtrTy, 2512 CGM.VoidPtrPtrTy, 2513 CGM.Int64Ty->getPointerTo(), 2514 CGM.Int64Ty->getPointerTo()}; 2515 auto *FnTy = 2516 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2517 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2518 break; 2519 } 2520 case OMPRTL__tgt_target_data_end: { 2521 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2522 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2523 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2524 CGM.Int32Ty, 2525 CGM.VoidPtrPtrTy, 2526 CGM.VoidPtrPtrTy, 2527 CGM.Int64Ty->getPointerTo(), 2528 CGM.Int64Ty->getPointerTo()}; 2529 auto *FnTy = 2530 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2531 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2532 break; 2533 } 2534 case OMPRTL__tgt_target_data_end_nowait: { 2535 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2536 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2537 // *arg_types); 2538 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2539 CGM.Int32Ty, 2540 CGM.VoidPtrPtrTy, 2541 CGM.VoidPtrPtrTy, 2542 CGM.Int64Ty->getPointerTo(), 2543 CGM.Int64Ty->getPointerTo()}; 2544 auto *FnTy = 2545 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2546 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2547 break; 2548 } 2549 case OMPRTL__tgt_target_data_update: { 2550 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2551 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2552 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2553 CGM.Int32Ty, 2554 CGM.VoidPtrPtrTy, 2555 CGM.VoidPtrPtrTy, 2556 CGM.Int64Ty->getPointerTo(), 2557 CGM.Int64Ty->getPointerTo()}; 2558 auto *FnTy = 2559 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2560 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2561 break; 2562 } 2563 case OMPRTL__tgt_target_data_update_nowait: { 2564 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2565 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2566 // *arg_types); 2567 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2568 CGM.Int32Ty, 2569 CGM.VoidPtrPtrTy, 2570 CGM.VoidPtrPtrTy, 2571 CGM.Int64Ty->getPointerTo(), 2572 CGM.Int64Ty->getPointerTo()}; 2573 auto *FnTy = 2574 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2575 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2576 break; 2577 } 2578 case OMPRTL__tgt_mapper_num_components: { 2579 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2580 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2581 auto *FnTy = 2582 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2583 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2584 break; 2585 } 2586 case OMPRTL__tgt_push_mapper_component: { 2587 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2588 // *base, void *begin, int64_t size, int64_t type); 2589 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2590 CGM.Int64Ty, CGM.Int64Ty}; 2591 auto *FnTy = 2592 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2593 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2594 break; 2595 } 2596 } 2597 assert(RTLFn && "Unable to find OpenMP runtime function"); 2598 return RTLFn; 2599 } 2600 2601 llvm::FunctionCallee 2602 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2603 assert((IVSize == 32 || IVSize == 64) && 2604 "IV size is not compatible with the omp runtime"); 2605 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2606 : "__kmpc_for_static_init_4u") 2607 : (IVSigned ? "__kmpc_for_static_init_8" 2608 : "__kmpc_for_static_init_8u"); 2609 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2610 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2611 llvm::Type *TypeParams[] = { 2612 getIdentTyPointerTy(), // loc 2613 CGM.Int32Ty, // tid 2614 CGM.Int32Ty, // schedtype 2615 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2616 PtrTy, // p_lower 2617 PtrTy, // p_upper 2618 PtrTy, // p_stride 2619 ITy, // incr 2620 ITy // chunk 2621 }; 2622 auto *FnTy = 2623 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2624 return CGM.CreateRuntimeFunction(FnTy, Name); 2625 } 2626 2627 llvm::FunctionCallee 2628 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2629 assert((IVSize == 32 || IVSize == 64) && 2630 "IV size is not compatible with the omp runtime"); 2631 StringRef Name = 2632 IVSize == 32 2633 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2634 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2635 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2636 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2637 CGM.Int32Ty, // tid 2638 CGM.Int32Ty, // schedtype 2639 ITy, // lower 2640 ITy, // upper 2641 ITy, // stride 2642 ITy // chunk 2643 }; 2644 auto *FnTy = 2645 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2646 return CGM.CreateRuntimeFunction(FnTy, Name); 2647 } 2648 2649 llvm::FunctionCallee 2650 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2651 assert((IVSize == 32 || IVSize == 64) && 2652 "IV size is not compatible with the omp runtime"); 2653 StringRef Name = 2654 IVSize == 32 2655 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2656 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2657 llvm::Type *TypeParams[] = { 2658 getIdentTyPointerTy(), // loc 2659 CGM.Int32Ty, // tid 2660 }; 2661 auto *FnTy = 2662 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2663 return CGM.CreateRuntimeFunction(FnTy, Name); 2664 } 2665 2666 llvm::FunctionCallee 2667 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2668 assert((IVSize == 32 || IVSize == 64) && 2669 "IV size is not compatible with the omp runtime"); 2670 StringRef Name = 2671 IVSize == 32 2672 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2673 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2674 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2675 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2676 llvm::Type *TypeParams[] = { 2677 getIdentTyPointerTy(), // loc 2678 CGM.Int32Ty, // tid 2679 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2680 PtrTy, // p_lower 2681 PtrTy, // p_upper 2682 PtrTy // p_stride 2683 }; 2684 auto *FnTy = 2685 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2686 return CGM.CreateRuntimeFunction(FnTy, Name); 2687 } 2688 2689 /// Obtain information that uniquely identifies a target entry. This 2690 /// consists of the file and device IDs as well as line number associated with 2691 /// the relevant entry source location. 2692 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2693 unsigned &DeviceID, unsigned &FileID, 2694 unsigned &LineNum) { 2695 SourceManager &SM = C.getSourceManager(); 2696 2697 // The loc should be always valid and have a file ID (the user cannot use 2698 // #pragma directives in macros) 2699 2700 assert(Loc.isValid() && "Source location is expected to be always valid."); 2701 2702 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2703 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2704 2705 llvm::sys::fs::UniqueID ID; 2706 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2707 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2708 << PLoc.getFilename() << EC.message(); 2709 2710 DeviceID = ID.getDevice(); 2711 FileID = ID.getFile(); 2712 LineNum = PLoc.getLine(); 2713 } 2714 2715 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2716 if (CGM.getLangOpts().OpenMPSimd) 2717 return Address::invalid(); 2718 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2719 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2720 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2721 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2722 HasRequiresUnifiedSharedMemory))) { 2723 SmallString<64> PtrName; 2724 { 2725 llvm::raw_svector_ostream OS(PtrName); 2726 OS << CGM.getMangledName(GlobalDecl(VD)); 2727 if (!VD->isExternallyVisible()) { 2728 unsigned DeviceID, FileID, Line; 2729 getTargetEntryUniqueInfo(CGM.getContext(), 2730 VD->getCanonicalDecl()->getBeginLoc(), 2731 DeviceID, FileID, Line); 2732 OS << llvm::format("_%x", FileID); 2733 } 2734 OS << "_decl_tgt_ref_ptr"; 2735 } 2736 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2737 if (!Ptr) { 2738 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2739 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2740 PtrName); 2741 2742 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2743 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2744 2745 if (!CGM.getLangOpts().OpenMPIsDevice) 2746 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2747 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2748 } 2749 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2750 } 2751 return Address::invalid(); 2752 } 2753 2754 llvm::Constant * 2755 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2756 assert(!CGM.getLangOpts().OpenMPUseTLS || 2757 !CGM.getContext().getTargetInfo().isTLSSupported()); 2758 // Lookup the entry, lazily creating it if necessary. 2759 std::string Suffix = getName({"cache", ""}); 2760 return getOrCreateInternalVariable( 2761 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2762 } 2763 2764 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2765 const VarDecl *VD, 2766 Address VDAddr, 2767 SourceLocation Loc) { 2768 if (CGM.getLangOpts().OpenMPUseTLS && 2769 CGM.getContext().getTargetInfo().isTLSSupported()) 2770 return VDAddr; 2771 2772 llvm::Type *VarTy = VDAddr.getElementType(); 2773 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2774 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2775 CGM.Int8PtrTy), 2776 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2777 getOrCreateThreadPrivateCache(VD)}; 2778 return Address(CGF.EmitRuntimeCall( 2779 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2780 VDAddr.getAlignment()); 2781 } 2782 2783 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2784 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2785 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2786 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2787 // library. 2788 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2789 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2790 OMPLoc); 2791 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2792 // to register constructor/destructor for variable. 2793 llvm::Value *Args[] = { 2794 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2795 Ctor, CopyCtor, Dtor}; 2796 CGF.EmitRuntimeCall( 2797 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2798 } 2799 2800 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2801 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2802 bool PerformInit, CodeGenFunction *CGF) { 2803 if (CGM.getLangOpts().OpenMPUseTLS && 2804 CGM.getContext().getTargetInfo().isTLSSupported()) 2805 return nullptr; 2806 2807 VD = VD->getDefinition(CGM.getContext()); 2808 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2809 QualType ASTTy = VD->getType(); 2810 2811 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2812 const Expr *Init = VD->getAnyInitializer(); 2813 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2814 // Generate function that re-emits the declaration's initializer into the 2815 // threadprivate copy of the variable VD 2816 CodeGenFunction CtorCGF(CGM); 2817 FunctionArgList Args; 2818 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2819 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2820 ImplicitParamDecl::Other); 2821 Args.push_back(&Dst); 2822 2823 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2824 CGM.getContext().VoidPtrTy, Args); 2825 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2826 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2827 llvm::Function *Fn = 2828 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2829 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2830 Args, Loc, Loc); 2831 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2832 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2833 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2834 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2835 Arg = CtorCGF.Builder.CreateElementBitCast( 2836 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2837 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2838 /*IsInitializer=*/true); 2839 ArgVal = CtorCGF.EmitLoadOfScalar( 2840 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2841 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2842 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2843 CtorCGF.FinishFunction(); 2844 Ctor = Fn; 2845 } 2846 if (VD->getType().isDestructedType() != QualType::DK_none) { 2847 // Generate function that emits destructor call for the threadprivate copy 2848 // of the variable VD 2849 CodeGenFunction DtorCGF(CGM); 2850 FunctionArgList Args; 2851 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2852 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2853 ImplicitParamDecl::Other); 2854 Args.push_back(&Dst); 2855 2856 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2857 CGM.getContext().VoidTy, Args); 2858 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2859 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2860 llvm::Function *Fn = 2861 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2862 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2863 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2864 Loc, Loc); 2865 // Create a scope with an artificial location for the body of this function. 2866 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2867 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2868 DtorCGF.GetAddrOfLocalVar(&Dst), 2869 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2870 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2871 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2872 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2873 DtorCGF.FinishFunction(); 2874 Dtor = Fn; 2875 } 2876 // Do not emit init function if it is not required. 2877 if (!Ctor && !Dtor) 2878 return nullptr; 2879 2880 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2881 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2882 /*isVarArg=*/false) 2883 ->getPointerTo(); 2884 // Copying constructor for the threadprivate variable. 2885 // Must be NULL - reserved by runtime, but currently it requires that this 2886 // parameter is always NULL. Otherwise it fires assertion. 2887 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2888 if (Ctor == nullptr) { 2889 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2890 /*isVarArg=*/false) 2891 ->getPointerTo(); 2892 Ctor = llvm::Constant::getNullValue(CtorTy); 2893 } 2894 if (Dtor == nullptr) { 2895 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2896 /*isVarArg=*/false) 2897 ->getPointerTo(); 2898 Dtor = llvm::Constant::getNullValue(DtorTy); 2899 } 2900 if (!CGF) { 2901 auto *InitFunctionTy = 2902 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2903 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2904 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2905 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2906 CodeGenFunction InitCGF(CGM); 2907 FunctionArgList ArgList; 2908 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2909 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2910 Loc, Loc); 2911 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2912 InitCGF.FinishFunction(); 2913 return InitFunction; 2914 } 2915 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2916 } 2917 return nullptr; 2918 } 2919 2920 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2921 llvm::GlobalVariable *Addr, 2922 bool PerformInit) { 2923 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2924 !CGM.getLangOpts().OpenMPIsDevice) 2925 return false; 2926 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2927 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2928 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2929 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2930 HasRequiresUnifiedSharedMemory)) 2931 return CGM.getLangOpts().OpenMPIsDevice; 2932 VD = VD->getDefinition(CGM.getContext()); 2933 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2934 return CGM.getLangOpts().OpenMPIsDevice; 2935 2936 QualType ASTTy = VD->getType(); 2937 2938 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2939 // Produce the unique prefix to identify the new target regions. We use 2940 // the source location of the variable declaration which we know to not 2941 // conflict with any target region. 2942 unsigned DeviceID; 2943 unsigned FileID; 2944 unsigned Line; 2945 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2946 SmallString<128> Buffer, Out; 2947 { 2948 llvm::raw_svector_ostream OS(Buffer); 2949 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2950 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2951 } 2952 2953 const Expr *Init = VD->getAnyInitializer(); 2954 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2955 llvm::Constant *Ctor; 2956 llvm::Constant *ID; 2957 if (CGM.getLangOpts().OpenMPIsDevice) { 2958 // Generate function that re-emits the declaration's initializer into 2959 // the threadprivate copy of the variable VD 2960 CodeGenFunction CtorCGF(CGM); 2961 2962 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2963 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2964 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2965 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2966 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2967 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2968 FunctionArgList(), Loc, Loc); 2969 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2970 CtorCGF.EmitAnyExprToMem(Init, 2971 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2972 Init->getType().getQualifiers(), 2973 /*IsInitializer=*/true); 2974 CtorCGF.FinishFunction(); 2975 Ctor = Fn; 2976 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2977 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2978 } else { 2979 Ctor = new llvm::GlobalVariable( 2980 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2981 llvm::GlobalValue::PrivateLinkage, 2982 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2983 ID = Ctor; 2984 } 2985 2986 // Register the information for the entry associated with the constructor. 2987 Out.clear(); 2988 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2989 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2990 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2991 } 2992 if (VD->getType().isDestructedType() != QualType::DK_none) { 2993 llvm::Constant *Dtor; 2994 llvm::Constant *ID; 2995 if (CGM.getLangOpts().OpenMPIsDevice) { 2996 // Generate function that emits destructor call for the threadprivate 2997 // copy of the variable VD 2998 CodeGenFunction DtorCGF(CGM); 2999 3000 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 3001 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 3002 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 3003 FTy, Twine(Buffer, "_dtor"), FI, Loc); 3004 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 3005 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 3006 FunctionArgList(), Loc, Loc); 3007 // Create a scope with an artificial location for the body of this 3008 // function. 3009 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 3010 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 3011 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 3012 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 3013 DtorCGF.FinishFunction(); 3014 Dtor = Fn; 3015 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 3016 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 3017 } else { 3018 Dtor = new llvm::GlobalVariable( 3019 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 3020 llvm::GlobalValue::PrivateLinkage, 3021 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 3022 ID = Dtor; 3023 } 3024 // Register the information for the entry associated with the destructor. 3025 Out.clear(); 3026 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 3027 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 3028 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 3029 } 3030 return CGM.getLangOpts().OpenMPIsDevice; 3031 } 3032 3033 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 3034 QualType VarType, 3035 StringRef Name) { 3036 std::string Suffix = getName({"artificial", ""}); 3037 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 3038 llvm::Value *GAddr = 3039 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 3040 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 3041 CGM.getTarget().isTLSSupported()) { 3042 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 3043 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 3044 } 3045 std::string CacheSuffix = getName({"cache", ""}); 3046 llvm::Value *Args[] = { 3047 emitUpdateLocation(CGF, SourceLocation()), 3048 getThreadID(CGF, SourceLocation()), 3049 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 3050 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 3051 /*isSigned=*/false), 3052 getOrCreateInternalVariable( 3053 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 3054 return Address( 3055 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3056 CGF.EmitRuntimeCall( 3057 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3058 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3059 CGM.getContext().getTypeAlignInChars(VarType)); 3060 } 3061 3062 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 3063 const RegionCodeGenTy &ThenGen, 3064 const RegionCodeGenTy &ElseGen) { 3065 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3066 3067 // If the condition constant folds and can be elided, try to avoid emitting 3068 // the condition and the dead arm of the if/else. 3069 bool CondConstant; 3070 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3071 if (CondConstant) 3072 ThenGen(CGF); 3073 else 3074 ElseGen(CGF); 3075 return; 3076 } 3077 3078 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3079 // emit the conditional branch. 3080 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3081 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3082 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3083 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3084 3085 // Emit the 'then' code. 3086 CGF.EmitBlock(ThenBlock); 3087 ThenGen(CGF); 3088 CGF.EmitBranch(ContBlock); 3089 // Emit the 'else' code if present. 3090 // There is no need to emit line number for unconditional branch. 3091 (void)ApplyDebugLocation::CreateEmpty(CGF); 3092 CGF.EmitBlock(ElseBlock); 3093 ElseGen(CGF); 3094 // There is no need to emit line number for unconditional branch. 3095 (void)ApplyDebugLocation::CreateEmpty(CGF); 3096 CGF.EmitBranch(ContBlock); 3097 // Emit the continuation block for code after the if. 3098 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3099 } 3100 3101 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3102 llvm::Function *OutlinedFn, 3103 ArrayRef<llvm::Value *> CapturedVars, 3104 const Expr *IfCond) { 3105 if (!CGF.HaveInsertPoint()) 3106 return; 3107 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3108 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3109 PrePostActionTy &) { 3110 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3111 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3112 llvm::Value *Args[] = { 3113 RTLoc, 3114 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3115 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3116 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3117 RealArgs.append(std::begin(Args), std::end(Args)); 3118 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3119 3120 llvm::FunctionCallee RTLFn = 3121 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3122 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3123 }; 3124 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3125 PrePostActionTy &) { 3126 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3127 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3128 // Build calls: 3129 // __kmpc_serialized_parallel(&Loc, GTid); 3130 llvm::Value *Args[] = {RTLoc, ThreadID}; 3131 CGF.EmitRuntimeCall( 3132 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3133 3134 // OutlinedFn(>id, &zero_bound, CapturedStruct); 3135 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 3136 Address ZeroAddrBound = 3137 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3138 /*Name=*/".bound.zero.addr"); 3139 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 3140 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3141 // ThreadId for serialized parallels is 0. 3142 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 3143 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 3144 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3145 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3146 3147 // __kmpc_end_serialized_parallel(&Loc, GTid); 3148 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3149 CGF.EmitRuntimeCall( 3150 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3151 EndArgs); 3152 }; 3153 if (IfCond) { 3154 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 3155 } else { 3156 RegionCodeGenTy ThenRCG(ThenGen); 3157 ThenRCG(CGF); 3158 } 3159 } 3160 3161 // If we're inside an (outlined) parallel region, use the region info's 3162 // thread-ID variable (it is passed in a first argument of the outlined function 3163 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3164 // regular serial code region, get thread ID by calling kmp_int32 3165 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3166 // return the address of that temp. 3167 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3168 SourceLocation Loc) { 3169 if (auto *OMPRegionInfo = 3170 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3171 if (OMPRegionInfo->getThreadIDVariable()) 3172 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 3173 3174 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3175 QualType Int32Ty = 3176 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3177 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3178 CGF.EmitStoreOfScalar(ThreadID, 3179 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3180 3181 return ThreadIDTemp; 3182 } 3183 3184 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3185 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3186 SmallString<256> Buffer; 3187 llvm::raw_svector_ostream Out(Buffer); 3188 Out << Name; 3189 StringRef RuntimeName = Out.str(); 3190 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3191 if (Elem.second) { 3192 assert(Elem.second->getType()->getPointerElementType() == Ty && 3193 "OMP internal variable has different type than requested"); 3194 return &*Elem.second; 3195 } 3196 3197 return Elem.second = new llvm::GlobalVariable( 3198 CGM.getModule(), Ty, /*IsConstant*/ false, 3199 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3200 Elem.first(), /*InsertBefore=*/nullptr, 3201 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3202 } 3203 3204 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3205 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3206 std::string Name = getName({Prefix, "var"}); 3207 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3208 } 3209 3210 namespace { 3211 /// Common pre(post)-action for different OpenMP constructs. 3212 class CommonActionTy final : public PrePostActionTy { 3213 llvm::FunctionCallee EnterCallee; 3214 ArrayRef<llvm::Value *> EnterArgs; 3215 llvm::FunctionCallee ExitCallee; 3216 ArrayRef<llvm::Value *> ExitArgs; 3217 bool Conditional; 3218 llvm::BasicBlock *ContBlock = nullptr; 3219 3220 public: 3221 CommonActionTy(llvm::FunctionCallee EnterCallee, 3222 ArrayRef<llvm::Value *> EnterArgs, 3223 llvm::FunctionCallee ExitCallee, 3224 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3225 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3226 ExitArgs(ExitArgs), Conditional(Conditional) {} 3227 void Enter(CodeGenFunction &CGF) override { 3228 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3229 if (Conditional) { 3230 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3231 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3232 ContBlock = CGF.createBasicBlock("omp_if.end"); 3233 // Generate the branch (If-stmt) 3234 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3235 CGF.EmitBlock(ThenBlock); 3236 } 3237 } 3238 void Done(CodeGenFunction &CGF) { 3239 // Emit the rest of blocks/branches 3240 CGF.EmitBranch(ContBlock); 3241 CGF.EmitBlock(ContBlock, true); 3242 } 3243 void Exit(CodeGenFunction &CGF) override { 3244 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3245 } 3246 }; 3247 } // anonymous namespace 3248 3249 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3250 StringRef CriticalName, 3251 const RegionCodeGenTy &CriticalOpGen, 3252 SourceLocation Loc, const Expr *Hint) { 3253 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3254 // CriticalOpGen(); 3255 // __kmpc_end_critical(ident_t *, gtid, Lock); 3256 // Prepare arguments and build a call to __kmpc_critical 3257 if (!CGF.HaveInsertPoint()) 3258 return; 3259 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3260 getCriticalRegionLock(CriticalName)}; 3261 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3262 std::end(Args)); 3263 if (Hint) { 3264 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3265 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3266 } 3267 CommonActionTy Action( 3268 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3269 : OMPRTL__kmpc_critical), 3270 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3271 CriticalOpGen.setAction(Action); 3272 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3273 } 3274 3275 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3276 const RegionCodeGenTy &MasterOpGen, 3277 SourceLocation Loc) { 3278 if (!CGF.HaveInsertPoint()) 3279 return; 3280 // if(__kmpc_master(ident_t *, gtid)) { 3281 // MasterOpGen(); 3282 // __kmpc_end_master(ident_t *, gtid); 3283 // } 3284 // Prepare arguments and build a call to __kmpc_master 3285 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3286 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3287 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3288 /*Conditional=*/true); 3289 MasterOpGen.setAction(Action); 3290 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3291 Action.Done(CGF); 3292 } 3293 3294 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3295 SourceLocation Loc) { 3296 if (!CGF.HaveInsertPoint()) 3297 return; 3298 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3299 llvm::Value *Args[] = { 3300 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3301 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3302 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 3303 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3304 Region->emitUntiedSwitch(CGF); 3305 } 3306 3307 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3308 const RegionCodeGenTy &TaskgroupOpGen, 3309 SourceLocation Loc) { 3310 if (!CGF.HaveInsertPoint()) 3311 return; 3312 // __kmpc_taskgroup(ident_t *, gtid); 3313 // TaskgroupOpGen(); 3314 // __kmpc_end_taskgroup(ident_t *, gtid); 3315 // Prepare arguments and build a call to __kmpc_taskgroup 3316 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3317 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3318 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3319 Args); 3320 TaskgroupOpGen.setAction(Action); 3321 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3322 } 3323 3324 /// Given an array of pointers to variables, project the address of a 3325 /// given variable. 3326 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3327 unsigned Index, const VarDecl *Var) { 3328 // Pull out the pointer to the variable. 3329 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3330 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3331 3332 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3333 Addr = CGF.Builder.CreateElementBitCast( 3334 Addr, CGF.ConvertTypeForMem(Var->getType())); 3335 return Addr; 3336 } 3337 3338 static llvm::Value *emitCopyprivateCopyFunction( 3339 CodeGenModule &CGM, llvm::Type *ArgsType, 3340 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3341 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3342 SourceLocation Loc) { 3343 ASTContext &C = CGM.getContext(); 3344 // void copy_func(void *LHSArg, void *RHSArg); 3345 FunctionArgList Args; 3346 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3347 ImplicitParamDecl::Other); 3348 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3349 ImplicitParamDecl::Other); 3350 Args.push_back(&LHSArg); 3351 Args.push_back(&RHSArg); 3352 const auto &CGFI = 3353 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3354 std::string Name = 3355 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3356 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3357 llvm::GlobalValue::InternalLinkage, Name, 3358 &CGM.getModule()); 3359 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3360 Fn->setDoesNotRecurse(); 3361 CodeGenFunction CGF(CGM); 3362 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3363 // Dest = (void*[n])(LHSArg); 3364 // Src = (void*[n])(RHSArg); 3365 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3366 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3367 ArgsType), CGF.getPointerAlign()); 3368 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3369 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3370 ArgsType), CGF.getPointerAlign()); 3371 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3372 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3373 // ... 3374 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3375 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3376 const auto *DestVar = 3377 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3378 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3379 3380 const auto *SrcVar = 3381 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3382 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3383 3384 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3385 QualType Type = VD->getType(); 3386 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3387 } 3388 CGF.FinishFunction(); 3389 return Fn; 3390 } 3391 3392 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3393 const RegionCodeGenTy &SingleOpGen, 3394 SourceLocation Loc, 3395 ArrayRef<const Expr *> CopyprivateVars, 3396 ArrayRef<const Expr *> SrcExprs, 3397 ArrayRef<const Expr *> DstExprs, 3398 ArrayRef<const Expr *> AssignmentOps) { 3399 if (!CGF.HaveInsertPoint()) 3400 return; 3401 assert(CopyprivateVars.size() == SrcExprs.size() && 3402 CopyprivateVars.size() == DstExprs.size() && 3403 CopyprivateVars.size() == AssignmentOps.size()); 3404 ASTContext &C = CGM.getContext(); 3405 // int32 did_it = 0; 3406 // if(__kmpc_single(ident_t *, gtid)) { 3407 // SingleOpGen(); 3408 // __kmpc_end_single(ident_t *, gtid); 3409 // did_it = 1; 3410 // } 3411 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3412 // <copy_func>, did_it); 3413 3414 Address DidIt = Address::invalid(); 3415 if (!CopyprivateVars.empty()) { 3416 // int32 did_it = 0; 3417 QualType KmpInt32Ty = 3418 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3419 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3420 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3421 } 3422 // Prepare arguments and build a call to __kmpc_single 3423 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3424 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3425 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3426 /*Conditional=*/true); 3427 SingleOpGen.setAction(Action); 3428 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3429 if (DidIt.isValid()) { 3430 // did_it = 1; 3431 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3432 } 3433 Action.Done(CGF); 3434 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3435 // <copy_func>, did_it); 3436 if (DidIt.isValid()) { 3437 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3438 QualType CopyprivateArrayTy = C.getConstantArrayType( 3439 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3440 /*IndexTypeQuals=*/0); 3441 // Create a list of all private variables for copyprivate. 3442 Address CopyprivateList = 3443 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3444 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3445 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3446 CGF.Builder.CreateStore( 3447 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3448 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 3449 CGF.VoidPtrTy), 3450 Elem); 3451 } 3452 // Build function that copies private values from single region to all other 3453 // threads in the corresponding parallel region. 3454 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3455 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3456 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3457 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3458 Address CL = 3459 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3460 CGF.VoidPtrTy); 3461 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3462 llvm::Value *Args[] = { 3463 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3464 getThreadID(CGF, Loc), // i32 <gtid> 3465 BufSize, // size_t <buf_size> 3466 CL.getPointer(), // void *<copyprivate list> 3467 CpyFn, // void (*) (void *, void *) <copy_func> 3468 DidItVal // i32 did_it 3469 }; 3470 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3471 } 3472 } 3473 3474 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3475 const RegionCodeGenTy &OrderedOpGen, 3476 SourceLocation Loc, bool IsThreads) { 3477 if (!CGF.HaveInsertPoint()) 3478 return; 3479 // __kmpc_ordered(ident_t *, gtid); 3480 // OrderedOpGen(); 3481 // __kmpc_end_ordered(ident_t *, gtid); 3482 // Prepare arguments and build a call to __kmpc_ordered 3483 if (IsThreads) { 3484 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3485 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3486 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3487 Args); 3488 OrderedOpGen.setAction(Action); 3489 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3490 return; 3491 } 3492 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3493 } 3494 3495 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3496 unsigned Flags; 3497 if (Kind == OMPD_for) 3498 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3499 else if (Kind == OMPD_sections) 3500 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3501 else if (Kind == OMPD_single) 3502 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3503 else if (Kind == OMPD_barrier) 3504 Flags = OMP_IDENT_BARRIER_EXPL; 3505 else 3506 Flags = OMP_IDENT_BARRIER_IMPL; 3507 return Flags; 3508 } 3509 3510 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3511 CodeGenFunction &CGF, const OMPLoopDirective &S, 3512 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3513 // Check if the loop directive is actually a doacross loop directive. In this 3514 // case choose static, 1 schedule. 3515 if (llvm::any_of( 3516 S.getClausesOfKind<OMPOrderedClause>(), 3517 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3518 ScheduleKind = OMPC_SCHEDULE_static; 3519 // Chunk size is 1 in this case. 3520 llvm::APInt ChunkSize(32, 1); 3521 ChunkExpr = IntegerLiteral::Create( 3522 CGF.getContext(), ChunkSize, 3523 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3524 SourceLocation()); 3525 } 3526 } 3527 3528 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3529 OpenMPDirectiveKind Kind, bool EmitChecks, 3530 bool ForceSimpleCall) { 3531 // Check if we should use the OMPBuilder 3532 auto *OMPRegionInfo = 3533 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 3534 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3535 if (OMPBuilder) { 3536 CGF.Builder.restoreIP(OMPBuilder->CreateBarrier( 3537 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 3538 return; 3539 } 3540 3541 if (!CGF.HaveInsertPoint()) 3542 return; 3543 // Build call __kmpc_cancel_barrier(loc, thread_id); 3544 // Build call __kmpc_barrier(loc, thread_id); 3545 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3546 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3547 // thread_id); 3548 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3549 getThreadID(CGF, Loc)}; 3550 if (OMPRegionInfo) { 3551 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3552 llvm::Value *Result = CGF.EmitRuntimeCall( 3553 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3554 if (EmitChecks) { 3555 // if (__kmpc_cancel_barrier()) { 3556 // exit from construct; 3557 // } 3558 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3559 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3560 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3561 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3562 CGF.EmitBlock(ExitBB); 3563 // exit from construct; 3564 CodeGenFunction::JumpDest CancelDestination = 3565 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3566 CGF.EmitBranchThroughCleanup(CancelDestination); 3567 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3568 } 3569 return; 3570 } 3571 } 3572 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3573 } 3574 3575 /// Map the OpenMP loop schedule to the runtime enumeration. 3576 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3577 bool Chunked, bool Ordered) { 3578 switch (ScheduleKind) { 3579 case OMPC_SCHEDULE_static: 3580 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3581 : (Ordered ? OMP_ord_static : OMP_sch_static); 3582 case OMPC_SCHEDULE_dynamic: 3583 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3584 case OMPC_SCHEDULE_guided: 3585 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3586 case OMPC_SCHEDULE_runtime: 3587 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3588 case OMPC_SCHEDULE_auto: 3589 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3590 case OMPC_SCHEDULE_unknown: 3591 assert(!Chunked && "chunk was specified but schedule kind not known"); 3592 return Ordered ? OMP_ord_static : OMP_sch_static; 3593 } 3594 llvm_unreachable("Unexpected runtime schedule"); 3595 } 3596 3597 /// Map the OpenMP distribute schedule to the runtime enumeration. 3598 static OpenMPSchedType 3599 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3600 // only static is allowed for dist_schedule 3601 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3602 } 3603 3604 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3605 bool Chunked) const { 3606 OpenMPSchedType Schedule = 3607 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3608 return Schedule == OMP_sch_static; 3609 } 3610 3611 bool CGOpenMPRuntime::isStaticNonchunked( 3612 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3613 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3614 return Schedule == OMP_dist_sch_static; 3615 } 3616 3617 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3618 bool Chunked) const { 3619 OpenMPSchedType Schedule = 3620 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3621 return Schedule == OMP_sch_static_chunked; 3622 } 3623 3624 bool CGOpenMPRuntime::isStaticChunked( 3625 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3626 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3627 return Schedule == OMP_dist_sch_static_chunked; 3628 } 3629 3630 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3631 OpenMPSchedType Schedule = 3632 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3633 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3634 return Schedule != OMP_sch_static; 3635 } 3636 3637 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3638 OpenMPScheduleClauseModifier M1, 3639 OpenMPScheduleClauseModifier M2) { 3640 int Modifier = 0; 3641 switch (M1) { 3642 case OMPC_SCHEDULE_MODIFIER_monotonic: 3643 Modifier = OMP_sch_modifier_monotonic; 3644 break; 3645 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3646 Modifier = OMP_sch_modifier_nonmonotonic; 3647 break; 3648 case OMPC_SCHEDULE_MODIFIER_simd: 3649 if (Schedule == OMP_sch_static_chunked) 3650 Schedule = OMP_sch_static_balanced_chunked; 3651 break; 3652 case OMPC_SCHEDULE_MODIFIER_last: 3653 case OMPC_SCHEDULE_MODIFIER_unknown: 3654 break; 3655 } 3656 switch (M2) { 3657 case OMPC_SCHEDULE_MODIFIER_monotonic: 3658 Modifier = OMP_sch_modifier_monotonic; 3659 break; 3660 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3661 Modifier = OMP_sch_modifier_nonmonotonic; 3662 break; 3663 case OMPC_SCHEDULE_MODIFIER_simd: 3664 if (Schedule == OMP_sch_static_chunked) 3665 Schedule = OMP_sch_static_balanced_chunked; 3666 break; 3667 case OMPC_SCHEDULE_MODIFIER_last: 3668 case OMPC_SCHEDULE_MODIFIER_unknown: 3669 break; 3670 } 3671 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3672 // If the static schedule kind is specified or if the ordered clause is 3673 // specified, and if the nonmonotonic modifier is not specified, the effect is 3674 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3675 // modifier is specified, the effect is as if the nonmonotonic modifier is 3676 // specified. 3677 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3678 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3679 Schedule == OMP_sch_static_balanced_chunked || 3680 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 3681 Schedule == OMP_dist_sch_static_chunked || 3682 Schedule == OMP_dist_sch_static)) 3683 Modifier = OMP_sch_modifier_nonmonotonic; 3684 } 3685 return Schedule | Modifier; 3686 } 3687 3688 void CGOpenMPRuntime::emitForDispatchInit( 3689 CodeGenFunction &CGF, SourceLocation Loc, 3690 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3691 bool Ordered, const DispatchRTInput &DispatchValues) { 3692 if (!CGF.HaveInsertPoint()) 3693 return; 3694 OpenMPSchedType Schedule = getRuntimeSchedule( 3695 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3696 assert(Ordered || 3697 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3698 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3699 Schedule != OMP_sch_static_balanced_chunked)); 3700 // Call __kmpc_dispatch_init( 3701 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3702 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3703 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3704 3705 // If the Chunk was not specified in the clause - use default value 1. 3706 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3707 : CGF.Builder.getIntN(IVSize, 1); 3708 llvm::Value *Args[] = { 3709 emitUpdateLocation(CGF, Loc), 3710 getThreadID(CGF, Loc), 3711 CGF.Builder.getInt32(addMonoNonMonoModifier( 3712 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3713 DispatchValues.LB, // Lower 3714 DispatchValues.UB, // Upper 3715 CGF.Builder.getIntN(IVSize, 1), // Stride 3716 Chunk // Chunk 3717 }; 3718 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3719 } 3720 3721 static void emitForStaticInitCall( 3722 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3723 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3724 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3725 const CGOpenMPRuntime::StaticRTInput &Values) { 3726 if (!CGF.HaveInsertPoint()) 3727 return; 3728 3729 assert(!Values.Ordered); 3730 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3731 Schedule == OMP_sch_static_balanced_chunked || 3732 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3733 Schedule == OMP_dist_sch_static || 3734 Schedule == OMP_dist_sch_static_chunked); 3735 3736 // Call __kmpc_for_static_init( 3737 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3738 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3739 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3740 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3741 llvm::Value *Chunk = Values.Chunk; 3742 if (Chunk == nullptr) { 3743 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3744 Schedule == OMP_dist_sch_static) && 3745 "expected static non-chunked schedule"); 3746 // If the Chunk was not specified in the clause - use default value 1. 3747 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3748 } else { 3749 assert((Schedule == OMP_sch_static_chunked || 3750 Schedule == OMP_sch_static_balanced_chunked || 3751 Schedule == OMP_ord_static_chunked || 3752 Schedule == OMP_dist_sch_static_chunked) && 3753 "expected static chunked schedule"); 3754 } 3755 llvm::Value *Args[] = { 3756 UpdateLocation, 3757 ThreadId, 3758 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3759 M2)), // Schedule type 3760 Values.IL.getPointer(), // &isLastIter 3761 Values.LB.getPointer(), // &LB 3762 Values.UB.getPointer(), // &UB 3763 Values.ST.getPointer(), // &Stride 3764 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3765 Chunk // Chunk 3766 }; 3767 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3768 } 3769 3770 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3771 SourceLocation Loc, 3772 OpenMPDirectiveKind DKind, 3773 const OpenMPScheduleTy &ScheduleKind, 3774 const StaticRTInput &Values) { 3775 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3776 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3777 assert(isOpenMPWorksharingDirective(DKind) && 3778 "Expected loop-based or sections-based directive."); 3779 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3780 isOpenMPLoopDirective(DKind) 3781 ? OMP_IDENT_WORK_LOOP 3782 : OMP_IDENT_WORK_SECTIONS); 3783 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3784 llvm::FunctionCallee StaticInitFunction = 3785 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3786 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3787 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3788 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3789 } 3790 3791 void CGOpenMPRuntime::emitDistributeStaticInit( 3792 CodeGenFunction &CGF, SourceLocation Loc, 3793 OpenMPDistScheduleClauseKind SchedKind, 3794 const CGOpenMPRuntime::StaticRTInput &Values) { 3795 OpenMPSchedType ScheduleNum = 3796 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3797 llvm::Value *UpdatedLocation = 3798 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3799 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3800 llvm::FunctionCallee StaticInitFunction = 3801 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3802 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3803 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3804 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3805 } 3806 3807 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3808 SourceLocation Loc, 3809 OpenMPDirectiveKind DKind) { 3810 if (!CGF.HaveInsertPoint()) 3811 return; 3812 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3813 llvm::Value *Args[] = { 3814 emitUpdateLocation(CGF, Loc, 3815 isOpenMPDistributeDirective(DKind) 3816 ? OMP_IDENT_WORK_DISTRIBUTE 3817 : isOpenMPLoopDirective(DKind) 3818 ? OMP_IDENT_WORK_LOOP 3819 : OMP_IDENT_WORK_SECTIONS), 3820 getThreadID(CGF, Loc)}; 3821 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3822 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3823 Args); 3824 } 3825 3826 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3827 SourceLocation Loc, 3828 unsigned IVSize, 3829 bool IVSigned) { 3830 if (!CGF.HaveInsertPoint()) 3831 return; 3832 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3833 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3834 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3835 } 3836 3837 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3838 SourceLocation Loc, unsigned IVSize, 3839 bool IVSigned, Address IL, 3840 Address LB, Address UB, 3841 Address ST) { 3842 // Call __kmpc_dispatch_next( 3843 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3844 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3845 // kmp_int[32|64] *p_stride); 3846 llvm::Value *Args[] = { 3847 emitUpdateLocation(CGF, Loc), 3848 getThreadID(CGF, Loc), 3849 IL.getPointer(), // &isLastIter 3850 LB.getPointer(), // &Lower 3851 UB.getPointer(), // &Upper 3852 ST.getPointer() // &Stride 3853 }; 3854 llvm::Value *Call = 3855 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3856 return CGF.EmitScalarConversion( 3857 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3858 CGF.getContext().BoolTy, Loc); 3859 } 3860 3861 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3862 llvm::Value *NumThreads, 3863 SourceLocation Loc) { 3864 if (!CGF.HaveInsertPoint()) 3865 return; 3866 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3867 llvm::Value *Args[] = { 3868 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3869 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3870 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3871 Args); 3872 } 3873 3874 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3875 ProcBindKind ProcBind, 3876 SourceLocation Loc) { 3877 if (!CGF.HaveInsertPoint()) 3878 return; 3879 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 3880 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3881 llvm::Value *Args[] = { 3882 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3883 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 3884 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3885 } 3886 3887 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3888 SourceLocation Loc, llvm::AtomicOrdering AO) { 3889 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3890 if (OMPBuilder) { 3891 OMPBuilder->CreateFlush(CGF.Builder); 3892 } else { 3893 if (!CGF.HaveInsertPoint()) 3894 return; 3895 // Build call void __kmpc_flush(ident_t *loc) 3896 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3897 emitUpdateLocation(CGF, Loc)); 3898 } 3899 } 3900 3901 namespace { 3902 /// Indexes of fields for type kmp_task_t. 3903 enum KmpTaskTFields { 3904 /// List of shared variables. 3905 KmpTaskTShareds, 3906 /// Task routine. 3907 KmpTaskTRoutine, 3908 /// Partition id for the untied tasks. 3909 KmpTaskTPartId, 3910 /// Function with call of destructors for private variables. 3911 Data1, 3912 /// Task priority. 3913 Data2, 3914 /// (Taskloops only) Lower bound. 3915 KmpTaskTLowerBound, 3916 /// (Taskloops only) Upper bound. 3917 KmpTaskTUpperBound, 3918 /// (Taskloops only) Stride. 3919 KmpTaskTStride, 3920 /// (Taskloops only) Is last iteration flag. 3921 KmpTaskTLastIter, 3922 /// (Taskloops only) Reduction data. 3923 KmpTaskTReductions, 3924 }; 3925 } // anonymous namespace 3926 3927 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3928 return OffloadEntriesTargetRegion.empty() && 3929 OffloadEntriesDeviceGlobalVar.empty(); 3930 } 3931 3932 /// Initialize target region entry. 3933 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3934 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3935 StringRef ParentName, unsigned LineNum, 3936 unsigned Order) { 3937 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3938 "only required for the device " 3939 "code generation."); 3940 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3941 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3942 OMPTargetRegionEntryTargetRegion); 3943 ++OffloadingEntriesNum; 3944 } 3945 3946 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3947 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3948 StringRef ParentName, unsigned LineNum, 3949 llvm::Constant *Addr, llvm::Constant *ID, 3950 OMPTargetRegionEntryKind Flags) { 3951 // If we are emitting code for a target, the entry is already initialized, 3952 // only has to be registered. 3953 if (CGM.getLangOpts().OpenMPIsDevice) { 3954 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3955 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3956 DiagnosticsEngine::Error, 3957 "Unable to find target region on line '%0' in the device code."); 3958 CGM.getDiags().Report(DiagID) << LineNum; 3959 return; 3960 } 3961 auto &Entry = 3962 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3963 assert(Entry.isValid() && "Entry not initialized!"); 3964 Entry.setAddress(Addr); 3965 Entry.setID(ID); 3966 Entry.setFlags(Flags); 3967 } else { 3968 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3969 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3970 ++OffloadingEntriesNum; 3971 } 3972 } 3973 3974 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3975 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3976 unsigned LineNum) const { 3977 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3978 if (PerDevice == OffloadEntriesTargetRegion.end()) 3979 return false; 3980 auto PerFile = PerDevice->second.find(FileID); 3981 if (PerFile == PerDevice->second.end()) 3982 return false; 3983 auto PerParentName = PerFile->second.find(ParentName); 3984 if (PerParentName == PerFile->second.end()) 3985 return false; 3986 auto PerLine = PerParentName->second.find(LineNum); 3987 if (PerLine == PerParentName->second.end()) 3988 return false; 3989 // Fail if this entry is already registered. 3990 if (PerLine->second.getAddress() || PerLine->second.getID()) 3991 return false; 3992 return true; 3993 } 3994 3995 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3996 const OffloadTargetRegionEntryInfoActTy &Action) { 3997 // Scan all target region entries and perform the provided action. 3998 for (const auto &D : OffloadEntriesTargetRegion) 3999 for (const auto &F : D.second) 4000 for (const auto &P : F.second) 4001 for (const auto &L : P.second) 4002 Action(D.first, F.first, P.first(), L.first, L.second); 4003 } 4004 4005 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4006 initializeDeviceGlobalVarEntryInfo(StringRef Name, 4007 OMPTargetGlobalVarEntryKind Flags, 4008 unsigned Order) { 4009 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 4010 "only required for the device " 4011 "code generation."); 4012 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 4013 ++OffloadingEntriesNum; 4014 } 4015 4016 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4017 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 4018 CharUnits VarSize, 4019 OMPTargetGlobalVarEntryKind Flags, 4020 llvm::GlobalValue::LinkageTypes Linkage) { 4021 if (CGM.getLangOpts().OpenMPIsDevice) { 4022 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4023 assert(Entry.isValid() && Entry.getFlags() == Flags && 4024 "Entry not initialized!"); 4025 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4026 "Resetting with the new address."); 4027 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 4028 if (Entry.getVarSize().isZero()) { 4029 Entry.setVarSize(VarSize); 4030 Entry.setLinkage(Linkage); 4031 } 4032 return; 4033 } 4034 Entry.setVarSize(VarSize); 4035 Entry.setLinkage(Linkage); 4036 Entry.setAddress(Addr); 4037 } else { 4038 if (hasDeviceGlobalVarEntryInfo(VarName)) { 4039 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4040 assert(Entry.isValid() && Entry.getFlags() == Flags && 4041 "Entry not initialized!"); 4042 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4043 "Resetting with the new address."); 4044 if (Entry.getVarSize().isZero()) { 4045 Entry.setVarSize(VarSize); 4046 Entry.setLinkage(Linkage); 4047 } 4048 return; 4049 } 4050 OffloadEntriesDeviceGlobalVar.try_emplace( 4051 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 4052 ++OffloadingEntriesNum; 4053 } 4054 } 4055 4056 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4057 actOnDeviceGlobalVarEntriesInfo( 4058 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4059 // Scan all target region entries and perform the provided action. 4060 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4061 Action(E.getKey(), E.getValue()); 4062 } 4063 4064 void CGOpenMPRuntime::createOffloadEntry( 4065 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4066 llvm::GlobalValue::LinkageTypes Linkage) { 4067 StringRef Name = Addr->getName(); 4068 llvm::Module &M = CGM.getModule(); 4069 llvm::LLVMContext &C = M.getContext(); 4070 4071 // Create constant string with the name. 4072 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4073 4074 std::string StringName = getName({"omp_offloading", "entry_name"}); 4075 auto *Str = new llvm::GlobalVariable( 4076 M, StrPtrInit->getType(), /*isConstant=*/true, 4077 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4078 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4079 4080 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4081 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4082 llvm::ConstantInt::get(CGM.SizeTy, Size), 4083 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4084 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4085 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4086 llvm::GlobalVariable *Entry = createGlobalStruct( 4087 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4088 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4089 4090 // The entry has to be created in the section the linker expects it to be. 4091 Entry->setSection("omp_offloading_entries"); 4092 } 4093 4094 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4095 // Emit the offloading entries and metadata so that the device codegen side 4096 // can easily figure out what to emit. The produced metadata looks like 4097 // this: 4098 // 4099 // !omp_offload.info = !{!1, ...} 4100 // 4101 // Right now we only generate metadata for function that contain target 4102 // regions. 4103 4104 // If we are in simd mode or there are no entries, we don't need to do 4105 // anything. 4106 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 4107 return; 4108 4109 llvm::Module &M = CGM.getModule(); 4110 llvm::LLVMContext &C = M.getContext(); 4111 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4112 SourceLocation, StringRef>, 4113 16> 4114 OrderedEntries(OffloadEntriesInfoManager.size()); 4115 llvm::SmallVector<StringRef, 16> ParentFunctions( 4116 OffloadEntriesInfoManager.size()); 4117 4118 // Auxiliary methods to create metadata values and strings. 4119 auto &&GetMDInt = [this](unsigned V) { 4120 return llvm::ConstantAsMetadata::get( 4121 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4122 }; 4123 4124 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4125 4126 // Create the offloading info metadata node. 4127 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4128 4129 // Create function that emits metadata for each target region entry; 4130 auto &&TargetRegionMetadataEmitter = 4131 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4132 &GetMDString]( 4133 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4134 unsigned Line, 4135 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4136 // Generate metadata for target regions. Each entry of this metadata 4137 // contains: 4138 // - Entry 0 -> Kind of this type of metadata (0). 4139 // - Entry 1 -> Device ID of the file where the entry was identified. 4140 // - Entry 2 -> File ID of the file where the entry was identified. 4141 // - Entry 3 -> Mangled name of the function where the entry was 4142 // identified. 4143 // - Entry 4 -> Line in the file where the entry was identified. 4144 // - Entry 5 -> Order the entry was created. 4145 // The first element of the metadata node is the kind. 4146 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4147 GetMDInt(FileID), GetMDString(ParentName), 4148 GetMDInt(Line), GetMDInt(E.getOrder())}; 4149 4150 SourceLocation Loc; 4151 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4152 E = CGM.getContext().getSourceManager().fileinfo_end(); 4153 I != E; ++I) { 4154 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4155 I->getFirst()->getUniqueID().getFile() == FileID) { 4156 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4157 I->getFirst(), Line, 1); 4158 break; 4159 } 4160 } 4161 // Save this entry in the right position of the ordered entries array. 4162 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4163 ParentFunctions[E.getOrder()] = ParentName; 4164 4165 // Add metadata to the named metadata node. 4166 MD->addOperand(llvm::MDNode::get(C, Ops)); 4167 }; 4168 4169 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4170 TargetRegionMetadataEmitter); 4171 4172 // Create function that emits metadata for each device global variable entry; 4173 auto &&DeviceGlobalVarMetadataEmitter = 4174 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4175 MD](StringRef MangledName, 4176 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4177 &E) { 4178 // Generate metadata for global variables. Each entry of this metadata 4179 // contains: 4180 // - Entry 0 -> Kind of this type of metadata (1). 4181 // - Entry 1 -> Mangled name of the variable. 4182 // - Entry 2 -> Declare target kind. 4183 // - Entry 3 -> Order the entry was created. 4184 // The first element of the metadata node is the kind. 4185 llvm::Metadata *Ops[] = { 4186 GetMDInt(E.getKind()), GetMDString(MangledName), 4187 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4188 4189 // Save this entry in the right position of the ordered entries array. 4190 OrderedEntries[E.getOrder()] = 4191 std::make_tuple(&E, SourceLocation(), MangledName); 4192 4193 // Add metadata to the named metadata node. 4194 MD->addOperand(llvm::MDNode::get(C, Ops)); 4195 }; 4196 4197 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4198 DeviceGlobalVarMetadataEmitter); 4199 4200 for (const auto &E : OrderedEntries) { 4201 assert(std::get<0>(E) && "All ordered entries must exist!"); 4202 if (const auto *CE = 4203 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4204 std::get<0>(E))) { 4205 if (!CE->getID() || !CE->getAddress()) { 4206 // Do not blame the entry if the parent funtion is not emitted. 4207 StringRef FnName = ParentFunctions[CE->getOrder()]; 4208 if (!CGM.GetGlobalValue(FnName)) 4209 continue; 4210 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4211 DiagnosticsEngine::Error, 4212 "Offloading entry for target region in %0 is incorrect: either the " 4213 "address or the ID is invalid."); 4214 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4215 continue; 4216 } 4217 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4218 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4219 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4220 OffloadEntryInfoDeviceGlobalVar>( 4221 std::get<0>(E))) { 4222 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4223 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4224 CE->getFlags()); 4225 switch (Flags) { 4226 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4227 if (CGM.getLangOpts().OpenMPIsDevice && 4228 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4229 continue; 4230 if (!CE->getAddress()) { 4231 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4232 DiagnosticsEngine::Error, "Offloading entry for declare target " 4233 "variable %0 is incorrect: the " 4234 "address is invalid."); 4235 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4236 continue; 4237 } 4238 // The vaiable has no definition - no need to add the entry. 4239 if (CE->getVarSize().isZero()) 4240 continue; 4241 break; 4242 } 4243 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4244 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4245 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4246 "Declaret target link address is set."); 4247 if (CGM.getLangOpts().OpenMPIsDevice) 4248 continue; 4249 if (!CE->getAddress()) { 4250 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4251 DiagnosticsEngine::Error, 4252 "Offloading entry for declare target variable is incorrect: the " 4253 "address is invalid."); 4254 CGM.getDiags().Report(DiagID); 4255 continue; 4256 } 4257 break; 4258 } 4259 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4260 CE->getVarSize().getQuantity(), Flags, 4261 CE->getLinkage()); 4262 } else { 4263 llvm_unreachable("Unsupported entry kind."); 4264 } 4265 } 4266 } 4267 4268 /// Loads all the offload entries information from the host IR 4269 /// metadata. 4270 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4271 // If we are in target mode, load the metadata from the host IR. This code has 4272 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4273 4274 if (!CGM.getLangOpts().OpenMPIsDevice) 4275 return; 4276 4277 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4278 return; 4279 4280 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4281 if (auto EC = Buf.getError()) { 4282 CGM.getDiags().Report(diag::err_cannot_open_file) 4283 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4284 return; 4285 } 4286 4287 llvm::LLVMContext C; 4288 auto ME = expectedToErrorOrAndEmitErrors( 4289 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4290 4291 if (auto EC = ME.getError()) { 4292 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4293 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4294 CGM.getDiags().Report(DiagID) 4295 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4296 return; 4297 } 4298 4299 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4300 if (!MD) 4301 return; 4302 4303 for (llvm::MDNode *MN : MD->operands()) { 4304 auto &&GetMDInt = [MN](unsigned Idx) { 4305 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4306 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4307 }; 4308 4309 auto &&GetMDString = [MN](unsigned Idx) { 4310 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4311 return V->getString(); 4312 }; 4313 4314 switch (GetMDInt(0)) { 4315 default: 4316 llvm_unreachable("Unexpected metadata!"); 4317 break; 4318 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4319 OffloadingEntryInfoTargetRegion: 4320 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4321 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4322 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4323 /*Order=*/GetMDInt(5)); 4324 break; 4325 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4326 OffloadingEntryInfoDeviceGlobalVar: 4327 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4328 /*MangledName=*/GetMDString(1), 4329 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4330 /*Flags=*/GetMDInt(2)), 4331 /*Order=*/GetMDInt(3)); 4332 break; 4333 } 4334 } 4335 } 4336 4337 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4338 if (!KmpRoutineEntryPtrTy) { 4339 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4340 ASTContext &C = CGM.getContext(); 4341 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4342 FunctionProtoType::ExtProtoInfo EPI; 4343 KmpRoutineEntryPtrQTy = C.getPointerType( 4344 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4345 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4346 } 4347 } 4348 4349 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4350 // Make sure the type of the entry is already created. This is the type we 4351 // have to create: 4352 // struct __tgt_offload_entry{ 4353 // void *addr; // Pointer to the offload entry info. 4354 // // (function or global) 4355 // char *name; // Name of the function or global. 4356 // size_t size; // Size of the entry info (0 if it a function). 4357 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4358 // int32_t reserved; // Reserved, to use by the runtime library. 4359 // }; 4360 if (TgtOffloadEntryQTy.isNull()) { 4361 ASTContext &C = CGM.getContext(); 4362 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4363 RD->startDefinition(); 4364 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4365 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4366 addFieldToRecordDecl(C, RD, C.getSizeType()); 4367 addFieldToRecordDecl( 4368 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4369 addFieldToRecordDecl( 4370 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4371 RD->completeDefinition(); 4372 RD->addAttr(PackedAttr::CreateImplicit(C)); 4373 TgtOffloadEntryQTy = C.getRecordType(RD); 4374 } 4375 return TgtOffloadEntryQTy; 4376 } 4377 4378 namespace { 4379 struct PrivateHelpersTy { 4380 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4381 const VarDecl *PrivateElemInit) 4382 : Original(Original), PrivateCopy(PrivateCopy), 4383 PrivateElemInit(PrivateElemInit) {} 4384 const VarDecl *Original; 4385 const VarDecl *PrivateCopy; 4386 const VarDecl *PrivateElemInit; 4387 }; 4388 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4389 } // anonymous namespace 4390 4391 static RecordDecl * 4392 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4393 if (!Privates.empty()) { 4394 ASTContext &C = CGM.getContext(); 4395 // Build struct .kmp_privates_t. { 4396 // /* private vars */ 4397 // }; 4398 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4399 RD->startDefinition(); 4400 for (const auto &Pair : Privates) { 4401 const VarDecl *VD = Pair.second.Original; 4402 QualType Type = VD->getType().getNonReferenceType(); 4403 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4404 if (VD->hasAttrs()) { 4405 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4406 E(VD->getAttrs().end()); 4407 I != E; ++I) 4408 FD->addAttr(*I); 4409 } 4410 } 4411 RD->completeDefinition(); 4412 return RD; 4413 } 4414 return nullptr; 4415 } 4416 4417 static RecordDecl * 4418 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4419 QualType KmpInt32Ty, 4420 QualType KmpRoutineEntryPointerQTy) { 4421 ASTContext &C = CGM.getContext(); 4422 // Build struct kmp_task_t { 4423 // void * shareds; 4424 // kmp_routine_entry_t routine; 4425 // kmp_int32 part_id; 4426 // kmp_cmplrdata_t data1; 4427 // kmp_cmplrdata_t data2; 4428 // For taskloops additional fields: 4429 // kmp_uint64 lb; 4430 // kmp_uint64 ub; 4431 // kmp_int64 st; 4432 // kmp_int32 liter; 4433 // void * reductions; 4434 // }; 4435 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4436 UD->startDefinition(); 4437 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4438 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4439 UD->completeDefinition(); 4440 QualType KmpCmplrdataTy = C.getRecordType(UD); 4441 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4442 RD->startDefinition(); 4443 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4444 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4445 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4446 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4447 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4448 if (isOpenMPTaskLoopDirective(Kind)) { 4449 QualType KmpUInt64Ty = 4450 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4451 QualType KmpInt64Ty = 4452 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4453 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4454 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4455 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4456 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4457 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4458 } 4459 RD->completeDefinition(); 4460 return RD; 4461 } 4462 4463 static RecordDecl * 4464 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4465 ArrayRef<PrivateDataTy> Privates) { 4466 ASTContext &C = CGM.getContext(); 4467 // Build struct kmp_task_t_with_privates { 4468 // kmp_task_t task_data; 4469 // .kmp_privates_t. privates; 4470 // }; 4471 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4472 RD->startDefinition(); 4473 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4474 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4475 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4476 RD->completeDefinition(); 4477 return RD; 4478 } 4479 4480 /// Emit a proxy function which accepts kmp_task_t as the second 4481 /// argument. 4482 /// \code 4483 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4484 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4485 /// For taskloops: 4486 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4487 /// tt->reductions, tt->shareds); 4488 /// return 0; 4489 /// } 4490 /// \endcode 4491 static llvm::Function * 4492 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4493 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4494 QualType KmpTaskTWithPrivatesPtrQTy, 4495 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4496 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4497 llvm::Value *TaskPrivatesMap) { 4498 ASTContext &C = CGM.getContext(); 4499 FunctionArgList Args; 4500 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4501 ImplicitParamDecl::Other); 4502 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4503 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4504 ImplicitParamDecl::Other); 4505 Args.push_back(&GtidArg); 4506 Args.push_back(&TaskTypeArg); 4507 const auto &TaskEntryFnInfo = 4508 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4509 llvm::FunctionType *TaskEntryTy = 4510 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4511 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4512 auto *TaskEntry = llvm::Function::Create( 4513 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4514 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4515 TaskEntry->setDoesNotRecurse(); 4516 CodeGenFunction CGF(CGM); 4517 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4518 Loc, Loc); 4519 4520 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4521 // tt, 4522 // For taskloops: 4523 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4524 // tt->task_data.shareds); 4525 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4526 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4527 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4528 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4529 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4530 const auto *KmpTaskTWithPrivatesQTyRD = 4531 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4532 LValue Base = 4533 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4534 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4535 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4536 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4537 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 4538 4539 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4540 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4541 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4542 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4543 CGF.ConvertTypeForMem(SharedsPtrTy)); 4544 4545 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4546 llvm::Value *PrivatesParam; 4547 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4548 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4549 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4550 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 4551 } else { 4552 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4553 } 4554 4555 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4556 TaskPrivatesMap, 4557 CGF.Builder 4558 .CreatePointerBitCastOrAddrSpaceCast( 4559 TDBase.getAddress(CGF), CGF.VoidPtrTy) 4560 .getPointer()}; 4561 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4562 std::end(CommonArgs)); 4563 if (isOpenMPTaskLoopDirective(Kind)) { 4564 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4565 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4566 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4567 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4568 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4569 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4570 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4571 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4572 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4573 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4574 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4575 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4576 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4577 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4578 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4579 CallArgs.push_back(LBParam); 4580 CallArgs.push_back(UBParam); 4581 CallArgs.push_back(StParam); 4582 CallArgs.push_back(LIParam); 4583 CallArgs.push_back(RParam); 4584 } 4585 CallArgs.push_back(SharedsParam); 4586 4587 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4588 CallArgs); 4589 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4590 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4591 CGF.FinishFunction(); 4592 return TaskEntry; 4593 } 4594 4595 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4596 SourceLocation Loc, 4597 QualType KmpInt32Ty, 4598 QualType KmpTaskTWithPrivatesPtrQTy, 4599 QualType KmpTaskTWithPrivatesQTy) { 4600 ASTContext &C = CGM.getContext(); 4601 FunctionArgList Args; 4602 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4603 ImplicitParamDecl::Other); 4604 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4605 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4606 ImplicitParamDecl::Other); 4607 Args.push_back(&GtidArg); 4608 Args.push_back(&TaskTypeArg); 4609 const auto &DestructorFnInfo = 4610 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4611 llvm::FunctionType *DestructorFnTy = 4612 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4613 std::string Name = 4614 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4615 auto *DestructorFn = 4616 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4617 Name, &CGM.getModule()); 4618 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4619 DestructorFnInfo); 4620 DestructorFn->setDoesNotRecurse(); 4621 CodeGenFunction CGF(CGM); 4622 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4623 Args, Loc, Loc); 4624 4625 LValue Base = CGF.EmitLoadOfPointerLValue( 4626 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4627 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4628 const auto *KmpTaskTWithPrivatesQTyRD = 4629 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4630 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4631 Base = CGF.EmitLValueForField(Base, *FI); 4632 for (const auto *Field : 4633 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4634 if (QualType::DestructionKind DtorKind = 4635 Field->getType().isDestructedType()) { 4636 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4637 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 4638 } 4639 } 4640 CGF.FinishFunction(); 4641 return DestructorFn; 4642 } 4643 4644 /// Emit a privates mapping function for correct handling of private and 4645 /// firstprivate variables. 4646 /// \code 4647 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4648 /// **noalias priv1,..., <tyn> **noalias privn) { 4649 /// *priv1 = &.privates.priv1; 4650 /// ...; 4651 /// *privn = &.privates.privn; 4652 /// } 4653 /// \endcode 4654 static llvm::Value * 4655 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4656 ArrayRef<const Expr *> PrivateVars, 4657 ArrayRef<const Expr *> FirstprivateVars, 4658 ArrayRef<const Expr *> LastprivateVars, 4659 QualType PrivatesQTy, 4660 ArrayRef<PrivateDataTy> Privates) { 4661 ASTContext &C = CGM.getContext(); 4662 FunctionArgList Args; 4663 ImplicitParamDecl TaskPrivatesArg( 4664 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4665 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4666 ImplicitParamDecl::Other); 4667 Args.push_back(&TaskPrivatesArg); 4668 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4669 unsigned Counter = 1; 4670 for (const Expr *E : PrivateVars) { 4671 Args.push_back(ImplicitParamDecl::Create( 4672 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4673 C.getPointerType(C.getPointerType(E->getType())) 4674 .withConst() 4675 .withRestrict(), 4676 ImplicitParamDecl::Other)); 4677 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4678 PrivateVarsPos[VD] = Counter; 4679 ++Counter; 4680 } 4681 for (const Expr *E : FirstprivateVars) { 4682 Args.push_back(ImplicitParamDecl::Create( 4683 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4684 C.getPointerType(C.getPointerType(E->getType())) 4685 .withConst() 4686 .withRestrict(), 4687 ImplicitParamDecl::Other)); 4688 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4689 PrivateVarsPos[VD] = Counter; 4690 ++Counter; 4691 } 4692 for (const Expr *E : LastprivateVars) { 4693 Args.push_back(ImplicitParamDecl::Create( 4694 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4695 C.getPointerType(C.getPointerType(E->getType())) 4696 .withConst() 4697 .withRestrict(), 4698 ImplicitParamDecl::Other)); 4699 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4700 PrivateVarsPos[VD] = Counter; 4701 ++Counter; 4702 } 4703 const auto &TaskPrivatesMapFnInfo = 4704 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4705 llvm::FunctionType *TaskPrivatesMapTy = 4706 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4707 std::string Name = 4708 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4709 auto *TaskPrivatesMap = llvm::Function::Create( 4710 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4711 &CGM.getModule()); 4712 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4713 TaskPrivatesMapFnInfo); 4714 if (CGM.getLangOpts().Optimize) { 4715 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4716 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4717 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4718 } 4719 CodeGenFunction CGF(CGM); 4720 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4721 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4722 4723 // *privi = &.privates.privi; 4724 LValue Base = CGF.EmitLoadOfPointerLValue( 4725 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4726 TaskPrivatesArg.getType()->castAs<PointerType>()); 4727 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4728 Counter = 0; 4729 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4730 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4731 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4732 LValue RefLVal = 4733 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4734 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4735 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 4736 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 4737 ++Counter; 4738 } 4739 CGF.FinishFunction(); 4740 return TaskPrivatesMap; 4741 } 4742 4743 /// Emit initialization for private variables in task-based directives. 4744 static void emitPrivatesInit(CodeGenFunction &CGF, 4745 const OMPExecutableDirective &D, 4746 Address KmpTaskSharedsPtr, LValue TDBase, 4747 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4748 QualType SharedsTy, QualType SharedsPtrTy, 4749 const OMPTaskDataTy &Data, 4750 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4751 ASTContext &C = CGF.getContext(); 4752 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4753 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4754 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4755 ? OMPD_taskloop 4756 : OMPD_task; 4757 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4758 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4759 LValue SrcBase; 4760 bool IsTargetTask = 4761 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4762 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4763 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4764 // PointersArray and SizesArray. The original variables for these arrays are 4765 // not captured and we get their addresses explicitly. 4766 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4767 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4768 SrcBase = CGF.MakeAddrLValue( 4769 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4770 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4771 SharedsTy); 4772 } 4773 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4774 for (const PrivateDataTy &Pair : Privates) { 4775 const VarDecl *VD = Pair.second.PrivateCopy; 4776 const Expr *Init = VD->getAnyInitializer(); 4777 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4778 !CGF.isTrivialInitializer(Init)))) { 4779 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4780 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4781 const VarDecl *OriginalVD = Pair.second.Original; 4782 // Check if the variable is the target-based BasePointersArray, 4783 // PointersArray or SizesArray. 4784 LValue SharedRefLValue; 4785 QualType Type = PrivateLValue.getType(); 4786 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4787 if (IsTargetTask && !SharedField) { 4788 assert(isa<ImplicitParamDecl>(OriginalVD) && 4789 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4790 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4791 ->getNumParams() == 0 && 4792 isa<TranslationUnitDecl>( 4793 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4794 ->getDeclContext()) && 4795 "Expected artificial target data variable."); 4796 SharedRefLValue = 4797 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4798 } else { 4799 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4800 SharedRefLValue = CGF.MakeAddrLValue( 4801 Address(SharedRefLValue.getPointer(CGF), 4802 C.getDeclAlign(OriginalVD)), 4803 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4804 SharedRefLValue.getTBAAInfo()); 4805 } 4806 if (Type->isArrayType()) { 4807 // Initialize firstprivate array. 4808 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4809 // Perform simple memcpy. 4810 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4811 } else { 4812 // Initialize firstprivate array using element-by-element 4813 // initialization. 4814 CGF.EmitOMPAggregateAssign( 4815 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 4816 Type, 4817 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4818 Address SrcElement) { 4819 // Clean up any temporaries needed by the initialization. 4820 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4821 InitScope.addPrivate( 4822 Elem, [SrcElement]() -> Address { return SrcElement; }); 4823 (void)InitScope.Privatize(); 4824 // Emit initialization for single element. 4825 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4826 CGF, &CapturesInfo); 4827 CGF.EmitAnyExprToMem(Init, DestElement, 4828 Init->getType().getQualifiers(), 4829 /*IsInitializer=*/false); 4830 }); 4831 } 4832 } else { 4833 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4834 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 4835 return SharedRefLValue.getAddress(CGF); 4836 }); 4837 (void)InitScope.Privatize(); 4838 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4839 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4840 /*capturedByInit=*/false); 4841 } 4842 } else { 4843 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4844 } 4845 } 4846 ++FI; 4847 } 4848 } 4849 4850 /// Check if duplication function is required for taskloops. 4851 static bool checkInitIsRequired(CodeGenFunction &CGF, 4852 ArrayRef<PrivateDataTy> Privates) { 4853 bool InitRequired = false; 4854 for (const PrivateDataTy &Pair : Privates) { 4855 const VarDecl *VD = Pair.second.PrivateCopy; 4856 const Expr *Init = VD->getAnyInitializer(); 4857 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4858 !CGF.isTrivialInitializer(Init)); 4859 if (InitRequired) 4860 break; 4861 } 4862 return InitRequired; 4863 } 4864 4865 4866 /// Emit task_dup function (for initialization of 4867 /// private/firstprivate/lastprivate vars and last_iter flag) 4868 /// \code 4869 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4870 /// lastpriv) { 4871 /// // setup lastprivate flag 4872 /// task_dst->last = lastpriv; 4873 /// // could be constructor calls here... 4874 /// } 4875 /// \endcode 4876 static llvm::Value * 4877 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4878 const OMPExecutableDirective &D, 4879 QualType KmpTaskTWithPrivatesPtrQTy, 4880 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4881 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4882 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4883 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4884 ASTContext &C = CGM.getContext(); 4885 FunctionArgList Args; 4886 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4887 KmpTaskTWithPrivatesPtrQTy, 4888 ImplicitParamDecl::Other); 4889 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4890 KmpTaskTWithPrivatesPtrQTy, 4891 ImplicitParamDecl::Other); 4892 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4893 ImplicitParamDecl::Other); 4894 Args.push_back(&DstArg); 4895 Args.push_back(&SrcArg); 4896 Args.push_back(&LastprivArg); 4897 const auto &TaskDupFnInfo = 4898 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4899 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4900 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4901 auto *TaskDup = llvm::Function::Create( 4902 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4903 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4904 TaskDup->setDoesNotRecurse(); 4905 CodeGenFunction CGF(CGM); 4906 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4907 Loc); 4908 4909 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4910 CGF.GetAddrOfLocalVar(&DstArg), 4911 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4912 // task_dst->liter = lastpriv; 4913 if (WithLastIter) { 4914 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4915 LValue Base = CGF.EmitLValueForField( 4916 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4917 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4918 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4919 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4920 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4921 } 4922 4923 // Emit initial values for private copies (if any). 4924 assert(!Privates.empty()); 4925 Address KmpTaskSharedsPtr = Address::invalid(); 4926 if (!Data.FirstprivateVars.empty()) { 4927 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4928 CGF.GetAddrOfLocalVar(&SrcArg), 4929 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4930 LValue Base = CGF.EmitLValueForField( 4931 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4932 KmpTaskSharedsPtr = Address( 4933 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4934 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4935 KmpTaskTShareds)), 4936 Loc), 4937 CGF.getNaturalTypeAlignment(SharedsTy)); 4938 } 4939 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4940 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4941 CGF.FinishFunction(); 4942 return TaskDup; 4943 } 4944 4945 /// Checks if destructor function is required to be generated. 4946 /// \return true if cleanups are required, false otherwise. 4947 static bool 4948 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4949 bool NeedsCleanup = false; 4950 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4951 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4952 for (const FieldDecl *FD : PrivateRD->fields()) { 4953 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4954 if (NeedsCleanup) 4955 break; 4956 } 4957 return NeedsCleanup; 4958 } 4959 4960 CGOpenMPRuntime::TaskResultTy 4961 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4962 const OMPExecutableDirective &D, 4963 llvm::Function *TaskFunction, QualType SharedsTy, 4964 Address Shareds, const OMPTaskDataTy &Data) { 4965 ASTContext &C = CGM.getContext(); 4966 llvm::SmallVector<PrivateDataTy, 4> Privates; 4967 // Aggregate privates and sort them by the alignment. 4968 auto I = Data.PrivateCopies.begin(); 4969 for (const Expr *E : Data.PrivateVars) { 4970 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4971 Privates.emplace_back( 4972 C.getDeclAlign(VD), 4973 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4974 /*PrivateElemInit=*/nullptr)); 4975 ++I; 4976 } 4977 I = Data.FirstprivateCopies.begin(); 4978 auto IElemInitRef = Data.FirstprivateInits.begin(); 4979 for (const Expr *E : Data.FirstprivateVars) { 4980 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4981 Privates.emplace_back( 4982 C.getDeclAlign(VD), 4983 PrivateHelpersTy( 4984 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4985 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4986 ++I; 4987 ++IElemInitRef; 4988 } 4989 I = Data.LastprivateCopies.begin(); 4990 for (const Expr *E : Data.LastprivateVars) { 4991 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4992 Privates.emplace_back( 4993 C.getDeclAlign(VD), 4994 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4995 /*PrivateElemInit=*/nullptr)); 4996 ++I; 4997 } 4998 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 4999 return L.first > R.first; 5000 }); 5001 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 5002 // Build type kmp_routine_entry_t (if not built yet). 5003 emitKmpRoutineEntryT(KmpInt32Ty); 5004 // Build type kmp_task_t (if not built yet). 5005 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 5006 if (SavedKmpTaskloopTQTy.isNull()) { 5007 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5008 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5009 } 5010 KmpTaskTQTy = SavedKmpTaskloopTQTy; 5011 } else { 5012 assert((D.getDirectiveKind() == OMPD_task || 5013 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 5014 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5015 "Expected taskloop, task or target directive"); 5016 if (SavedKmpTaskTQTy.isNull()) { 5017 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5018 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5019 } 5020 KmpTaskTQTy = SavedKmpTaskTQTy; 5021 } 5022 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5023 // Build particular struct kmp_task_t for the given task. 5024 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5025 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5026 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5027 QualType KmpTaskTWithPrivatesPtrQTy = 5028 C.getPointerType(KmpTaskTWithPrivatesQTy); 5029 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5030 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5031 KmpTaskTWithPrivatesTy->getPointerTo(); 5032 llvm::Value *KmpTaskTWithPrivatesTySize = 5033 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5034 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5035 5036 // Emit initial values for private copies (if any). 5037 llvm::Value *TaskPrivatesMap = nullptr; 5038 llvm::Type *TaskPrivatesMapTy = 5039 std::next(TaskFunction->arg_begin(), 3)->getType(); 5040 if (!Privates.empty()) { 5041 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5042 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5043 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5044 FI->getType(), Privates); 5045 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5046 TaskPrivatesMap, TaskPrivatesMapTy); 5047 } else { 5048 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5049 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5050 } 5051 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5052 // kmp_task_t *tt); 5053 llvm::Function *TaskEntry = emitProxyTaskFunction( 5054 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5055 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5056 TaskPrivatesMap); 5057 5058 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5059 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5060 // kmp_routine_entry_t *task_entry); 5061 // Task flags. Format is taken from 5062 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5063 // description of kmp_tasking_flags struct. 5064 enum { 5065 TiedFlag = 0x1, 5066 FinalFlag = 0x2, 5067 DestructorsFlag = 0x8, 5068 PriorityFlag = 0x20 5069 }; 5070 unsigned Flags = Data.Tied ? TiedFlag : 0; 5071 bool NeedsCleanup = false; 5072 if (!Privates.empty()) { 5073 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5074 if (NeedsCleanup) 5075 Flags = Flags | DestructorsFlag; 5076 } 5077 if (Data.Priority.getInt()) 5078 Flags = Flags | PriorityFlag; 5079 llvm::Value *TaskFlags = 5080 Data.Final.getPointer() 5081 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5082 CGF.Builder.getInt32(FinalFlag), 5083 CGF.Builder.getInt32(/*C=*/0)) 5084 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5085 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5086 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5087 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5088 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5089 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5090 TaskEntry, KmpRoutineEntryPtrTy)}; 5091 llvm::Value *NewTask; 5092 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5093 // Check if we have any device clause associated with the directive. 5094 const Expr *Device = nullptr; 5095 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5096 Device = C->getDevice(); 5097 // Emit device ID if any otherwise use default value. 5098 llvm::Value *DeviceID; 5099 if (Device) 5100 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5101 CGF.Int64Ty, /*isSigned=*/true); 5102 else 5103 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5104 AllocArgs.push_back(DeviceID); 5105 NewTask = CGF.EmitRuntimeCall( 5106 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5107 } else { 5108 NewTask = CGF.EmitRuntimeCall( 5109 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5110 } 5111 llvm::Value *NewTaskNewTaskTTy = 5112 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5113 NewTask, KmpTaskTWithPrivatesPtrTy); 5114 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5115 KmpTaskTWithPrivatesQTy); 5116 LValue TDBase = 5117 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5118 // Fill the data in the resulting kmp_task_t record. 5119 // Copy shareds if there are any. 5120 Address KmpTaskSharedsPtr = Address::invalid(); 5121 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5122 KmpTaskSharedsPtr = 5123 Address(CGF.EmitLoadOfScalar( 5124 CGF.EmitLValueForField( 5125 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5126 KmpTaskTShareds)), 5127 Loc), 5128 CGF.getNaturalTypeAlignment(SharedsTy)); 5129 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5130 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5131 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5132 } 5133 // Emit initial values for private copies (if any). 5134 TaskResultTy Result; 5135 if (!Privates.empty()) { 5136 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5137 SharedsTy, SharedsPtrTy, Data, Privates, 5138 /*ForDup=*/false); 5139 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5140 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5141 Result.TaskDupFn = emitTaskDupFunction( 5142 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5143 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5144 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5145 } 5146 } 5147 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5148 enum { Priority = 0, Destructors = 1 }; 5149 // Provide pointer to function with destructors for privates. 5150 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5151 const RecordDecl *KmpCmplrdataUD = 5152 (*FI)->getType()->getAsUnionType()->getDecl(); 5153 if (NeedsCleanup) { 5154 llvm::Value *DestructorFn = emitDestructorsFunction( 5155 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5156 KmpTaskTWithPrivatesQTy); 5157 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5158 LValue DestructorsLV = CGF.EmitLValueForField( 5159 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5160 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5161 DestructorFn, KmpRoutineEntryPtrTy), 5162 DestructorsLV); 5163 } 5164 // Set priority. 5165 if (Data.Priority.getInt()) { 5166 LValue Data2LV = CGF.EmitLValueForField( 5167 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5168 LValue PriorityLV = CGF.EmitLValueForField( 5169 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5170 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5171 } 5172 Result.NewTask = NewTask; 5173 Result.TaskEntry = TaskEntry; 5174 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5175 Result.TDBase = TDBase; 5176 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5177 return Result; 5178 } 5179 5180 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5181 const OMPExecutableDirective &D, 5182 llvm::Function *TaskFunction, 5183 QualType SharedsTy, Address Shareds, 5184 const Expr *IfCond, 5185 const OMPTaskDataTy &Data) { 5186 if (!CGF.HaveInsertPoint()) 5187 return; 5188 5189 TaskResultTy Result = 5190 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5191 llvm::Value *NewTask = Result.NewTask; 5192 llvm::Function *TaskEntry = Result.TaskEntry; 5193 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5194 LValue TDBase = Result.TDBase; 5195 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5196 ASTContext &C = CGM.getContext(); 5197 // Process list of dependences. 5198 Address DependenciesArray = Address::invalid(); 5199 unsigned NumDependencies = Data.Dependences.size(); 5200 if (NumDependencies) { 5201 // Dependence kind for RTL. 5202 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 }; 5203 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5204 RecordDecl *KmpDependInfoRD; 5205 QualType FlagsTy = 5206 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5207 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5208 if (KmpDependInfoTy.isNull()) { 5209 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5210 KmpDependInfoRD->startDefinition(); 5211 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5212 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5213 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5214 KmpDependInfoRD->completeDefinition(); 5215 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5216 } else { 5217 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5218 } 5219 // Define type kmp_depend_info[<Dependences.size()>]; 5220 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5221 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5222 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5223 // kmp_depend_info[<Dependences.size()>] deps; 5224 DependenciesArray = 5225 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5226 for (unsigned I = 0; I < NumDependencies; ++I) { 5227 const Expr *E = Data.Dependences[I].second; 5228 LValue Addr = CGF.EmitLValue(E); 5229 llvm::Value *Size; 5230 QualType Ty = E->getType(); 5231 if (const auto *ASE = 5232 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5233 LValue UpAddrLVal = 5234 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5235 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 5236 UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 5237 llvm::Value *LowIntPtr = 5238 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy); 5239 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5240 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5241 } else { 5242 Size = CGF.getTypeSize(Ty); 5243 } 5244 LValue Base = CGF.MakeAddrLValue( 5245 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I), 5246 KmpDependInfoTy); 5247 // deps[i].base_addr = &<Dependences[i].second>; 5248 LValue BaseAddrLVal = CGF.EmitLValueForField( 5249 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5250 CGF.EmitStoreOfScalar( 5251 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy), 5252 BaseAddrLVal); 5253 // deps[i].len = sizeof(<Dependences[i].second>); 5254 LValue LenLVal = CGF.EmitLValueForField( 5255 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5256 CGF.EmitStoreOfScalar(Size, LenLVal); 5257 // deps[i].flags = <Dependences[i].first>; 5258 RTLDependenceKindTy DepKind; 5259 switch (Data.Dependences[I].first) { 5260 case OMPC_DEPEND_in: 5261 DepKind = DepIn; 5262 break; 5263 // Out and InOut dependencies must use the same code. 5264 case OMPC_DEPEND_out: 5265 case OMPC_DEPEND_inout: 5266 DepKind = DepInOut; 5267 break; 5268 case OMPC_DEPEND_mutexinoutset: 5269 DepKind = DepMutexInOutSet; 5270 break; 5271 case OMPC_DEPEND_source: 5272 case OMPC_DEPEND_sink: 5273 case OMPC_DEPEND_unknown: 5274 llvm_unreachable("Unknown task dependence type"); 5275 } 5276 LValue FlagsLVal = CGF.EmitLValueForField( 5277 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5278 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5279 FlagsLVal); 5280 } 5281 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5282 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); 5283 } 5284 5285 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5286 // libcall. 5287 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5288 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5289 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5290 // list is not empty 5291 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5292 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5293 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5294 llvm::Value *DepTaskArgs[7]; 5295 if (NumDependencies) { 5296 DepTaskArgs[0] = UpLoc; 5297 DepTaskArgs[1] = ThreadID; 5298 DepTaskArgs[2] = NewTask; 5299 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 5300 DepTaskArgs[4] = DependenciesArray.getPointer(); 5301 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5302 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5303 } 5304 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 5305 &TaskArgs, 5306 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5307 if (!Data.Tied) { 5308 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5309 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5310 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5311 } 5312 if (NumDependencies) { 5313 CGF.EmitRuntimeCall( 5314 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5315 } else { 5316 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5317 TaskArgs); 5318 } 5319 // Check if parent region is untied and build return for untied task; 5320 if (auto *Region = 5321 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5322 Region->emitUntiedSwitch(CGF); 5323 }; 5324 5325 llvm::Value *DepWaitTaskArgs[6]; 5326 if (NumDependencies) { 5327 DepWaitTaskArgs[0] = UpLoc; 5328 DepWaitTaskArgs[1] = ThreadID; 5329 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 5330 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5331 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5332 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5333 } 5334 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5335 NumDependencies, &DepWaitTaskArgs, 5336 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5337 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5338 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5339 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5340 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5341 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5342 // is specified. 5343 if (NumDependencies) 5344 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5345 DepWaitTaskArgs); 5346 // Call proxy_task_entry(gtid, new_task); 5347 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5348 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5349 Action.Enter(CGF); 5350 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5351 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5352 OutlinedFnArgs); 5353 }; 5354 5355 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5356 // kmp_task_t *new_task); 5357 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5358 // kmp_task_t *new_task); 5359 RegionCodeGenTy RCG(CodeGen); 5360 CommonActionTy Action( 5361 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5362 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5363 RCG.setAction(Action); 5364 RCG(CGF); 5365 }; 5366 5367 if (IfCond) { 5368 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5369 } else { 5370 RegionCodeGenTy ThenRCG(ThenCodeGen); 5371 ThenRCG(CGF); 5372 } 5373 } 5374 5375 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5376 const OMPLoopDirective &D, 5377 llvm::Function *TaskFunction, 5378 QualType SharedsTy, Address Shareds, 5379 const Expr *IfCond, 5380 const OMPTaskDataTy &Data) { 5381 if (!CGF.HaveInsertPoint()) 5382 return; 5383 TaskResultTy Result = 5384 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5385 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5386 // libcall. 5387 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5388 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5389 // sched, kmp_uint64 grainsize, void *task_dup); 5390 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5391 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5392 llvm::Value *IfVal; 5393 if (IfCond) { 5394 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5395 /*isSigned=*/true); 5396 } else { 5397 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5398 } 5399 5400 LValue LBLVal = CGF.EmitLValueForField( 5401 Result.TDBase, 5402 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5403 const auto *LBVar = 5404 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5405 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5406 LBLVal.getQuals(), 5407 /*IsInitializer=*/true); 5408 LValue UBLVal = CGF.EmitLValueForField( 5409 Result.TDBase, 5410 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5411 const auto *UBVar = 5412 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5413 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5414 UBLVal.getQuals(), 5415 /*IsInitializer=*/true); 5416 LValue StLVal = CGF.EmitLValueForField( 5417 Result.TDBase, 5418 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5419 const auto *StVar = 5420 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5421 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5422 StLVal.getQuals(), 5423 /*IsInitializer=*/true); 5424 // Store reductions address. 5425 LValue RedLVal = CGF.EmitLValueForField( 5426 Result.TDBase, 5427 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5428 if (Data.Reductions) { 5429 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5430 } else { 5431 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5432 CGF.getContext().VoidPtrTy); 5433 } 5434 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5435 llvm::Value *TaskArgs[] = { 5436 UpLoc, 5437 ThreadID, 5438 Result.NewTask, 5439 IfVal, 5440 LBLVal.getPointer(CGF), 5441 UBLVal.getPointer(CGF), 5442 CGF.EmitLoadOfScalar(StLVal, Loc), 5443 llvm::ConstantInt::getSigned( 5444 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5445 llvm::ConstantInt::getSigned( 5446 CGF.IntTy, Data.Schedule.getPointer() 5447 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5448 : NoSchedule), 5449 Data.Schedule.getPointer() 5450 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5451 /*isSigned=*/false) 5452 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5453 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5454 Result.TaskDupFn, CGF.VoidPtrTy) 5455 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5456 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5457 } 5458 5459 /// Emit reduction operation for each element of array (required for 5460 /// array sections) LHS op = RHS. 5461 /// \param Type Type of array. 5462 /// \param LHSVar Variable on the left side of the reduction operation 5463 /// (references element of array in original variable). 5464 /// \param RHSVar Variable on the right side of the reduction operation 5465 /// (references element of array in original variable). 5466 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5467 /// RHSVar. 5468 static void EmitOMPAggregateReduction( 5469 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5470 const VarDecl *RHSVar, 5471 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5472 const Expr *, const Expr *)> &RedOpGen, 5473 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5474 const Expr *UpExpr = nullptr) { 5475 // Perform element-by-element initialization. 5476 QualType ElementTy; 5477 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5478 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5479 5480 // Drill down to the base element type on both arrays. 5481 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5482 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5483 5484 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5485 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5486 // Cast from pointer to array type to pointer to single element. 5487 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5488 // The basic structure here is a while-do loop. 5489 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5490 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5491 llvm::Value *IsEmpty = 5492 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5493 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5494 5495 // Enter the loop body, making that address the current address. 5496 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5497 CGF.EmitBlock(BodyBB); 5498 5499 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5500 5501 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5502 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5503 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5504 Address RHSElementCurrent = 5505 Address(RHSElementPHI, 5506 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5507 5508 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5509 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5510 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5511 Address LHSElementCurrent = 5512 Address(LHSElementPHI, 5513 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5514 5515 // Emit copy. 5516 CodeGenFunction::OMPPrivateScope Scope(CGF); 5517 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5518 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5519 Scope.Privatize(); 5520 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5521 Scope.ForceCleanup(); 5522 5523 // Shift the address forward by one element. 5524 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5525 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5526 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5527 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5528 // Check whether we've reached the end. 5529 llvm::Value *Done = 5530 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5531 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5532 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5533 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5534 5535 // Done. 5536 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5537 } 5538 5539 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5540 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5541 /// UDR combiner function. 5542 static void emitReductionCombiner(CodeGenFunction &CGF, 5543 const Expr *ReductionOp) { 5544 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5545 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5546 if (const auto *DRE = 5547 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5548 if (const auto *DRD = 5549 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5550 std::pair<llvm::Function *, llvm::Function *> Reduction = 5551 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5552 RValue Func = RValue::get(Reduction.first); 5553 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5554 CGF.EmitIgnoredExpr(ReductionOp); 5555 return; 5556 } 5557 CGF.EmitIgnoredExpr(ReductionOp); 5558 } 5559 5560 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5561 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5562 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5563 ArrayRef<const Expr *> ReductionOps) { 5564 ASTContext &C = CGM.getContext(); 5565 5566 // void reduction_func(void *LHSArg, void *RHSArg); 5567 FunctionArgList Args; 5568 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5569 ImplicitParamDecl::Other); 5570 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5571 ImplicitParamDecl::Other); 5572 Args.push_back(&LHSArg); 5573 Args.push_back(&RHSArg); 5574 const auto &CGFI = 5575 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5576 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5577 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5578 llvm::GlobalValue::InternalLinkage, Name, 5579 &CGM.getModule()); 5580 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5581 Fn->setDoesNotRecurse(); 5582 CodeGenFunction CGF(CGM); 5583 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5584 5585 // Dst = (void*[n])(LHSArg); 5586 // Src = (void*[n])(RHSArg); 5587 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5588 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5589 ArgsType), CGF.getPointerAlign()); 5590 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5591 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5592 ArgsType), CGF.getPointerAlign()); 5593 5594 // ... 5595 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5596 // ... 5597 CodeGenFunction::OMPPrivateScope Scope(CGF); 5598 auto IPriv = Privates.begin(); 5599 unsigned Idx = 0; 5600 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5601 const auto *RHSVar = 5602 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5603 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5604 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5605 }); 5606 const auto *LHSVar = 5607 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5608 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5609 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5610 }); 5611 QualType PrivTy = (*IPriv)->getType(); 5612 if (PrivTy->isVariablyModifiedType()) { 5613 // Get array size and emit VLA type. 5614 ++Idx; 5615 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5616 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5617 const VariableArrayType *VLA = 5618 CGF.getContext().getAsVariableArrayType(PrivTy); 5619 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5620 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5621 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5622 CGF.EmitVariablyModifiedType(PrivTy); 5623 } 5624 } 5625 Scope.Privatize(); 5626 IPriv = Privates.begin(); 5627 auto ILHS = LHSExprs.begin(); 5628 auto IRHS = RHSExprs.begin(); 5629 for (const Expr *E : ReductionOps) { 5630 if ((*IPriv)->getType()->isArrayType()) { 5631 // Emit reduction for array section. 5632 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5633 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5634 EmitOMPAggregateReduction( 5635 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5636 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5637 emitReductionCombiner(CGF, E); 5638 }); 5639 } else { 5640 // Emit reduction for array subscript or single variable. 5641 emitReductionCombiner(CGF, E); 5642 } 5643 ++IPriv; 5644 ++ILHS; 5645 ++IRHS; 5646 } 5647 Scope.ForceCleanup(); 5648 CGF.FinishFunction(); 5649 return Fn; 5650 } 5651 5652 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5653 const Expr *ReductionOp, 5654 const Expr *PrivateRef, 5655 const DeclRefExpr *LHS, 5656 const DeclRefExpr *RHS) { 5657 if (PrivateRef->getType()->isArrayType()) { 5658 // Emit reduction for array section. 5659 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5660 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5661 EmitOMPAggregateReduction( 5662 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5663 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5664 emitReductionCombiner(CGF, ReductionOp); 5665 }); 5666 } else { 5667 // Emit reduction for array subscript or single variable. 5668 emitReductionCombiner(CGF, ReductionOp); 5669 } 5670 } 5671 5672 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5673 ArrayRef<const Expr *> Privates, 5674 ArrayRef<const Expr *> LHSExprs, 5675 ArrayRef<const Expr *> RHSExprs, 5676 ArrayRef<const Expr *> ReductionOps, 5677 ReductionOptionsTy Options) { 5678 if (!CGF.HaveInsertPoint()) 5679 return; 5680 5681 bool WithNowait = Options.WithNowait; 5682 bool SimpleReduction = Options.SimpleReduction; 5683 5684 // Next code should be emitted for reduction: 5685 // 5686 // static kmp_critical_name lock = { 0 }; 5687 // 5688 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5689 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5690 // ... 5691 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5692 // *(Type<n>-1*)rhs[<n>-1]); 5693 // } 5694 // 5695 // ... 5696 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5697 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5698 // RedList, reduce_func, &<lock>)) { 5699 // case 1: 5700 // ... 5701 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5702 // ... 5703 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5704 // break; 5705 // case 2: 5706 // ... 5707 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5708 // ... 5709 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5710 // break; 5711 // default:; 5712 // } 5713 // 5714 // if SimpleReduction is true, only the next code is generated: 5715 // ... 5716 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5717 // ... 5718 5719 ASTContext &C = CGM.getContext(); 5720 5721 if (SimpleReduction) { 5722 CodeGenFunction::RunCleanupsScope Scope(CGF); 5723 auto IPriv = Privates.begin(); 5724 auto ILHS = LHSExprs.begin(); 5725 auto IRHS = RHSExprs.begin(); 5726 for (const Expr *E : ReductionOps) { 5727 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5728 cast<DeclRefExpr>(*IRHS)); 5729 ++IPriv; 5730 ++ILHS; 5731 ++IRHS; 5732 } 5733 return; 5734 } 5735 5736 // 1. Build a list of reduction variables. 5737 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5738 auto Size = RHSExprs.size(); 5739 for (const Expr *E : Privates) { 5740 if (E->getType()->isVariablyModifiedType()) 5741 // Reserve place for array size. 5742 ++Size; 5743 } 5744 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5745 QualType ReductionArrayTy = 5746 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5747 /*IndexTypeQuals=*/0); 5748 Address ReductionList = 5749 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5750 auto IPriv = Privates.begin(); 5751 unsigned Idx = 0; 5752 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5753 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5754 CGF.Builder.CreateStore( 5755 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5756 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5757 Elem); 5758 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5759 // Store array size. 5760 ++Idx; 5761 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5762 llvm::Value *Size = CGF.Builder.CreateIntCast( 5763 CGF.getVLASize( 5764 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5765 .NumElts, 5766 CGF.SizeTy, /*isSigned=*/false); 5767 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5768 Elem); 5769 } 5770 } 5771 5772 // 2. Emit reduce_func(). 5773 llvm::Function *ReductionFn = emitReductionFunction( 5774 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5775 LHSExprs, RHSExprs, ReductionOps); 5776 5777 // 3. Create static kmp_critical_name lock = { 0 }; 5778 std::string Name = getName({"reduction"}); 5779 llvm::Value *Lock = getCriticalRegionLock(Name); 5780 5781 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5782 // RedList, reduce_func, &<lock>); 5783 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5784 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5785 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5786 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5787 ReductionList.getPointer(), CGF.VoidPtrTy); 5788 llvm::Value *Args[] = { 5789 IdentTLoc, // ident_t *<loc> 5790 ThreadId, // i32 <gtid> 5791 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5792 ReductionArrayTySize, // size_type sizeof(RedList) 5793 RL, // void *RedList 5794 ReductionFn, // void (*) (void *, void *) <reduce_func> 5795 Lock // kmp_critical_name *&<lock> 5796 }; 5797 llvm::Value *Res = CGF.EmitRuntimeCall( 5798 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 5799 : OMPRTL__kmpc_reduce), 5800 Args); 5801 5802 // 5. Build switch(res) 5803 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5804 llvm::SwitchInst *SwInst = 5805 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5806 5807 // 6. Build case 1: 5808 // ... 5809 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5810 // ... 5811 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5812 // break; 5813 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5814 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5815 CGF.EmitBlock(Case1BB); 5816 5817 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5818 llvm::Value *EndArgs[] = { 5819 IdentTLoc, // ident_t *<loc> 5820 ThreadId, // i32 <gtid> 5821 Lock // kmp_critical_name *&<lock> 5822 }; 5823 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5824 CodeGenFunction &CGF, PrePostActionTy &Action) { 5825 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5826 auto IPriv = Privates.begin(); 5827 auto ILHS = LHSExprs.begin(); 5828 auto IRHS = RHSExprs.begin(); 5829 for (const Expr *E : ReductionOps) { 5830 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5831 cast<DeclRefExpr>(*IRHS)); 5832 ++IPriv; 5833 ++ILHS; 5834 ++IRHS; 5835 } 5836 }; 5837 RegionCodeGenTy RCG(CodeGen); 5838 CommonActionTy Action( 5839 nullptr, llvm::None, 5840 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 5841 : OMPRTL__kmpc_end_reduce), 5842 EndArgs); 5843 RCG.setAction(Action); 5844 RCG(CGF); 5845 5846 CGF.EmitBranch(DefaultBB); 5847 5848 // 7. Build case 2: 5849 // ... 5850 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5851 // ... 5852 // break; 5853 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5854 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5855 CGF.EmitBlock(Case2BB); 5856 5857 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5858 CodeGenFunction &CGF, PrePostActionTy &Action) { 5859 auto ILHS = LHSExprs.begin(); 5860 auto IRHS = RHSExprs.begin(); 5861 auto IPriv = Privates.begin(); 5862 for (const Expr *E : ReductionOps) { 5863 const Expr *XExpr = nullptr; 5864 const Expr *EExpr = nullptr; 5865 const Expr *UpExpr = nullptr; 5866 BinaryOperatorKind BO = BO_Comma; 5867 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5868 if (BO->getOpcode() == BO_Assign) { 5869 XExpr = BO->getLHS(); 5870 UpExpr = BO->getRHS(); 5871 } 5872 } 5873 // Try to emit update expression as a simple atomic. 5874 const Expr *RHSExpr = UpExpr; 5875 if (RHSExpr) { 5876 // Analyze RHS part of the whole expression. 5877 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5878 RHSExpr->IgnoreParenImpCasts())) { 5879 // If this is a conditional operator, analyze its condition for 5880 // min/max reduction operator. 5881 RHSExpr = ACO->getCond(); 5882 } 5883 if (const auto *BORHS = 5884 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5885 EExpr = BORHS->getRHS(); 5886 BO = BORHS->getOpcode(); 5887 } 5888 } 5889 if (XExpr) { 5890 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5891 auto &&AtomicRedGen = [BO, VD, 5892 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5893 const Expr *EExpr, const Expr *UpExpr) { 5894 LValue X = CGF.EmitLValue(XExpr); 5895 RValue E; 5896 if (EExpr) 5897 E = CGF.EmitAnyExpr(EExpr); 5898 CGF.EmitOMPAtomicSimpleUpdateExpr( 5899 X, E, BO, /*IsXLHSInRHSPart=*/true, 5900 llvm::AtomicOrdering::Monotonic, Loc, 5901 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5902 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5903 PrivateScope.addPrivate( 5904 VD, [&CGF, VD, XRValue, Loc]() { 5905 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5906 CGF.emitOMPSimpleStore( 5907 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5908 VD->getType().getNonReferenceType(), Loc); 5909 return LHSTemp; 5910 }); 5911 (void)PrivateScope.Privatize(); 5912 return CGF.EmitAnyExpr(UpExpr); 5913 }); 5914 }; 5915 if ((*IPriv)->getType()->isArrayType()) { 5916 // Emit atomic reduction for array section. 5917 const auto *RHSVar = 5918 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5919 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5920 AtomicRedGen, XExpr, EExpr, UpExpr); 5921 } else { 5922 // Emit atomic reduction for array subscript or single variable. 5923 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5924 } 5925 } else { 5926 // Emit as a critical region. 5927 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5928 const Expr *, const Expr *) { 5929 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5930 std::string Name = RT.getName({"atomic_reduction"}); 5931 RT.emitCriticalRegion( 5932 CGF, Name, 5933 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5934 Action.Enter(CGF); 5935 emitReductionCombiner(CGF, E); 5936 }, 5937 Loc); 5938 }; 5939 if ((*IPriv)->getType()->isArrayType()) { 5940 const auto *LHSVar = 5941 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5942 const auto *RHSVar = 5943 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5944 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5945 CritRedGen); 5946 } else { 5947 CritRedGen(CGF, nullptr, nullptr, nullptr); 5948 } 5949 } 5950 ++ILHS; 5951 ++IRHS; 5952 ++IPriv; 5953 } 5954 }; 5955 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5956 if (!WithNowait) { 5957 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5958 llvm::Value *EndArgs[] = { 5959 IdentTLoc, // ident_t *<loc> 5960 ThreadId, // i32 <gtid> 5961 Lock // kmp_critical_name *&<lock> 5962 }; 5963 CommonActionTy Action(nullptr, llvm::None, 5964 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 5965 EndArgs); 5966 AtomicRCG.setAction(Action); 5967 AtomicRCG(CGF); 5968 } else { 5969 AtomicRCG(CGF); 5970 } 5971 5972 CGF.EmitBranch(DefaultBB); 5973 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5974 } 5975 5976 /// Generates unique name for artificial threadprivate variables. 5977 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5978 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5979 const Expr *Ref) { 5980 SmallString<256> Buffer; 5981 llvm::raw_svector_ostream Out(Buffer); 5982 const clang::DeclRefExpr *DE; 5983 const VarDecl *D = ::getBaseDecl(Ref, DE); 5984 if (!D) 5985 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5986 D = D->getCanonicalDecl(); 5987 std::string Name = CGM.getOpenMPRuntime().getName( 5988 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5989 Out << Prefix << Name << "_" 5990 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5991 return std::string(Out.str()); 5992 } 5993 5994 /// Emits reduction initializer function: 5995 /// \code 5996 /// void @.red_init(void* %arg) { 5997 /// %0 = bitcast void* %arg to <type>* 5998 /// store <type> <init>, <type>* %0 5999 /// ret void 6000 /// } 6001 /// \endcode 6002 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 6003 SourceLocation Loc, 6004 ReductionCodeGen &RCG, unsigned N) { 6005 ASTContext &C = CGM.getContext(); 6006 FunctionArgList Args; 6007 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6008 ImplicitParamDecl::Other); 6009 Args.emplace_back(&Param); 6010 const auto &FnInfo = 6011 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6012 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6013 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6014 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6015 Name, &CGM.getModule()); 6016 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6017 Fn->setDoesNotRecurse(); 6018 CodeGenFunction CGF(CGM); 6019 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6020 Address PrivateAddr = CGF.EmitLoadOfPointer( 6021 CGF.GetAddrOfLocalVar(&Param), 6022 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6023 llvm::Value *Size = nullptr; 6024 // If the size of the reduction item is non-constant, load it from global 6025 // threadprivate variable. 6026 if (RCG.getSizes(N).second) { 6027 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6028 CGF, CGM.getContext().getSizeType(), 6029 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6030 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6031 CGM.getContext().getSizeType(), Loc); 6032 } 6033 RCG.emitAggregateType(CGF, N, Size); 6034 LValue SharedLVal; 6035 // If initializer uses initializer from declare reduction construct, emit a 6036 // pointer to the address of the original reduction item (reuired by reduction 6037 // initializer) 6038 if (RCG.usesReductionInitializer(N)) { 6039 Address SharedAddr = 6040 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6041 CGF, CGM.getContext().VoidPtrTy, 6042 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6043 SharedAddr = CGF.EmitLoadOfPointer( 6044 SharedAddr, 6045 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6046 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6047 } else { 6048 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6049 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6050 CGM.getContext().VoidPtrTy); 6051 } 6052 // Emit the initializer: 6053 // %0 = bitcast void* %arg to <type>* 6054 // store <type> <init>, <type>* %0 6055 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6056 [](CodeGenFunction &) { return false; }); 6057 CGF.FinishFunction(); 6058 return Fn; 6059 } 6060 6061 /// Emits reduction combiner function: 6062 /// \code 6063 /// void @.red_comb(void* %arg0, void* %arg1) { 6064 /// %lhs = bitcast void* %arg0 to <type>* 6065 /// %rhs = bitcast void* %arg1 to <type>* 6066 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6067 /// store <type> %2, <type>* %lhs 6068 /// ret void 6069 /// } 6070 /// \endcode 6071 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6072 SourceLocation Loc, 6073 ReductionCodeGen &RCG, unsigned N, 6074 const Expr *ReductionOp, 6075 const Expr *LHS, const Expr *RHS, 6076 const Expr *PrivateRef) { 6077 ASTContext &C = CGM.getContext(); 6078 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6079 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6080 FunctionArgList Args; 6081 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6082 C.VoidPtrTy, ImplicitParamDecl::Other); 6083 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6084 ImplicitParamDecl::Other); 6085 Args.emplace_back(&ParamInOut); 6086 Args.emplace_back(&ParamIn); 6087 const auto &FnInfo = 6088 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6089 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6090 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6091 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6092 Name, &CGM.getModule()); 6093 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6094 Fn->setDoesNotRecurse(); 6095 CodeGenFunction CGF(CGM); 6096 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6097 llvm::Value *Size = nullptr; 6098 // If the size of the reduction item is non-constant, load it from global 6099 // threadprivate variable. 6100 if (RCG.getSizes(N).second) { 6101 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6102 CGF, CGM.getContext().getSizeType(), 6103 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6104 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6105 CGM.getContext().getSizeType(), Loc); 6106 } 6107 RCG.emitAggregateType(CGF, N, Size); 6108 // Remap lhs and rhs variables to the addresses of the function arguments. 6109 // %lhs = bitcast void* %arg0 to <type>* 6110 // %rhs = bitcast void* %arg1 to <type>* 6111 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6112 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6113 // Pull out the pointer to the variable. 6114 Address PtrAddr = CGF.EmitLoadOfPointer( 6115 CGF.GetAddrOfLocalVar(&ParamInOut), 6116 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6117 return CGF.Builder.CreateElementBitCast( 6118 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6119 }); 6120 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6121 // Pull out the pointer to the variable. 6122 Address PtrAddr = CGF.EmitLoadOfPointer( 6123 CGF.GetAddrOfLocalVar(&ParamIn), 6124 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6125 return CGF.Builder.CreateElementBitCast( 6126 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6127 }); 6128 PrivateScope.Privatize(); 6129 // Emit the combiner body: 6130 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6131 // store <type> %2, <type>* %lhs 6132 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6133 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6134 cast<DeclRefExpr>(RHS)); 6135 CGF.FinishFunction(); 6136 return Fn; 6137 } 6138 6139 /// Emits reduction finalizer function: 6140 /// \code 6141 /// void @.red_fini(void* %arg) { 6142 /// %0 = bitcast void* %arg to <type>* 6143 /// <destroy>(<type>* %0) 6144 /// ret void 6145 /// } 6146 /// \endcode 6147 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6148 SourceLocation Loc, 6149 ReductionCodeGen &RCG, unsigned N) { 6150 if (!RCG.needCleanups(N)) 6151 return nullptr; 6152 ASTContext &C = CGM.getContext(); 6153 FunctionArgList Args; 6154 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6155 ImplicitParamDecl::Other); 6156 Args.emplace_back(&Param); 6157 const auto &FnInfo = 6158 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6159 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6160 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6161 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6162 Name, &CGM.getModule()); 6163 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6164 Fn->setDoesNotRecurse(); 6165 CodeGenFunction CGF(CGM); 6166 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6167 Address PrivateAddr = CGF.EmitLoadOfPointer( 6168 CGF.GetAddrOfLocalVar(&Param), 6169 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6170 llvm::Value *Size = nullptr; 6171 // If the size of the reduction item is non-constant, load it from global 6172 // threadprivate variable. 6173 if (RCG.getSizes(N).second) { 6174 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6175 CGF, CGM.getContext().getSizeType(), 6176 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6177 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6178 CGM.getContext().getSizeType(), Loc); 6179 } 6180 RCG.emitAggregateType(CGF, N, Size); 6181 // Emit the finalizer body: 6182 // <destroy>(<type>* %0) 6183 RCG.emitCleanups(CGF, N, PrivateAddr); 6184 CGF.FinishFunction(Loc); 6185 return Fn; 6186 } 6187 6188 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6189 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6190 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6191 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6192 return nullptr; 6193 6194 // Build typedef struct: 6195 // kmp_task_red_input { 6196 // void *reduce_shar; // shared reduction item 6197 // size_t reduce_size; // size of data item 6198 // void *reduce_init; // data initialization routine 6199 // void *reduce_fini; // data finalization routine 6200 // void *reduce_comb; // data combiner routine 6201 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6202 // } kmp_task_red_input_t; 6203 ASTContext &C = CGM.getContext(); 6204 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6205 RD->startDefinition(); 6206 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6207 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6208 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6209 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6210 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6211 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6212 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6213 RD->completeDefinition(); 6214 QualType RDType = C.getRecordType(RD); 6215 unsigned Size = Data.ReductionVars.size(); 6216 llvm::APInt ArraySize(/*numBits=*/64, Size); 6217 QualType ArrayRDType = C.getConstantArrayType( 6218 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6219 // kmp_task_red_input_t .rd_input.[Size]; 6220 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6221 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6222 Data.ReductionOps); 6223 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6224 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6225 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6226 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6227 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6228 TaskRedInput.getPointer(), Idxs, 6229 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6230 ".rd_input.gep."); 6231 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6232 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6233 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6234 RCG.emitSharedLValue(CGF, Cnt); 6235 llvm::Value *CastedShared = 6236 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6237 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6238 RCG.emitAggregateType(CGF, Cnt); 6239 llvm::Value *SizeValInChars; 6240 llvm::Value *SizeVal; 6241 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6242 // We use delayed creation/initialization for VLAs, array sections and 6243 // custom reduction initializations. It is required because runtime does not 6244 // provide the way to pass the sizes of VLAs/array sections to 6245 // initializer/combiner/finalizer functions and does not pass the pointer to 6246 // original reduction item to the initializer. Instead threadprivate global 6247 // variables are used to store these values and use them in the functions. 6248 bool DelayedCreation = !!SizeVal; 6249 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6250 /*isSigned=*/false); 6251 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6252 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6253 // ElemLVal.reduce_init = init; 6254 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6255 llvm::Value *InitAddr = 6256 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6257 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6258 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6259 // ElemLVal.reduce_fini = fini; 6260 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6261 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6262 llvm::Value *FiniAddr = Fini 6263 ? CGF.EmitCastToVoidPtr(Fini) 6264 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6265 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6266 // ElemLVal.reduce_comb = comb; 6267 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6268 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6269 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6270 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6271 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6272 // ElemLVal.flags = 0; 6273 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6274 if (DelayedCreation) { 6275 CGF.EmitStoreOfScalar( 6276 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6277 FlagsLVal); 6278 } else 6279 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6280 FlagsLVal.getType()); 6281 } 6282 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6283 // *data); 6284 llvm::Value *Args[] = { 6285 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6286 /*isSigned=*/true), 6287 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6288 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6289 CGM.VoidPtrTy)}; 6290 return CGF.EmitRuntimeCall( 6291 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6292 } 6293 6294 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6295 SourceLocation Loc, 6296 ReductionCodeGen &RCG, 6297 unsigned N) { 6298 auto Sizes = RCG.getSizes(N); 6299 // Emit threadprivate global variable if the type is non-constant 6300 // (Sizes.second = nullptr). 6301 if (Sizes.second) { 6302 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6303 /*isSigned=*/false); 6304 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6305 CGF, CGM.getContext().getSizeType(), 6306 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6307 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6308 } 6309 // Store address of the original reduction item if custom initializer is used. 6310 if (RCG.usesReductionInitializer(N)) { 6311 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6312 CGF, CGM.getContext().VoidPtrTy, 6313 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6314 CGF.Builder.CreateStore( 6315 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6316 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy), 6317 SharedAddr, /*IsVolatile=*/false); 6318 } 6319 } 6320 6321 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6322 SourceLocation Loc, 6323 llvm::Value *ReductionsPtr, 6324 LValue SharedLVal) { 6325 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6326 // *d); 6327 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6328 CGM.IntTy, 6329 /*isSigned=*/true), 6330 ReductionsPtr, 6331 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6332 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6333 return Address( 6334 CGF.EmitRuntimeCall( 6335 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6336 SharedLVal.getAlignment()); 6337 } 6338 6339 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6340 SourceLocation Loc) { 6341 if (!CGF.HaveInsertPoint()) 6342 return; 6343 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6344 // global_tid); 6345 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6346 // Ignore return result until untied tasks are supported. 6347 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6348 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6349 Region->emitUntiedSwitch(CGF); 6350 } 6351 6352 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6353 OpenMPDirectiveKind InnerKind, 6354 const RegionCodeGenTy &CodeGen, 6355 bool HasCancel) { 6356 if (!CGF.HaveInsertPoint()) 6357 return; 6358 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6359 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6360 } 6361 6362 namespace { 6363 enum RTCancelKind { 6364 CancelNoreq = 0, 6365 CancelParallel = 1, 6366 CancelLoop = 2, 6367 CancelSections = 3, 6368 CancelTaskgroup = 4 6369 }; 6370 } // anonymous namespace 6371 6372 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6373 RTCancelKind CancelKind = CancelNoreq; 6374 if (CancelRegion == OMPD_parallel) 6375 CancelKind = CancelParallel; 6376 else if (CancelRegion == OMPD_for) 6377 CancelKind = CancelLoop; 6378 else if (CancelRegion == OMPD_sections) 6379 CancelKind = CancelSections; 6380 else { 6381 assert(CancelRegion == OMPD_taskgroup); 6382 CancelKind = CancelTaskgroup; 6383 } 6384 return CancelKind; 6385 } 6386 6387 void CGOpenMPRuntime::emitCancellationPointCall( 6388 CodeGenFunction &CGF, SourceLocation Loc, 6389 OpenMPDirectiveKind CancelRegion) { 6390 if (!CGF.HaveInsertPoint()) 6391 return; 6392 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6393 // global_tid, kmp_int32 cncl_kind); 6394 if (auto *OMPRegionInfo = 6395 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6396 // For 'cancellation point taskgroup', the task region info may not have a 6397 // cancel. This may instead happen in another adjacent task. 6398 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6399 llvm::Value *Args[] = { 6400 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6401 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6402 // Ignore return result until untied tasks are supported. 6403 llvm::Value *Result = CGF.EmitRuntimeCall( 6404 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6405 // if (__kmpc_cancellationpoint()) { 6406 // exit from construct; 6407 // } 6408 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6409 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6410 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6411 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6412 CGF.EmitBlock(ExitBB); 6413 // exit from construct; 6414 CodeGenFunction::JumpDest CancelDest = 6415 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6416 CGF.EmitBranchThroughCleanup(CancelDest); 6417 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6418 } 6419 } 6420 } 6421 6422 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6423 const Expr *IfCond, 6424 OpenMPDirectiveKind CancelRegion) { 6425 if (!CGF.HaveInsertPoint()) 6426 return; 6427 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6428 // kmp_int32 cncl_kind); 6429 if (auto *OMPRegionInfo = 6430 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6431 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6432 PrePostActionTy &) { 6433 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6434 llvm::Value *Args[] = { 6435 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6436 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6437 // Ignore return result until untied tasks are supported. 6438 llvm::Value *Result = CGF.EmitRuntimeCall( 6439 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6440 // if (__kmpc_cancel()) { 6441 // exit from construct; 6442 // } 6443 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6444 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6445 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6446 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6447 CGF.EmitBlock(ExitBB); 6448 // exit from construct; 6449 CodeGenFunction::JumpDest CancelDest = 6450 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6451 CGF.EmitBranchThroughCleanup(CancelDest); 6452 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6453 }; 6454 if (IfCond) { 6455 emitIfClause(CGF, IfCond, ThenGen, 6456 [](CodeGenFunction &, PrePostActionTy &) {}); 6457 } else { 6458 RegionCodeGenTy ThenRCG(ThenGen); 6459 ThenRCG(CGF); 6460 } 6461 } 6462 } 6463 6464 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6465 const OMPExecutableDirective &D, StringRef ParentName, 6466 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6467 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6468 assert(!ParentName.empty() && "Invalid target region parent name!"); 6469 HasEmittedTargetRegion = true; 6470 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6471 IsOffloadEntry, CodeGen); 6472 } 6473 6474 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6475 const OMPExecutableDirective &D, StringRef ParentName, 6476 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6477 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6478 // Create a unique name for the entry function using the source location 6479 // information of the current target region. The name will be something like: 6480 // 6481 // __omp_offloading_DD_FFFF_PP_lBB 6482 // 6483 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6484 // mangled name of the function that encloses the target region and BB is the 6485 // line number of the target region. 6486 6487 unsigned DeviceID; 6488 unsigned FileID; 6489 unsigned Line; 6490 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6491 Line); 6492 SmallString<64> EntryFnName; 6493 { 6494 llvm::raw_svector_ostream OS(EntryFnName); 6495 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6496 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6497 } 6498 6499 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6500 6501 CodeGenFunction CGF(CGM, true); 6502 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6503 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6504 6505 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6506 6507 // If this target outline function is not an offload entry, we don't need to 6508 // register it. 6509 if (!IsOffloadEntry) 6510 return; 6511 6512 // The target region ID is used by the runtime library to identify the current 6513 // target region, so it only has to be unique and not necessarily point to 6514 // anything. It could be the pointer to the outlined function that implements 6515 // the target region, but we aren't using that so that the compiler doesn't 6516 // need to keep that, and could therefore inline the host function if proven 6517 // worthwhile during optimization. In the other hand, if emitting code for the 6518 // device, the ID has to be the function address so that it can retrieved from 6519 // the offloading entry and launched by the runtime library. We also mark the 6520 // outlined function to have external linkage in case we are emitting code for 6521 // the device, because these functions will be entry points to the device. 6522 6523 if (CGM.getLangOpts().OpenMPIsDevice) { 6524 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6525 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6526 OutlinedFn->setDSOLocal(false); 6527 } else { 6528 std::string Name = getName({EntryFnName, "region_id"}); 6529 OutlinedFnID = new llvm::GlobalVariable( 6530 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6531 llvm::GlobalValue::WeakAnyLinkage, 6532 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6533 } 6534 6535 // Register the information for the entry associated with this target region. 6536 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6537 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6538 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6539 } 6540 6541 /// Checks if the expression is constant or does not have non-trivial function 6542 /// calls. 6543 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6544 // We can skip constant expressions. 6545 // We can skip expressions with trivial calls or simple expressions. 6546 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6547 !E->hasNonTrivialCall(Ctx)) && 6548 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6549 } 6550 6551 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6552 const Stmt *Body) { 6553 const Stmt *Child = Body->IgnoreContainers(); 6554 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6555 Child = nullptr; 6556 for (const Stmt *S : C->body()) { 6557 if (const auto *E = dyn_cast<Expr>(S)) { 6558 if (isTrivial(Ctx, E)) 6559 continue; 6560 } 6561 // Some of the statements can be ignored. 6562 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6563 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6564 continue; 6565 // Analyze declarations. 6566 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6567 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6568 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6569 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6570 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6571 isa<UsingDirectiveDecl>(D) || 6572 isa<OMPDeclareReductionDecl>(D) || 6573 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6574 return true; 6575 const auto *VD = dyn_cast<VarDecl>(D); 6576 if (!VD) 6577 return false; 6578 return VD->isConstexpr() || 6579 ((VD->getType().isTrivialType(Ctx) || 6580 VD->getType()->isReferenceType()) && 6581 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6582 })) 6583 continue; 6584 } 6585 // Found multiple children - cannot get the one child only. 6586 if (Child) 6587 return nullptr; 6588 Child = S; 6589 } 6590 if (Child) 6591 Child = Child->IgnoreContainers(); 6592 } 6593 return Child; 6594 } 6595 6596 /// Emit the number of teams for a target directive. Inspect the num_teams 6597 /// clause associated with a teams construct combined or closely nested 6598 /// with the target directive. 6599 /// 6600 /// Emit a team of size one for directives such as 'target parallel' that 6601 /// have no associated teams construct. 6602 /// 6603 /// Otherwise, return nullptr. 6604 static llvm::Value * 6605 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6606 const OMPExecutableDirective &D) { 6607 assert(!CGF.getLangOpts().OpenMPIsDevice && 6608 "Clauses associated with the teams directive expected to be emitted " 6609 "only for the host!"); 6610 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6611 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6612 "Expected target-based executable directive."); 6613 CGBuilderTy &Bld = CGF.Builder; 6614 switch (DirectiveKind) { 6615 case OMPD_target: { 6616 const auto *CS = D.getInnermostCapturedStmt(); 6617 const auto *Body = 6618 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6619 const Stmt *ChildStmt = 6620 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6621 if (const auto *NestedDir = 6622 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6623 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6624 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6625 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6626 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6627 const Expr *NumTeams = 6628 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6629 llvm::Value *NumTeamsVal = 6630 CGF.EmitScalarExpr(NumTeams, 6631 /*IgnoreResultAssign*/ true); 6632 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6633 /*isSigned=*/true); 6634 } 6635 return Bld.getInt32(0); 6636 } 6637 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6638 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6639 return Bld.getInt32(1); 6640 return Bld.getInt32(0); 6641 } 6642 return nullptr; 6643 } 6644 case OMPD_target_teams: 6645 case OMPD_target_teams_distribute: 6646 case OMPD_target_teams_distribute_simd: 6647 case OMPD_target_teams_distribute_parallel_for: 6648 case OMPD_target_teams_distribute_parallel_for_simd: { 6649 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6650 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6651 const Expr *NumTeams = 6652 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6653 llvm::Value *NumTeamsVal = 6654 CGF.EmitScalarExpr(NumTeams, 6655 /*IgnoreResultAssign*/ true); 6656 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6657 /*isSigned=*/true); 6658 } 6659 return Bld.getInt32(0); 6660 } 6661 case OMPD_target_parallel: 6662 case OMPD_target_parallel_for: 6663 case OMPD_target_parallel_for_simd: 6664 case OMPD_target_simd: 6665 return Bld.getInt32(1); 6666 case OMPD_parallel: 6667 case OMPD_for: 6668 case OMPD_parallel_for: 6669 case OMPD_parallel_master: 6670 case OMPD_parallel_sections: 6671 case OMPD_for_simd: 6672 case OMPD_parallel_for_simd: 6673 case OMPD_cancel: 6674 case OMPD_cancellation_point: 6675 case OMPD_ordered: 6676 case OMPD_threadprivate: 6677 case OMPD_allocate: 6678 case OMPD_task: 6679 case OMPD_simd: 6680 case OMPD_sections: 6681 case OMPD_section: 6682 case OMPD_single: 6683 case OMPD_master: 6684 case OMPD_critical: 6685 case OMPD_taskyield: 6686 case OMPD_barrier: 6687 case OMPD_taskwait: 6688 case OMPD_taskgroup: 6689 case OMPD_atomic: 6690 case OMPD_flush: 6691 case OMPD_teams: 6692 case OMPD_target_data: 6693 case OMPD_target_exit_data: 6694 case OMPD_target_enter_data: 6695 case OMPD_distribute: 6696 case OMPD_distribute_simd: 6697 case OMPD_distribute_parallel_for: 6698 case OMPD_distribute_parallel_for_simd: 6699 case OMPD_teams_distribute: 6700 case OMPD_teams_distribute_simd: 6701 case OMPD_teams_distribute_parallel_for: 6702 case OMPD_teams_distribute_parallel_for_simd: 6703 case OMPD_target_update: 6704 case OMPD_declare_simd: 6705 case OMPD_declare_variant: 6706 case OMPD_declare_target: 6707 case OMPD_end_declare_target: 6708 case OMPD_declare_reduction: 6709 case OMPD_declare_mapper: 6710 case OMPD_taskloop: 6711 case OMPD_taskloop_simd: 6712 case OMPD_master_taskloop: 6713 case OMPD_master_taskloop_simd: 6714 case OMPD_parallel_master_taskloop: 6715 case OMPD_parallel_master_taskloop_simd: 6716 case OMPD_requires: 6717 case OMPD_unknown: 6718 break; 6719 } 6720 llvm_unreachable("Unexpected directive kind."); 6721 } 6722 6723 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6724 llvm::Value *DefaultThreadLimitVal) { 6725 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6726 CGF.getContext(), CS->getCapturedStmt()); 6727 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6728 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6729 llvm::Value *NumThreads = nullptr; 6730 llvm::Value *CondVal = nullptr; 6731 // Handle if clause. If if clause present, the number of threads is 6732 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6733 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6734 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6735 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6736 const OMPIfClause *IfClause = nullptr; 6737 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6738 if (C->getNameModifier() == OMPD_unknown || 6739 C->getNameModifier() == OMPD_parallel) { 6740 IfClause = C; 6741 break; 6742 } 6743 } 6744 if (IfClause) { 6745 const Expr *Cond = IfClause->getCondition(); 6746 bool Result; 6747 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6748 if (!Result) 6749 return CGF.Builder.getInt32(1); 6750 } else { 6751 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6752 if (const auto *PreInit = 6753 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6754 for (const auto *I : PreInit->decls()) { 6755 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6756 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6757 } else { 6758 CodeGenFunction::AutoVarEmission Emission = 6759 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6760 CGF.EmitAutoVarCleanups(Emission); 6761 } 6762 } 6763 } 6764 CondVal = CGF.EvaluateExprAsBool(Cond); 6765 } 6766 } 6767 } 6768 // Check the value of num_threads clause iff if clause was not specified 6769 // or is not evaluated to false. 6770 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6771 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6772 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6773 const auto *NumThreadsClause = 6774 Dir->getSingleClause<OMPNumThreadsClause>(); 6775 CodeGenFunction::LexicalScope Scope( 6776 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6777 if (const auto *PreInit = 6778 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6779 for (const auto *I : PreInit->decls()) { 6780 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6781 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6782 } else { 6783 CodeGenFunction::AutoVarEmission Emission = 6784 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6785 CGF.EmitAutoVarCleanups(Emission); 6786 } 6787 } 6788 } 6789 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6790 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6791 /*isSigned=*/false); 6792 if (DefaultThreadLimitVal) 6793 NumThreads = CGF.Builder.CreateSelect( 6794 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6795 DefaultThreadLimitVal, NumThreads); 6796 } else { 6797 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6798 : CGF.Builder.getInt32(0); 6799 } 6800 // Process condition of the if clause. 6801 if (CondVal) { 6802 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6803 CGF.Builder.getInt32(1)); 6804 } 6805 return NumThreads; 6806 } 6807 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6808 return CGF.Builder.getInt32(1); 6809 return DefaultThreadLimitVal; 6810 } 6811 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6812 : CGF.Builder.getInt32(0); 6813 } 6814 6815 /// Emit the number of threads for a target directive. Inspect the 6816 /// thread_limit clause associated with a teams construct combined or closely 6817 /// nested with the target directive. 6818 /// 6819 /// Emit the num_threads clause for directives such as 'target parallel' that 6820 /// have no associated teams construct. 6821 /// 6822 /// Otherwise, return nullptr. 6823 static llvm::Value * 6824 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6825 const OMPExecutableDirective &D) { 6826 assert(!CGF.getLangOpts().OpenMPIsDevice && 6827 "Clauses associated with the teams directive expected to be emitted " 6828 "only for the host!"); 6829 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6830 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6831 "Expected target-based executable directive."); 6832 CGBuilderTy &Bld = CGF.Builder; 6833 llvm::Value *ThreadLimitVal = nullptr; 6834 llvm::Value *NumThreadsVal = nullptr; 6835 switch (DirectiveKind) { 6836 case OMPD_target: { 6837 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6838 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6839 return NumThreads; 6840 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6841 CGF.getContext(), CS->getCapturedStmt()); 6842 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6843 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6844 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6845 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6846 const auto *ThreadLimitClause = 6847 Dir->getSingleClause<OMPThreadLimitClause>(); 6848 CodeGenFunction::LexicalScope Scope( 6849 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6850 if (const auto *PreInit = 6851 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6852 for (const auto *I : PreInit->decls()) { 6853 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6854 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6855 } else { 6856 CodeGenFunction::AutoVarEmission Emission = 6857 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6858 CGF.EmitAutoVarCleanups(Emission); 6859 } 6860 } 6861 } 6862 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6863 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6864 ThreadLimitVal = 6865 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6866 } 6867 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6868 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6869 CS = Dir->getInnermostCapturedStmt(); 6870 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6871 CGF.getContext(), CS->getCapturedStmt()); 6872 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6873 } 6874 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6875 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6876 CS = Dir->getInnermostCapturedStmt(); 6877 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6878 return NumThreads; 6879 } 6880 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6881 return Bld.getInt32(1); 6882 } 6883 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6884 } 6885 case OMPD_target_teams: { 6886 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6887 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6888 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6889 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6890 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6891 ThreadLimitVal = 6892 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6893 } 6894 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6895 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6896 return NumThreads; 6897 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6898 CGF.getContext(), CS->getCapturedStmt()); 6899 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6900 if (Dir->getDirectiveKind() == OMPD_distribute) { 6901 CS = Dir->getInnermostCapturedStmt(); 6902 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6903 return NumThreads; 6904 } 6905 } 6906 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6907 } 6908 case OMPD_target_teams_distribute: 6909 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6910 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6911 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6912 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6913 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6914 ThreadLimitVal = 6915 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6916 } 6917 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6918 case OMPD_target_parallel: 6919 case OMPD_target_parallel_for: 6920 case OMPD_target_parallel_for_simd: 6921 case OMPD_target_teams_distribute_parallel_for: 6922 case OMPD_target_teams_distribute_parallel_for_simd: { 6923 llvm::Value *CondVal = nullptr; 6924 // Handle if clause. If if clause present, the number of threads is 6925 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6926 if (D.hasClausesOfKind<OMPIfClause>()) { 6927 const OMPIfClause *IfClause = nullptr; 6928 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6929 if (C->getNameModifier() == OMPD_unknown || 6930 C->getNameModifier() == OMPD_parallel) { 6931 IfClause = C; 6932 break; 6933 } 6934 } 6935 if (IfClause) { 6936 const Expr *Cond = IfClause->getCondition(); 6937 bool Result; 6938 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6939 if (!Result) 6940 return Bld.getInt32(1); 6941 } else { 6942 CodeGenFunction::RunCleanupsScope Scope(CGF); 6943 CondVal = CGF.EvaluateExprAsBool(Cond); 6944 } 6945 } 6946 } 6947 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6948 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6949 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6950 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6951 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6952 ThreadLimitVal = 6953 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6954 } 6955 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6956 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6957 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6958 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6959 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6960 NumThreadsVal = 6961 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 6962 ThreadLimitVal = ThreadLimitVal 6963 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6964 ThreadLimitVal), 6965 NumThreadsVal, ThreadLimitVal) 6966 : NumThreadsVal; 6967 } 6968 if (!ThreadLimitVal) 6969 ThreadLimitVal = Bld.getInt32(0); 6970 if (CondVal) 6971 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 6972 return ThreadLimitVal; 6973 } 6974 case OMPD_target_teams_distribute_simd: 6975 case OMPD_target_simd: 6976 return Bld.getInt32(1); 6977 case OMPD_parallel: 6978 case OMPD_for: 6979 case OMPD_parallel_for: 6980 case OMPD_parallel_master: 6981 case OMPD_parallel_sections: 6982 case OMPD_for_simd: 6983 case OMPD_parallel_for_simd: 6984 case OMPD_cancel: 6985 case OMPD_cancellation_point: 6986 case OMPD_ordered: 6987 case OMPD_threadprivate: 6988 case OMPD_allocate: 6989 case OMPD_task: 6990 case OMPD_simd: 6991 case OMPD_sections: 6992 case OMPD_section: 6993 case OMPD_single: 6994 case OMPD_master: 6995 case OMPD_critical: 6996 case OMPD_taskyield: 6997 case OMPD_barrier: 6998 case OMPD_taskwait: 6999 case OMPD_taskgroup: 7000 case OMPD_atomic: 7001 case OMPD_flush: 7002 case OMPD_teams: 7003 case OMPD_target_data: 7004 case OMPD_target_exit_data: 7005 case OMPD_target_enter_data: 7006 case OMPD_distribute: 7007 case OMPD_distribute_simd: 7008 case OMPD_distribute_parallel_for: 7009 case OMPD_distribute_parallel_for_simd: 7010 case OMPD_teams_distribute: 7011 case OMPD_teams_distribute_simd: 7012 case OMPD_teams_distribute_parallel_for: 7013 case OMPD_teams_distribute_parallel_for_simd: 7014 case OMPD_target_update: 7015 case OMPD_declare_simd: 7016 case OMPD_declare_variant: 7017 case OMPD_declare_target: 7018 case OMPD_end_declare_target: 7019 case OMPD_declare_reduction: 7020 case OMPD_declare_mapper: 7021 case OMPD_taskloop: 7022 case OMPD_taskloop_simd: 7023 case OMPD_master_taskloop: 7024 case OMPD_master_taskloop_simd: 7025 case OMPD_parallel_master_taskloop: 7026 case OMPD_parallel_master_taskloop_simd: 7027 case OMPD_requires: 7028 case OMPD_unknown: 7029 break; 7030 } 7031 llvm_unreachable("Unsupported directive kind."); 7032 } 7033 7034 namespace { 7035 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7036 7037 // Utility to handle information from clauses associated with a given 7038 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7039 // It provides a convenient interface to obtain the information and generate 7040 // code for that information. 7041 class MappableExprsHandler { 7042 public: 7043 /// Values for bit flags used to specify the mapping type for 7044 /// offloading. 7045 enum OpenMPOffloadMappingFlags : uint64_t { 7046 /// No flags 7047 OMP_MAP_NONE = 0x0, 7048 /// Allocate memory on the device and move data from host to device. 7049 OMP_MAP_TO = 0x01, 7050 /// Allocate memory on the device and move data from device to host. 7051 OMP_MAP_FROM = 0x02, 7052 /// Always perform the requested mapping action on the element, even 7053 /// if it was already mapped before. 7054 OMP_MAP_ALWAYS = 0x04, 7055 /// Delete the element from the device environment, ignoring the 7056 /// current reference count associated with the element. 7057 OMP_MAP_DELETE = 0x08, 7058 /// The element being mapped is a pointer-pointee pair; both the 7059 /// pointer and the pointee should be mapped. 7060 OMP_MAP_PTR_AND_OBJ = 0x10, 7061 /// This flags signals that the base address of an entry should be 7062 /// passed to the target kernel as an argument. 7063 OMP_MAP_TARGET_PARAM = 0x20, 7064 /// Signal that the runtime library has to return the device pointer 7065 /// in the current position for the data being mapped. Used when we have the 7066 /// use_device_ptr clause. 7067 OMP_MAP_RETURN_PARAM = 0x40, 7068 /// This flag signals that the reference being passed is a pointer to 7069 /// private data. 7070 OMP_MAP_PRIVATE = 0x80, 7071 /// Pass the element to the device by value. 7072 OMP_MAP_LITERAL = 0x100, 7073 /// Implicit map 7074 OMP_MAP_IMPLICIT = 0x200, 7075 /// Close is a hint to the runtime to allocate memory close to 7076 /// the target device. 7077 OMP_MAP_CLOSE = 0x400, 7078 /// The 16 MSBs of the flags indicate whether the entry is member of some 7079 /// struct/class. 7080 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7081 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7082 }; 7083 7084 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7085 static unsigned getFlagMemberOffset() { 7086 unsigned Offset = 0; 7087 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7088 Remain = Remain >> 1) 7089 Offset++; 7090 return Offset; 7091 } 7092 7093 /// Class that associates information with a base pointer to be passed to the 7094 /// runtime library. 7095 class BasePointerInfo { 7096 /// The base pointer. 7097 llvm::Value *Ptr = nullptr; 7098 /// The base declaration that refers to this device pointer, or null if 7099 /// there is none. 7100 const ValueDecl *DevPtrDecl = nullptr; 7101 7102 public: 7103 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7104 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7105 llvm::Value *operator*() const { return Ptr; } 7106 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7107 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7108 }; 7109 7110 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7111 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7112 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7113 7114 /// Map between a struct and the its lowest & highest elements which have been 7115 /// mapped. 7116 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7117 /// HE(FieldIndex, Pointer)} 7118 struct StructRangeInfoTy { 7119 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7120 0, Address::invalid()}; 7121 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7122 0, Address::invalid()}; 7123 Address Base = Address::invalid(); 7124 }; 7125 7126 private: 7127 /// Kind that defines how a device pointer has to be returned. 7128 struct MapInfo { 7129 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7130 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7131 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7132 bool ReturnDevicePointer = false; 7133 bool IsImplicit = false; 7134 7135 MapInfo() = default; 7136 MapInfo( 7137 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7138 OpenMPMapClauseKind MapType, 7139 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7140 bool ReturnDevicePointer, bool IsImplicit) 7141 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7142 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7143 }; 7144 7145 /// If use_device_ptr is used on a pointer which is a struct member and there 7146 /// is no map information about it, then emission of that entry is deferred 7147 /// until the whole struct has been processed. 7148 struct DeferredDevicePtrEntryTy { 7149 const Expr *IE = nullptr; 7150 const ValueDecl *VD = nullptr; 7151 7152 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7153 : IE(IE), VD(VD) {} 7154 }; 7155 7156 /// The target directive from where the mappable clauses were extracted. It 7157 /// is either a executable directive or a user-defined mapper directive. 7158 llvm::PointerUnion<const OMPExecutableDirective *, 7159 const OMPDeclareMapperDecl *> 7160 CurDir; 7161 7162 /// Function the directive is being generated for. 7163 CodeGenFunction &CGF; 7164 7165 /// Set of all first private variables in the current directive. 7166 /// bool data is set to true if the variable is implicitly marked as 7167 /// firstprivate, false otherwise. 7168 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7169 7170 /// Map between device pointer declarations and their expression components. 7171 /// The key value for declarations in 'this' is null. 7172 llvm::DenseMap< 7173 const ValueDecl *, 7174 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7175 DevPointersMap; 7176 7177 llvm::Value *getExprTypeSize(const Expr *E) const { 7178 QualType ExprTy = E->getType().getCanonicalType(); 7179 7180 // Reference types are ignored for mapping purposes. 7181 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7182 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7183 7184 // Given that an array section is considered a built-in type, we need to 7185 // do the calculation based on the length of the section instead of relying 7186 // on CGF.getTypeSize(E->getType()). 7187 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7188 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7189 OAE->getBase()->IgnoreParenImpCasts()) 7190 .getCanonicalType(); 7191 7192 // If there is no length associated with the expression and lower bound is 7193 // not specified too, that means we are using the whole length of the 7194 // base. 7195 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7196 !OAE->getLowerBound()) 7197 return CGF.getTypeSize(BaseTy); 7198 7199 llvm::Value *ElemSize; 7200 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7201 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7202 } else { 7203 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7204 assert(ATy && "Expecting array type if not a pointer type."); 7205 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7206 } 7207 7208 // If we don't have a length at this point, that is because we have an 7209 // array section with a single element. 7210 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7211 return ElemSize; 7212 7213 if (const Expr *LenExpr = OAE->getLength()) { 7214 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7215 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7216 CGF.getContext().getSizeType(), 7217 LenExpr->getExprLoc()); 7218 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7219 } 7220 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7221 OAE->getLowerBound() && "expected array_section[lb:]."); 7222 // Size = sizetype - lb * elemtype; 7223 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7224 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7225 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7226 CGF.getContext().getSizeType(), 7227 OAE->getLowerBound()->getExprLoc()); 7228 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7229 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7230 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7231 LengthVal = CGF.Builder.CreateSelect( 7232 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7233 return LengthVal; 7234 } 7235 return CGF.getTypeSize(ExprTy); 7236 } 7237 7238 /// Return the corresponding bits for a given map clause modifier. Add 7239 /// a flag marking the map as a pointer if requested. Add a flag marking the 7240 /// map as the first one of a series of maps that relate to the same map 7241 /// expression. 7242 OpenMPOffloadMappingFlags getMapTypeBits( 7243 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7244 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7245 OpenMPOffloadMappingFlags Bits = 7246 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7247 switch (MapType) { 7248 case OMPC_MAP_alloc: 7249 case OMPC_MAP_release: 7250 // alloc and release is the default behavior in the runtime library, i.e. 7251 // if we don't pass any bits alloc/release that is what the runtime is 7252 // going to do. Therefore, we don't need to signal anything for these two 7253 // type modifiers. 7254 break; 7255 case OMPC_MAP_to: 7256 Bits |= OMP_MAP_TO; 7257 break; 7258 case OMPC_MAP_from: 7259 Bits |= OMP_MAP_FROM; 7260 break; 7261 case OMPC_MAP_tofrom: 7262 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7263 break; 7264 case OMPC_MAP_delete: 7265 Bits |= OMP_MAP_DELETE; 7266 break; 7267 case OMPC_MAP_unknown: 7268 llvm_unreachable("Unexpected map type!"); 7269 } 7270 if (AddPtrFlag) 7271 Bits |= OMP_MAP_PTR_AND_OBJ; 7272 if (AddIsTargetParamFlag) 7273 Bits |= OMP_MAP_TARGET_PARAM; 7274 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7275 != MapModifiers.end()) 7276 Bits |= OMP_MAP_ALWAYS; 7277 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7278 != MapModifiers.end()) 7279 Bits |= OMP_MAP_CLOSE; 7280 return Bits; 7281 } 7282 7283 /// Return true if the provided expression is a final array section. A 7284 /// final array section, is one whose length can't be proved to be one. 7285 bool isFinalArraySectionExpression(const Expr *E) const { 7286 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7287 7288 // It is not an array section and therefore not a unity-size one. 7289 if (!OASE) 7290 return false; 7291 7292 // An array section with no colon always refer to a single element. 7293 if (OASE->getColonLoc().isInvalid()) 7294 return false; 7295 7296 const Expr *Length = OASE->getLength(); 7297 7298 // If we don't have a length we have to check if the array has size 1 7299 // for this dimension. Also, we should always expect a length if the 7300 // base type is pointer. 7301 if (!Length) { 7302 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7303 OASE->getBase()->IgnoreParenImpCasts()) 7304 .getCanonicalType(); 7305 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7306 return ATy->getSize().getSExtValue() != 1; 7307 // If we don't have a constant dimension length, we have to consider 7308 // the current section as having any size, so it is not necessarily 7309 // unitary. If it happen to be unity size, that's user fault. 7310 return true; 7311 } 7312 7313 // Check if the length evaluates to 1. 7314 Expr::EvalResult Result; 7315 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7316 return true; // Can have more that size 1. 7317 7318 llvm::APSInt ConstLength = Result.Val.getInt(); 7319 return ConstLength.getSExtValue() != 1; 7320 } 7321 7322 /// Generate the base pointers, section pointers, sizes and map type 7323 /// bits for the provided map type, map modifier, and expression components. 7324 /// \a IsFirstComponent should be set to true if the provided set of 7325 /// components is the first associated with a capture. 7326 void generateInfoForComponentList( 7327 OpenMPMapClauseKind MapType, 7328 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7329 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7330 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7331 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7332 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7333 bool IsImplicit, 7334 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7335 OverlappedElements = llvm::None) const { 7336 // The following summarizes what has to be generated for each map and the 7337 // types below. The generated information is expressed in this order: 7338 // base pointer, section pointer, size, flags 7339 // (to add to the ones that come from the map type and modifier). 7340 // 7341 // double d; 7342 // int i[100]; 7343 // float *p; 7344 // 7345 // struct S1 { 7346 // int i; 7347 // float f[50]; 7348 // } 7349 // struct S2 { 7350 // int i; 7351 // float f[50]; 7352 // S1 s; 7353 // double *p; 7354 // struct S2 *ps; 7355 // } 7356 // S2 s; 7357 // S2 *ps; 7358 // 7359 // map(d) 7360 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7361 // 7362 // map(i) 7363 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7364 // 7365 // map(i[1:23]) 7366 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7367 // 7368 // map(p) 7369 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7370 // 7371 // map(p[1:24]) 7372 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7373 // 7374 // map(s) 7375 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7376 // 7377 // map(s.i) 7378 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7379 // 7380 // map(s.s.f) 7381 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7382 // 7383 // map(s.p) 7384 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7385 // 7386 // map(to: s.p[:22]) 7387 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7388 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7389 // &(s.p), &(s.p[0]), 22*sizeof(double), 7390 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7391 // (*) alloc space for struct members, only this is a target parameter 7392 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7393 // optimizes this entry out, same in the examples below) 7394 // (***) map the pointee (map: to) 7395 // 7396 // map(s.ps) 7397 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7398 // 7399 // map(from: s.ps->s.i) 7400 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7401 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7402 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7403 // 7404 // map(to: s.ps->ps) 7405 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7406 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7407 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7408 // 7409 // map(s.ps->ps->ps) 7410 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7411 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7412 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7413 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7414 // 7415 // map(to: s.ps->ps->s.f[:22]) 7416 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7417 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7418 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7419 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7420 // 7421 // map(ps) 7422 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7423 // 7424 // map(ps->i) 7425 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7426 // 7427 // map(ps->s.f) 7428 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7429 // 7430 // map(from: ps->p) 7431 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7432 // 7433 // map(to: ps->p[:22]) 7434 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7435 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7436 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7437 // 7438 // map(ps->ps) 7439 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7440 // 7441 // map(from: ps->ps->s.i) 7442 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7443 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7444 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7445 // 7446 // map(from: ps->ps->ps) 7447 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7448 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7449 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7450 // 7451 // map(ps->ps->ps->ps) 7452 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7453 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7454 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7455 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7456 // 7457 // map(to: ps->ps->ps->s.f[:22]) 7458 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7459 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7460 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7461 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7462 // 7463 // map(to: s.f[:22]) map(from: s.p[:33]) 7464 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7465 // sizeof(double*) (**), TARGET_PARAM 7466 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7467 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7468 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7469 // (*) allocate contiguous space needed to fit all mapped members even if 7470 // we allocate space for members not mapped (in this example, 7471 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7472 // them as well because they fall between &s.f[0] and &s.p) 7473 // 7474 // map(from: s.f[:22]) map(to: ps->p[:33]) 7475 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7476 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7477 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7478 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7479 // (*) the struct this entry pertains to is the 2nd element in the list of 7480 // arguments, hence MEMBER_OF(2) 7481 // 7482 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7483 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7484 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7485 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7486 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7487 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7488 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7489 // (*) the struct this entry pertains to is the 4th element in the list 7490 // of arguments, hence MEMBER_OF(4) 7491 7492 // Track if the map information being generated is the first for a capture. 7493 bool IsCaptureFirstInfo = IsFirstComponentList; 7494 // When the variable is on a declare target link or in a to clause with 7495 // unified memory, a reference is needed to hold the host/device address 7496 // of the variable. 7497 bool RequiresReference = false; 7498 7499 // Scan the components from the base to the complete expression. 7500 auto CI = Components.rbegin(); 7501 auto CE = Components.rend(); 7502 auto I = CI; 7503 7504 // Track if the map information being generated is the first for a list of 7505 // components. 7506 bool IsExpressionFirstInfo = true; 7507 Address BP = Address::invalid(); 7508 const Expr *AssocExpr = I->getAssociatedExpression(); 7509 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7510 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7511 7512 if (isa<MemberExpr>(AssocExpr)) { 7513 // The base is the 'this' pointer. The content of the pointer is going 7514 // to be the base of the field being mapped. 7515 BP = CGF.LoadCXXThisAddress(); 7516 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7517 (OASE && 7518 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7519 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7520 } else { 7521 // The base is the reference to the variable. 7522 // BP = &Var. 7523 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7524 if (const auto *VD = 7525 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7526 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7527 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7528 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7529 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7530 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7531 RequiresReference = true; 7532 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7533 } 7534 } 7535 } 7536 7537 // If the variable is a pointer and is being dereferenced (i.e. is not 7538 // the last component), the base has to be the pointer itself, not its 7539 // reference. References are ignored for mapping purposes. 7540 QualType Ty = 7541 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7542 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7543 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7544 7545 // We do not need to generate individual map information for the 7546 // pointer, it can be associated with the combined storage. 7547 ++I; 7548 } 7549 } 7550 7551 // Track whether a component of the list should be marked as MEMBER_OF some 7552 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7553 // in a component list should be marked as MEMBER_OF, all subsequent entries 7554 // do not belong to the base struct. E.g. 7555 // struct S2 s; 7556 // s.ps->ps->ps->f[:] 7557 // (1) (2) (3) (4) 7558 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7559 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7560 // is the pointee of ps(2) which is not member of struct s, so it should not 7561 // be marked as such (it is still PTR_AND_OBJ). 7562 // The variable is initialized to false so that PTR_AND_OBJ entries which 7563 // are not struct members are not considered (e.g. array of pointers to 7564 // data). 7565 bool ShouldBeMemberOf = false; 7566 7567 // Variable keeping track of whether or not we have encountered a component 7568 // in the component list which is a member expression. Useful when we have a 7569 // pointer or a final array section, in which case it is the previous 7570 // component in the list which tells us whether we have a member expression. 7571 // E.g. X.f[:] 7572 // While processing the final array section "[:]" it is "f" which tells us 7573 // whether we are dealing with a member of a declared struct. 7574 const MemberExpr *EncounteredME = nullptr; 7575 7576 for (; I != CE; ++I) { 7577 // If the current component is member of a struct (parent struct) mark it. 7578 if (!EncounteredME) { 7579 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7580 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7581 // as MEMBER_OF the parent struct. 7582 if (EncounteredME) 7583 ShouldBeMemberOf = true; 7584 } 7585 7586 auto Next = std::next(I); 7587 7588 // We need to generate the addresses and sizes if this is the last 7589 // component, if the component is a pointer or if it is an array section 7590 // whose length can't be proved to be one. If this is a pointer, it 7591 // becomes the base address for the following components. 7592 7593 // A final array section, is one whose length can't be proved to be one. 7594 bool IsFinalArraySection = 7595 isFinalArraySectionExpression(I->getAssociatedExpression()); 7596 7597 // Get information on whether the element is a pointer. Have to do a 7598 // special treatment for array sections given that they are built-in 7599 // types. 7600 const auto *OASE = 7601 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7602 bool IsPointer = 7603 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7604 .getCanonicalType() 7605 ->isAnyPointerType()) || 7606 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7607 7608 if (Next == CE || IsPointer || IsFinalArraySection) { 7609 // If this is not the last component, we expect the pointer to be 7610 // associated with an array expression or member expression. 7611 assert((Next == CE || 7612 isa<MemberExpr>(Next->getAssociatedExpression()) || 7613 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7614 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 7615 "Unexpected expression"); 7616 7617 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7618 .getAddress(CGF); 7619 7620 // If this component is a pointer inside the base struct then we don't 7621 // need to create any entry for it - it will be combined with the object 7622 // it is pointing to into a single PTR_AND_OBJ entry. 7623 bool IsMemberPointer = 7624 IsPointer && EncounteredME && 7625 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7626 EncounteredME); 7627 if (!OverlappedElements.empty()) { 7628 // Handle base element with the info for overlapped elements. 7629 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7630 assert(Next == CE && 7631 "Expected last element for the overlapped elements."); 7632 assert(!IsPointer && 7633 "Unexpected base element with the pointer type."); 7634 // Mark the whole struct as the struct that requires allocation on the 7635 // device. 7636 PartialStruct.LowestElem = {0, LB}; 7637 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7638 I->getAssociatedExpression()->getType()); 7639 Address HB = CGF.Builder.CreateConstGEP( 7640 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7641 CGF.VoidPtrTy), 7642 TypeSize.getQuantity() - 1); 7643 PartialStruct.HighestElem = { 7644 std::numeric_limits<decltype( 7645 PartialStruct.HighestElem.first)>::max(), 7646 HB}; 7647 PartialStruct.Base = BP; 7648 // Emit data for non-overlapped data. 7649 OpenMPOffloadMappingFlags Flags = 7650 OMP_MAP_MEMBER_OF | 7651 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7652 /*AddPtrFlag=*/false, 7653 /*AddIsTargetParamFlag=*/false); 7654 LB = BP; 7655 llvm::Value *Size = nullptr; 7656 // Do bitcopy of all non-overlapped structure elements. 7657 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7658 Component : OverlappedElements) { 7659 Address ComponentLB = Address::invalid(); 7660 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7661 Component) { 7662 if (MC.getAssociatedDeclaration()) { 7663 ComponentLB = 7664 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7665 .getAddress(CGF); 7666 Size = CGF.Builder.CreatePtrDiff( 7667 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7668 CGF.EmitCastToVoidPtr(LB.getPointer())); 7669 break; 7670 } 7671 } 7672 BasePointers.push_back(BP.getPointer()); 7673 Pointers.push_back(LB.getPointer()); 7674 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7675 /*isSigned=*/true)); 7676 Types.push_back(Flags); 7677 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7678 } 7679 BasePointers.push_back(BP.getPointer()); 7680 Pointers.push_back(LB.getPointer()); 7681 Size = CGF.Builder.CreatePtrDiff( 7682 CGF.EmitCastToVoidPtr( 7683 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7684 CGF.EmitCastToVoidPtr(LB.getPointer())); 7685 Sizes.push_back( 7686 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7687 Types.push_back(Flags); 7688 break; 7689 } 7690 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7691 if (!IsMemberPointer) { 7692 BasePointers.push_back(BP.getPointer()); 7693 Pointers.push_back(LB.getPointer()); 7694 Sizes.push_back( 7695 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7696 7697 // We need to add a pointer flag for each map that comes from the 7698 // same expression except for the first one. We also need to signal 7699 // this map is the first one that relates with the current capture 7700 // (there is a set of entries for each capture). 7701 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7702 MapType, MapModifiers, IsImplicit, 7703 !IsExpressionFirstInfo || RequiresReference, 7704 IsCaptureFirstInfo && !RequiresReference); 7705 7706 if (!IsExpressionFirstInfo) { 7707 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7708 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7709 if (IsPointer) 7710 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7711 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7712 7713 if (ShouldBeMemberOf) { 7714 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7715 // should be later updated with the correct value of MEMBER_OF. 7716 Flags |= OMP_MAP_MEMBER_OF; 7717 // From now on, all subsequent PTR_AND_OBJ entries should not be 7718 // marked as MEMBER_OF. 7719 ShouldBeMemberOf = false; 7720 } 7721 } 7722 7723 Types.push_back(Flags); 7724 } 7725 7726 // If we have encountered a member expression so far, keep track of the 7727 // mapped member. If the parent is "*this", then the value declaration 7728 // is nullptr. 7729 if (EncounteredME) { 7730 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl()); 7731 unsigned FieldIndex = FD->getFieldIndex(); 7732 7733 // Update info about the lowest and highest elements for this struct 7734 if (!PartialStruct.Base.isValid()) { 7735 PartialStruct.LowestElem = {FieldIndex, LB}; 7736 PartialStruct.HighestElem = {FieldIndex, LB}; 7737 PartialStruct.Base = BP; 7738 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7739 PartialStruct.LowestElem = {FieldIndex, LB}; 7740 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7741 PartialStruct.HighestElem = {FieldIndex, LB}; 7742 } 7743 } 7744 7745 // If we have a final array section, we are done with this expression. 7746 if (IsFinalArraySection) 7747 break; 7748 7749 // The pointer becomes the base for the next element. 7750 if (Next != CE) 7751 BP = LB; 7752 7753 IsExpressionFirstInfo = false; 7754 IsCaptureFirstInfo = false; 7755 } 7756 } 7757 } 7758 7759 /// Return the adjusted map modifiers if the declaration a capture refers to 7760 /// appears in a first-private clause. This is expected to be used only with 7761 /// directives that start with 'target'. 7762 MappableExprsHandler::OpenMPOffloadMappingFlags 7763 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7764 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7765 7766 // A first private variable captured by reference will use only the 7767 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7768 // declaration is known as first-private in this handler. 7769 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7770 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7771 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7772 return MappableExprsHandler::OMP_MAP_ALWAYS | 7773 MappableExprsHandler::OMP_MAP_TO; 7774 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7775 return MappableExprsHandler::OMP_MAP_TO | 7776 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7777 return MappableExprsHandler::OMP_MAP_PRIVATE | 7778 MappableExprsHandler::OMP_MAP_TO; 7779 } 7780 return MappableExprsHandler::OMP_MAP_TO | 7781 MappableExprsHandler::OMP_MAP_FROM; 7782 } 7783 7784 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7785 // Rotate by getFlagMemberOffset() bits. 7786 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7787 << getFlagMemberOffset()); 7788 } 7789 7790 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7791 OpenMPOffloadMappingFlags MemberOfFlag) { 7792 // If the entry is PTR_AND_OBJ but has not been marked with the special 7793 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7794 // marked as MEMBER_OF. 7795 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7796 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7797 return; 7798 7799 // Reset the placeholder value to prepare the flag for the assignment of the 7800 // proper MEMBER_OF value. 7801 Flags &= ~OMP_MAP_MEMBER_OF; 7802 Flags |= MemberOfFlag; 7803 } 7804 7805 void getPlainLayout(const CXXRecordDecl *RD, 7806 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7807 bool AsBase) const { 7808 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7809 7810 llvm::StructType *St = 7811 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7812 7813 unsigned NumElements = St->getNumElements(); 7814 llvm::SmallVector< 7815 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7816 RecordLayout(NumElements); 7817 7818 // Fill bases. 7819 for (const auto &I : RD->bases()) { 7820 if (I.isVirtual()) 7821 continue; 7822 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7823 // Ignore empty bases. 7824 if (Base->isEmpty() || CGF.getContext() 7825 .getASTRecordLayout(Base) 7826 .getNonVirtualSize() 7827 .isZero()) 7828 continue; 7829 7830 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7831 RecordLayout[FieldIndex] = Base; 7832 } 7833 // Fill in virtual bases. 7834 for (const auto &I : RD->vbases()) { 7835 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7836 // Ignore empty bases. 7837 if (Base->isEmpty()) 7838 continue; 7839 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7840 if (RecordLayout[FieldIndex]) 7841 continue; 7842 RecordLayout[FieldIndex] = Base; 7843 } 7844 // Fill in all the fields. 7845 assert(!RD->isUnion() && "Unexpected union."); 7846 for (const auto *Field : RD->fields()) { 7847 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7848 // will fill in later.) 7849 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 7850 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7851 RecordLayout[FieldIndex] = Field; 7852 } 7853 } 7854 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7855 &Data : RecordLayout) { 7856 if (Data.isNull()) 7857 continue; 7858 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7859 getPlainLayout(Base, Layout, /*AsBase=*/true); 7860 else 7861 Layout.push_back(Data.get<const FieldDecl *>()); 7862 } 7863 } 7864 7865 public: 7866 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7867 : CurDir(&Dir), CGF(CGF) { 7868 // Extract firstprivate clause information. 7869 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7870 for (const auto *D : C->varlists()) 7871 FirstPrivateDecls.try_emplace( 7872 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 7873 // Extract device pointer clause information. 7874 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 7875 for (auto L : C->component_lists()) 7876 DevPointersMap[L.first].push_back(L.second); 7877 } 7878 7879 /// Constructor for the declare mapper directive. 7880 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 7881 : CurDir(&Dir), CGF(CGF) {} 7882 7883 /// Generate code for the combined entry if we have a partially mapped struct 7884 /// and take care of the mapping flags of the arguments corresponding to 7885 /// individual struct members. 7886 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 7887 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7888 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 7889 const StructRangeInfoTy &PartialStruct) const { 7890 // Base is the base of the struct 7891 BasePointers.push_back(PartialStruct.Base.getPointer()); 7892 // Pointer is the address of the lowest element 7893 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 7894 Pointers.push_back(LB); 7895 // Size is (addr of {highest+1} element) - (addr of lowest element) 7896 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 7897 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 7898 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 7899 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 7900 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 7901 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 7902 /*isSigned=*/false); 7903 Sizes.push_back(Size); 7904 // Map type is always TARGET_PARAM 7905 Types.push_back(OMP_MAP_TARGET_PARAM); 7906 // Remove TARGET_PARAM flag from the first element 7907 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 7908 7909 // All other current entries will be MEMBER_OF the combined entry 7910 // (except for PTR_AND_OBJ entries which do not have a placeholder value 7911 // 0xFFFF in the MEMBER_OF field). 7912 OpenMPOffloadMappingFlags MemberOfFlag = 7913 getMemberOfFlag(BasePointers.size() - 1); 7914 for (auto &M : CurTypes) 7915 setCorrectMemberOfFlag(M, MemberOfFlag); 7916 } 7917 7918 /// Generate all the base pointers, section pointers, sizes and map 7919 /// types for the extracted mappable expressions. Also, for each item that 7920 /// relates with a device pointer, a pair of the relevant declaration and 7921 /// index where it occurs is appended to the device pointers info array. 7922 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 7923 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7924 MapFlagsArrayTy &Types) const { 7925 // We have to process the component lists that relate with the same 7926 // declaration in a single chunk so that we can generate the map flags 7927 // correctly. Therefore, we organize all lists in a map. 7928 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7929 7930 // Helper function to fill the information map for the different supported 7931 // clauses. 7932 auto &&InfoGen = [&Info]( 7933 const ValueDecl *D, 7934 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 7935 OpenMPMapClauseKind MapType, 7936 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7937 bool ReturnDevicePointer, bool IsImplicit) { 7938 const ValueDecl *VD = 7939 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 7940 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 7941 IsImplicit); 7942 }; 7943 7944 assert(CurDir.is<const OMPExecutableDirective *>() && 7945 "Expect a executable directive"); 7946 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 7947 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 7948 for (const auto L : C->component_lists()) { 7949 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 7950 /*ReturnDevicePointer=*/false, C->isImplicit()); 7951 } 7952 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 7953 for (const auto L : C->component_lists()) { 7954 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 7955 /*ReturnDevicePointer=*/false, C->isImplicit()); 7956 } 7957 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 7958 for (const auto L : C->component_lists()) { 7959 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 7960 /*ReturnDevicePointer=*/false, C->isImplicit()); 7961 } 7962 7963 // Look at the use_device_ptr clause information and mark the existing map 7964 // entries as such. If there is no map information for an entry in the 7965 // use_device_ptr list, we create one with map type 'alloc' and zero size 7966 // section. It is the user fault if that was not mapped before. If there is 7967 // no map information and the pointer is a struct member, then we defer the 7968 // emission of that entry until the whole struct has been processed. 7969 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 7970 DeferredInfo; 7971 7972 for (const auto *C : 7973 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 7974 for (const auto L : C->component_lists()) { 7975 assert(!L.second.empty() && "Not expecting empty list of components!"); 7976 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 7977 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 7978 const Expr *IE = L.second.back().getAssociatedExpression(); 7979 // If the first component is a member expression, we have to look into 7980 // 'this', which maps to null in the map of map information. Otherwise 7981 // look directly for the information. 7982 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 7983 7984 // We potentially have map information for this declaration already. 7985 // Look for the first set of components that refer to it. 7986 if (It != Info.end()) { 7987 auto CI = std::find_if( 7988 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 7989 return MI.Components.back().getAssociatedDeclaration() == VD; 7990 }); 7991 // If we found a map entry, signal that the pointer has to be returned 7992 // and move on to the next declaration. 7993 if (CI != It->second.end()) { 7994 CI->ReturnDevicePointer = true; 7995 continue; 7996 } 7997 } 7998 7999 // We didn't find any match in our map information - generate a zero 8000 // size array section - if the pointer is a struct member we defer this 8001 // action until the whole struct has been processed. 8002 if (isa<MemberExpr>(IE)) { 8003 // Insert the pointer into Info to be processed by 8004 // generateInfoForComponentList. Because it is a member pointer 8005 // without a pointee, no entry will be generated for it, therefore 8006 // we need to generate one after the whole struct has been processed. 8007 // Nonetheless, generateInfoForComponentList must be called to take 8008 // the pointer into account for the calculation of the range of the 8009 // partial struct. 8010 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 8011 /*ReturnDevicePointer=*/false, C->isImplicit()); 8012 DeferredInfo[nullptr].emplace_back(IE, VD); 8013 } else { 8014 llvm::Value *Ptr = 8015 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8016 BasePointers.emplace_back(Ptr, VD); 8017 Pointers.push_back(Ptr); 8018 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8019 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8020 } 8021 } 8022 } 8023 8024 for (const auto &M : Info) { 8025 // We need to know when we generate information for the first component 8026 // associated with a capture, because the mapping flags depend on it. 8027 bool IsFirstComponentList = true; 8028 8029 // Temporary versions of arrays 8030 MapBaseValuesArrayTy CurBasePointers; 8031 MapValuesArrayTy CurPointers; 8032 MapValuesArrayTy CurSizes; 8033 MapFlagsArrayTy CurTypes; 8034 StructRangeInfoTy PartialStruct; 8035 8036 for (const MapInfo &L : M.second) { 8037 assert(!L.Components.empty() && 8038 "Not expecting declaration with no component lists."); 8039 8040 // Remember the current base pointer index. 8041 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8042 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8043 CurBasePointers, CurPointers, CurSizes, 8044 CurTypes, PartialStruct, 8045 IsFirstComponentList, L.IsImplicit); 8046 8047 // If this entry relates with a device pointer, set the relevant 8048 // declaration and add the 'return pointer' flag. 8049 if (L.ReturnDevicePointer) { 8050 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8051 "Unexpected number of mapped base pointers."); 8052 8053 const ValueDecl *RelevantVD = 8054 L.Components.back().getAssociatedDeclaration(); 8055 assert(RelevantVD && 8056 "No relevant declaration related with device pointer??"); 8057 8058 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8059 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8060 } 8061 IsFirstComponentList = false; 8062 } 8063 8064 // Append any pending zero-length pointers which are struct members and 8065 // used with use_device_ptr. 8066 auto CI = DeferredInfo.find(M.first); 8067 if (CI != DeferredInfo.end()) { 8068 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8069 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8070 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8071 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8072 CurBasePointers.emplace_back(BasePtr, L.VD); 8073 CurPointers.push_back(Ptr); 8074 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8075 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8076 // value MEMBER_OF=FFFF so that the entry is later updated with the 8077 // correct value of MEMBER_OF. 8078 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8079 OMP_MAP_MEMBER_OF); 8080 } 8081 } 8082 8083 // If there is an entry in PartialStruct it means we have a struct with 8084 // individual members mapped. Emit an extra combined entry. 8085 if (PartialStruct.Base.isValid()) 8086 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8087 PartialStruct); 8088 8089 // We need to append the results of this capture to what we already have. 8090 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8091 Pointers.append(CurPointers.begin(), CurPointers.end()); 8092 Sizes.append(CurSizes.begin(), CurSizes.end()); 8093 Types.append(CurTypes.begin(), CurTypes.end()); 8094 } 8095 } 8096 8097 /// Generate all the base pointers, section pointers, sizes and map types for 8098 /// the extracted map clauses of user-defined mapper. 8099 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8100 MapValuesArrayTy &Pointers, 8101 MapValuesArrayTy &Sizes, 8102 MapFlagsArrayTy &Types) const { 8103 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8104 "Expect a declare mapper directive"); 8105 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8106 // We have to process the component lists that relate with the same 8107 // declaration in a single chunk so that we can generate the map flags 8108 // correctly. Therefore, we organize all lists in a map. 8109 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8110 8111 // Helper function to fill the information map for the different supported 8112 // clauses. 8113 auto &&InfoGen = [&Info]( 8114 const ValueDecl *D, 8115 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8116 OpenMPMapClauseKind MapType, 8117 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8118 bool ReturnDevicePointer, bool IsImplicit) { 8119 const ValueDecl *VD = 8120 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8121 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8122 IsImplicit); 8123 }; 8124 8125 for (const auto *C : CurMapperDir->clauselists()) { 8126 const auto *MC = cast<OMPMapClause>(C); 8127 for (const auto L : MC->component_lists()) { 8128 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8129 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8130 } 8131 } 8132 8133 for (const auto &M : Info) { 8134 // We need to know when we generate information for the first component 8135 // associated with a capture, because the mapping flags depend on it. 8136 bool IsFirstComponentList = true; 8137 8138 // Temporary versions of arrays 8139 MapBaseValuesArrayTy CurBasePointers; 8140 MapValuesArrayTy CurPointers; 8141 MapValuesArrayTy CurSizes; 8142 MapFlagsArrayTy CurTypes; 8143 StructRangeInfoTy PartialStruct; 8144 8145 for (const MapInfo &L : M.second) { 8146 assert(!L.Components.empty() && 8147 "Not expecting declaration with no component lists."); 8148 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8149 CurBasePointers, CurPointers, CurSizes, 8150 CurTypes, PartialStruct, 8151 IsFirstComponentList, L.IsImplicit); 8152 IsFirstComponentList = false; 8153 } 8154 8155 // If there is an entry in PartialStruct it means we have a struct with 8156 // individual members mapped. Emit an extra combined entry. 8157 if (PartialStruct.Base.isValid()) 8158 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8159 PartialStruct); 8160 8161 // We need to append the results of this capture to what we already have. 8162 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8163 Pointers.append(CurPointers.begin(), CurPointers.end()); 8164 Sizes.append(CurSizes.begin(), CurSizes.end()); 8165 Types.append(CurTypes.begin(), CurTypes.end()); 8166 } 8167 } 8168 8169 /// Emit capture info for lambdas for variables captured by reference. 8170 void generateInfoForLambdaCaptures( 8171 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8172 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8173 MapFlagsArrayTy &Types, 8174 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8175 const auto *RD = VD->getType() 8176 .getCanonicalType() 8177 .getNonReferenceType() 8178 ->getAsCXXRecordDecl(); 8179 if (!RD || !RD->isLambda()) 8180 return; 8181 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8182 LValue VDLVal = CGF.MakeAddrLValue( 8183 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8184 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8185 FieldDecl *ThisCapture = nullptr; 8186 RD->getCaptureFields(Captures, ThisCapture); 8187 if (ThisCapture) { 8188 LValue ThisLVal = 8189 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8190 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8191 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8192 VDLVal.getPointer(CGF)); 8193 BasePointers.push_back(ThisLVal.getPointer(CGF)); 8194 Pointers.push_back(ThisLValVal.getPointer(CGF)); 8195 Sizes.push_back( 8196 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8197 CGF.Int64Ty, /*isSigned=*/true)); 8198 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8199 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8200 } 8201 for (const LambdaCapture &LC : RD->captures()) { 8202 if (!LC.capturesVariable()) 8203 continue; 8204 const VarDecl *VD = LC.getCapturedVar(); 8205 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8206 continue; 8207 auto It = Captures.find(VD); 8208 assert(It != Captures.end() && "Found lambda capture without field."); 8209 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8210 if (LC.getCaptureKind() == LCK_ByRef) { 8211 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8212 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8213 VDLVal.getPointer(CGF)); 8214 BasePointers.push_back(VarLVal.getPointer(CGF)); 8215 Pointers.push_back(VarLValVal.getPointer(CGF)); 8216 Sizes.push_back(CGF.Builder.CreateIntCast( 8217 CGF.getTypeSize( 8218 VD->getType().getCanonicalType().getNonReferenceType()), 8219 CGF.Int64Ty, /*isSigned=*/true)); 8220 } else { 8221 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8222 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8223 VDLVal.getPointer(CGF)); 8224 BasePointers.push_back(VarLVal.getPointer(CGF)); 8225 Pointers.push_back(VarRVal.getScalarVal()); 8226 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8227 } 8228 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8229 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8230 } 8231 } 8232 8233 /// Set correct indices for lambdas captures. 8234 void adjustMemberOfForLambdaCaptures( 8235 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8236 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8237 MapFlagsArrayTy &Types) const { 8238 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8239 // Set correct member_of idx for all implicit lambda captures. 8240 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8241 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8242 continue; 8243 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8244 assert(BasePtr && "Unable to find base lambda address."); 8245 int TgtIdx = -1; 8246 for (unsigned J = I; J > 0; --J) { 8247 unsigned Idx = J - 1; 8248 if (Pointers[Idx] != BasePtr) 8249 continue; 8250 TgtIdx = Idx; 8251 break; 8252 } 8253 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8254 // All other current entries will be MEMBER_OF the combined entry 8255 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8256 // 0xFFFF in the MEMBER_OF field). 8257 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8258 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8259 } 8260 } 8261 8262 /// Generate the base pointers, section pointers, sizes and map types 8263 /// associated to a given capture. 8264 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8265 llvm::Value *Arg, 8266 MapBaseValuesArrayTy &BasePointers, 8267 MapValuesArrayTy &Pointers, 8268 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8269 StructRangeInfoTy &PartialStruct) const { 8270 assert(!Cap->capturesVariableArrayType() && 8271 "Not expecting to generate map info for a variable array type!"); 8272 8273 // We need to know when we generating information for the first component 8274 const ValueDecl *VD = Cap->capturesThis() 8275 ? nullptr 8276 : Cap->getCapturedVar()->getCanonicalDecl(); 8277 8278 // If this declaration appears in a is_device_ptr clause we just have to 8279 // pass the pointer by value. If it is a reference to a declaration, we just 8280 // pass its value. 8281 if (DevPointersMap.count(VD)) { 8282 BasePointers.emplace_back(Arg, VD); 8283 Pointers.push_back(Arg); 8284 Sizes.push_back( 8285 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8286 CGF.Int64Ty, /*isSigned=*/true)); 8287 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8288 return; 8289 } 8290 8291 using MapData = 8292 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8293 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8294 SmallVector<MapData, 4> DeclComponentLists; 8295 assert(CurDir.is<const OMPExecutableDirective *>() && 8296 "Expect a executable directive"); 8297 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8298 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8299 for (const auto L : C->decl_component_lists(VD)) { 8300 assert(L.first == VD && 8301 "We got information for the wrong declaration??"); 8302 assert(!L.second.empty() && 8303 "Not expecting declaration with no component lists."); 8304 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8305 C->getMapTypeModifiers(), 8306 C->isImplicit()); 8307 } 8308 } 8309 8310 // Find overlapping elements (including the offset from the base element). 8311 llvm::SmallDenseMap< 8312 const MapData *, 8313 llvm::SmallVector< 8314 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8315 4> 8316 OverlappedData; 8317 size_t Count = 0; 8318 for (const MapData &L : DeclComponentLists) { 8319 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8320 OpenMPMapClauseKind MapType; 8321 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8322 bool IsImplicit; 8323 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8324 ++Count; 8325 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8326 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8327 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8328 auto CI = Components.rbegin(); 8329 auto CE = Components.rend(); 8330 auto SI = Components1.rbegin(); 8331 auto SE = Components1.rend(); 8332 for (; CI != CE && SI != SE; ++CI, ++SI) { 8333 if (CI->getAssociatedExpression()->getStmtClass() != 8334 SI->getAssociatedExpression()->getStmtClass()) 8335 break; 8336 // Are we dealing with different variables/fields? 8337 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8338 break; 8339 } 8340 // Found overlapping if, at least for one component, reached the head of 8341 // the components list. 8342 if (CI == CE || SI == SE) { 8343 assert((CI != CE || SI != SE) && 8344 "Unexpected full match of the mapping components."); 8345 const MapData &BaseData = CI == CE ? L : L1; 8346 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8347 SI == SE ? Components : Components1; 8348 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8349 OverlappedElements.getSecond().push_back(SubData); 8350 } 8351 } 8352 } 8353 // Sort the overlapped elements for each item. 8354 llvm::SmallVector<const FieldDecl *, 4> Layout; 8355 if (!OverlappedData.empty()) { 8356 if (const auto *CRD = 8357 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8358 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8359 else { 8360 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8361 Layout.append(RD->field_begin(), RD->field_end()); 8362 } 8363 } 8364 for (auto &Pair : OverlappedData) { 8365 llvm::sort( 8366 Pair.getSecond(), 8367 [&Layout]( 8368 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8369 OMPClauseMappableExprCommon::MappableExprComponentListRef 8370 Second) { 8371 auto CI = First.rbegin(); 8372 auto CE = First.rend(); 8373 auto SI = Second.rbegin(); 8374 auto SE = Second.rend(); 8375 for (; CI != CE && SI != SE; ++CI, ++SI) { 8376 if (CI->getAssociatedExpression()->getStmtClass() != 8377 SI->getAssociatedExpression()->getStmtClass()) 8378 break; 8379 // Are we dealing with different variables/fields? 8380 if (CI->getAssociatedDeclaration() != 8381 SI->getAssociatedDeclaration()) 8382 break; 8383 } 8384 8385 // Lists contain the same elements. 8386 if (CI == CE && SI == SE) 8387 return false; 8388 8389 // List with less elements is less than list with more elements. 8390 if (CI == CE || SI == SE) 8391 return CI == CE; 8392 8393 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8394 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8395 if (FD1->getParent() == FD2->getParent()) 8396 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8397 const auto It = 8398 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8399 return FD == FD1 || FD == FD2; 8400 }); 8401 return *It == FD1; 8402 }); 8403 } 8404 8405 // Associated with a capture, because the mapping flags depend on it. 8406 // Go through all of the elements with the overlapped elements. 8407 for (const auto &Pair : OverlappedData) { 8408 const MapData &L = *Pair.getFirst(); 8409 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8410 OpenMPMapClauseKind MapType; 8411 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8412 bool IsImplicit; 8413 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8414 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8415 OverlappedComponents = Pair.getSecond(); 8416 bool IsFirstComponentList = true; 8417 generateInfoForComponentList(MapType, MapModifiers, Components, 8418 BasePointers, Pointers, Sizes, Types, 8419 PartialStruct, IsFirstComponentList, 8420 IsImplicit, OverlappedComponents); 8421 } 8422 // Go through other elements without overlapped elements. 8423 bool IsFirstComponentList = OverlappedData.empty(); 8424 for (const MapData &L : DeclComponentLists) { 8425 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8426 OpenMPMapClauseKind MapType; 8427 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8428 bool IsImplicit; 8429 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8430 auto It = OverlappedData.find(&L); 8431 if (It == OverlappedData.end()) 8432 generateInfoForComponentList(MapType, MapModifiers, Components, 8433 BasePointers, Pointers, Sizes, Types, 8434 PartialStruct, IsFirstComponentList, 8435 IsImplicit); 8436 IsFirstComponentList = false; 8437 } 8438 } 8439 8440 /// Generate the base pointers, section pointers, sizes and map types 8441 /// associated with the declare target link variables. 8442 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8443 MapValuesArrayTy &Pointers, 8444 MapValuesArrayTy &Sizes, 8445 MapFlagsArrayTy &Types) const { 8446 assert(CurDir.is<const OMPExecutableDirective *>() && 8447 "Expect a executable directive"); 8448 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8449 // Map other list items in the map clause which are not captured variables 8450 // but "declare target link" global variables. 8451 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8452 for (const auto L : C->component_lists()) { 8453 if (!L.first) 8454 continue; 8455 const auto *VD = dyn_cast<VarDecl>(L.first); 8456 if (!VD) 8457 continue; 8458 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8459 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8460 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8461 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8462 continue; 8463 StructRangeInfoTy PartialStruct; 8464 generateInfoForComponentList( 8465 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8466 Pointers, Sizes, Types, PartialStruct, 8467 /*IsFirstComponentList=*/true, C->isImplicit()); 8468 assert(!PartialStruct.Base.isValid() && 8469 "No partial structs for declare target link expected."); 8470 } 8471 } 8472 } 8473 8474 /// Generate the default map information for a given capture \a CI, 8475 /// record field declaration \a RI and captured value \a CV. 8476 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8477 const FieldDecl &RI, llvm::Value *CV, 8478 MapBaseValuesArrayTy &CurBasePointers, 8479 MapValuesArrayTy &CurPointers, 8480 MapValuesArrayTy &CurSizes, 8481 MapFlagsArrayTy &CurMapTypes) const { 8482 bool IsImplicit = true; 8483 // Do the default mapping. 8484 if (CI.capturesThis()) { 8485 CurBasePointers.push_back(CV); 8486 CurPointers.push_back(CV); 8487 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8488 CurSizes.push_back( 8489 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8490 CGF.Int64Ty, /*isSigned=*/true)); 8491 // Default map type. 8492 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8493 } else if (CI.capturesVariableByCopy()) { 8494 CurBasePointers.push_back(CV); 8495 CurPointers.push_back(CV); 8496 if (!RI.getType()->isAnyPointerType()) { 8497 // We have to signal to the runtime captures passed by value that are 8498 // not pointers. 8499 CurMapTypes.push_back(OMP_MAP_LITERAL); 8500 CurSizes.push_back(CGF.Builder.CreateIntCast( 8501 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8502 } else { 8503 // Pointers are implicitly mapped with a zero size and no flags 8504 // (other than first map that is added for all implicit maps). 8505 CurMapTypes.push_back(OMP_MAP_NONE); 8506 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8507 } 8508 const VarDecl *VD = CI.getCapturedVar(); 8509 auto I = FirstPrivateDecls.find(VD); 8510 if (I != FirstPrivateDecls.end()) 8511 IsImplicit = I->getSecond(); 8512 } else { 8513 assert(CI.capturesVariable() && "Expected captured reference."); 8514 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8515 QualType ElementType = PtrTy->getPointeeType(); 8516 CurSizes.push_back(CGF.Builder.CreateIntCast( 8517 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8518 // The default map type for a scalar/complex type is 'to' because by 8519 // default the value doesn't have to be retrieved. For an aggregate 8520 // type, the default is 'tofrom'. 8521 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8522 const VarDecl *VD = CI.getCapturedVar(); 8523 auto I = FirstPrivateDecls.find(VD); 8524 if (I != FirstPrivateDecls.end() && 8525 VD->getType().isConstant(CGF.getContext())) { 8526 llvm::Constant *Addr = 8527 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8528 // Copy the value of the original variable to the new global copy. 8529 CGF.Builder.CreateMemCpy( 8530 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 8531 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8532 CurSizes.back(), /*IsVolatile=*/false); 8533 // Use new global variable as the base pointers. 8534 CurBasePointers.push_back(Addr); 8535 CurPointers.push_back(Addr); 8536 } else { 8537 CurBasePointers.push_back(CV); 8538 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8539 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8540 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8541 AlignmentSource::Decl)); 8542 CurPointers.push_back(PtrAddr.getPointer()); 8543 } else { 8544 CurPointers.push_back(CV); 8545 } 8546 } 8547 if (I != FirstPrivateDecls.end()) 8548 IsImplicit = I->getSecond(); 8549 } 8550 // Every default map produces a single argument which is a target parameter. 8551 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8552 8553 // Add flag stating this is an implicit map. 8554 if (IsImplicit) 8555 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8556 } 8557 }; 8558 } // anonymous namespace 8559 8560 /// Emit the arrays used to pass the captures and map information to the 8561 /// offloading runtime library. If there is no map or capture information, 8562 /// return nullptr by reference. 8563 static void 8564 emitOffloadingArrays(CodeGenFunction &CGF, 8565 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8566 MappableExprsHandler::MapValuesArrayTy &Pointers, 8567 MappableExprsHandler::MapValuesArrayTy &Sizes, 8568 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8569 CGOpenMPRuntime::TargetDataInfo &Info) { 8570 CodeGenModule &CGM = CGF.CGM; 8571 ASTContext &Ctx = CGF.getContext(); 8572 8573 // Reset the array information. 8574 Info.clearArrayInfo(); 8575 Info.NumberOfPtrs = BasePointers.size(); 8576 8577 if (Info.NumberOfPtrs) { 8578 // Detect if we have any capture size requiring runtime evaluation of the 8579 // size so that a constant array could be eventually used. 8580 bool hasRuntimeEvaluationCaptureSize = false; 8581 for (llvm::Value *S : Sizes) 8582 if (!isa<llvm::Constant>(S)) { 8583 hasRuntimeEvaluationCaptureSize = true; 8584 break; 8585 } 8586 8587 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8588 QualType PointerArrayType = Ctx.getConstantArrayType( 8589 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8590 /*IndexTypeQuals=*/0); 8591 8592 Info.BasePointersArray = 8593 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8594 Info.PointersArray = 8595 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8596 8597 // If we don't have any VLA types or other types that require runtime 8598 // evaluation, we can use a constant array for the map sizes, otherwise we 8599 // need to fill up the arrays as we do for the pointers. 8600 QualType Int64Ty = 8601 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8602 if (hasRuntimeEvaluationCaptureSize) { 8603 QualType SizeArrayType = Ctx.getConstantArrayType( 8604 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8605 /*IndexTypeQuals=*/0); 8606 Info.SizesArray = 8607 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8608 } else { 8609 // We expect all the sizes to be constant, so we collect them to create 8610 // a constant array. 8611 SmallVector<llvm::Constant *, 16> ConstSizes; 8612 for (llvm::Value *S : Sizes) 8613 ConstSizes.push_back(cast<llvm::Constant>(S)); 8614 8615 auto *SizesArrayInit = llvm::ConstantArray::get( 8616 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8617 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8618 auto *SizesArrayGbl = new llvm::GlobalVariable( 8619 CGM.getModule(), SizesArrayInit->getType(), 8620 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8621 SizesArrayInit, Name); 8622 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8623 Info.SizesArray = SizesArrayGbl; 8624 } 8625 8626 // The map types are always constant so we don't need to generate code to 8627 // fill arrays. Instead, we create an array constant. 8628 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8629 llvm::copy(MapTypes, Mapping.begin()); 8630 llvm::Constant *MapTypesArrayInit = 8631 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8632 std::string MaptypesName = 8633 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8634 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8635 CGM.getModule(), MapTypesArrayInit->getType(), 8636 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8637 MapTypesArrayInit, MaptypesName); 8638 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8639 Info.MapTypesArray = MapTypesArrayGbl; 8640 8641 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8642 llvm::Value *BPVal = *BasePointers[I]; 8643 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8644 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8645 Info.BasePointersArray, 0, I); 8646 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8647 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8648 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8649 CGF.Builder.CreateStore(BPVal, BPAddr); 8650 8651 if (Info.requiresDevicePointerInfo()) 8652 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8653 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8654 8655 llvm::Value *PVal = Pointers[I]; 8656 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8657 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8658 Info.PointersArray, 0, I); 8659 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8660 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8661 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8662 CGF.Builder.CreateStore(PVal, PAddr); 8663 8664 if (hasRuntimeEvaluationCaptureSize) { 8665 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8666 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8667 Info.SizesArray, 8668 /*Idx0=*/0, 8669 /*Idx1=*/I); 8670 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8671 CGF.Builder.CreateStore( 8672 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8673 SAddr); 8674 } 8675 } 8676 } 8677 } 8678 8679 /// Emit the arguments to be passed to the runtime library based on the 8680 /// arrays of pointers, sizes and map types. 8681 static void emitOffloadingArraysArgument( 8682 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8683 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8684 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8685 CodeGenModule &CGM = CGF.CGM; 8686 if (Info.NumberOfPtrs) { 8687 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8688 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8689 Info.BasePointersArray, 8690 /*Idx0=*/0, /*Idx1=*/0); 8691 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8692 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8693 Info.PointersArray, 8694 /*Idx0=*/0, 8695 /*Idx1=*/0); 8696 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8697 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8698 /*Idx0=*/0, /*Idx1=*/0); 8699 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8700 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8701 Info.MapTypesArray, 8702 /*Idx0=*/0, 8703 /*Idx1=*/0); 8704 } else { 8705 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8706 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8707 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8708 MapTypesArrayArg = 8709 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8710 } 8711 } 8712 8713 /// Check for inner distribute directive. 8714 static const OMPExecutableDirective * 8715 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8716 const auto *CS = D.getInnermostCapturedStmt(); 8717 const auto *Body = 8718 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8719 const Stmt *ChildStmt = 8720 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8721 8722 if (const auto *NestedDir = 8723 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8724 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8725 switch (D.getDirectiveKind()) { 8726 case OMPD_target: 8727 if (isOpenMPDistributeDirective(DKind)) 8728 return NestedDir; 8729 if (DKind == OMPD_teams) { 8730 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8731 /*IgnoreCaptured=*/true); 8732 if (!Body) 8733 return nullptr; 8734 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8735 if (const auto *NND = 8736 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8737 DKind = NND->getDirectiveKind(); 8738 if (isOpenMPDistributeDirective(DKind)) 8739 return NND; 8740 } 8741 } 8742 return nullptr; 8743 case OMPD_target_teams: 8744 if (isOpenMPDistributeDirective(DKind)) 8745 return NestedDir; 8746 return nullptr; 8747 case OMPD_target_parallel: 8748 case OMPD_target_simd: 8749 case OMPD_target_parallel_for: 8750 case OMPD_target_parallel_for_simd: 8751 return nullptr; 8752 case OMPD_target_teams_distribute: 8753 case OMPD_target_teams_distribute_simd: 8754 case OMPD_target_teams_distribute_parallel_for: 8755 case OMPD_target_teams_distribute_parallel_for_simd: 8756 case OMPD_parallel: 8757 case OMPD_for: 8758 case OMPD_parallel_for: 8759 case OMPD_parallel_master: 8760 case OMPD_parallel_sections: 8761 case OMPD_for_simd: 8762 case OMPD_parallel_for_simd: 8763 case OMPD_cancel: 8764 case OMPD_cancellation_point: 8765 case OMPD_ordered: 8766 case OMPD_threadprivate: 8767 case OMPD_allocate: 8768 case OMPD_task: 8769 case OMPD_simd: 8770 case OMPD_sections: 8771 case OMPD_section: 8772 case OMPD_single: 8773 case OMPD_master: 8774 case OMPD_critical: 8775 case OMPD_taskyield: 8776 case OMPD_barrier: 8777 case OMPD_taskwait: 8778 case OMPD_taskgroup: 8779 case OMPD_atomic: 8780 case OMPD_flush: 8781 case OMPD_teams: 8782 case OMPD_target_data: 8783 case OMPD_target_exit_data: 8784 case OMPD_target_enter_data: 8785 case OMPD_distribute: 8786 case OMPD_distribute_simd: 8787 case OMPD_distribute_parallel_for: 8788 case OMPD_distribute_parallel_for_simd: 8789 case OMPD_teams_distribute: 8790 case OMPD_teams_distribute_simd: 8791 case OMPD_teams_distribute_parallel_for: 8792 case OMPD_teams_distribute_parallel_for_simd: 8793 case OMPD_target_update: 8794 case OMPD_declare_simd: 8795 case OMPD_declare_variant: 8796 case OMPD_declare_target: 8797 case OMPD_end_declare_target: 8798 case OMPD_declare_reduction: 8799 case OMPD_declare_mapper: 8800 case OMPD_taskloop: 8801 case OMPD_taskloop_simd: 8802 case OMPD_master_taskloop: 8803 case OMPD_master_taskloop_simd: 8804 case OMPD_parallel_master_taskloop: 8805 case OMPD_parallel_master_taskloop_simd: 8806 case OMPD_requires: 8807 case OMPD_unknown: 8808 llvm_unreachable("Unexpected directive."); 8809 } 8810 } 8811 8812 return nullptr; 8813 } 8814 8815 /// Emit the user-defined mapper function. The code generation follows the 8816 /// pattern in the example below. 8817 /// \code 8818 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 8819 /// void *base, void *begin, 8820 /// int64_t size, int64_t type) { 8821 /// // Allocate space for an array section first. 8822 /// if (size > 1 && !maptype.IsDelete) 8823 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8824 /// size*sizeof(Ty), clearToFrom(type)); 8825 /// // Map members. 8826 /// for (unsigned i = 0; i < size; i++) { 8827 /// // For each component specified by this mapper: 8828 /// for (auto c : all_components) { 8829 /// if (c.hasMapper()) 8830 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 8831 /// c.arg_type); 8832 /// else 8833 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 8834 /// c.arg_begin, c.arg_size, c.arg_type); 8835 /// } 8836 /// } 8837 /// // Delete the array section. 8838 /// if (size > 1 && maptype.IsDelete) 8839 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8840 /// size*sizeof(Ty), clearToFrom(type)); 8841 /// } 8842 /// \endcode 8843 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 8844 CodeGenFunction *CGF) { 8845 if (UDMMap.count(D) > 0) 8846 return; 8847 ASTContext &C = CGM.getContext(); 8848 QualType Ty = D->getType(); 8849 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 8850 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 8851 auto *MapperVarDecl = 8852 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 8853 SourceLocation Loc = D->getLocation(); 8854 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 8855 8856 // Prepare mapper function arguments and attributes. 8857 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8858 C.VoidPtrTy, ImplicitParamDecl::Other); 8859 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 8860 ImplicitParamDecl::Other); 8861 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8862 C.VoidPtrTy, ImplicitParamDecl::Other); 8863 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8864 ImplicitParamDecl::Other); 8865 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8866 ImplicitParamDecl::Other); 8867 FunctionArgList Args; 8868 Args.push_back(&HandleArg); 8869 Args.push_back(&BaseArg); 8870 Args.push_back(&BeginArg); 8871 Args.push_back(&SizeArg); 8872 Args.push_back(&TypeArg); 8873 const CGFunctionInfo &FnInfo = 8874 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 8875 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 8876 SmallString<64> TyStr; 8877 llvm::raw_svector_ostream Out(TyStr); 8878 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 8879 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 8880 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 8881 Name, &CGM.getModule()); 8882 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 8883 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 8884 // Start the mapper function code generation. 8885 CodeGenFunction MapperCGF(CGM); 8886 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 8887 // Compute the starting and end addreses of array elements. 8888 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 8889 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 8890 C.getPointerType(Int64Ty), Loc); 8891 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 8892 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 8893 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 8894 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 8895 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 8896 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 8897 C.getPointerType(Int64Ty), Loc); 8898 // Prepare common arguments for array initiation and deletion. 8899 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 8900 MapperCGF.GetAddrOfLocalVar(&HandleArg), 8901 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8902 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 8903 MapperCGF.GetAddrOfLocalVar(&BaseArg), 8904 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8905 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 8906 MapperCGF.GetAddrOfLocalVar(&BeginArg), 8907 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8908 8909 // Emit array initiation if this is an array section and \p MapType indicates 8910 // that memory allocation is required. 8911 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 8912 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 8913 ElementSize, HeadBB, /*IsInit=*/true); 8914 8915 // Emit a for loop to iterate through SizeArg of elements and map all of them. 8916 8917 // Emit the loop header block. 8918 MapperCGF.EmitBlock(HeadBB); 8919 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 8920 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 8921 // Evaluate whether the initial condition is satisfied. 8922 llvm::Value *IsEmpty = 8923 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 8924 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 8925 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 8926 8927 // Emit the loop body block. 8928 MapperCGF.EmitBlock(BodyBB); 8929 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 8930 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 8931 PtrPHI->addIncoming(PtrBegin, EntryBB); 8932 Address PtrCurrent = 8933 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 8934 .getAlignment() 8935 .alignmentOfArrayElement(ElementSize)); 8936 // Privatize the declared variable of mapper to be the current array element. 8937 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 8938 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 8939 return MapperCGF 8940 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 8941 .getAddress(MapperCGF); 8942 }); 8943 (void)Scope.Privatize(); 8944 8945 // Get map clause information. Fill up the arrays with all mapped variables. 8946 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 8947 MappableExprsHandler::MapValuesArrayTy Pointers; 8948 MappableExprsHandler::MapValuesArrayTy Sizes; 8949 MappableExprsHandler::MapFlagsArrayTy MapTypes; 8950 MappableExprsHandler MEHandler(*D, MapperCGF); 8951 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 8952 8953 // Call the runtime API __tgt_mapper_num_components to get the number of 8954 // pre-existing components. 8955 llvm::Value *OffloadingArgs[] = {Handle}; 8956 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 8957 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 8958 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 8959 PreviousSize, 8960 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 8961 8962 // Fill up the runtime mapper handle for all components. 8963 for (unsigned I = 0; I < BasePointers.size(); ++I) { 8964 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 8965 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8966 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 8967 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8968 llvm::Value *CurSizeArg = Sizes[I]; 8969 8970 // Extract the MEMBER_OF field from the map type. 8971 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 8972 MapperCGF.EmitBlock(MemberBB); 8973 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 8974 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 8975 OriMapType, 8976 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 8977 llvm::BasicBlock *MemberCombineBB = 8978 MapperCGF.createBasicBlock("omp.member.combine"); 8979 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 8980 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 8981 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 8982 // Add the number of pre-existing components to the MEMBER_OF field if it 8983 // is valid. 8984 MapperCGF.EmitBlock(MemberCombineBB); 8985 llvm::Value *CombinedMember = 8986 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 8987 // Do nothing if it is not a member of previous components. 8988 MapperCGF.EmitBlock(TypeBB); 8989 llvm::PHINode *MemberMapType = 8990 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 8991 MemberMapType->addIncoming(OriMapType, MemberBB); 8992 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 8993 8994 // Combine the map type inherited from user-defined mapper with that 8995 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 8996 // bits of the \a MapType, which is the input argument of the mapper 8997 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 8998 // bits of MemberMapType. 8999 // [OpenMP 5.0], 1.2.6. map-type decay. 9000 // | alloc | to | from | tofrom | release | delete 9001 // ---------------------------------------------------------- 9002 // alloc | alloc | alloc | alloc | alloc | release | delete 9003 // to | alloc | to | alloc | to | release | delete 9004 // from | alloc | alloc | from | from | release | delete 9005 // tofrom | alloc | to | from | tofrom | release | delete 9006 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9007 MapType, 9008 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9009 MappableExprsHandler::OMP_MAP_FROM)); 9010 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9011 llvm::BasicBlock *AllocElseBB = 9012 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9013 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9014 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9015 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9016 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9017 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9018 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9019 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9020 MapperCGF.EmitBlock(AllocBB); 9021 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9022 MemberMapType, 9023 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9024 MappableExprsHandler::OMP_MAP_FROM))); 9025 MapperCGF.Builder.CreateBr(EndBB); 9026 MapperCGF.EmitBlock(AllocElseBB); 9027 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9028 LeftToFrom, 9029 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9030 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9031 // In case of to, clear OMP_MAP_FROM. 9032 MapperCGF.EmitBlock(ToBB); 9033 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9034 MemberMapType, 9035 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9036 MapperCGF.Builder.CreateBr(EndBB); 9037 MapperCGF.EmitBlock(ToElseBB); 9038 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9039 LeftToFrom, 9040 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9041 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9042 // In case of from, clear OMP_MAP_TO. 9043 MapperCGF.EmitBlock(FromBB); 9044 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9045 MemberMapType, 9046 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9047 // In case of tofrom, do nothing. 9048 MapperCGF.EmitBlock(EndBB); 9049 llvm::PHINode *CurMapType = 9050 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9051 CurMapType->addIncoming(AllocMapType, AllocBB); 9052 CurMapType->addIncoming(ToMapType, ToBB); 9053 CurMapType->addIncoming(FromMapType, FromBB); 9054 CurMapType->addIncoming(MemberMapType, ToElseBB); 9055 9056 // TODO: call the corresponding mapper function if a user-defined mapper is 9057 // associated with this map clause. 9058 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9059 // data structure. 9060 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9061 CurSizeArg, CurMapType}; 9062 MapperCGF.EmitRuntimeCall( 9063 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9064 OffloadingArgs); 9065 } 9066 9067 // Update the pointer to point to the next element that needs to be mapped, 9068 // and check whether we have mapped all elements. 9069 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9070 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9071 PtrPHI->addIncoming(PtrNext, BodyBB); 9072 llvm::Value *IsDone = 9073 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9074 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9075 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9076 9077 MapperCGF.EmitBlock(ExitBB); 9078 // Emit array deletion if this is an array section and \p MapType indicates 9079 // that deletion is required. 9080 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9081 ElementSize, DoneBB, /*IsInit=*/false); 9082 9083 // Emit the function exit block. 9084 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9085 MapperCGF.FinishFunction(); 9086 UDMMap.try_emplace(D, Fn); 9087 if (CGF) { 9088 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9089 Decls.second.push_back(D); 9090 } 9091 } 9092 9093 /// Emit the array initialization or deletion portion for user-defined mapper 9094 /// code generation. First, it evaluates whether an array section is mapped and 9095 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9096 /// true, and \a MapType indicates to not delete this array, array 9097 /// initialization code is generated. If \a IsInit is false, and \a MapType 9098 /// indicates to not this array, array deletion code is generated. 9099 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9100 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9101 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9102 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9103 StringRef Prefix = IsInit ? ".init" : ".del"; 9104 9105 // Evaluate if this is an array section. 9106 llvm::BasicBlock *IsDeleteBB = 9107 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"})); 9108 llvm::BasicBlock *BodyBB = 9109 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 9110 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9111 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9112 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9113 9114 // Evaluate if we are going to delete this section. 9115 MapperCGF.EmitBlock(IsDeleteBB); 9116 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9117 MapType, 9118 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9119 llvm::Value *DeleteCond; 9120 if (IsInit) { 9121 DeleteCond = MapperCGF.Builder.CreateIsNull( 9122 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9123 } else { 9124 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9125 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9126 } 9127 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9128 9129 MapperCGF.EmitBlock(BodyBB); 9130 // Get the array size by multiplying element size and element number (i.e., \p 9131 // Size). 9132 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9133 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9134 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9135 // memory allocation/deletion purpose only. 9136 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9137 MapType, 9138 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9139 MappableExprsHandler::OMP_MAP_FROM))); 9140 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9141 // data structure. 9142 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9143 MapperCGF.EmitRuntimeCall( 9144 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9145 } 9146 9147 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9148 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9149 llvm::Value *DeviceID, 9150 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9151 const OMPLoopDirective &D)> 9152 SizeEmitter) { 9153 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9154 const OMPExecutableDirective *TD = &D; 9155 // Get nested teams distribute kind directive, if any. 9156 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9157 TD = getNestedDistributeDirective(CGM.getContext(), D); 9158 if (!TD) 9159 return; 9160 const auto *LD = cast<OMPLoopDirective>(TD); 9161 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9162 PrePostActionTy &) { 9163 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9164 llvm::Value *Args[] = {DeviceID, NumIterations}; 9165 CGF.EmitRuntimeCall( 9166 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9167 } 9168 }; 9169 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9170 } 9171 9172 void CGOpenMPRuntime::emitTargetCall( 9173 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9174 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9175 const Expr *Device, 9176 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9177 const OMPLoopDirective &D)> 9178 SizeEmitter) { 9179 if (!CGF.HaveInsertPoint()) 9180 return; 9181 9182 assert(OutlinedFn && "Invalid outlined function!"); 9183 9184 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9185 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9186 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9187 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9188 PrePostActionTy &) { 9189 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9190 }; 9191 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9192 9193 CodeGenFunction::OMPTargetDataInfo InputInfo; 9194 llvm::Value *MapTypesArray = nullptr; 9195 // Fill up the pointer arrays and transfer execution to the device. 9196 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9197 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9198 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9199 // On top of the arrays that were filled up, the target offloading call 9200 // takes as arguments the device id as well as the host pointer. The host 9201 // pointer is used by the runtime library to identify the current target 9202 // region, so it only has to be unique and not necessarily point to 9203 // anything. It could be the pointer to the outlined function that 9204 // implements the target region, but we aren't using that so that the 9205 // compiler doesn't need to keep that, and could therefore inline the host 9206 // function if proven worthwhile during optimization. 9207 9208 // From this point on, we need to have an ID of the target region defined. 9209 assert(OutlinedFnID && "Invalid outlined function ID!"); 9210 9211 // Emit device ID if any. 9212 llvm::Value *DeviceID; 9213 if (Device) { 9214 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9215 CGF.Int64Ty, /*isSigned=*/true); 9216 } else { 9217 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9218 } 9219 9220 // Emit the number of elements in the offloading arrays. 9221 llvm::Value *PointerNum = 9222 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9223 9224 // Return value of the runtime offloading call. 9225 llvm::Value *Return; 9226 9227 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9228 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9229 9230 // Emit tripcount for the target loop-based directive. 9231 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9232 9233 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9234 // The target region is an outlined function launched by the runtime 9235 // via calls __tgt_target() or __tgt_target_teams(). 9236 // 9237 // __tgt_target() launches a target region with one team and one thread, 9238 // executing a serial region. This master thread may in turn launch 9239 // more threads within its team upon encountering a parallel region, 9240 // however, no additional teams can be launched on the device. 9241 // 9242 // __tgt_target_teams() launches a target region with one or more teams, 9243 // each with one or more threads. This call is required for target 9244 // constructs such as: 9245 // 'target teams' 9246 // 'target' / 'teams' 9247 // 'target teams distribute parallel for' 9248 // 'target parallel' 9249 // and so on. 9250 // 9251 // Note that on the host and CPU targets, the runtime implementation of 9252 // these calls simply call the outlined function without forking threads. 9253 // The outlined functions themselves have runtime calls to 9254 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9255 // the compiler in emitTeamsCall() and emitParallelCall(). 9256 // 9257 // In contrast, on the NVPTX target, the implementation of 9258 // __tgt_target_teams() launches a GPU kernel with the requested number 9259 // of teams and threads so no additional calls to the runtime are required. 9260 if (NumTeams) { 9261 // If we have NumTeams defined this means that we have an enclosed teams 9262 // region. Therefore we also expect to have NumThreads defined. These two 9263 // values should be defined in the presence of a teams directive, 9264 // regardless of having any clauses associated. If the user is using teams 9265 // but no clauses, these two values will be the default that should be 9266 // passed to the runtime library - a 32-bit integer with the value zero. 9267 assert(NumThreads && "Thread limit expression should be available along " 9268 "with number of teams."); 9269 llvm::Value *OffloadingArgs[] = {DeviceID, 9270 OutlinedFnID, 9271 PointerNum, 9272 InputInfo.BasePointersArray.getPointer(), 9273 InputInfo.PointersArray.getPointer(), 9274 InputInfo.SizesArray.getPointer(), 9275 MapTypesArray, 9276 NumTeams, 9277 NumThreads}; 9278 Return = CGF.EmitRuntimeCall( 9279 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9280 : OMPRTL__tgt_target_teams), 9281 OffloadingArgs); 9282 } else { 9283 llvm::Value *OffloadingArgs[] = {DeviceID, 9284 OutlinedFnID, 9285 PointerNum, 9286 InputInfo.BasePointersArray.getPointer(), 9287 InputInfo.PointersArray.getPointer(), 9288 InputInfo.SizesArray.getPointer(), 9289 MapTypesArray}; 9290 Return = CGF.EmitRuntimeCall( 9291 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9292 : OMPRTL__tgt_target), 9293 OffloadingArgs); 9294 } 9295 9296 // Check the error code and execute the host version if required. 9297 llvm::BasicBlock *OffloadFailedBlock = 9298 CGF.createBasicBlock("omp_offload.failed"); 9299 llvm::BasicBlock *OffloadContBlock = 9300 CGF.createBasicBlock("omp_offload.cont"); 9301 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9302 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9303 9304 CGF.EmitBlock(OffloadFailedBlock); 9305 if (RequiresOuterTask) { 9306 CapturedVars.clear(); 9307 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9308 } 9309 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9310 CGF.EmitBranch(OffloadContBlock); 9311 9312 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9313 }; 9314 9315 // Notify that the host version must be executed. 9316 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9317 RequiresOuterTask](CodeGenFunction &CGF, 9318 PrePostActionTy &) { 9319 if (RequiresOuterTask) { 9320 CapturedVars.clear(); 9321 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9322 } 9323 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9324 }; 9325 9326 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9327 &CapturedVars, RequiresOuterTask, 9328 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9329 // Fill up the arrays with all the captured variables. 9330 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9331 MappableExprsHandler::MapValuesArrayTy Pointers; 9332 MappableExprsHandler::MapValuesArrayTy Sizes; 9333 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9334 9335 // Get mappable expression information. 9336 MappableExprsHandler MEHandler(D, CGF); 9337 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9338 9339 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9340 auto CV = CapturedVars.begin(); 9341 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9342 CE = CS.capture_end(); 9343 CI != CE; ++CI, ++RI, ++CV) { 9344 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9345 MappableExprsHandler::MapValuesArrayTy CurPointers; 9346 MappableExprsHandler::MapValuesArrayTy CurSizes; 9347 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9348 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9349 9350 // VLA sizes are passed to the outlined region by copy and do not have map 9351 // information associated. 9352 if (CI->capturesVariableArrayType()) { 9353 CurBasePointers.push_back(*CV); 9354 CurPointers.push_back(*CV); 9355 CurSizes.push_back(CGF.Builder.CreateIntCast( 9356 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9357 // Copy to the device as an argument. No need to retrieve it. 9358 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9359 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9360 MappableExprsHandler::OMP_MAP_IMPLICIT); 9361 } else { 9362 // If we have any information in the map clause, we use it, otherwise we 9363 // just do a default mapping. 9364 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9365 CurSizes, CurMapTypes, PartialStruct); 9366 if (CurBasePointers.empty()) 9367 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9368 CurPointers, CurSizes, CurMapTypes); 9369 // Generate correct mapping for variables captured by reference in 9370 // lambdas. 9371 if (CI->capturesVariable()) 9372 MEHandler.generateInfoForLambdaCaptures( 9373 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9374 CurMapTypes, LambdaPointers); 9375 } 9376 // We expect to have at least an element of information for this capture. 9377 assert(!CurBasePointers.empty() && 9378 "Non-existing map pointer for capture!"); 9379 assert(CurBasePointers.size() == CurPointers.size() && 9380 CurBasePointers.size() == CurSizes.size() && 9381 CurBasePointers.size() == CurMapTypes.size() && 9382 "Inconsistent map information sizes!"); 9383 9384 // If there is an entry in PartialStruct it means we have a struct with 9385 // individual members mapped. Emit an extra combined entry. 9386 if (PartialStruct.Base.isValid()) 9387 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9388 CurMapTypes, PartialStruct); 9389 9390 // We need to append the results of this capture to what we already have. 9391 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9392 Pointers.append(CurPointers.begin(), CurPointers.end()); 9393 Sizes.append(CurSizes.begin(), CurSizes.end()); 9394 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9395 } 9396 // Adjust MEMBER_OF flags for the lambdas captures. 9397 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9398 Pointers, MapTypes); 9399 // Map other list items in the map clause which are not captured variables 9400 // but "declare target link" global variables. 9401 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9402 MapTypes); 9403 9404 TargetDataInfo Info; 9405 // Fill up the arrays and create the arguments. 9406 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9407 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9408 Info.PointersArray, Info.SizesArray, 9409 Info.MapTypesArray, Info); 9410 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9411 InputInfo.BasePointersArray = 9412 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9413 InputInfo.PointersArray = 9414 Address(Info.PointersArray, CGM.getPointerAlign()); 9415 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9416 MapTypesArray = Info.MapTypesArray; 9417 if (RequiresOuterTask) 9418 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9419 else 9420 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9421 }; 9422 9423 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9424 CodeGenFunction &CGF, PrePostActionTy &) { 9425 if (RequiresOuterTask) { 9426 CodeGenFunction::OMPTargetDataInfo InputInfo; 9427 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9428 } else { 9429 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9430 } 9431 }; 9432 9433 // If we have a target function ID it means that we need to support 9434 // offloading, otherwise, just execute on the host. We need to execute on host 9435 // regardless of the conditional in the if clause if, e.g., the user do not 9436 // specify target triples. 9437 if (OutlinedFnID) { 9438 if (IfCond) { 9439 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9440 } else { 9441 RegionCodeGenTy ThenRCG(TargetThenGen); 9442 ThenRCG(CGF); 9443 } 9444 } else { 9445 RegionCodeGenTy ElseRCG(TargetElseGen); 9446 ElseRCG(CGF); 9447 } 9448 } 9449 9450 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9451 StringRef ParentName) { 9452 if (!S) 9453 return; 9454 9455 // Codegen OMP target directives that offload compute to the device. 9456 bool RequiresDeviceCodegen = 9457 isa<OMPExecutableDirective>(S) && 9458 isOpenMPTargetExecutionDirective( 9459 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9460 9461 if (RequiresDeviceCodegen) { 9462 const auto &E = *cast<OMPExecutableDirective>(S); 9463 unsigned DeviceID; 9464 unsigned FileID; 9465 unsigned Line; 9466 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9467 FileID, Line); 9468 9469 // Is this a target region that should not be emitted as an entry point? If 9470 // so just signal we are done with this target region. 9471 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9472 ParentName, Line)) 9473 return; 9474 9475 switch (E.getDirectiveKind()) { 9476 case OMPD_target: 9477 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9478 cast<OMPTargetDirective>(E)); 9479 break; 9480 case OMPD_target_parallel: 9481 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9482 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9483 break; 9484 case OMPD_target_teams: 9485 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9486 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9487 break; 9488 case OMPD_target_teams_distribute: 9489 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9490 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9491 break; 9492 case OMPD_target_teams_distribute_simd: 9493 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9494 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9495 break; 9496 case OMPD_target_parallel_for: 9497 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9498 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9499 break; 9500 case OMPD_target_parallel_for_simd: 9501 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9502 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9503 break; 9504 case OMPD_target_simd: 9505 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9506 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9507 break; 9508 case OMPD_target_teams_distribute_parallel_for: 9509 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9510 CGM, ParentName, 9511 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9512 break; 9513 case OMPD_target_teams_distribute_parallel_for_simd: 9514 CodeGenFunction:: 9515 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9516 CGM, ParentName, 9517 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9518 break; 9519 case OMPD_parallel: 9520 case OMPD_for: 9521 case OMPD_parallel_for: 9522 case OMPD_parallel_master: 9523 case OMPD_parallel_sections: 9524 case OMPD_for_simd: 9525 case OMPD_parallel_for_simd: 9526 case OMPD_cancel: 9527 case OMPD_cancellation_point: 9528 case OMPD_ordered: 9529 case OMPD_threadprivate: 9530 case OMPD_allocate: 9531 case OMPD_task: 9532 case OMPD_simd: 9533 case OMPD_sections: 9534 case OMPD_section: 9535 case OMPD_single: 9536 case OMPD_master: 9537 case OMPD_critical: 9538 case OMPD_taskyield: 9539 case OMPD_barrier: 9540 case OMPD_taskwait: 9541 case OMPD_taskgroup: 9542 case OMPD_atomic: 9543 case OMPD_flush: 9544 case OMPD_teams: 9545 case OMPD_target_data: 9546 case OMPD_target_exit_data: 9547 case OMPD_target_enter_data: 9548 case OMPD_distribute: 9549 case OMPD_distribute_simd: 9550 case OMPD_distribute_parallel_for: 9551 case OMPD_distribute_parallel_for_simd: 9552 case OMPD_teams_distribute: 9553 case OMPD_teams_distribute_simd: 9554 case OMPD_teams_distribute_parallel_for: 9555 case OMPD_teams_distribute_parallel_for_simd: 9556 case OMPD_target_update: 9557 case OMPD_declare_simd: 9558 case OMPD_declare_variant: 9559 case OMPD_declare_target: 9560 case OMPD_end_declare_target: 9561 case OMPD_declare_reduction: 9562 case OMPD_declare_mapper: 9563 case OMPD_taskloop: 9564 case OMPD_taskloop_simd: 9565 case OMPD_master_taskloop: 9566 case OMPD_master_taskloop_simd: 9567 case OMPD_parallel_master_taskloop: 9568 case OMPD_parallel_master_taskloop_simd: 9569 case OMPD_requires: 9570 case OMPD_unknown: 9571 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9572 } 9573 return; 9574 } 9575 9576 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9577 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9578 return; 9579 9580 scanForTargetRegionsFunctions( 9581 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9582 return; 9583 } 9584 9585 // If this is a lambda function, look into its body. 9586 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9587 S = L->getBody(); 9588 9589 // Keep looking for target regions recursively. 9590 for (const Stmt *II : S->children()) 9591 scanForTargetRegionsFunctions(II, ParentName); 9592 } 9593 9594 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9595 // If emitting code for the host, we do not process FD here. Instead we do 9596 // the normal code generation. 9597 if (!CGM.getLangOpts().OpenMPIsDevice) { 9598 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9599 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9600 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9601 // Do not emit device_type(nohost) functions for the host. 9602 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9603 return true; 9604 } 9605 return false; 9606 } 9607 9608 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9609 // Try to detect target regions in the function. 9610 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9611 StringRef Name = CGM.getMangledName(GD); 9612 scanForTargetRegionsFunctions(FD->getBody(), Name); 9613 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9614 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9615 // Do not emit device_type(nohost) functions for the host. 9616 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9617 return true; 9618 } 9619 9620 // Do not to emit function if it is not marked as declare target. 9621 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9622 AlreadyEmittedTargetDecls.count(VD) == 0; 9623 } 9624 9625 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9626 if (!CGM.getLangOpts().OpenMPIsDevice) 9627 return false; 9628 9629 // Check if there are Ctors/Dtors in this declaration and look for target 9630 // regions in it. We use the complete variant to produce the kernel name 9631 // mangling. 9632 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9633 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9634 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9635 StringRef ParentName = 9636 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9637 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9638 } 9639 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9640 StringRef ParentName = 9641 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9642 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9643 } 9644 } 9645 9646 // Do not to emit variable if it is not marked as declare target. 9647 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9648 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9649 cast<VarDecl>(GD.getDecl())); 9650 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9651 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9652 HasRequiresUnifiedSharedMemory)) { 9653 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9654 return true; 9655 } 9656 return false; 9657 } 9658 9659 llvm::Constant * 9660 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9661 const VarDecl *VD) { 9662 assert(VD->getType().isConstant(CGM.getContext()) && 9663 "Expected constant variable."); 9664 StringRef VarName; 9665 llvm::Constant *Addr; 9666 llvm::GlobalValue::LinkageTypes Linkage; 9667 QualType Ty = VD->getType(); 9668 SmallString<128> Buffer; 9669 { 9670 unsigned DeviceID; 9671 unsigned FileID; 9672 unsigned Line; 9673 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9674 FileID, Line); 9675 llvm::raw_svector_ostream OS(Buffer); 9676 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9677 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9678 VarName = OS.str(); 9679 } 9680 Linkage = llvm::GlobalValue::InternalLinkage; 9681 Addr = 9682 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9683 getDefaultFirstprivateAddressSpace()); 9684 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9685 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9686 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9687 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9688 VarName, Addr, VarSize, 9689 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9690 return Addr; 9691 } 9692 9693 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9694 llvm::Constant *Addr) { 9695 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9696 !CGM.getLangOpts().OpenMPIsDevice) 9697 return; 9698 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9699 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9700 if (!Res) { 9701 if (CGM.getLangOpts().OpenMPIsDevice) { 9702 // Register non-target variables being emitted in device code (debug info 9703 // may cause this). 9704 StringRef VarName = CGM.getMangledName(VD); 9705 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9706 } 9707 return; 9708 } 9709 // Register declare target variables. 9710 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9711 StringRef VarName; 9712 CharUnits VarSize; 9713 llvm::GlobalValue::LinkageTypes Linkage; 9714 9715 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9716 !HasRequiresUnifiedSharedMemory) { 9717 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9718 VarName = CGM.getMangledName(VD); 9719 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9720 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9721 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9722 } else { 9723 VarSize = CharUnits::Zero(); 9724 } 9725 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9726 // Temp solution to prevent optimizations of the internal variables. 9727 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9728 std::string RefName = getName({VarName, "ref"}); 9729 if (!CGM.GetGlobalValue(RefName)) { 9730 llvm::Constant *AddrRef = 9731 getOrCreateInternalVariable(Addr->getType(), RefName); 9732 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9733 GVAddrRef->setConstant(/*Val=*/true); 9734 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9735 GVAddrRef->setInitializer(Addr); 9736 CGM.addCompilerUsedGlobal(GVAddrRef); 9737 } 9738 } 9739 } else { 9740 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9741 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9742 HasRequiresUnifiedSharedMemory)) && 9743 "Declare target attribute must link or to with unified memory."); 9744 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9745 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9746 else 9747 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9748 9749 if (CGM.getLangOpts().OpenMPIsDevice) { 9750 VarName = Addr->getName(); 9751 Addr = nullptr; 9752 } else { 9753 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9754 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9755 } 9756 VarSize = CGM.getPointerSize(); 9757 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9758 } 9759 9760 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9761 VarName, Addr, VarSize, Flags, Linkage); 9762 } 9763 9764 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9765 if (isa<FunctionDecl>(GD.getDecl()) || 9766 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9767 return emitTargetFunctions(GD); 9768 9769 return emitTargetGlobalVariable(GD); 9770 } 9771 9772 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9773 for (const VarDecl *VD : DeferredGlobalVariables) { 9774 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9775 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9776 if (!Res) 9777 continue; 9778 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9779 !HasRequiresUnifiedSharedMemory) { 9780 CGM.EmitGlobal(VD); 9781 } else { 9782 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 9783 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9784 HasRequiresUnifiedSharedMemory)) && 9785 "Expected link clause or to clause with unified memory."); 9786 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 9787 } 9788 } 9789 } 9790 9791 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9792 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9793 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9794 " Expected target-based directive."); 9795 } 9796 9797 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 9798 for (const OMPClause *Clause : D->clauselists()) { 9799 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9800 HasRequiresUnifiedSharedMemory = true; 9801 } else if (const auto *AC = 9802 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 9803 switch (AC->getAtomicDefaultMemOrderKind()) { 9804 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 9805 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 9806 break; 9807 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 9808 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 9809 break; 9810 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 9811 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 9812 break; 9813 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 9814 break; 9815 } 9816 } 9817 } 9818 } 9819 9820 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 9821 return RequiresAtomicOrdering; 9822 } 9823 9824 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9825 LangAS &AS) { 9826 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9827 return false; 9828 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9829 switch(A->getAllocatorType()) { 9830 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9831 // Not supported, fallback to the default mem space. 9832 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9833 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9834 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9835 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9836 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9837 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9838 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9839 AS = LangAS::Default; 9840 return true; 9841 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9842 llvm_unreachable("Expected predefined allocator for the variables with the " 9843 "static storage."); 9844 } 9845 return false; 9846 } 9847 9848 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9849 return HasRequiresUnifiedSharedMemory; 9850 } 9851 9852 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9853 CodeGenModule &CGM) 9854 : CGM(CGM) { 9855 if (CGM.getLangOpts().OpenMPIsDevice) { 9856 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9857 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9858 } 9859 } 9860 9861 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9862 if (CGM.getLangOpts().OpenMPIsDevice) 9863 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9864 } 9865 9866 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9867 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9868 return true; 9869 9870 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9871 // Do not to emit function if it is marked as declare target as it was already 9872 // emitted. 9873 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9874 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 9875 if (auto *F = dyn_cast_or_null<llvm::Function>( 9876 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 9877 return !F->isDeclaration(); 9878 return false; 9879 } 9880 return true; 9881 } 9882 9883 return !AlreadyEmittedTargetDecls.insert(D).second; 9884 } 9885 9886 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9887 // If we don't have entries or if we are emitting code for the device, we 9888 // don't need to do anything. 9889 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9890 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9891 (OffloadEntriesInfoManager.empty() && 9892 !HasEmittedDeclareTargetRegion && 9893 !HasEmittedTargetRegion)) 9894 return nullptr; 9895 9896 // Create and register the function that handles the requires directives. 9897 ASTContext &C = CGM.getContext(); 9898 9899 llvm::Function *RequiresRegFn; 9900 { 9901 CodeGenFunction CGF(CGM); 9902 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 9903 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 9904 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 9905 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 9906 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 9907 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 9908 // TODO: check for other requires clauses. 9909 // The requires directive takes effect only when a target region is 9910 // present in the compilation unit. Otherwise it is ignored and not 9911 // passed to the runtime. This avoids the runtime from throwing an error 9912 // for mismatching requires clauses across compilation units that don't 9913 // contain at least 1 target region. 9914 assert((HasEmittedTargetRegion || 9915 HasEmittedDeclareTargetRegion || 9916 !OffloadEntriesInfoManager.empty()) && 9917 "Target or declare target region expected."); 9918 if (HasRequiresUnifiedSharedMemory) 9919 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 9920 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 9921 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 9922 CGF.FinishFunction(); 9923 } 9924 return RequiresRegFn; 9925 } 9926 9927 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 9928 const OMPExecutableDirective &D, 9929 SourceLocation Loc, 9930 llvm::Function *OutlinedFn, 9931 ArrayRef<llvm::Value *> CapturedVars) { 9932 if (!CGF.HaveInsertPoint()) 9933 return; 9934 9935 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9936 CodeGenFunction::RunCleanupsScope Scope(CGF); 9937 9938 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 9939 llvm::Value *Args[] = { 9940 RTLoc, 9941 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 9942 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 9943 llvm::SmallVector<llvm::Value *, 16> RealArgs; 9944 RealArgs.append(std::begin(Args), std::end(Args)); 9945 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 9946 9947 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 9948 CGF.EmitRuntimeCall(RTLFn, RealArgs); 9949 } 9950 9951 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 9952 const Expr *NumTeams, 9953 const Expr *ThreadLimit, 9954 SourceLocation Loc) { 9955 if (!CGF.HaveInsertPoint()) 9956 return; 9957 9958 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9959 9960 llvm::Value *NumTeamsVal = 9961 NumTeams 9962 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 9963 CGF.CGM.Int32Ty, /* isSigned = */ true) 9964 : CGF.Builder.getInt32(0); 9965 9966 llvm::Value *ThreadLimitVal = 9967 ThreadLimit 9968 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 9969 CGF.CGM.Int32Ty, /* isSigned = */ true) 9970 : CGF.Builder.getInt32(0); 9971 9972 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 9973 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 9974 ThreadLimitVal}; 9975 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 9976 PushNumTeamsArgs); 9977 } 9978 9979 void CGOpenMPRuntime::emitTargetDataCalls( 9980 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 9981 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 9982 if (!CGF.HaveInsertPoint()) 9983 return; 9984 9985 // Action used to replace the default codegen action and turn privatization 9986 // off. 9987 PrePostActionTy NoPrivAction; 9988 9989 // Generate the code for the opening of the data environment. Capture all the 9990 // arguments of the runtime call by reference because they are used in the 9991 // closing of the region. 9992 auto &&BeginThenGen = [this, &D, Device, &Info, 9993 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 9994 // Fill up the arrays with all the mapped variables. 9995 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9996 MappableExprsHandler::MapValuesArrayTy Pointers; 9997 MappableExprsHandler::MapValuesArrayTy Sizes; 9998 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9999 10000 // Get map clause information. 10001 MappableExprsHandler MCHandler(D, CGF); 10002 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10003 10004 // Fill up the arrays and create the arguments. 10005 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10006 10007 llvm::Value *BasePointersArrayArg = nullptr; 10008 llvm::Value *PointersArrayArg = nullptr; 10009 llvm::Value *SizesArrayArg = nullptr; 10010 llvm::Value *MapTypesArrayArg = nullptr; 10011 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10012 SizesArrayArg, MapTypesArrayArg, Info); 10013 10014 // Emit device ID if any. 10015 llvm::Value *DeviceID = nullptr; 10016 if (Device) { 10017 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10018 CGF.Int64Ty, /*isSigned=*/true); 10019 } else { 10020 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10021 } 10022 10023 // Emit the number of elements in the offloading arrays. 10024 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10025 10026 llvm::Value *OffloadingArgs[] = { 10027 DeviceID, PointerNum, BasePointersArrayArg, 10028 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10029 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 10030 OffloadingArgs); 10031 10032 // If device pointer privatization is required, emit the body of the region 10033 // here. It will have to be duplicated: with and without privatization. 10034 if (!Info.CaptureDeviceAddrMap.empty()) 10035 CodeGen(CGF); 10036 }; 10037 10038 // Generate code for the closing of the data region. 10039 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10040 PrePostActionTy &) { 10041 assert(Info.isValid() && "Invalid data environment closing arguments."); 10042 10043 llvm::Value *BasePointersArrayArg = nullptr; 10044 llvm::Value *PointersArrayArg = nullptr; 10045 llvm::Value *SizesArrayArg = nullptr; 10046 llvm::Value *MapTypesArrayArg = nullptr; 10047 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10048 SizesArrayArg, MapTypesArrayArg, Info); 10049 10050 // Emit device ID if any. 10051 llvm::Value *DeviceID = nullptr; 10052 if (Device) { 10053 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10054 CGF.Int64Ty, /*isSigned=*/true); 10055 } else { 10056 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10057 } 10058 10059 // Emit the number of elements in the offloading arrays. 10060 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10061 10062 llvm::Value *OffloadingArgs[] = { 10063 DeviceID, PointerNum, BasePointersArrayArg, 10064 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10065 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10066 OffloadingArgs); 10067 }; 10068 10069 // If we need device pointer privatization, we need to emit the body of the 10070 // region with no privatization in the 'else' branch of the conditional. 10071 // Otherwise, we don't have to do anything. 10072 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10073 PrePostActionTy &) { 10074 if (!Info.CaptureDeviceAddrMap.empty()) { 10075 CodeGen.setAction(NoPrivAction); 10076 CodeGen(CGF); 10077 } 10078 }; 10079 10080 // We don't have to do anything to close the region if the if clause evaluates 10081 // to false. 10082 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10083 10084 if (IfCond) { 10085 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10086 } else { 10087 RegionCodeGenTy RCG(BeginThenGen); 10088 RCG(CGF); 10089 } 10090 10091 // If we don't require privatization of device pointers, we emit the body in 10092 // between the runtime calls. This avoids duplicating the body code. 10093 if (Info.CaptureDeviceAddrMap.empty()) { 10094 CodeGen.setAction(NoPrivAction); 10095 CodeGen(CGF); 10096 } 10097 10098 if (IfCond) { 10099 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10100 } else { 10101 RegionCodeGenTy RCG(EndThenGen); 10102 RCG(CGF); 10103 } 10104 } 10105 10106 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10107 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10108 const Expr *Device) { 10109 if (!CGF.HaveInsertPoint()) 10110 return; 10111 10112 assert((isa<OMPTargetEnterDataDirective>(D) || 10113 isa<OMPTargetExitDataDirective>(D) || 10114 isa<OMPTargetUpdateDirective>(D)) && 10115 "Expecting either target enter, exit data, or update directives."); 10116 10117 CodeGenFunction::OMPTargetDataInfo InputInfo; 10118 llvm::Value *MapTypesArray = nullptr; 10119 // Generate the code for the opening of the data environment. 10120 auto &&ThenGen = [this, &D, Device, &InputInfo, 10121 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10122 // Emit device ID if any. 10123 llvm::Value *DeviceID = nullptr; 10124 if (Device) { 10125 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10126 CGF.Int64Ty, /*isSigned=*/true); 10127 } else { 10128 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10129 } 10130 10131 // Emit the number of elements in the offloading arrays. 10132 llvm::Constant *PointerNum = 10133 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10134 10135 llvm::Value *OffloadingArgs[] = {DeviceID, 10136 PointerNum, 10137 InputInfo.BasePointersArray.getPointer(), 10138 InputInfo.PointersArray.getPointer(), 10139 InputInfo.SizesArray.getPointer(), 10140 MapTypesArray}; 10141 10142 // Select the right runtime function call for each expected standalone 10143 // directive. 10144 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10145 OpenMPRTLFunction RTLFn; 10146 switch (D.getDirectiveKind()) { 10147 case OMPD_target_enter_data: 10148 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10149 : OMPRTL__tgt_target_data_begin; 10150 break; 10151 case OMPD_target_exit_data: 10152 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10153 : OMPRTL__tgt_target_data_end; 10154 break; 10155 case OMPD_target_update: 10156 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10157 : OMPRTL__tgt_target_data_update; 10158 break; 10159 case OMPD_parallel: 10160 case OMPD_for: 10161 case OMPD_parallel_for: 10162 case OMPD_parallel_master: 10163 case OMPD_parallel_sections: 10164 case OMPD_for_simd: 10165 case OMPD_parallel_for_simd: 10166 case OMPD_cancel: 10167 case OMPD_cancellation_point: 10168 case OMPD_ordered: 10169 case OMPD_threadprivate: 10170 case OMPD_allocate: 10171 case OMPD_task: 10172 case OMPD_simd: 10173 case OMPD_sections: 10174 case OMPD_section: 10175 case OMPD_single: 10176 case OMPD_master: 10177 case OMPD_critical: 10178 case OMPD_taskyield: 10179 case OMPD_barrier: 10180 case OMPD_taskwait: 10181 case OMPD_taskgroup: 10182 case OMPD_atomic: 10183 case OMPD_flush: 10184 case OMPD_teams: 10185 case OMPD_target_data: 10186 case OMPD_distribute: 10187 case OMPD_distribute_simd: 10188 case OMPD_distribute_parallel_for: 10189 case OMPD_distribute_parallel_for_simd: 10190 case OMPD_teams_distribute: 10191 case OMPD_teams_distribute_simd: 10192 case OMPD_teams_distribute_parallel_for: 10193 case OMPD_teams_distribute_parallel_for_simd: 10194 case OMPD_declare_simd: 10195 case OMPD_declare_variant: 10196 case OMPD_declare_target: 10197 case OMPD_end_declare_target: 10198 case OMPD_declare_reduction: 10199 case OMPD_declare_mapper: 10200 case OMPD_taskloop: 10201 case OMPD_taskloop_simd: 10202 case OMPD_master_taskloop: 10203 case OMPD_master_taskloop_simd: 10204 case OMPD_parallel_master_taskloop: 10205 case OMPD_parallel_master_taskloop_simd: 10206 case OMPD_target: 10207 case OMPD_target_simd: 10208 case OMPD_target_teams_distribute: 10209 case OMPD_target_teams_distribute_simd: 10210 case OMPD_target_teams_distribute_parallel_for: 10211 case OMPD_target_teams_distribute_parallel_for_simd: 10212 case OMPD_target_teams: 10213 case OMPD_target_parallel: 10214 case OMPD_target_parallel_for: 10215 case OMPD_target_parallel_for_simd: 10216 case OMPD_requires: 10217 case OMPD_unknown: 10218 llvm_unreachable("Unexpected standalone target data directive."); 10219 break; 10220 } 10221 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10222 }; 10223 10224 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10225 CodeGenFunction &CGF, PrePostActionTy &) { 10226 // Fill up the arrays with all the mapped variables. 10227 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10228 MappableExprsHandler::MapValuesArrayTy Pointers; 10229 MappableExprsHandler::MapValuesArrayTy Sizes; 10230 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10231 10232 // Get map clause information. 10233 MappableExprsHandler MEHandler(D, CGF); 10234 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10235 10236 TargetDataInfo Info; 10237 // Fill up the arrays and create the arguments. 10238 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10239 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10240 Info.PointersArray, Info.SizesArray, 10241 Info.MapTypesArray, Info); 10242 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10243 InputInfo.BasePointersArray = 10244 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10245 InputInfo.PointersArray = 10246 Address(Info.PointersArray, CGM.getPointerAlign()); 10247 InputInfo.SizesArray = 10248 Address(Info.SizesArray, CGM.getPointerAlign()); 10249 MapTypesArray = Info.MapTypesArray; 10250 if (D.hasClausesOfKind<OMPDependClause>()) 10251 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10252 else 10253 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10254 }; 10255 10256 if (IfCond) { 10257 emitIfClause(CGF, IfCond, TargetThenGen, 10258 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10259 } else { 10260 RegionCodeGenTy ThenRCG(TargetThenGen); 10261 ThenRCG(CGF); 10262 } 10263 } 10264 10265 namespace { 10266 /// Kind of parameter in a function with 'declare simd' directive. 10267 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10268 /// Attribute set of the parameter. 10269 struct ParamAttrTy { 10270 ParamKindTy Kind = Vector; 10271 llvm::APSInt StrideOrArg; 10272 llvm::APSInt Alignment; 10273 }; 10274 } // namespace 10275 10276 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10277 ArrayRef<ParamAttrTy> ParamAttrs) { 10278 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10279 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10280 // of that clause. The VLEN value must be power of 2. 10281 // In other case the notion of the function`s "characteristic data type" (CDT) 10282 // is used to compute the vector length. 10283 // CDT is defined in the following order: 10284 // a) For non-void function, the CDT is the return type. 10285 // b) If the function has any non-uniform, non-linear parameters, then the 10286 // CDT is the type of the first such parameter. 10287 // c) If the CDT determined by a) or b) above is struct, union, or class 10288 // type which is pass-by-value (except for the type that maps to the 10289 // built-in complex data type), the characteristic data type is int. 10290 // d) If none of the above three cases is applicable, the CDT is int. 10291 // The VLEN is then determined based on the CDT and the size of vector 10292 // register of that ISA for which current vector version is generated. The 10293 // VLEN is computed using the formula below: 10294 // VLEN = sizeof(vector_register) / sizeof(CDT), 10295 // where vector register size specified in section 3.2.1 Registers and the 10296 // Stack Frame of original AMD64 ABI document. 10297 QualType RetType = FD->getReturnType(); 10298 if (RetType.isNull()) 10299 return 0; 10300 ASTContext &C = FD->getASTContext(); 10301 QualType CDT; 10302 if (!RetType.isNull() && !RetType->isVoidType()) { 10303 CDT = RetType; 10304 } else { 10305 unsigned Offset = 0; 10306 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10307 if (ParamAttrs[Offset].Kind == Vector) 10308 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10309 ++Offset; 10310 } 10311 if (CDT.isNull()) { 10312 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10313 if (ParamAttrs[I + Offset].Kind == Vector) { 10314 CDT = FD->getParamDecl(I)->getType(); 10315 break; 10316 } 10317 } 10318 } 10319 } 10320 if (CDT.isNull()) 10321 CDT = C.IntTy; 10322 CDT = CDT->getCanonicalTypeUnqualified(); 10323 if (CDT->isRecordType() || CDT->isUnionType()) 10324 CDT = C.IntTy; 10325 return C.getTypeSize(CDT); 10326 } 10327 10328 static void 10329 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10330 const llvm::APSInt &VLENVal, 10331 ArrayRef<ParamAttrTy> ParamAttrs, 10332 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10333 struct ISADataTy { 10334 char ISA; 10335 unsigned VecRegSize; 10336 }; 10337 ISADataTy ISAData[] = { 10338 { 10339 'b', 128 10340 }, // SSE 10341 { 10342 'c', 256 10343 }, // AVX 10344 { 10345 'd', 256 10346 }, // AVX2 10347 { 10348 'e', 512 10349 }, // AVX512 10350 }; 10351 llvm::SmallVector<char, 2> Masked; 10352 switch (State) { 10353 case OMPDeclareSimdDeclAttr::BS_Undefined: 10354 Masked.push_back('N'); 10355 Masked.push_back('M'); 10356 break; 10357 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10358 Masked.push_back('N'); 10359 break; 10360 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10361 Masked.push_back('M'); 10362 break; 10363 } 10364 for (char Mask : Masked) { 10365 for (const ISADataTy &Data : ISAData) { 10366 SmallString<256> Buffer; 10367 llvm::raw_svector_ostream Out(Buffer); 10368 Out << "_ZGV" << Data.ISA << Mask; 10369 if (!VLENVal) { 10370 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10371 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10372 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10373 } else { 10374 Out << VLENVal; 10375 } 10376 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10377 switch (ParamAttr.Kind){ 10378 case LinearWithVarStride: 10379 Out << 's' << ParamAttr.StrideOrArg; 10380 break; 10381 case Linear: 10382 Out << 'l'; 10383 if (!!ParamAttr.StrideOrArg) 10384 Out << ParamAttr.StrideOrArg; 10385 break; 10386 case Uniform: 10387 Out << 'u'; 10388 break; 10389 case Vector: 10390 Out << 'v'; 10391 break; 10392 } 10393 if (!!ParamAttr.Alignment) 10394 Out << 'a' << ParamAttr.Alignment; 10395 } 10396 Out << '_' << Fn->getName(); 10397 Fn->addFnAttr(Out.str()); 10398 } 10399 } 10400 } 10401 10402 // This are the Functions that are needed to mangle the name of the 10403 // vector functions generated by the compiler, according to the rules 10404 // defined in the "Vector Function ABI specifications for AArch64", 10405 // available at 10406 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10407 10408 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10409 /// 10410 /// TODO: Need to implement the behavior for reference marked with a 10411 /// var or no linear modifiers (1.b in the section). For this, we 10412 /// need to extend ParamKindTy to support the linear modifiers. 10413 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10414 QT = QT.getCanonicalType(); 10415 10416 if (QT->isVoidType()) 10417 return false; 10418 10419 if (Kind == ParamKindTy::Uniform) 10420 return false; 10421 10422 if (Kind == ParamKindTy::Linear) 10423 return false; 10424 10425 // TODO: Handle linear references with modifiers 10426 10427 if (Kind == ParamKindTy::LinearWithVarStride) 10428 return false; 10429 10430 return true; 10431 } 10432 10433 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10434 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10435 QT = QT.getCanonicalType(); 10436 unsigned Size = C.getTypeSize(QT); 10437 10438 // Only scalars and complex within 16 bytes wide set PVB to true. 10439 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10440 return false; 10441 10442 if (QT->isFloatingType()) 10443 return true; 10444 10445 if (QT->isIntegerType()) 10446 return true; 10447 10448 if (QT->isPointerType()) 10449 return true; 10450 10451 // TODO: Add support for complex types (section 3.1.2, item 2). 10452 10453 return false; 10454 } 10455 10456 /// Computes the lane size (LS) of a return type or of an input parameter, 10457 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10458 /// TODO: Add support for references, section 3.2.1, item 1. 10459 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10460 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10461 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10462 if (getAArch64PBV(PTy, C)) 10463 return C.getTypeSize(PTy); 10464 } 10465 if (getAArch64PBV(QT, C)) 10466 return C.getTypeSize(QT); 10467 10468 return C.getTypeSize(C.getUIntPtrType()); 10469 } 10470 10471 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10472 // signature of the scalar function, as defined in 3.2.2 of the 10473 // AAVFABI. 10474 static std::tuple<unsigned, unsigned, bool> 10475 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10476 QualType RetType = FD->getReturnType().getCanonicalType(); 10477 10478 ASTContext &C = FD->getASTContext(); 10479 10480 bool OutputBecomesInput = false; 10481 10482 llvm::SmallVector<unsigned, 8> Sizes; 10483 if (!RetType->isVoidType()) { 10484 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10485 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10486 OutputBecomesInput = true; 10487 } 10488 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10489 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10490 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10491 } 10492 10493 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10494 // The LS of a function parameter / return value can only be a power 10495 // of 2, starting from 8 bits, up to 128. 10496 assert(std::all_of(Sizes.begin(), Sizes.end(), 10497 [](unsigned Size) { 10498 return Size == 8 || Size == 16 || Size == 32 || 10499 Size == 64 || Size == 128; 10500 }) && 10501 "Invalid size"); 10502 10503 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10504 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10505 OutputBecomesInput); 10506 } 10507 10508 /// Mangle the parameter part of the vector function name according to 10509 /// their OpenMP classification. The mangling function is defined in 10510 /// section 3.5 of the AAVFABI. 10511 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10512 SmallString<256> Buffer; 10513 llvm::raw_svector_ostream Out(Buffer); 10514 for (const auto &ParamAttr : ParamAttrs) { 10515 switch (ParamAttr.Kind) { 10516 case LinearWithVarStride: 10517 Out << "ls" << ParamAttr.StrideOrArg; 10518 break; 10519 case Linear: 10520 Out << 'l'; 10521 // Don't print the step value if it is not present or if it is 10522 // equal to 1. 10523 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10524 Out << ParamAttr.StrideOrArg; 10525 break; 10526 case Uniform: 10527 Out << 'u'; 10528 break; 10529 case Vector: 10530 Out << 'v'; 10531 break; 10532 } 10533 10534 if (!!ParamAttr.Alignment) 10535 Out << 'a' << ParamAttr.Alignment; 10536 } 10537 10538 return std::string(Out.str()); 10539 } 10540 10541 // Function used to add the attribute. The parameter `VLEN` is 10542 // templated to allow the use of "x" when targeting scalable functions 10543 // for SVE. 10544 template <typename T> 10545 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10546 char ISA, StringRef ParSeq, 10547 StringRef MangledName, bool OutputBecomesInput, 10548 llvm::Function *Fn) { 10549 SmallString<256> Buffer; 10550 llvm::raw_svector_ostream Out(Buffer); 10551 Out << Prefix << ISA << LMask << VLEN; 10552 if (OutputBecomesInput) 10553 Out << "v"; 10554 Out << ParSeq << "_" << MangledName; 10555 Fn->addFnAttr(Out.str()); 10556 } 10557 10558 // Helper function to generate the Advanced SIMD names depending on 10559 // the value of the NDS when simdlen is not present. 10560 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10561 StringRef Prefix, char ISA, 10562 StringRef ParSeq, StringRef MangledName, 10563 bool OutputBecomesInput, 10564 llvm::Function *Fn) { 10565 switch (NDS) { 10566 case 8: 10567 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10568 OutputBecomesInput, Fn); 10569 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10570 OutputBecomesInput, Fn); 10571 break; 10572 case 16: 10573 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10574 OutputBecomesInput, Fn); 10575 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10576 OutputBecomesInput, Fn); 10577 break; 10578 case 32: 10579 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10580 OutputBecomesInput, Fn); 10581 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10582 OutputBecomesInput, Fn); 10583 break; 10584 case 64: 10585 case 128: 10586 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10587 OutputBecomesInput, Fn); 10588 break; 10589 default: 10590 llvm_unreachable("Scalar type is too wide."); 10591 } 10592 } 10593 10594 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10595 static void emitAArch64DeclareSimdFunction( 10596 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10597 ArrayRef<ParamAttrTy> ParamAttrs, 10598 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10599 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10600 10601 // Get basic data for building the vector signature. 10602 const auto Data = getNDSWDS(FD, ParamAttrs); 10603 const unsigned NDS = std::get<0>(Data); 10604 const unsigned WDS = std::get<1>(Data); 10605 const bool OutputBecomesInput = std::get<2>(Data); 10606 10607 // Check the values provided via `simdlen` by the user. 10608 // 1. A `simdlen(1)` doesn't produce vector signatures, 10609 if (UserVLEN == 1) { 10610 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10611 DiagnosticsEngine::Warning, 10612 "The clause simdlen(1) has no effect when targeting aarch64."); 10613 CGM.getDiags().Report(SLoc, DiagID); 10614 return; 10615 } 10616 10617 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10618 // Advanced SIMD output. 10619 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10620 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10621 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10622 "power of 2 when targeting Advanced SIMD."); 10623 CGM.getDiags().Report(SLoc, DiagID); 10624 return; 10625 } 10626 10627 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10628 // limits. 10629 if (ISA == 's' && UserVLEN != 0) { 10630 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10631 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10632 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10633 "lanes in the architectural constraints " 10634 "for SVE (min is 128-bit, max is " 10635 "2048-bit, by steps of 128-bit)"); 10636 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10637 return; 10638 } 10639 } 10640 10641 // Sort out parameter sequence. 10642 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10643 StringRef Prefix = "_ZGV"; 10644 // Generate simdlen from user input (if any). 10645 if (UserVLEN) { 10646 if (ISA == 's') { 10647 // SVE generates only a masked function. 10648 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10649 OutputBecomesInput, Fn); 10650 } else { 10651 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10652 // Advanced SIMD generates one or two functions, depending on 10653 // the `[not]inbranch` clause. 10654 switch (State) { 10655 case OMPDeclareSimdDeclAttr::BS_Undefined: 10656 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10657 OutputBecomesInput, Fn); 10658 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10659 OutputBecomesInput, Fn); 10660 break; 10661 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10662 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10663 OutputBecomesInput, Fn); 10664 break; 10665 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10666 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10667 OutputBecomesInput, Fn); 10668 break; 10669 } 10670 } 10671 } else { 10672 // If no user simdlen is provided, follow the AAVFABI rules for 10673 // generating the vector length. 10674 if (ISA == 's') { 10675 // SVE, section 3.4.1, item 1. 10676 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10677 OutputBecomesInput, Fn); 10678 } else { 10679 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10680 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10681 // two vector names depending on the use of the clause 10682 // `[not]inbranch`. 10683 switch (State) { 10684 case OMPDeclareSimdDeclAttr::BS_Undefined: 10685 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10686 OutputBecomesInput, Fn); 10687 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10688 OutputBecomesInput, Fn); 10689 break; 10690 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10691 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10692 OutputBecomesInput, Fn); 10693 break; 10694 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10695 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10696 OutputBecomesInput, Fn); 10697 break; 10698 } 10699 } 10700 } 10701 } 10702 10703 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10704 llvm::Function *Fn) { 10705 ASTContext &C = CGM.getContext(); 10706 FD = FD->getMostRecentDecl(); 10707 // Map params to their positions in function decl. 10708 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10709 if (isa<CXXMethodDecl>(FD)) 10710 ParamPositions.try_emplace(FD, 0); 10711 unsigned ParamPos = ParamPositions.size(); 10712 for (const ParmVarDecl *P : FD->parameters()) { 10713 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10714 ++ParamPos; 10715 } 10716 while (FD) { 10717 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10718 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10719 // Mark uniform parameters. 10720 for (const Expr *E : Attr->uniforms()) { 10721 E = E->IgnoreParenImpCasts(); 10722 unsigned Pos; 10723 if (isa<CXXThisExpr>(E)) { 10724 Pos = ParamPositions[FD]; 10725 } else { 10726 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10727 ->getCanonicalDecl(); 10728 Pos = ParamPositions[PVD]; 10729 } 10730 ParamAttrs[Pos].Kind = Uniform; 10731 } 10732 // Get alignment info. 10733 auto NI = Attr->alignments_begin(); 10734 for (const Expr *E : Attr->aligneds()) { 10735 E = E->IgnoreParenImpCasts(); 10736 unsigned Pos; 10737 QualType ParmTy; 10738 if (isa<CXXThisExpr>(E)) { 10739 Pos = ParamPositions[FD]; 10740 ParmTy = E->getType(); 10741 } else { 10742 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10743 ->getCanonicalDecl(); 10744 Pos = ParamPositions[PVD]; 10745 ParmTy = PVD->getType(); 10746 } 10747 ParamAttrs[Pos].Alignment = 10748 (*NI) 10749 ? (*NI)->EvaluateKnownConstInt(C) 10750 : llvm::APSInt::getUnsigned( 10751 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10752 .getQuantity()); 10753 ++NI; 10754 } 10755 // Mark linear parameters. 10756 auto SI = Attr->steps_begin(); 10757 auto MI = Attr->modifiers_begin(); 10758 for (const Expr *E : Attr->linears()) { 10759 E = E->IgnoreParenImpCasts(); 10760 unsigned Pos; 10761 if (isa<CXXThisExpr>(E)) { 10762 Pos = ParamPositions[FD]; 10763 } else { 10764 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10765 ->getCanonicalDecl(); 10766 Pos = ParamPositions[PVD]; 10767 } 10768 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10769 ParamAttr.Kind = Linear; 10770 if (*SI) { 10771 Expr::EvalResult Result; 10772 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10773 if (const auto *DRE = 10774 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10775 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10776 ParamAttr.Kind = LinearWithVarStride; 10777 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10778 ParamPositions[StridePVD->getCanonicalDecl()]); 10779 } 10780 } 10781 } else { 10782 ParamAttr.StrideOrArg = Result.Val.getInt(); 10783 } 10784 } 10785 ++SI; 10786 ++MI; 10787 } 10788 llvm::APSInt VLENVal; 10789 SourceLocation ExprLoc; 10790 const Expr *VLENExpr = Attr->getSimdlen(); 10791 if (VLENExpr) { 10792 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10793 ExprLoc = VLENExpr->getExprLoc(); 10794 } 10795 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10796 if (CGM.getTriple().isX86()) { 10797 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10798 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10799 unsigned VLEN = VLENVal.getExtValue(); 10800 StringRef MangledName = Fn->getName(); 10801 if (CGM.getTarget().hasFeature("sve")) 10802 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10803 MangledName, 's', 128, Fn, ExprLoc); 10804 if (CGM.getTarget().hasFeature("neon")) 10805 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10806 MangledName, 'n', 128, Fn, ExprLoc); 10807 } 10808 } 10809 FD = FD->getPreviousDecl(); 10810 } 10811 } 10812 10813 namespace { 10814 /// Cleanup action for doacross support. 10815 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10816 public: 10817 static const int DoacrossFinArgs = 2; 10818 10819 private: 10820 llvm::FunctionCallee RTLFn; 10821 llvm::Value *Args[DoacrossFinArgs]; 10822 10823 public: 10824 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10825 ArrayRef<llvm::Value *> CallArgs) 10826 : RTLFn(RTLFn) { 10827 assert(CallArgs.size() == DoacrossFinArgs); 10828 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10829 } 10830 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10831 if (!CGF.HaveInsertPoint()) 10832 return; 10833 CGF.EmitRuntimeCall(RTLFn, Args); 10834 } 10835 }; 10836 } // namespace 10837 10838 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10839 const OMPLoopDirective &D, 10840 ArrayRef<Expr *> NumIterations) { 10841 if (!CGF.HaveInsertPoint()) 10842 return; 10843 10844 ASTContext &C = CGM.getContext(); 10845 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10846 RecordDecl *RD; 10847 if (KmpDimTy.isNull()) { 10848 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10849 // kmp_int64 lo; // lower 10850 // kmp_int64 up; // upper 10851 // kmp_int64 st; // stride 10852 // }; 10853 RD = C.buildImplicitRecord("kmp_dim"); 10854 RD->startDefinition(); 10855 addFieldToRecordDecl(C, RD, Int64Ty); 10856 addFieldToRecordDecl(C, RD, Int64Ty); 10857 addFieldToRecordDecl(C, RD, Int64Ty); 10858 RD->completeDefinition(); 10859 KmpDimTy = C.getRecordType(RD); 10860 } else { 10861 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10862 } 10863 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10864 QualType ArrayTy = 10865 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 10866 10867 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10868 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10869 enum { LowerFD = 0, UpperFD, StrideFD }; 10870 // Fill dims with data. 10871 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10872 LValue DimsLVal = CGF.MakeAddrLValue( 10873 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10874 // dims.upper = num_iterations; 10875 LValue UpperLVal = CGF.EmitLValueForField( 10876 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10877 llvm::Value *NumIterVal = 10878 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 10879 D.getNumIterations()->getType(), Int64Ty, 10880 D.getNumIterations()->getExprLoc()); 10881 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10882 // dims.stride = 1; 10883 LValue StrideLVal = CGF.EmitLValueForField( 10884 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10885 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10886 StrideLVal); 10887 } 10888 10889 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10890 // kmp_int32 num_dims, struct kmp_dim * dims); 10891 llvm::Value *Args[] = { 10892 emitUpdateLocation(CGF, D.getBeginLoc()), 10893 getThreadID(CGF, D.getBeginLoc()), 10894 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 10895 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10896 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 10897 CGM.VoidPtrTy)}; 10898 10899 llvm::FunctionCallee RTLFn = 10900 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 10901 CGF.EmitRuntimeCall(RTLFn, Args); 10902 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 10903 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 10904 llvm::FunctionCallee FiniRTLFn = 10905 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 10906 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10907 llvm::makeArrayRef(FiniArgs)); 10908 } 10909 10910 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10911 const OMPDependClause *C) { 10912 QualType Int64Ty = 10913 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 10914 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 10915 QualType ArrayTy = CGM.getContext().getConstantArrayType( 10916 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 10917 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 10918 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 10919 const Expr *CounterVal = C->getLoopData(I); 10920 assert(CounterVal); 10921 llvm::Value *CntVal = CGF.EmitScalarConversion( 10922 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 10923 CounterVal->getExprLoc()); 10924 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 10925 /*Volatile=*/false, Int64Ty); 10926 } 10927 llvm::Value *Args[] = { 10928 emitUpdateLocation(CGF, C->getBeginLoc()), 10929 getThreadID(CGF, C->getBeginLoc()), 10930 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 10931 llvm::FunctionCallee RTLFn; 10932 if (C->getDependencyKind() == OMPC_DEPEND_source) { 10933 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 10934 } else { 10935 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 10936 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 10937 } 10938 CGF.EmitRuntimeCall(RTLFn, Args); 10939 } 10940 10941 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 10942 llvm::FunctionCallee Callee, 10943 ArrayRef<llvm::Value *> Args) const { 10944 assert(Loc.isValid() && "Outlined function call location must be valid."); 10945 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 10946 10947 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 10948 if (Fn->doesNotThrow()) { 10949 CGF.EmitNounwindRuntimeCall(Fn, Args); 10950 return; 10951 } 10952 } 10953 CGF.EmitRuntimeCall(Callee, Args); 10954 } 10955 10956 void CGOpenMPRuntime::emitOutlinedFunctionCall( 10957 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 10958 ArrayRef<llvm::Value *> Args) const { 10959 emitCall(CGF, Loc, OutlinedFn, Args); 10960 } 10961 10962 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 10963 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 10964 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 10965 HasEmittedDeclareTargetRegion = true; 10966 } 10967 10968 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 10969 const VarDecl *NativeParam, 10970 const VarDecl *TargetParam) const { 10971 return CGF.GetAddrOfLocalVar(NativeParam); 10972 } 10973 10974 namespace { 10975 /// Cleanup action for allocate support. 10976 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 10977 public: 10978 static const int CleanupArgs = 3; 10979 10980 private: 10981 llvm::FunctionCallee RTLFn; 10982 llvm::Value *Args[CleanupArgs]; 10983 10984 public: 10985 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 10986 ArrayRef<llvm::Value *> CallArgs) 10987 : RTLFn(RTLFn) { 10988 assert(CallArgs.size() == CleanupArgs && 10989 "Size of arguments does not match."); 10990 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10991 } 10992 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10993 if (!CGF.HaveInsertPoint()) 10994 return; 10995 CGF.EmitRuntimeCall(RTLFn, Args); 10996 } 10997 }; 10998 } // namespace 10999 11000 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 11001 const VarDecl *VD) { 11002 if (!VD) 11003 return Address::invalid(); 11004 const VarDecl *CVD = VD->getCanonicalDecl(); 11005 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 11006 return Address::invalid(); 11007 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 11008 // Use the default allocation. 11009 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 11010 !AA->getAllocator()) 11011 return Address::invalid(); 11012 llvm::Value *Size; 11013 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11014 if (CVD->getType()->isVariablyModifiedType()) { 11015 Size = CGF.getTypeSize(CVD->getType()); 11016 // Align the size: ((size + align - 1) / align) * align 11017 Size = CGF.Builder.CreateNUWAdd( 11018 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11019 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11020 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11021 } else { 11022 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 11023 Size = CGM.getSize(Sz.alignTo(Align)); 11024 } 11025 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11026 assert(AA->getAllocator() && 11027 "Expected allocator expression for non-default allocator."); 11028 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11029 // According to the standard, the original allocator type is a enum (integer). 11030 // Convert to pointer type, if required. 11031 if (Allocator->getType()->isIntegerTy()) 11032 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11033 else if (Allocator->getType()->isPointerTy()) 11034 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11035 CGM.VoidPtrTy); 11036 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11037 11038 llvm::Value *Addr = 11039 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11040 getName({CVD->getName(), ".void.addr"})); 11041 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11042 Allocator}; 11043 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11044 11045 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11046 llvm::makeArrayRef(FiniArgs)); 11047 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11048 Addr, 11049 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11050 getName({CVD->getName(), ".addr"})); 11051 return Address(Addr, Align); 11052 } 11053 11054 namespace { 11055 using OMPContextSelectorData = 11056 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>; 11057 using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>; 11058 } // anonymous namespace 11059 11060 /// Checks current context and returns true if it matches the context selector. 11061 template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx, 11062 typename... Arguments> 11063 static bool checkContext(const OMPContextSelectorData &Data, 11064 Arguments... Params) { 11065 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown && 11066 "Unknown context selector or context selector set."); 11067 return false; 11068 } 11069 11070 /// Checks for implementation={vendor(<vendor>)} context selector. 11071 /// \returns true iff <vendor>="llvm", false otherwise. 11072 template <> 11073 bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>( 11074 const OMPContextSelectorData &Data) { 11075 return llvm::all_of(Data.Names, 11076 [](StringRef S) { return !S.compare_lower("llvm"); }); 11077 } 11078 11079 /// Checks for device={kind(<kind>)} context selector. 11080 /// \returns true if <kind>="host" and compilation is for host. 11081 /// true if <kind>="nohost" and compilation is for device. 11082 /// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU. 11083 /// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN. 11084 /// false otherwise. 11085 template <> 11086 bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>( 11087 const OMPContextSelectorData &Data, CodeGenModule &CGM) { 11088 for (StringRef Name : Data.Names) { 11089 if (!Name.compare_lower("host")) { 11090 if (CGM.getLangOpts().OpenMPIsDevice) 11091 return false; 11092 continue; 11093 } 11094 if (!Name.compare_lower("nohost")) { 11095 if (!CGM.getLangOpts().OpenMPIsDevice) 11096 return false; 11097 continue; 11098 } 11099 switch (CGM.getTriple().getArch()) { 11100 case llvm::Triple::arm: 11101 case llvm::Triple::armeb: 11102 case llvm::Triple::aarch64: 11103 case llvm::Triple::aarch64_be: 11104 case llvm::Triple::aarch64_32: 11105 case llvm::Triple::ppc: 11106 case llvm::Triple::ppc64: 11107 case llvm::Triple::ppc64le: 11108 case llvm::Triple::x86: 11109 case llvm::Triple::x86_64: 11110 if (Name.compare_lower("cpu")) 11111 return false; 11112 break; 11113 case llvm::Triple::amdgcn: 11114 case llvm::Triple::nvptx: 11115 case llvm::Triple::nvptx64: 11116 if (Name.compare_lower("gpu")) 11117 return false; 11118 break; 11119 case llvm::Triple::UnknownArch: 11120 case llvm::Triple::arc: 11121 case llvm::Triple::avr: 11122 case llvm::Triple::bpfel: 11123 case llvm::Triple::bpfeb: 11124 case llvm::Triple::hexagon: 11125 case llvm::Triple::mips: 11126 case llvm::Triple::mipsel: 11127 case llvm::Triple::mips64: 11128 case llvm::Triple::mips64el: 11129 case llvm::Triple::msp430: 11130 case llvm::Triple::r600: 11131 case llvm::Triple::riscv32: 11132 case llvm::Triple::riscv64: 11133 case llvm::Triple::sparc: 11134 case llvm::Triple::sparcv9: 11135 case llvm::Triple::sparcel: 11136 case llvm::Triple::systemz: 11137 case llvm::Triple::tce: 11138 case llvm::Triple::tcele: 11139 case llvm::Triple::thumb: 11140 case llvm::Triple::thumbeb: 11141 case llvm::Triple::xcore: 11142 case llvm::Triple::le32: 11143 case llvm::Triple::le64: 11144 case llvm::Triple::amdil: 11145 case llvm::Triple::amdil64: 11146 case llvm::Triple::hsail: 11147 case llvm::Triple::hsail64: 11148 case llvm::Triple::spir: 11149 case llvm::Triple::spir64: 11150 case llvm::Triple::kalimba: 11151 case llvm::Triple::shave: 11152 case llvm::Triple::lanai: 11153 case llvm::Triple::wasm32: 11154 case llvm::Triple::wasm64: 11155 case llvm::Triple::renderscript32: 11156 case llvm::Triple::renderscript64: 11157 case llvm::Triple::ve: 11158 return false; 11159 } 11160 } 11161 return true; 11162 } 11163 11164 static bool matchesContext(CodeGenModule &CGM, 11165 const CompleteOMPContextSelectorData &ContextData) { 11166 for (const OMPContextSelectorData &Data : ContextData) { 11167 switch (Data.Ctx) { 11168 case OMP_CTX_vendor: 11169 assert(Data.CtxSet == OMP_CTX_SET_implementation && 11170 "Expected implementation context selector set."); 11171 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data)) 11172 return false; 11173 break; 11174 case OMP_CTX_kind: 11175 assert(Data.CtxSet == OMP_CTX_SET_device && 11176 "Expected device context selector set."); 11177 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data, 11178 CGM)) 11179 return false; 11180 break; 11181 case OMP_CTX_unknown: 11182 llvm_unreachable("Unknown context selector kind."); 11183 } 11184 } 11185 return true; 11186 } 11187 11188 static CompleteOMPContextSelectorData 11189 translateAttrToContextSelectorData(ASTContext &C, 11190 const OMPDeclareVariantAttr *A) { 11191 CompleteOMPContextSelectorData Data; 11192 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) { 11193 Data.emplace_back(); 11194 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>( 11195 *std::next(A->ctxSelectorSets_begin(), I)); 11196 auto Ctx = static_cast<OpenMPContextSelectorKind>( 11197 *std::next(A->ctxSelectors_begin(), I)); 11198 Data.back().CtxSet = CtxSet; 11199 Data.back().Ctx = Ctx; 11200 const Expr *Score = *std::next(A->scores_begin(), I); 11201 Data.back().Score = Score->EvaluateKnownConstInt(C); 11202 switch (Ctx) { 11203 case OMP_CTX_vendor: 11204 assert(CtxSet == OMP_CTX_SET_implementation && 11205 "Expected implementation context selector set."); 11206 Data.back().Names = 11207 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end()); 11208 break; 11209 case OMP_CTX_kind: 11210 assert(CtxSet == OMP_CTX_SET_device && 11211 "Expected device context selector set."); 11212 Data.back().Names = 11213 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end()); 11214 break; 11215 case OMP_CTX_unknown: 11216 llvm_unreachable("Unknown context selector kind."); 11217 } 11218 } 11219 return Data; 11220 } 11221 11222 static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS, 11223 const CompleteOMPContextSelectorData &RHS) { 11224 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData; 11225 for (const OMPContextSelectorData &D : RHS) { 11226 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx)); 11227 Pair.getSecond().insert(D.Names.begin(), D.Names.end()); 11228 } 11229 bool AllSetsAreEqual = true; 11230 for (const OMPContextSelectorData &D : LHS) { 11231 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx)); 11232 if (It == RHSData.end()) 11233 return false; 11234 if (D.Names.size() > It->getSecond().size()) 11235 return false; 11236 if (llvm::set_union(It->getSecond(), D.Names)) 11237 return false; 11238 AllSetsAreEqual = 11239 AllSetsAreEqual && (D.Names.size() == It->getSecond().size()); 11240 } 11241 11242 return LHS.size() != RHS.size() || !AllSetsAreEqual; 11243 } 11244 11245 static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS, 11246 const CompleteOMPContextSelectorData &RHS) { 11247 // Score is calculated as sum of all scores + 1. 11248 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11249 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS); 11250 if (RHSIsSubsetOfLHS) { 11251 LHSScore = llvm::APSInt::get(0); 11252 } else { 11253 for (const OMPContextSelectorData &Data : LHS) { 11254 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) { 11255 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11256 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) { 11257 LHSScore += Data.Score.extend(LHSScore.getBitWidth()); 11258 } else { 11259 LHSScore += Data.Score; 11260 } 11261 } 11262 } 11263 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11264 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) { 11265 RHSScore = llvm::APSInt::get(0); 11266 } else { 11267 for (const OMPContextSelectorData &Data : RHS) { 11268 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) { 11269 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11270 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) { 11271 RHSScore += Data.Score.extend(RHSScore.getBitWidth()); 11272 } else { 11273 RHSScore += Data.Score; 11274 } 11275 } 11276 } 11277 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0; 11278 } 11279 11280 /// Finds the variant function that matches current context with its context 11281 /// selector. 11282 static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM, 11283 const FunctionDecl *FD) { 11284 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) 11285 return FD; 11286 // Iterate through all DeclareVariant attributes and check context selectors. 11287 const OMPDeclareVariantAttr *TopMostAttr = nullptr; 11288 CompleteOMPContextSelectorData TopMostData; 11289 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { 11290 CompleteOMPContextSelectorData Data = 11291 translateAttrToContextSelectorData(CGM.getContext(), A); 11292 if (!matchesContext(CGM, Data)) 11293 continue; 11294 // If the attribute matches the context, find the attribute with the highest 11295 // score. 11296 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) { 11297 TopMostAttr = A; 11298 TopMostData.swap(Data); 11299 } 11300 } 11301 if (!TopMostAttr) 11302 return FD; 11303 return cast<FunctionDecl>( 11304 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) 11305 ->getDecl()); 11306 } 11307 11308 bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { 11309 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11310 // If the original function is defined already, use its definition. 11311 StringRef MangledName = CGM.getMangledName(GD); 11312 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); 11313 if (Orig && !Orig->isDeclaration()) 11314 return false; 11315 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D); 11316 // Emit original function if it does not have declare variant attribute or the 11317 // context does not match. 11318 if (NewFD == D) 11319 return false; 11320 GlobalDecl NewGD = GD.getWithDecl(NewFD); 11321 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) { 11322 DeferredVariantFunction.erase(D); 11323 return true; 11324 } 11325 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD))); 11326 return true; 11327 } 11328 11329 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 11330 CodeGenModule &CGM, const OMPLoopDirective &S) 11331 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 11332 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11333 if (!NeedToPush) 11334 return; 11335 NontemporalDeclsSet &DS = 11336 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 11337 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 11338 for (const Stmt *Ref : C->private_refs()) { 11339 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 11340 const ValueDecl *VD; 11341 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 11342 VD = DRE->getDecl(); 11343 } else { 11344 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 11345 assert((ME->isImplicitCXXThis() || 11346 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 11347 "Expected member of current class."); 11348 VD = ME->getMemberDecl(); 11349 } 11350 DS.insert(VD); 11351 } 11352 } 11353 } 11354 11355 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 11356 if (!NeedToPush) 11357 return; 11358 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 11359 } 11360 11361 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 11362 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11363 11364 return llvm::any_of( 11365 CGM.getOpenMPRuntime().NontemporalDeclsStack, 11366 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 11367 } 11368 11369 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 11370 const OMPExecutableDirective &S, 11371 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 11372 const { 11373 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 11374 // Vars in target/task regions must be excluded completely. 11375 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 11376 isOpenMPTaskingDirective(S.getDirectiveKind())) { 11377 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11378 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 11379 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 11380 for (const CapturedStmt::Capture &Cap : CS->captures()) { 11381 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 11382 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 11383 } 11384 } 11385 // Exclude vars in private clauses. 11386 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 11387 for (const Expr *Ref : C->varlists()) { 11388 if (!Ref->getType()->isScalarType()) 11389 continue; 11390 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11391 if (!DRE) 11392 continue; 11393 NeedToCheckForLPCs.insert(DRE->getDecl()); 11394 } 11395 } 11396 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 11397 for (const Expr *Ref : C->varlists()) { 11398 if (!Ref->getType()->isScalarType()) 11399 continue; 11400 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11401 if (!DRE) 11402 continue; 11403 NeedToCheckForLPCs.insert(DRE->getDecl()); 11404 } 11405 } 11406 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11407 for (const Expr *Ref : C->varlists()) { 11408 if (!Ref->getType()->isScalarType()) 11409 continue; 11410 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11411 if (!DRE) 11412 continue; 11413 NeedToCheckForLPCs.insert(DRE->getDecl()); 11414 } 11415 } 11416 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 11417 for (const Expr *Ref : C->varlists()) { 11418 if (!Ref->getType()->isScalarType()) 11419 continue; 11420 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11421 if (!DRE) 11422 continue; 11423 NeedToCheckForLPCs.insert(DRE->getDecl()); 11424 } 11425 } 11426 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 11427 for (const Expr *Ref : C->varlists()) { 11428 if (!Ref->getType()->isScalarType()) 11429 continue; 11430 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11431 if (!DRE) 11432 continue; 11433 NeedToCheckForLPCs.insert(DRE->getDecl()); 11434 } 11435 } 11436 for (const Decl *VD : NeedToCheckForLPCs) { 11437 for (const LastprivateConditionalData &Data : 11438 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 11439 if (Data.DeclToUniqueName.count(VD) > 0) { 11440 if (!Data.Disabled) 11441 NeedToAddForLPCsAsDisabled.insert(VD); 11442 break; 11443 } 11444 } 11445 } 11446 } 11447 11448 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11449 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 11450 : CGM(CGF.CGM), 11451 Action((CGM.getLangOpts().OpenMP >= 50 && 11452 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 11453 [](const OMPLastprivateClause *C) { 11454 return C->getKind() == 11455 OMPC_LASTPRIVATE_conditional; 11456 })) 11457 ? ActionToDo::PushAsLastprivateConditional 11458 : ActionToDo::DoNotPush) { 11459 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11460 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 11461 return; 11462 assert(Action == ActionToDo::PushAsLastprivateConditional && 11463 "Expected a push action."); 11464 LastprivateConditionalData &Data = 11465 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11466 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11467 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 11468 continue; 11469 11470 for (const Expr *Ref : C->varlists()) { 11471 Data.DeclToUniqueName.insert(std::make_pair( 11472 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 11473 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 11474 } 11475 } 11476 Data.IVLVal = IVLVal; 11477 Data.Fn = CGF.CurFn; 11478 } 11479 11480 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11481 CodeGenFunction &CGF, const OMPExecutableDirective &S) 11482 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 11483 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11484 if (CGM.getLangOpts().OpenMP < 50) 11485 return; 11486 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 11487 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 11488 if (!NeedToAddForLPCsAsDisabled.empty()) { 11489 Action = ActionToDo::DisableLastprivateConditional; 11490 LastprivateConditionalData &Data = 11491 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11492 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 11493 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 11494 Data.Fn = CGF.CurFn; 11495 Data.Disabled = true; 11496 } 11497 } 11498 11499 CGOpenMPRuntime::LastprivateConditionalRAII 11500 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 11501 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 11502 return LastprivateConditionalRAII(CGF, S); 11503 } 11504 11505 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 11506 if (CGM.getLangOpts().OpenMP < 50) 11507 return; 11508 if (Action == ActionToDo::DisableLastprivateConditional) { 11509 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11510 "Expected list of disabled private vars."); 11511 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11512 } 11513 if (Action == ActionToDo::PushAsLastprivateConditional) { 11514 assert( 11515 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11516 "Expected list of lastprivate conditional vars."); 11517 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11518 } 11519 } 11520 11521 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 11522 const VarDecl *VD) { 11523 ASTContext &C = CGM.getContext(); 11524 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 11525 if (I == LastprivateConditionalToTypes.end()) 11526 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 11527 QualType NewType; 11528 const FieldDecl *VDField; 11529 const FieldDecl *FiredField; 11530 LValue BaseLVal; 11531 auto VI = I->getSecond().find(VD); 11532 if (VI == I->getSecond().end()) { 11533 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 11534 RD->startDefinition(); 11535 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 11536 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 11537 RD->completeDefinition(); 11538 NewType = C.getRecordType(RD); 11539 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 11540 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 11541 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 11542 } else { 11543 NewType = std::get<0>(VI->getSecond()); 11544 VDField = std::get<1>(VI->getSecond()); 11545 FiredField = std::get<2>(VI->getSecond()); 11546 BaseLVal = std::get<3>(VI->getSecond()); 11547 } 11548 LValue FiredLVal = 11549 CGF.EmitLValueForField(BaseLVal, FiredField); 11550 CGF.EmitStoreOfScalar( 11551 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 11552 FiredLVal); 11553 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 11554 } 11555 11556 namespace { 11557 /// Checks if the lastprivate conditional variable is referenced in LHS. 11558 class LastprivateConditionalRefChecker final 11559 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 11560 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 11561 const Expr *FoundE = nullptr; 11562 const Decl *FoundD = nullptr; 11563 StringRef UniqueDeclName; 11564 LValue IVLVal; 11565 llvm::Function *FoundFn = nullptr; 11566 SourceLocation Loc; 11567 11568 public: 11569 bool VisitDeclRefExpr(const DeclRefExpr *E) { 11570 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11571 llvm::reverse(LPM)) { 11572 auto It = D.DeclToUniqueName.find(E->getDecl()); 11573 if (It == D.DeclToUniqueName.end()) 11574 continue; 11575 if (D.Disabled) 11576 return false; 11577 FoundE = E; 11578 FoundD = E->getDecl()->getCanonicalDecl(); 11579 UniqueDeclName = It->second; 11580 IVLVal = D.IVLVal; 11581 FoundFn = D.Fn; 11582 break; 11583 } 11584 return FoundE == E; 11585 } 11586 bool VisitMemberExpr(const MemberExpr *E) { 11587 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 11588 return false; 11589 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11590 llvm::reverse(LPM)) { 11591 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 11592 if (It == D.DeclToUniqueName.end()) 11593 continue; 11594 if (D.Disabled) 11595 return false; 11596 FoundE = E; 11597 FoundD = E->getMemberDecl()->getCanonicalDecl(); 11598 UniqueDeclName = It->second; 11599 IVLVal = D.IVLVal; 11600 FoundFn = D.Fn; 11601 break; 11602 } 11603 return FoundE == E; 11604 } 11605 bool VisitStmt(const Stmt *S) { 11606 for (const Stmt *Child : S->children()) { 11607 if (!Child) 11608 continue; 11609 if (const auto *E = dyn_cast<Expr>(Child)) 11610 if (!E->isGLValue()) 11611 continue; 11612 if (Visit(Child)) 11613 return true; 11614 } 11615 return false; 11616 } 11617 explicit LastprivateConditionalRefChecker( 11618 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 11619 : LPM(LPM) {} 11620 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 11621 getFoundData() const { 11622 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 11623 } 11624 }; 11625 } // namespace 11626 11627 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 11628 LValue IVLVal, 11629 StringRef UniqueDeclName, 11630 LValue LVal, 11631 SourceLocation Loc) { 11632 // Last updated loop counter for the lastprivate conditional var. 11633 // int<xx> last_iv = 0; 11634 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 11635 llvm::Constant *LastIV = 11636 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 11637 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 11638 IVLVal.getAlignment().getAsAlign()); 11639 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 11640 11641 // Last value of the lastprivate conditional. 11642 // decltype(priv_a) last_a; 11643 llvm::Constant *Last = getOrCreateInternalVariable( 11644 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 11645 cast<llvm::GlobalVariable>(Last)->setAlignment( 11646 LVal.getAlignment().getAsAlign()); 11647 LValue LastLVal = 11648 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 11649 11650 // Global loop counter. Required to handle inner parallel-for regions. 11651 // iv 11652 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 11653 11654 // #pragma omp critical(a) 11655 // if (last_iv <= iv) { 11656 // last_iv = iv; 11657 // last_a = priv_a; 11658 // } 11659 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 11660 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 11661 Action.Enter(CGF); 11662 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 11663 // (last_iv <= iv) ? Check if the variable is updated and store new 11664 // value in global var. 11665 llvm::Value *CmpRes; 11666 if (IVLVal.getType()->isSignedIntegerType()) { 11667 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 11668 } else { 11669 assert(IVLVal.getType()->isUnsignedIntegerType() && 11670 "Loop iteration variable must be integer."); 11671 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 11672 } 11673 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 11674 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 11675 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 11676 // { 11677 CGF.EmitBlock(ThenBB); 11678 11679 // last_iv = iv; 11680 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 11681 11682 // last_a = priv_a; 11683 switch (CGF.getEvaluationKind(LVal.getType())) { 11684 case TEK_Scalar: { 11685 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 11686 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 11687 break; 11688 } 11689 case TEK_Complex: { 11690 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 11691 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 11692 break; 11693 } 11694 case TEK_Aggregate: 11695 llvm_unreachable( 11696 "Aggregates are not supported in lastprivate conditional."); 11697 } 11698 // } 11699 CGF.EmitBranch(ExitBB); 11700 // There is no need to emit line number for unconditional branch. 11701 (void)ApplyDebugLocation::CreateEmpty(CGF); 11702 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 11703 }; 11704 11705 if (CGM.getLangOpts().OpenMPSimd) { 11706 // Do not emit as a critical region as no parallel region could be emitted. 11707 RegionCodeGenTy ThenRCG(CodeGen); 11708 ThenRCG(CGF); 11709 } else { 11710 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 11711 } 11712 } 11713 11714 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 11715 const Expr *LHS) { 11716 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11717 return; 11718 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 11719 if (!Checker.Visit(LHS)) 11720 return; 11721 const Expr *FoundE; 11722 const Decl *FoundD; 11723 StringRef UniqueDeclName; 11724 LValue IVLVal; 11725 llvm::Function *FoundFn; 11726 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 11727 Checker.getFoundData(); 11728 if (FoundFn != CGF.CurFn) { 11729 // Special codegen for inner parallel regions. 11730 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 11731 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 11732 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 11733 "Lastprivate conditional is not found in outer region."); 11734 QualType StructTy = std::get<0>(It->getSecond()); 11735 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 11736 LValue PrivLVal = CGF.EmitLValue(FoundE); 11737 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11738 PrivLVal.getAddress(CGF), 11739 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 11740 LValue BaseLVal = 11741 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 11742 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 11743 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 11744 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 11745 FiredLVal, llvm::AtomicOrdering::Unordered, 11746 /*IsVolatile=*/true, /*isInit=*/false); 11747 return; 11748 } 11749 11750 // Private address of the lastprivate conditional in the current context. 11751 // priv_a 11752 LValue LVal = CGF.EmitLValue(FoundE); 11753 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 11754 FoundE->getExprLoc()); 11755 } 11756 11757 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 11758 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11759 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 11760 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11761 return; 11762 auto Range = llvm::reverse(LastprivateConditionalStack); 11763 auto It = llvm::find_if( 11764 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 11765 if (It == Range.end() || It->Fn != CGF.CurFn) 11766 return; 11767 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 11768 assert(LPCI != LastprivateConditionalToTypes.end() && 11769 "Lastprivates must be registered already."); 11770 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11771 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 11772 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 11773 for (const auto &Pair : It->DeclToUniqueName) { 11774 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 11775 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 11776 continue; 11777 auto I = LPCI->getSecond().find(Pair.first); 11778 assert(I != LPCI->getSecond().end() && 11779 "Lastprivate must be rehistered already."); 11780 // bool Cmp = priv_a.Fired != 0; 11781 LValue BaseLVal = std::get<3>(I->getSecond()); 11782 LValue FiredLVal = 11783 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 11784 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 11785 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 11786 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 11787 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 11788 // if (Cmp) { 11789 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 11790 CGF.EmitBlock(ThenBB); 11791 Address Addr = CGF.GetAddrOfLocalVar(VD); 11792 LValue LVal; 11793 if (VD->getType()->isReferenceType()) 11794 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 11795 AlignmentSource::Decl); 11796 else 11797 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 11798 AlignmentSource::Decl); 11799 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 11800 D.getBeginLoc()); 11801 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 11802 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 11803 // } 11804 } 11805 } 11806 11807 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 11808 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 11809 SourceLocation Loc) { 11810 if (CGF.getLangOpts().OpenMP < 50) 11811 return; 11812 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 11813 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 11814 "Unknown lastprivate conditional variable."); 11815 StringRef UniqueName = It->second; 11816 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 11817 // The variable was not updated in the region - exit. 11818 if (!GV) 11819 return; 11820 LValue LPLVal = CGF.MakeAddrLValue( 11821 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 11822 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 11823 CGF.EmitStoreOfScalar(Res, PrivLVal); 11824 } 11825 11826 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11827 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11828 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11829 llvm_unreachable("Not supported in SIMD-only mode"); 11830 } 11831 11832 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11833 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11834 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11835 llvm_unreachable("Not supported in SIMD-only mode"); 11836 } 11837 11838 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11839 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11840 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11841 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11842 bool Tied, unsigned &NumberOfParts) { 11843 llvm_unreachable("Not supported in SIMD-only mode"); 11844 } 11845 11846 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11847 SourceLocation Loc, 11848 llvm::Function *OutlinedFn, 11849 ArrayRef<llvm::Value *> CapturedVars, 11850 const Expr *IfCond) { 11851 llvm_unreachable("Not supported in SIMD-only mode"); 11852 } 11853 11854 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11855 CodeGenFunction &CGF, StringRef CriticalName, 11856 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11857 const Expr *Hint) { 11858 llvm_unreachable("Not supported in SIMD-only mode"); 11859 } 11860 11861 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11862 const RegionCodeGenTy &MasterOpGen, 11863 SourceLocation Loc) { 11864 llvm_unreachable("Not supported in SIMD-only mode"); 11865 } 11866 11867 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11868 SourceLocation Loc) { 11869 llvm_unreachable("Not supported in SIMD-only mode"); 11870 } 11871 11872 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11873 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11874 SourceLocation Loc) { 11875 llvm_unreachable("Not supported in SIMD-only mode"); 11876 } 11877 11878 void CGOpenMPSIMDRuntime::emitSingleRegion( 11879 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11880 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11881 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11882 ArrayRef<const Expr *> AssignmentOps) { 11883 llvm_unreachable("Not supported in SIMD-only mode"); 11884 } 11885 11886 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11887 const RegionCodeGenTy &OrderedOpGen, 11888 SourceLocation Loc, 11889 bool IsThreads) { 11890 llvm_unreachable("Not supported in SIMD-only mode"); 11891 } 11892 11893 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11894 SourceLocation Loc, 11895 OpenMPDirectiveKind Kind, 11896 bool EmitChecks, 11897 bool ForceSimpleCall) { 11898 llvm_unreachable("Not supported in SIMD-only mode"); 11899 } 11900 11901 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11902 CodeGenFunction &CGF, SourceLocation Loc, 11903 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11904 bool Ordered, const DispatchRTInput &DispatchValues) { 11905 llvm_unreachable("Not supported in SIMD-only mode"); 11906 } 11907 11908 void CGOpenMPSIMDRuntime::emitForStaticInit( 11909 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11910 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11911 llvm_unreachable("Not supported in SIMD-only mode"); 11912 } 11913 11914 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11915 CodeGenFunction &CGF, SourceLocation Loc, 11916 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11917 llvm_unreachable("Not supported in SIMD-only mode"); 11918 } 11919 11920 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11921 SourceLocation Loc, 11922 unsigned IVSize, 11923 bool IVSigned) { 11924 llvm_unreachable("Not supported in SIMD-only mode"); 11925 } 11926 11927 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11928 SourceLocation Loc, 11929 OpenMPDirectiveKind DKind) { 11930 llvm_unreachable("Not supported in SIMD-only mode"); 11931 } 11932 11933 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11934 SourceLocation Loc, 11935 unsigned IVSize, bool IVSigned, 11936 Address IL, Address LB, 11937 Address UB, Address ST) { 11938 llvm_unreachable("Not supported in SIMD-only mode"); 11939 } 11940 11941 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11942 llvm::Value *NumThreads, 11943 SourceLocation Loc) { 11944 llvm_unreachable("Not supported in SIMD-only mode"); 11945 } 11946 11947 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11948 ProcBindKind ProcBind, 11949 SourceLocation Loc) { 11950 llvm_unreachable("Not supported in SIMD-only mode"); 11951 } 11952 11953 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11954 const VarDecl *VD, 11955 Address VDAddr, 11956 SourceLocation Loc) { 11957 llvm_unreachable("Not supported in SIMD-only mode"); 11958 } 11959 11960 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11961 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11962 CodeGenFunction *CGF) { 11963 llvm_unreachable("Not supported in SIMD-only mode"); 11964 } 11965 11966 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11967 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11968 llvm_unreachable("Not supported in SIMD-only mode"); 11969 } 11970 11971 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11972 ArrayRef<const Expr *> Vars, 11973 SourceLocation Loc, 11974 llvm::AtomicOrdering AO) { 11975 llvm_unreachable("Not supported in SIMD-only mode"); 11976 } 11977 11978 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11979 const OMPExecutableDirective &D, 11980 llvm::Function *TaskFunction, 11981 QualType SharedsTy, Address Shareds, 11982 const Expr *IfCond, 11983 const OMPTaskDataTy &Data) { 11984 llvm_unreachable("Not supported in SIMD-only mode"); 11985 } 11986 11987 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11988 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11989 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11990 const Expr *IfCond, const OMPTaskDataTy &Data) { 11991 llvm_unreachable("Not supported in SIMD-only mode"); 11992 } 11993 11994 void CGOpenMPSIMDRuntime::emitReduction( 11995 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 11996 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 11997 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 11998 assert(Options.SimpleReduction && "Only simple reduction is expected."); 11999 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 12000 ReductionOps, Options); 12001 } 12002 12003 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 12004 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 12005 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 12006 llvm_unreachable("Not supported in SIMD-only mode"); 12007 } 12008 12009 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 12010 SourceLocation Loc, 12011 ReductionCodeGen &RCG, 12012 unsigned N) { 12013 llvm_unreachable("Not supported in SIMD-only mode"); 12014 } 12015 12016 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 12017 SourceLocation Loc, 12018 llvm::Value *ReductionsPtr, 12019 LValue SharedLVal) { 12020 llvm_unreachable("Not supported in SIMD-only mode"); 12021 } 12022 12023 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 12024 SourceLocation Loc) { 12025 llvm_unreachable("Not supported in SIMD-only mode"); 12026 } 12027 12028 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 12029 CodeGenFunction &CGF, SourceLocation Loc, 12030 OpenMPDirectiveKind CancelRegion) { 12031 llvm_unreachable("Not supported in SIMD-only mode"); 12032 } 12033 12034 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 12035 SourceLocation Loc, const Expr *IfCond, 12036 OpenMPDirectiveKind CancelRegion) { 12037 llvm_unreachable("Not supported in SIMD-only mode"); 12038 } 12039 12040 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 12041 const OMPExecutableDirective &D, StringRef ParentName, 12042 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 12043 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 12044 llvm_unreachable("Not supported in SIMD-only mode"); 12045 } 12046 12047 void CGOpenMPSIMDRuntime::emitTargetCall( 12048 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12049 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 12050 const Expr *Device, 12051 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 12052 const OMPLoopDirective &D)> 12053 SizeEmitter) { 12054 llvm_unreachable("Not supported in SIMD-only mode"); 12055 } 12056 12057 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 12058 llvm_unreachable("Not supported in SIMD-only mode"); 12059 } 12060 12061 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 12062 llvm_unreachable("Not supported in SIMD-only mode"); 12063 } 12064 12065 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 12066 return false; 12067 } 12068 12069 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 12070 const OMPExecutableDirective &D, 12071 SourceLocation Loc, 12072 llvm::Function *OutlinedFn, 12073 ArrayRef<llvm::Value *> CapturedVars) { 12074 llvm_unreachable("Not supported in SIMD-only mode"); 12075 } 12076 12077 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 12078 const Expr *NumTeams, 12079 const Expr *ThreadLimit, 12080 SourceLocation Loc) { 12081 llvm_unreachable("Not supported in SIMD-only mode"); 12082 } 12083 12084 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 12085 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12086 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 12087 llvm_unreachable("Not supported in SIMD-only mode"); 12088 } 12089 12090 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 12091 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12092 const Expr *Device) { 12093 llvm_unreachable("Not supported in SIMD-only mode"); 12094 } 12095 12096 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 12097 const OMPLoopDirective &D, 12098 ArrayRef<Expr *> NumIterations) { 12099 llvm_unreachable("Not supported in SIMD-only mode"); 12100 } 12101 12102 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12103 const OMPDependClause *C) { 12104 llvm_unreachable("Not supported in SIMD-only mode"); 12105 } 12106 12107 const VarDecl * 12108 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 12109 const VarDecl *NativeParam) const { 12110 llvm_unreachable("Not supported in SIMD-only mode"); 12111 } 12112 12113 Address 12114 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 12115 const VarDecl *NativeParam, 12116 const VarDecl *TargetParam) const { 12117 llvm_unreachable("Not supported in SIMD-only mode"); 12118 } 12119