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/FileManager.h" 25 #include "clang/Basic/OpenMPKinds.h" 26 #include "clang/Basic/SourceManager.h" 27 #include "clang/CodeGen/ConstantInitBuilder.h" 28 #include "llvm/ADT/ArrayRef.h" 29 #include "llvm/ADT/SetOperations.h" 30 #include "llvm/ADT/StringExtras.h" 31 #include "llvm/Bitcode/BitcodeReader.h" 32 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" 33 #include "llvm/IR/Constants.h" 34 #include "llvm/IR/DerivedTypes.h" 35 #include "llvm/IR/GlobalValue.h" 36 #include "llvm/IR/Value.h" 37 #include "llvm/Support/AtomicOrdering.h" 38 #include "llvm/Support/Format.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include <cassert> 41 42 using namespace clang; 43 using namespace CodeGen; 44 using namespace llvm::omp; 45 46 namespace { 47 /// Base class for handling code generation inside OpenMP regions. 48 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 49 public: 50 /// Kinds of OpenMP regions used in codegen. 51 enum CGOpenMPRegionKind { 52 /// Region with outlined function for standalone 'parallel' 53 /// directive. 54 ParallelOutlinedRegion, 55 /// Region with outlined function for standalone 'task' directive. 56 TaskOutlinedRegion, 57 /// Region for constructs that do not require function outlining, 58 /// like 'for', 'sections', 'atomic' etc. directives. 59 InlinedRegion, 60 /// Region with outlined function for standalone 'target' directive. 61 TargetRegion, 62 }; 63 64 CGOpenMPRegionInfo(const CapturedStmt &CS, 65 const CGOpenMPRegionKind RegionKind, 66 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 67 bool HasCancel) 68 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 69 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 70 71 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 72 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 73 bool HasCancel) 74 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 75 Kind(Kind), HasCancel(HasCancel) {} 76 77 /// Get a variable or parameter for storing global thread id 78 /// inside OpenMP construct. 79 virtual const VarDecl *getThreadIDVariable() const = 0; 80 81 /// Emit the captured statement body. 82 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 83 84 /// Get an LValue for the current ThreadID variable. 85 /// \return LValue for thread id variable. This LValue always has type int32*. 86 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 87 88 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 89 90 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 91 92 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 93 94 bool hasCancel() const { return HasCancel; } 95 96 static bool classof(const CGCapturedStmtInfo *Info) { 97 return Info->getKind() == CR_OpenMP; 98 } 99 100 ~CGOpenMPRegionInfo() override = default; 101 102 protected: 103 CGOpenMPRegionKind RegionKind; 104 RegionCodeGenTy CodeGen; 105 OpenMPDirectiveKind Kind; 106 bool HasCancel; 107 }; 108 109 /// API for captured statement code generation in OpenMP constructs. 110 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 111 public: 112 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 113 const RegionCodeGenTy &CodeGen, 114 OpenMPDirectiveKind Kind, bool HasCancel, 115 StringRef HelperName) 116 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 117 HasCancel), 118 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 119 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 120 } 121 122 /// Get a variable or parameter for storing global thread id 123 /// inside OpenMP construct. 124 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 125 126 /// Get the name of the capture helper. 127 StringRef getHelperName() const override { return HelperName; } 128 129 static bool classof(const CGCapturedStmtInfo *Info) { 130 return CGOpenMPRegionInfo::classof(Info) && 131 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 132 ParallelOutlinedRegion; 133 } 134 135 private: 136 /// A variable or parameter storing global thread id for OpenMP 137 /// constructs. 138 const VarDecl *ThreadIDVar; 139 StringRef HelperName; 140 }; 141 142 /// API for captured statement code generation in OpenMP constructs. 143 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 144 public: 145 class UntiedTaskActionTy final : public PrePostActionTy { 146 bool Untied; 147 const VarDecl *PartIDVar; 148 const RegionCodeGenTy UntiedCodeGen; 149 llvm::SwitchInst *UntiedSwitch = nullptr; 150 151 public: 152 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 153 const RegionCodeGenTy &UntiedCodeGen) 154 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 155 void Enter(CodeGenFunction &CGF) override { 156 if (Untied) { 157 // Emit task switching point. 158 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 159 CGF.GetAddrOfLocalVar(PartIDVar), 160 PartIDVar->getType()->castAs<PointerType>()); 161 llvm::Value *Res = 162 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 163 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 164 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 165 CGF.EmitBlock(DoneBB); 166 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 167 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 168 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 169 CGF.Builder.GetInsertBlock()); 170 emitUntiedSwitch(CGF); 171 } 172 } 173 void emitUntiedSwitch(CodeGenFunction &CGF) const { 174 if (Untied) { 175 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 176 CGF.GetAddrOfLocalVar(PartIDVar), 177 PartIDVar->getType()->castAs<PointerType>()); 178 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 179 PartIdLVal); 180 UntiedCodeGen(CGF); 181 CodeGenFunction::JumpDest CurPoint = 182 CGF.getJumpDestInCurrentScope(".untied.next."); 183 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 184 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 185 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 186 CGF.Builder.GetInsertBlock()); 187 CGF.EmitBranchThroughCleanup(CurPoint); 188 CGF.EmitBlock(CurPoint.getBlock()); 189 } 190 } 191 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 192 }; 193 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 194 const VarDecl *ThreadIDVar, 195 const RegionCodeGenTy &CodeGen, 196 OpenMPDirectiveKind Kind, bool HasCancel, 197 const UntiedTaskActionTy &Action) 198 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 199 ThreadIDVar(ThreadIDVar), Action(Action) { 200 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 201 } 202 203 /// Get a variable or parameter for storing global thread id 204 /// inside OpenMP construct. 205 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 206 207 /// Get an LValue for the current ThreadID variable. 208 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 209 210 /// Get the name of the capture helper. 211 StringRef getHelperName() const override { return ".omp_outlined."; } 212 213 void emitUntiedSwitch(CodeGenFunction &CGF) override { 214 Action.emitUntiedSwitch(CGF); 215 } 216 217 static bool classof(const CGCapturedStmtInfo *Info) { 218 return CGOpenMPRegionInfo::classof(Info) && 219 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 220 TaskOutlinedRegion; 221 } 222 223 private: 224 /// A variable or parameter storing global thread id for OpenMP 225 /// constructs. 226 const VarDecl *ThreadIDVar; 227 /// Action for emitting code for untied tasks. 228 const UntiedTaskActionTy &Action; 229 }; 230 231 /// API for inlined captured statement code generation in OpenMP 232 /// constructs. 233 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 234 public: 235 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 236 const RegionCodeGenTy &CodeGen, 237 OpenMPDirectiveKind Kind, bool HasCancel) 238 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 239 OldCSI(OldCSI), 240 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 241 242 // Retrieve the value of the context parameter. 243 llvm::Value *getContextValue() const override { 244 if (OuterRegionInfo) 245 return OuterRegionInfo->getContextValue(); 246 llvm_unreachable("No context value for inlined OpenMP region"); 247 } 248 249 void setContextValue(llvm::Value *V) override { 250 if (OuterRegionInfo) { 251 OuterRegionInfo->setContextValue(V); 252 return; 253 } 254 llvm_unreachable("No context value for inlined OpenMP region"); 255 } 256 257 /// Lookup the captured field decl for a variable. 258 const FieldDecl *lookup(const VarDecl *VD) const override { 259 if (OuterRegionInfo) 260 return OuterRegionInfo->lookup(VD); 261 // If there is no outer outlined region,no need to lookup in a list of 262 // captured variables, we can use the original one. 263 return nullptr; 264 } 265 266 FieldDecl *getThisFieldDecl() const override { 267 if (OuterRegionInfo) 268 return OuterRegionInfo->getThisFieldDecl(); 269 return nullptr; 270 } 271 272 /// Get a variable or parameter for storing global thread id 273 /// inside OpenMP construct. 274 const VarDecl *getThreadIDVariable() const override { 275 if (OuterRegionInfo) 276 return OuterRegionInfo->getThreadIDVariable(); 277 return nullptr; 278 } 279 280 /// Get an LValue for the current ThreadID variable. 281 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 282 if (OuterRegionInfo) 283 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 284 llvm_unreachable("No LValue for inlined OpenMP construct"); 285 } 286 287 /// Get the name of the capture helper. 288 StringRef getHelperName() const override { 289 if (auto *OuterRegionInfo = getOldCSI()) 290 return OuterRegionInfo->getHelperName(); 291 llvm_unreachable("No helper name for inlined OpenMP construct"); 292 } 293 294 void emitUntiedSwitch(CodeGenFunction &CGF) override { 295 if (OuterRegionInfo) 296 OuterRegionInfo->emitUntiedSwitch(CGF); 297 } 298 299 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 300 301 static bool classof(const CGCapturedStmtInfo *Info) { 302 return CGOpenMPRegionInfo::classof(Info) && 303 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 304 } 305 306 ~CGOpenMPInlinedRegionInfo() override = default; 307 308 private: 309 /// CodeGen info about outer OpenMP region. 310 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 311 CGOpenMPRegionInfo *OuterRegionInfo; 312 }; 313 314 /// API for captured statement code generation in OpenMP target 315 /// constructs. For this captures, implicit parameters are used instead of the 316 /// captured fields. The name of the target region has to be unique in a given 317 /// application so it is provided by the client, because only the client has 318 /// the information to generate that. 319 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 320 public: 321 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 322 const RegionCodeGenTy &CodeGen, StringRef HelperName) 323 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 324 /*HasCancel=*/false), 325 HelperName(HelperName) {} 326 327 /// This is unused for target regions because each starts executing 328 /// with a single thread. 329 const VarDecl *getThreadIDVariable() const override { return nullptr; } 330 331 /// Get the name of the capture helper. 332 StringRef getHelperName() const override { return HelperName; } 333 334 static bool classof(const CGCapturedStmtInfo *Info) { 335 return CGOpenMPRegionInfo::classof(Info) && 336 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 337 } 338 339 private: 340 StringRef HelperName; 341 }; 342 343 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 344 llvm_unreachable("No codegen for expressions"); 345 } 346 /// API for generation of expressions captured in a innermost OpenMP 347 /// region. 348 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 349 public: 350 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 351 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 352 OMPD_unknown, 353 /*HasCancel=*/false), 354 PrivScope(CGF) { 355 // Make sure the globals captured in the provided statement are local by 356 // using the privatization logic. We assume the same variable is not 357 // captured more than once. 358 for (const auto &C : CS.captures()) { 359 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 360 continue; 361 362 const VarDecl *VD = C.getCapturedVar(); 363 if (VD->isLocalVarDeclOrParm()) 364 continue; 365 366 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 367 /*RefersToEnclosingVariableOrCapture=*/false, 368 VD->getType().getNonReferenceType(), VK_LValue, 369 C.getLocation()); 370 PrivScope.addPrivate( 371 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 372 } 373 (void)PrivScope.Privatize(); 374 } 375 376 /// Lookup the captured field decl for a variable. 377 const FieldDecl *lookup(const VarDecl *VD) const override { 378 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 379 return FD; 380 return nullptr; 381 } 382 383 /// Emit the captured statement body. 384 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 385 llvm_unreachable("No body for expressions"); 386 } 387 388 /// Get a variable or parameter for storing global thread id 389 /// inside OpenMP construct. 390 const VarDecl *getThreadIDVariable() const override { 391 llvm_unreachable("No thread id for expressions"); 392 } 393 394 /// Get the name of the capture helper. 395 StringRef getHelperName() const override { 396 llvm_unreachable("No helper name for expressions"); 397 } 398 399 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 400 401 private: 402 /// Private scope to capture global variables. 403 CodeGenFunction::OMPPrivateScope PrivScope; 404 }; 405 406 /// RAII for emitting code of OpenMP constructs. 407 class InlinedOpenMPRegionRAII { 408 CodeGenFunction &CGF; 409 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 410 FieldDecl *LambdaThisCaptureField = nullptr; 411 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 412 413 public: 414 /// Constructs region for combined constructs. 415 /// \param CodeGen Code generation sequence for combined directives. Includes 416 /// a list of functions used for code generation of implicitly inlined 417 /// regions. 418 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 419 OpenMPDirectiveKind Kind, bool HasCancel) 420 : CGF(CGF) { 421 // Start emission for the construct. 422 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 423 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 424 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 425 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 426 CGF.LambdaThisCaptureField = nullptr; 427 BlockInfo = CGF.BlockInfo; 428 CGF.BlockInfo = nullptr; 429 } 430 431 ~InlinedOpenMPRegionRAII() { 432 // Restore original CapturedStmtInfo only if we're done with code emission. 433 auto *OldCSI = 434 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 435 delete CGF.CapturedStmtInfo; 436 CGF.CapturedStmtInfo = OldCSI; 437 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 438 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 439 CGF.BlockInfo = BlockInfo; 440 } 441 }; 442 443 /// Values for bit flags used in the ident_t to describe the fields. 444 /// All enumeric elements are named and described in accordance with the code 445 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 446 enum OpenMPLocationFlags : unsigned { 447 /// Use trampoline for internal microtask. 448 OMP_IDENT_IMD = 0x01, 449 /// Use c-style ident structure. 450 OMP_IDENT_KMPC = 0x02, 451 /// Atomic reduction option for kmpc_reduce. 452 OMP_ATOMIC_REDUCE = 0x10, 453 /// Explicit 'barrier' directive. 454 OMP_IDENT_BARRIER_EXPL = 0x20, 455 /// Implicit barrier in code. 456 OMP_IDENT_BARRIER_IMPL = 0x40, 457 /// Implicit barrier in 'for' directive. 458 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 459 /// Implicit barrier in 'sections' directive. 460 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 461 /// Implicit barrier in 'single' directive. 462 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 463 /// Call of __kmp_for_static_init for static loop. 464 OMP_IDENT_WORK_LOOP = 0x200, 465 /// Call of __kmp_for_static_init for sections. 466 OMP_IDENT_WORK_SECTIONS = 0x400, 467 /// Call of __kmp_for_static_init for distribute. 468 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 469 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 470 }; 471 472 namespace { 473 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 474 /// Values for bit flags for marking which requires clauses have been used. 475 enum OpenMPOffloadingRequiresDirFlags : int64_t { 476 /// flag undefined. 477 OMP_REQ_UNDEFINED = 0x000, 478 /// no requires clause present. 479 OMP_REQ_NONE = 0x001, 480 /// reverse_offload clause. 481 OMP_REQ_REVERSE_OFFLOAD = 0x002, 482 /// unified_address clause. 483 OMP_REQ_UNIFIED_ADDRESS = 0x004, 484 /// unified_shared_memory clause. 485 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 486 /// dynamic_allocators clause. 487 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 488 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 489 }; 490 491 enum OpenMPOffloadingReservedDeviceIDs { 492 /// Device ID if the device was not defined, runtime should get it 493 /// from environment variables in the spec. 494 OMP_DEVICEID_UNDEF = -1, 495 }; 496 } // anonymous namespace 497 498 /// Describes ident structure that describes a source location. 499 /// All descriptions are taken from 500 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 501 /// Original structure: 502 /// typedef struct ident { 503 /// kmp_int32 reserved_1; /**< might be used in Fortran; 504 /// see above */ 505 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 506 /// KMP_IDENT_KMPC identifies this union 507 /// member */ 508 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 509 /// see above */ 510 ///#if USE_ITT_BUILD 511 /// /* but currently used for storing 512 /// region-specific ITT */ 513 /// /* contextual information. */ 514 ///#endif /* USE_ITT_BUILD */ 515 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 516 /// C++ */ 517 /// char const *psource; /**< String describing the source location. 518 /// The string is composed of semi-colon separated 519 // fields which describe the source file, 520 /// the function and a pair of line numbers that 521 /// delimit the construct. 522 /// */ 523 /// } ident_t; 524 enum IdentFieldIndex { 525 /// might be used in Fortran 526 IdentField_Reserved_1, 527 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 528 IdentField_Flags, 529 /// Not really used in Fortran any more 530 IdentField_Reserved_2, 531 /// Source[4] in Fortran, do not use for C++ 532 IdentField_Reserved_3, 533 /// String describing the source location. The string is composed of 534 /// semi-colon separated fields which describe the source file, the function 535 /// and a pair of line numbers that delimit the construct. 536 IdentField_PSource 537 }; 538 539 /// Schedule types for 'omp for' loops (these enumerators are taken from 540 /// the enum sched_type in kmp.h). 541 enum OpenMPSchedType { 542 /// Lower bound for default (unordered) versions. 543 OMP_sch_lower = 32, 544 OMP_sch_static_chunked = 33, 545 OMP_sch_static = 34, 546 OMP_sch_dynamic_chunked = 35, 547 OMP_sch_guided_chunked = 36, 548 OMP_sch_runtime = 37, 549 OMP_sch_auto = 38, 550 /// static with chunk adjustment (e.g., simd) 551 OMP_sch_static_balanced_chunked = 45, 552 /// Lower bound for 'ordered' versions. 553 OMP_ord_lower = 64, 554 OMP_ord_static_chunked = 65, 555 OMP_ord_static = 66, 556 OMP_ord_dynamic_chunked = 67, 557 OMP_ord_guided_chunked = 68, 558 OMP_ord_runtime = 69, 559 OMP_ord_auto = 70, 560 OMP_sch_default = OMP_sch_static, 561 /// dist_schedule types 562 OMP_dist_sch_static_chunked = 91, 563 OMP_dist_sch_static = 92, 564 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 565 /// Set if the monotonic schedule modifier was present. 566 OMP_sch_modifier_monotonic = (1 << 29), 567 /// Set if the nonmonotonic schedule modifier was present. 568 OMP_sch_modifier_nonmonotonic = (1 << 30), 569 }; 570 571 enum OpenMPRTLFunction { 572 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 573 /// kmpc_micro microtask, ...); 574 OMPRTL__kmpc_fork_call, 575 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 576 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 577 OMPRTL__kmpc_threadprivate_cached, 578 /// Call to void __kmpc_threadprivate_register( ident_t *, 579 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 580 OMPRTL__kmpc_threadprivate_register, 581 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 582 OMPRTL__kmpc_global_thread_num, 583 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 584 // kmp_critical_name *crit); 585 OMPRTL__kmpc_critical, 586 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 587 // global_tid, kmp_critical_name *crit, uintptr_t hint); 588 OMPRTL__kmpc_critical_with_hint, 589 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 590 // kmp_critical_name *crit); 591 OMPRTL__kmpc_end_critical, 592 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 593 // global_tid); 594 OMPRTL__kmpc_cancel_barrier, 595 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 596 OMPRTL__kmpc_barrier, 597 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 598 OMPRTL__kmpc_for_static_fini, 599 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 600 // global_tid); 601 OMPRTL__kmpc_serialized_parallel, 602 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 603 // global_tid); 604 OMPRTL__kmpc_end_serialized_parallel, 605 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 606 // kmp_int32 num_threads); 607 OMPRTL__kmpc_push_num_threads, 608 // Call to void __kmpc_flush(ident_t *loc); 609 OMPRTL__kmpc_flush, 610 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 611 OMPRTL__kmpc_master, 612 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 613 OMPRTL__kmpc_end_master, 614 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 615 // int end_part); 616 OMPRTL__kmpc_omp_taskyield, 617 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 618 OMPRTL__kmpc_single, 619 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 620 OMPRTL__kmpc_end_single, 621 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 622 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 623 // kmp_routine_entry_t *task_entry); 624 OMPRTL__kmpc_omp_task_alloc, 625 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 626 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 627 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 628 // kmp_int64 device_id); 629 OMPRTL__kmpc_omp_target_task_alloc, 630 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 631 // new_task); 632 OMPRTL__kmpc_omp_task, 633 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 634 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 635 // kmp_int32 didit); 636 OMPRTL__kmpc_copyprivate, 637 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 638 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 639 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 640 OMPRTL__kmpc_reduce, 641 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 642 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 643 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 644 // *lck); 645 OMPRTL__kmpc_reduce_nowait, 646 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 647 // kmp_critical_name *lck); 648 OMPRTL__kmpc_end_reduce, 649 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 650 // kmp_critical_name *lck); 651 OMPRTL__kmpc_end_reduce_nowait, 652 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 653 // kmp_task_t * new_task); 654 OMPRTL__kmpc_omp_task_begin_if0, 655 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 656 // kmp_task_t * new_task); 657 OMPRTL__kmpc_omp_task_complete_if0, 658 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 659 OMPRTL__kmpc_ordered, 660 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 661 OMPRTL__kmpc_end_ordered, 662 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 663 // global_tid); 664 OMPRTL__kmpc_omp_taskwait, 665 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 666 OMPRTL__kmpc_taskgroup, 667 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 668 OMPRTL__kmpc_end_taskgroup, 669 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 670 // int proc_bind); 671 OMPRTL__kmpc_push_proc_bind, 672 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 673 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 674 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 675 OMPRTL__kmpc_omp_task_with_deps, 676 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 677 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 678 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 679 OMPRTL__kmpc_omp_wait_deps, 680 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 681 // global_tid, kmp_int32 cncl_kind); 682 OMPRTL__kmpc_cancellationpoint, 683 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 684 // kmp_int32 cncl_kind); 685 OMPRTL__kmpc_cancel, 686 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 687 // kmp_int32 num_teams, kmp_int32 thread_limit); 688 OMPRTL__kmpc_push_num_teams, 689 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 690 // microtask, ...); 691 OMPRTL__kmpc_fork_teams, 692 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 693 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 694 // sched, kmp_uint64 grainsize, void *task_dup); 695 OMPRTL__kmpc_taskloop, 696 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 697 // num_dims, struct kmp_dim *dims); 698 OMPRTL__kmpc_doacross_init, 699 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 700 OMPRTL__kmpc_doacross_fini, 701 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 702 // *vec); 703 OMPRTL__kmpc_doacross_post, 704 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 705 // *vec); 706 OMPRTL__kmpc_doacross_wait, 707 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 708 // *data); 709 OMPRTL__kmpc_task_reduction_init, 710 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 711 // *d); 712 OMPRTL__kmpc_task_reduction_get_th_data, 713 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 714 OMPRTL__kmpc_alloc, 715 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 716 OMPRTL__kmpc_free, 717 718 // 719 // Offloading related calls 720 // 721 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 722 // size); 723 OMPRTL__kmpc_push_target_tripcount, 724 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 725 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 726 // *arg_types); 727 OMPRTL__tgt_target, 728 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 729 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 730 // *arg_types); 731 OMPRTL__tgt_target_nowait, 732 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 733 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 734 // *arg_types, int32_t num_teams, int32_t thread_limit); 735 OMPRTL__tgt_target_teams, 736 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 737 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 738 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 739 OMPRTL__tgt_target_teams_nowait, 740 // Call to void __tgt_register_requires(int64_t flags); 741 OMPRTL__tgt_register_requires, 742 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 743 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 744 OMPRTL__tgt_target_data_begin, 745 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 746 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 747 // *arg_types); 748 OMPRTL__tgt_target_data_begin_nowait, 749 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 750 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 751 OMPRTL__tgt_target_data_end, 752 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 753 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 754 // *arg_types); 755 OMPRTL__tgt_target_data_end_nowait, 756 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 757 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 758 OMPRTL__tgt_target_data_update, 759 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 760 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 761 // *arg_types); 762 OMPRTL__tgt_target_data_update_nowait, 763 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 764 OMPRTL__tgt_mapper_num_components, 765 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 766 // *base, void *begin, int64_t size, int64_t type); 767 OMPRTL__tgt_push_mapper_component, 768 // Call to kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 769 // int gtid, kmp_task_t *task); 770 OMPRTL__kmpc_task_allow_completion_event, 771 }; 772 773 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 774 /// region. 775 class CleanupTy final : public EHScopeStack::Cleanup { 776 PrePostActionTy *Action; 777 778 public: 779 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 780 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 781 if (!CGF.HaveInsertPoint()) 782 return; 783 Action->Exit(CGF); 784 } 785 }; 786 787 } // anonymous namespace 788 789 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 790 CodeGenFunction::RunCleanupsScope Scope(CGF); 791 if (PrePostAction) { 792 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 793 Callback(CodeGen, CGF, *PrePostAction); 794 } else { 795 PrePostActionTy Action; 796 Callback(CodeGen, CGF, Action); 797 } 798 } 799 800 /// Check if the combiner is a call to UDR combiner and if it is so return the 801 /// UDR decl used for reduction. 802 static const OMPDeclareReductionDecl * 803 getReductionInit(const Expr *ReductionOp) { 804 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 805 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 806 if (const auto *DRE = 807 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 808 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 809 return DRD; 810 return nullptr; 811 } 812 813 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 814 const OMPDeclareReductionDecl *DRD, 815 const Expr *InitOp, 816 Address Private, Address Original, 817 QualType Ty) { 818 if (DRD->getInitializer()) { 819 std::pair<llvm::Function *, llvm::Function *> Reduction = 820 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 821 const auto *CE = cast<CallExpr>(InitOp); 822 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 823 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 824 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 825 const auto *LHSDRE = 826 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 827 const auto *RHSDRE = 828 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 829 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 830 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 831 [=]() { return Private; }); 832 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 833 [=]() { return Original; }); 834 (void)PrivateScope.Privatize(); 835 RValue Func = RValue::get(Reduction.second); 836 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 837 CGF.EmitIgnoredExpr(InitOp); 838 } else { 839 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 840 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 841 auto *GV = new llvm::GlobalVariable( 842 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 843 llvm::GlobalValue::PrivateLinkage, Init, Name); 844 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 845 RValue InitRVal; 846 switch (CGF.getEvaluationKind(Ty)) { 847 case TEK_Scalar: 848 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 849 break; 850 case TEK_Complex: 851 InitRVal = 852 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 853 break; 854 case TEK_Aggregate: 855 InitRVal = RValue::getAggregate(LV.getAddress(CGF)); 856 break; 857 } 858 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 859 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 860 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 861 /*IsInitializer=*/false); 862 } 863 } 864 865 /// Emit initialization of arrays of complex types. 866 /// \param DestAddr Address of the array. 867 /// \param Type Type of array. 868 /// \param Init Initial expression of array. 869 /// \param SrcAddr Address of the original array. 870 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 871 QualType Type, bool EmitDeclareReductionInit, 872 const Expr *Init, 873 const OMPDeclareReductionDecl *DRD, 874 Address SrcAddr = Address::invalid()) { 875 // Perform element-by-element initialization. 876 QualType ElementTy; 877 878 // Drill down to the base element type on both arrays. 879 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 880 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 881 DestAddr = 882 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 883 if (DRD) 884 SrcAddr = 885 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 886 887 llvm::Value *SrcBegin = nullptr; 888 if (DRD) 889 SrcBegin = SrcAddr.getPointer(); 890 llvm::Value *DestBegin = DestAddr.getPointer(); 891 // Cast from pointer to array type to pointer to single element. 892 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 893 // The basic structure here is a while-do loop. 894 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 895 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 896 llvm::Value *IsEmpty = 897 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 898 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 899 900 // Enter the loop body, making that address the current address. 901 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 902 CGF.EmitBlock(BodyBB); 903 904 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 905 906 llvm::PHINode *SrcElementPHI = nullptr; 907 Address SrcElementCurrent = Address::invalid(); 908 if (DRD) { 909 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 910 "omp.arraycpy.srcElementPast"); 911 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 912 SrcElementCurrent = 913 Address(SrcElementPHI, 914 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 915 } 916 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 917 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 918 DestElementPHI->addIncoming(DestBegin, EntryBB); 919 Address DestElementCurrent = 920 Address(DestElementPHI, 921 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 922 923 // Emit copy. 924 { 925 CodeGenFunction::RunCleanupsScope InitScope(CGF); 926 if (EmitDeclareReductionInit) { 927 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 928 SrcElementCurrent, ElementTy); 929 } else 930 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 931 /*IsInitializer=*/false); 932 } 933 934 if (DRD) { 935 // Shift the address forward by one element. 936 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 937 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 938 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 939 } 940 941 // Shift the address forward by one element. 942 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 943 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 944 // Check whether we've reached the end. 945 llvm::Value *Done = 946 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 947 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 948 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 949 950 // Done. 951 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 952 } 953 954 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 955 return CGF.EmitOMPSharedLValue(E); 956 } 957 958 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 959 const Expr *E) { 960 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 961 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 962 return LValue(); 963 } 964 965 void ReductionCodeGen::emitAggregateInitialization( 966 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 967 const OMPDeclareReductionDecl *DRD) { 968 // Emit VarDecl with copy init for arrays. 969 // Get the address of the original variable captured in current 970 // captured region. 971 const auto *PrivateVD = 972 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 973 bool EmitDeclareReductionInit = 974 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 975 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 976 EmitDeclareReductionInit, 977 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 978 : PrivateVD->getInit(), 979 DRD, SharedLVal.getAddress(CGF)); 980 } 981 982 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 983 ArrayRef<const Expr *> Privates, 984 ArrayRef<const Expr *> ReductionOps) { 985 ClausesData.reserve(Shareds.size()); 986 SharedAddresses.reserve(Shareds.size()); 987 Sizes.reserve(Shareds.size()); 988 BaseDecls.reserve(Shareds.size()); 989 auto IPriv = Privates.begin(); 990 auto IRed = ReductionOps.begin(); 991 for (const Expr *Ref : Shareds) { 992 ClausesData.emplace_back(Ref, *IPriv, *IRed); 993 std::advance(IPriv, 1); 994 std::advance(IRed, 1); 995 } 996 } 997 998 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 999 assert(SharedAddresses.size() == N && 1000 "Number of generated lvalues must be exactly N."); 1001 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 1002 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 1003 SharedAddresses.emplace_back(First, Second); 1004 } 1005 1006 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 1007 const auto *PrivateVD = 1008 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1009 QualType PrivateType = PrivateVD->getType(); 1010 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1011 if (!PrivateType->isVariablyModifiedType()) { 1012 Sizes.emplace_back( 1013 CGF.getTypeSize( 1014 SharedAddresses[N].first.getType().getNonReferenceType()), 1015 nullptr); 1016 return; 1017 } 1018 llvm::Value *Size; 1019 llvm::Value *SizeInChars; 1020 auto *ElemType = cast<llvm::PointerType>( 1021 SharedAddresses[N].first.getPointer(CGF)->getType()) 1022 ->getElementType(); 1023 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1024 if (AsArraySection) { 1025 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF), 1026 SharedAddresses[N].first.getPointer(CGF)); 1027 Size = CGF.Builder.CreateNUWAdd( 1028 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1029 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1030 } else { 1031 SizeInChars = CGF.getTypeSize( 1032 SharedAddresses[N].first.getType().getNonReferenceType()); 1033 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1034 } 1035 Sizes.emplace_back(SizeInChars, Size); 1036 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1037 CGF, 1038 cast<OpaqueValueExpr>( 1039 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1040 RValue::get(Size)); 1041 CGF.EmitVariablyModifiedType(PrivateType); 1042 } 1043 1044 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1045 llvm::Value *Size) { 1046 const auto *PrivateVD = 1047 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1048 QualType PrivateType = PrivateVD->getType(); 1049 if (!PrivateType->isVariablyModifiedType()) { 1050 assert(!Size && !Sizes[N].second && 1051 "Size should be nullptr for non-variably modified reduction " 1052 "items."); 1053 return; 1054 } 1055 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1056 CGF, 1057 cast<OpaqueValueExpr>( 1058 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1059 RValue::get(Size)); 1060 CGF.EmitVariablyModifiedType(PrivateType); 1061 } 1062 1063 void ReductionCodeGen::emitInitialization( 1064 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1065 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1066 assert(SharedAddresses.size() > N && "No variable was generated"); 1067 const auto *PrivateVD = 1068 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1069 const OMPDeclareReductionDecl *DRD = 1070 getReductionInit(ClausesData[N].ReductionOp); 1071 QualType PrivateType = PrivateVD->getType(); 1072 PrivateAddr = CGF.Builder.CreateElementBitCast( 1073 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1074 QualType SharedType = SharedAddresses[N].first.getType(); 1075 SharedLVal = CGF.MakeAddrLValue( 1076 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 1077 CGF.ConvertTypeForMem(SharedType)), 1078 SharedType, SharedAddresses[N].first.getBaseInfo(), 1079 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1080 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1081 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1082 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1083 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1084 PrivateAddr, SharedLVal.getAddress(CGF), 1085 SharedLVal.getType()); 1086 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1087 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1088 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1089 PrivateVD->getType().getQualifiers(), 1090 /*IsInitializer=*/false); 1091 } 1092 } 1093 1094 bool ReductionCodeGen::needCleanups(unsigned N) { 1095 const auto *PrivateVD = 1096 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1097 QualType PrivateType = PrivateVD->getType(); 1098 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1099 return DTorKind != QualType::DK_none; 1100 } 1101 1102 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1103 Address PrivateAddr) { 1104 const auto *PrivateVD = 1105 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1106 QualType PrivateType = PrivateVD->getType(); 1107 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1108 if (needCleanups(N)) { 1109 PrivateAddr = CGF.Builder.CreateElementBitCast( 1110 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1111 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1112 } 1113 } 1114 1115 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1116 LValue BaseLV) { 1117 BaseTy = BaseTy.getNonReferenceType(); 1118 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1119 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1120 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1121 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 1122 } else { 1123 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 1124 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1125 } 1126 BaseTy = BaseTy->getPointeeType(); 1127 } 1128 return CGF.MakeAddrLValue( 1129 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 1130 CGF.ConvertTypeForMem(ElTy)), 1131 BaseLV.getType(), BaseLV.getBaseInfo(), 1132 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1133 } 1134 1135 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1136 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1137 llvm::Value *Addr) { 1138 Address Tmp = Address::invalid(); 1139 Address TopTmp = Address::invalid(); 1140 Address MostTopTmp = Address::invalid(); 1141 BaseTy = BaseTy.getNonReferenceType(); 1142 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1143 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1144 Tmp = CGF.CreateMemTemp(BaseTy); 1145 if (TopTmp.isValid()) 1146 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1147 else 1148 MostTopTmp = Tmp; 1149 TopTmp = Tmp; 1150 BaseTy = BaseTy->getPointeeType(); 1151 } 1152 llvm::Type *Ty = BaseLVType; 1153 if (Tmp.isValid()) 1154 Ty = Tmp.getElementType(); 1155 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1156 if (Tmp.isValid()) { 1157 CGF.Builder.CreateStore(Addr, Tmp); 1158 return MostTopTmp; 1159 } 1160 return Address(Addr, BaseLVAlignment); 1161 } 1162 1163 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1164 const VarDecl *OrigVD = nullptr; 1165 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1166 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1167 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1168 Base = TempOASE->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 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1174 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1175 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1176 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1177 DE = cast<DeclRefExpr>(Base); 1178 OrigVD = cast<VarDecl>(DE->getDecl()); 1179 } 1180 return OrigVD; 1181 } 1182 1183 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1184 Address PrivateAddr) { 1185 const DeclRefExpr *DE; 1186 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1187 BaseDecls.emplace_back(OrigVD); 1188 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1189 LValue BaseLValue = 1190 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1191 OriginalBaseLValue); 1192 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1193 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1194 llvm::Value *PrivatePointer = 1195 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1196 PrivateAddr.getPointer(), 1197 SharedAddresses[N].first.getAddress(CGF).getType()); 1198 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1199 return castToBase(CGF, OrigVD->getType(), 1200 SharedAddresses[N].first.getType(), 1201 OriginalBaseLValue.getAddress(CGF).getType(), 1202 OriginalBaseLValue.getAlignment(), Ptr); 1203 } 1204 BaseDecls.emplace_back( 1205 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1206 return PrivateAddr; 1207 } 1208 1209 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1210 const OMPDeclareReductionDecl *DRD = 1211 getReductionInit(ClausesData[N].ReductionOp); 1212 return DRD && DRD->getInitializer(); 1213 } 1214 1215 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1216 return CGF.EmitLoadOfPointerLValue( 1217 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1218 getThreadIDVariable()->getType()->castAs<PointerType>()); 1219 } 1220 1221 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1222 if (!CGF.HaveInsertPoint()) 1223 return; 1224 // 1.2.2 OpenMP Language Terminology 1225 // Structured block - An executable statement with a single entry at the 1226 // top and a single exit at the bottom. 1227 // The point of exit cannot be a branch out of the structured block. 1228 // longjmp() and throw() must not violate the entry/exit criteria. 1229 CGF.EHStack.pushTerminate(); 1230 CodeGen(CGF); 1231 CGF.EHStack.popTerminate(); 1232 } 1233 1234 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1235 CodeGenFunction &CGF) { 1236 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1237 getThreadIDVariable()->getType(), 1238 AlignmentSource::Decl); 1239 } 1240 1241 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1242 QualType FieldTy) { 1243 auto *Field = FieldDecl::Create( 1244 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1245 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1246 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1247 Field->setAccess(AS_public); 1248 DC->addDecl(Field); 1249 return Field; 1250 } 1251 1252 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1253 StringRef Separator) 1254 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1255 OffloadEntriesInfoManager(CGM) { 1256 ASTContext &C = CGM.getContext(); 1257 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1258 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1259 RD->startDefinition(); 1260 // reserved_1 1261 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1262 // flags 1263 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1264 // reserved_2 1265 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1266 // reserved_3 1267 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1268 // psource 1269 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1270 RD->completeDefinition(); 1271 IdentQTy = C.getRecordType(RD); 1272 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1273 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1274 1275 loadOffloadInfoMetadata(); 1276 } 1277 1278 bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD, 1279 const GlobalDecl &OldGD, 1280 llvm::GlobalValue *OrigAddr, 1281 bool IsForDefinition) { 1282 // Emit at least a definition for the aliasee if the the address of the 1283 // original function is requested. 1284 if (IsForDefinition || OrigAddr) 1285 (void)CGM.GetAddrOfGlobal(NewGD); 1286 StringRef NewMangledName = CGM.getMangledName(NewGD); 1287 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName); 1288 if (Addr && !Addr->isDeclaration()) { 1289 const auto *D = cast<FunctionDecl>(OldGD.getDecl()); 1290 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(NewGD); 1291 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI); 1292 1293 // Create a reference to the named value. This ensures that it is emitted 1294 // if a deferred decl. 1295 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD); 1296 1297 // Create the new alias itself, but don't set a name yet. 1298 auto *GA = 1299 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule()); 1300 1301 if (OrigAddr) { 1302 assert(OrigAddr->isDeclaration() && "Expected declaration"); 1303 1304 GA->takeName(OrigAddr); 1305 OrigAddr->replaceAllUsesWith( 1306 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType())); 1307 OrigAddr->eraseFromParent(); 1308 } else { 1309 GA->setName(CGM.getMangledName(OldGD)); 1310 } 1311 1312 // Set attributes which are particular to an alias; this is a 1313 // specialization of the attributes which may be set on a global function. 1314 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || 1315 D->isWeakImported()) 1316 GA->setLinkage(llvm::Function::WeakAnyLinkage); 1317 1318 CGM.SetCommonAttributes(OldGD, GA); 1319 return true; 1320 } 1321 return false; 1322 } 1323 1324 void CGOpenMPRuntime::clear() { 1325 InternalVars.clear(); 1326 // Clean non-target variable declarations possibly used only in debug info. 1327 for (const auto &Data : EmittedNonTargetVariables) { 1328 if (!Data.getValue().pointsToAliveValue()) 1329 continue; 1330 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1331 if (!GV) 1332 continue; 1333 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1334 continue; 1335 GV->eraseFromParent(); 1336 } 1337 // Emit aliases for the deferred aliasees. 1338 for (const auto &Pair : DeferredVariantFunction) { 1339 StringRef MangledName = CGM.getMangledName(Pair.second.second); 1340 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName); 1341 // If not able to emit alias, just emit original declaration. 1342 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr, 1343 /*IsForDefinition=*/false); 1344 } 1345 } 1346 1347 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1348 SmallString<128> Buffer; 1349 llvm::raw_svector_ostream OS(Buffer); 1350 StringRef Sep = FirstSeparator; 1351 for (StringRef Part : Parts) { 1352 OS << Sep << Part; 1353 Sep = Separator; 1354 } 1355 return std::string(OS.str()); 1356 } 1357 1358 static llvm::Function * 1359 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1360 const Expr *CombinerInitializer, const VarDecl *In, 1361 const VarDecl *Out, bool IsCombiner) { 1362 // void .omp_combiner.(Ty *in, Ty *out); 1363 ASTContext &C = CGM.getContext(); 1364 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1365 FunctionArgList Args; 1366 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1367 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1368 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1369 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1370 Args.push_back(&OmpOutParm); 1371 Args.push_back(&OmpInParm); 1372 const CGFunctionInfo &FnInfo = 1373 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1374 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1375 std::string Name = CGM.getOpenMPRuntime().getName( 1376 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1377 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1378 Name, &CGM.getModule()); 1379 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1380 if (CGM.getLangOpts().Optimize) { 1381 Fn->removeFnAttr(llvm::Attribute::NoInline); 1382 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1383 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1384 } 1385 CodeGenFunction CGF(CGM); 1386 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1387 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1388 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1389 Out->getLocation()); 1390 CodeGenFunction::OMPPrivateScope Scope(CGF); 1391 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1392 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1393 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1394 .getAddress(CGF); 1395 }); 1396 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1397 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1398 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1399 .getAddress(CGF); 1400 }); 1401 (void)Scope.Privatize(); 1402 if (!IsCombiner && Out->hasInit() && 1403 !CGF.isTrivialInitializer(Out->getInit())) { 1404 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1405 Out->getType().getQualifiers(), 1406 /*IsInitializer=*/true); 1407 } 1408 if (CombinerInitializer) 1409 CGF.EmitIgnoredExpr(CombinerInitializer); 1410 Scope.ForceCleanup(); 1411 CGF.FinishFunction(); 1412 return Fn; 1413 } 1414 1415 void CGOpenMPRuntime::emitUserDefinedReduction( 1416 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1417 if (UDRMap.count(D) > 0) 1418 return; 1419 llvm::Function *Combiner = emitCombinerOrInitializer( 1420 CGM, D->getType(), D->getCombiner(), 1421 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1422 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1423 /*IsCombiner=*/true); 1424 llvm::Function *Initializer = nullptr; 1425 if (const Expr *Init = D->getInitializer()) { 1426 Initializer = emitCombinerOrInitializer( 1427 CGM, D->getType(), 1428 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1429 : nullptr, 1430 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1431 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1432 /*IsCombiner=*/false); 1433 } 1434 UDRMap.try_emplace(D, Combiner, Initializer); 1435 if (CGF) { 1436 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1437 Decls.second.push_back(D); 1438 } 1439 } 1440 1441 std::pair<llvm::Function *, llvm::Function *> 1442 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1443 auto I = UDRMap.find(D); 1444 if (I != UDRMap.end()) 1445 return I->second; 1446 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1447 return UDRMap.lookup(D); 1448 } 1449 1450 namespace { 1451 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1452 // Builder if one is present. 1453 struct PushAndPopStackRAII { 1454 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1455 bool HasCancel) 1456 : OMPBuilder(OMPBuilder) { 1457 if (!OMPBuilder) 1458 return; 1459 1460 // The following callback is the crucial part of clangs cleanup process. 1461 // 1462 // NOTE: 1463 // Once the OpenMPIRBuilder is used to create parallel regions (and 1464 // similar), the cancellation destination (Dest below) is determined via 1465 // IP. That means if we have variables to finalize we split the block at IP, 1466 // use the new block (=BB) as destination to build a JumpDest (via 1467 // getJumpDestInCurrentScope(BB)) which then is fed to 1468 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1469 // to push & pop an FinalizationInfo object. 1470 // The FiniCB will still be needed but at the point where the 1471 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1472 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1473 assert(IP.getBlock()->end() == IP.getPoint() && 1474 "Clang CG should cause non-terminated block!"); 1475 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1476 CGF.Builder.restoreIP(IP); 1477 CodeGenFunction::JumpDest Dest = 1478 CGF.getOMPCancelDestination(OMPD_parallel); 1479 CGF.EmitBranchThroughCleanup(Dest); 1480 }; 1481 1482 // TODO: Remove this once we emit parallel regions through the 1483 // OpenMPIRBuilder as it can do this setup internally. 1484 llvm::OpenMPIRBuilder::FinalizationInfo FI( 1485 {FiniCB, OMPD_parallel, HasCancel}); 1486 OMPBuilder->pushFinalizationCB(std::move(FI)); 1487 } 1488 ~PushAndPopStackRAII() { 1489 if (OMPBuilder) 1490 OMPBuilder->popFinalizationCB(); 1491 } 1492 llvm::OpenMPIRBuilder *OMPBuilder; 1493 }; 1494 } // namespace 1495 1496 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1497 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1498 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1499 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1500 assert(ThreadIDVar->getType()->isPointerType() && 1501 "thread id variable must be of type kmp_int32 *"); 1502 CodeGenFunction CGF(CGM, true); 1503 bool HasCancel = false; 1504 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1505 HasCancel = OPD->hasCancel(); 1506 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1507 HasCancel = OPSD->hasCancel(); 1508 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1509 HasCancel = OPFD->hasCancel(); 1510 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1511 HasCancel = OPFD->hasCancel(); 1512 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1513 HasCancel = OPFD->hasCancel(); 1514 else if (const auto *OPFD = 1515 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1516 HasCancel = OPFD->hasCancel(); 1517 else if (const auto *OPFD = 1518 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1519 HasCancel = OPFD->hasCancel(); 1520 1521 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1522 // parallel region to make cancellation barriers work properly. 1523 llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder(); 1524 PushAndPopStackRAII PSR(OMPBuilder, CGF, HasCancel); 1525 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1526 HasCancel, OutlinedHelperName); 1527 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1528 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1529 } 1530 1531 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1532 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1533 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1534 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1535 return emitParallelOrTeamsOutlinedFunction( 1536 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1537 } 1538 1539 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1540 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1541 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1542 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1543 return emitParallelOrTeamsOutlinedFunction( 1544 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1545 } 1546 1547 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1548 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1549 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1550 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1551 bool Tied, unsigned &NumberOfParts) { 1552 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1553 PrePostActionTy &) { 1554 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1555 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1556 llvm::Value *TaskArgs[] = { 1557 UpLoc, ThreadID, 1558 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1559 TaskTVar->getType()->castAs<PointerType>()) 1560 .getPointer(CGF)}; 1561 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1562 }; 1563 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1564 UntiedCodeGen); 1565 CodeGen.setAction(Action); 1566 assert(!ThreadIDVar->getType()->isPointerType() && 1567 "thread id variable must be of type kmp_int32 for tasks"); 1568 const OpenMPDirectiveKind Region = 1569 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1570 : OMPD_task; 1571 const CapturedStmt *CS = D.getCapturedStmt(Region); 1572 bool HasCancel = false; 1573 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D)) 1574 HasCancel = TD->hasCancel(); 1575 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D)) 1576 HasCancel = TD->hasCancel(); 1577 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D)) 1578 HasCancel = TD->hasCancel(); 1579 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D)) 1580 HasCancel = TD->hasCancel(); 1581 1582 CodeGenFunction CGF(CGM, true); 1583 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1584 InnermostKind, HasCancel, Action); 1585 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1586 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1587 if (!Tied) 1588 NumberOfParts = Action.getNumberOfParts(); 1589 return Res; 1590 } 1591 1592 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1593 const RecordDecl *RD, const CGRecordLayout &RL, 1594 ArrayRef<llvm::Constant *> Data) { 1595 llvm::StructType *StructTy = RL.getLLVMType(); 1596 unsigned PrevIdx = 0; 1597 ConstantInitBuilder CIBuilder(CGM); 1598 auto DI = Data.begin(); 1599 for (const FieldDecl *FD : RD->fields()) { 1600 unsigned Idx = RL.getLLVMFieldNo(FD); 1601 // Fill the alignment. 1602 for (unsigned I = PrevIdx; I < Idx; ++I) 1603 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1604 PrevIdx = Idx + 1; 1605 Fields.add(*DI); 1606 ++DI; 1607 } 1608 } 1609 1610 template <class... As> 1611 static llvm::GlobalVariable * 1612 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1613 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1614 As &&... Args) { 1615 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1616 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1617 ConstantInitBuilder CIBuilder(CGM); 1618 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1619 buildStructValue(Fields, CGM, RD, RL, Data); 1620 return Fields.finishAndCreateGlobal( 1621 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1622 std::forward<As>(Args)...); 1623 } 1624 1625 template <typename T> 1626 static void 1627 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1628 ArrayRef<llvm::Constant *> Data, 1629 T &Parent) { 1630 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1631 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1632 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1633 buildStructValue(Fields, CGM, RD, RL, Data); 1634 Fields.finishAndAddTo(Parent); 1635 } 1636 1637 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1638 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1639 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1640 FlagsTy FlagsKey(Flags, Reserved2Flags); 1641 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1642 if (!Entry) { 1643 if (!DefaultOpenMPPSource) { 1644 // Initialize default location for psource field of ident_t structure of 1645 // all ident_t objects. Format is ";file;function;line;column;;". 1646 // Taken from 1647 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1648 DefaultOpenMPPSource = 1649 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1650 DefaultOpenMPPSource = 1651 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1652 } 1653 1654 llvm::Constant *Data[] = { 1655 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1656 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1657 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1658 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1659 llvm::GlobalValue *DefaultOpenMPLocation = 1660 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1661 llvm::GlobalValue::PrivateLinkage); 1662 DefaultOpenMPLocation->setUnnamedAddr( 1663 llvm::GlobalValue::UnnamedAddr::Global); 1664 1665 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1666 } 1667 return Address(Entry, Align); 1668 } 1669 1670 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1671 bool AtCurrentPoint) { 1672 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1673 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1674 1675 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1676 if (AtCurrentPoint) { 1677 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1678 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1679 } else { 1680 Elem.second.ServiceInsertPt = 1681 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1682 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1683 } 1684 } 1685 1686 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1687 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1688 if (Elem.second.ServiceInsertPt) { 1689 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1690 Elem.second.ServiceInsertPt = nullptr; 1691 Ptr->eraseFromParent(); 1692 } 1693 } 1694 1695 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1696 SourceLocation Loc, 1697 unsigned Flags) { 1698 Flags |= OMP_IDENT_KMPC; 1699 // If no debug info is generated - return global default location. 1700 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1701 Loc.isInvalid()) 1702 return getOrCreateDefaultLocation(Flags).getPointer(); 1703 1704 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1705 1706 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1707 Address LocValue = Address::invalid(); 1708 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1709 if (I != OpenMPLocThreadIDMap.end()) 1710 LocValue = Address(I->second.DebugLoc, Align); 1711 1712 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1713 // GetOpenMPThreadID was called before this routine. 1714 if (!LocValue.isValid()) { 1715 // Generate "ident_t .kmpc_loc.addr;" 1716 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1717 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1718 Elem.second.DebugLoc = AI.getPointer(); 1719 LocValue = AI; 1720 1721 if (!Elem.second.ServiceInsertPt) 1722 setLocThreadIdInsertPt(CGF); 1723 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1724 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1725 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1726 CGF.getTypeSize(IdentQTy)); 1727 } 1728 1729 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1730 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1731 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1732 LValue PSource = 1733 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1734 1735 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1736 if (OMPDebugLoc == nullptr) { 1737 SmallString<128> Buffer2; 1738 llvm::raw_svector_ostream OS2(Buffer2); 1739 // Build debug location 1740 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1741 OS2 << ";" << PLoc.getFilename() << ";"; 1742 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1743 OS2 << FD->getQualifiedNameAsString(); 1744 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1745 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1746 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1747 } 1748 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1749 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1750 1751 // Our callers always pass this to a runtime function, so for 1752 // convenience, go ahead and return a naked pointer. 1753 return LocValue.getPointer(); 1754 } 1755 1756 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1757 SourceLocation Loc) { 1758 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1759 1760 llvm::Value *ThreadID = nullptr; 1761 // Check whether we've already cached a load of the thread id in this 1762 // function. 1763 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1764 if (I != OpenMPLocThreadIDMap.end()) { 1765 ThreadID = I->second.ThreadID; 1766 if (ThreadID != nullptr) 1767 return ThreadID; 1768 } 1769 // If exceptions are enabled, do not use parameter to avoid possible crash. 1770 if (auto *OMPRegionInfo = 1771 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1772 if (OMPRegionInfo->getThreadIDVariable()) { 1773 // Check if this an outlined function with thread id passed as argument. 1774 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1775 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1776 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1777 !CGF.getLangOpts().CXXExceptions || 1778 CGF.Builder.GetInsertBlock() == TopBlock || 1779 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1780 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1781 TopBlock || 1782 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1783 CGF.Builder.GetInsertBlock()) { 1784 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1785 // If value loaded in entry block, cache it and use it everywhere in 1786 // function. 1787 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1788 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1789 Elem.second.ThreadID = ThreadID; 1790 } 1791 return ThreadID; 1792 } 1793 } 1794 } 1795 1796 // This is not an outlined function region - need to call __kmpc_int32 1797 // kmpc_global_thread_num(ident_t *loc). 1798 // Generate thread id value and cache this value for use across the 1799 // function. 1800 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1801 if (!Elem.second.ServiceInsertPt) 1802 setLocThreadIdInsertPt(CGF); 1803 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1804 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1805 llvm::CallInst *Call = CGF.Builder.CreateCall( 1806 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1807 emitUpdateLocation(CGF, Loc)); 1808 Call->setCallingConv(CGF.getRuntimeCC()); 1809 Elem.second.ThreadID = Call; 1810 return Call; 1811 } 1812 1813 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1814 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1815 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1816 clearLocThreadIdInsertPt(CGF); 1817 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1818 } 1819 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1820 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1821 UDRMap.erase(D); 1822 FunctionUDRMap.erase(CGF.CurFn); 1823 } 1824 auto I = FunctionUDMMap.find(CGF.CurFn); 1825 if (I != FunctionUDMMap.end()) { 1826 for(const auto *D : I->second) 1827 UDMMap.erase(D); 1828 FunctionUDMMap.erase(I); 1829 } 1830 LastprivateConditionalToTypes.erase(CGF.CurFn); 1831 } 1832 1833 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1834 return IdentTy->getPointerTo(); 1835 } 1836 1837 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1838 if (!Kmpc_MicroTy) { 1839 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1840 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1841 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1842 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1843 } 1844 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1845 } 1846 1847 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1848 llvm::FunctionCallee RTLFn = nullptr; 1849 switch (static_cast<OpenMPRTLFunction>(Function)) { 1850 case OMPRTL__kmpc_fork_call: { 1851 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1852 // microtask, ...); 1853 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1854 getKmpc_MicroPointerTy()}; 1855 auto *FnTy = 1856 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1857 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1858 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1859 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1860 llvm::LLVMContext &Ctx = F->getContext(); 1861 llvm::MDBuilder MDB(Ctx); 1862 // Annotate the callback behavior of the __kmpc_fork_call: 1863 // - The callback callee is argument number 2 (microtask). 1864 // - The first two arguments of the callback callee are unknown (-1). 1865 // - All variadic arguments to the __kmpc_fork_call are passed to the 1866 // callback callee. 1867 F->addMetadata( 1868 llvm::LLVMContext::MD_callback, 1869 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1870 2, {-1, -1}, 1871 /* VarArgsArePassed */ true)})); 1872 } 1873 } 1874 break; 1875 } 1876 case OMPRTL__kmpc_global_thread_num: { 1877 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1878 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1879 auto *FnTy = 1880 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1881 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1882 break; 1883 } 1884 case OMPRTL__kmpc_threadprivate_cached: { 1885 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1886 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1887 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1888 CGM.VoidPtrTy, CGM.SizeTy, 1889 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1890 auto *FnTy = 1891 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1892 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1893 break; 1894 } 1895 case OMPRTL__kmpc_critical: { 1896 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1897 // kmp_critical_name *crit); 1898 llvm::Type *TypeParams[] = { 1899 getIdentTyPointerTy(), CGM.Int32Ty, 1900 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1901 auto *FnTy = 1902 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1903 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1904 break; 1905 } 1906 case OMPRTL__kmpc_critical_with_hint: { 1907 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1908 // kmp_critical_name *crit, uintptr_t hint); 1909 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1910 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1911 CGM.IntPtrTy}; 1912 auto *FnTy = 1913 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1914 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1915 break; 1916 } 1917 case OMPRTL__kmpc_threadprivate_register: { 1918 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1919 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1920 // typedef void *(*kmpc_ctor)(void *); 1921 auto *KmpcCtorTy = 1922 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1923 /*isVarArg*/ false)->getPointerTo(); 1924 // typedef void *(*kmpc_cctor)(void *, void *); 1925 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1926 auto *KmpcCopyCtorTy = 1927 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1928 /*isVarArg*/ false) 1929 ->getPointerTo(); 1930 // typedef void (*kmpc_dtor)(void *); 1931 auto *KmpcDtorTy = 1932 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1933 ->getPointerTo(); 1934 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1935 KmpcCopyCtorTy, KmpcDtorTy}; 1936 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1937 /*isVarArg*/ false); 1938 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1939 break; 1940 } 1941 case OMPRTL__kmpc_end_critical: { 1942 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1943 // kmp_critical_name *crit); 1944 llvm::Type *TypeParams[] = { 1945 getIdentTyPointerTy(), CGM.Int32Ty, 1946 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1947 auto *FnTy = 1948 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1949 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1950 break; 1951 } 1952 case OMPRTL__kmpc_cancel_barrier: { 1953 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1954 // global_tid); 1955 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1956 auto *FnTy = 1957 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1958 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1959 break; 1960 } 1961 case OMPRTL__kmpc_barrier: { 1962 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1963 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1964 auto *FnTy = 1965 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1966 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1967 break; 1968 } 1969 case OMPRTL__kmpc_for_static_fini: { 1970 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1971 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1972 auto *FnTy = 1973 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1974 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1975 break; 1976 } 1977 case OMPRTL__kmpc_push_num_threads: { 1978 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1979 // kmp_int32 num_threads) 1980 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1981 CGM.Int32Ty}; 1982 auto *FnTy = 1983 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1984 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1985 break; 1986 } 1987 case OMPRTL__kmpc_serialized_parallel: { 1988 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1989 // global_tid); 1990 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1991 auto *FnTy = 1992 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1993 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1994 break; 1995 } 1996 case OMPRTL__kmpc_end_serialized_parallel: { 1997 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1998 // global_tid); 1999 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2000 auto *FnTy = 2001 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2002 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 2003 break; 2004 } 2005 case OMPRTL__kmpc_flush: { 2006 // Build void __kmpc_flush(ident_t *loc); 2007 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 2008 auto *FnTy = 2009 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2010 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 2011 break; 2012 } 2013 case OMPRTL__kmpc_master: { 2014 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 2015 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2016 auto *FnTy = 2017 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2018 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 2019 break; 2020 } 2021 case OMPRTL__kmpc_end_master: { 2022 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 2023 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2024 auto *FnTy = 2025 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2026 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 2027 break; 2028 } 2029 case OMPRTL__kmpc_omp_taskyield: { 2030 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 2031 // int end_part); 2032 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2033 auto *FnTy = 2034 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2035 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 2036 break; 2037 } 2038 case OMPRTL__kmpc_single: { 2039 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 2040 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2041 auto *FnTy = 2042 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2043 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 2044 break; 2045 } 2046 case OMPRTL__kmpc_end_single: { 2047 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 2048 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2049 auto *FnTy = 2050 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2051 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 2052 break; 2053 } 2054 case OMPRTL__kmpc_omp_task_alloc: { 2055 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 2056 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2057 // kmp_routine_entry_t *task_entry); 2058 assert(KmpRoutineEntryPtrTy != nullptr && 2059 "Type kmp_routine_entry_t must be created."); 2060 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2061 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 2062 // Return void * and then cast to particular kmp_task_t type. 2063 auto *FnTy = 2064 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2065 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 2066 break; 2067 } 2068 case OMPRTL__kmpc_omp_target_task_alloc: { 2069 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 2070 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2071 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 2072 assert(KmpRoutineEntryPtrTy != nullptr && 2073 "Type kmp_routine_entry_t must be created."); 2074 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2075 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 2076 CGM.Int64Ty}; 2077 // Return void * and then cast to particular kmp_task_t type. 2078 auto *FnTy = 2079 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2080 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2081 break; 2082 } 2083 case OMPRTL__kmpc_omp_task: { 2084 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2085 // *new_task); 2086 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2087 CGM.VoidPtrTy}; 2088 auto *FnTy = 2089 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2090 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2091 break; 2092 } 2093 case OMPRTL__kmpc_copyprivate: { 2094 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2095 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2096 // kmp_int32 didit); 2097 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2098 auto *CpyFnTy = 2099 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2100 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2101 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2102 CGM.Int32Ty}; 2103 auto *FnTy = 2104 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2105 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2106 break; 2107 } 2108 case OMPRTL__kmpc_reduce: { 2109 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2110 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2111 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2112 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2113 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2114 /*isVarArg=*/false); 2115 llvm::Type *TypeParams[] = { 2116 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2117 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2118 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2119 auto *FnTy = 2120 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2121 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2122 break; 2123 } 2124 case OMPRTL__kmpc_reduce_nowait: { 2125 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2126 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2127 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2128 // *lck); 2129 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2130 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2131 /*isVarArg=*/false); 2132 llvm::Type *TypeParams[] = { 2133 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2134 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2135 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2136 auto *FnTy = 2137 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2138 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2139 break; 2140 } 2141 case OMPRTL__kmpc_end_reduce: { 2142 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2143 // kmp_critical_name *lck); 2144 llvm::Type *TypeParams[] = { 2145 getIdentTyPointerTy(), CGM.Int32Ty, 2146 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2147 auto *FnTy = 2148 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2149 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2150 break; 2151 } 2152 case OMPRTL__kmpc_end_reduce_nowait: { 2153 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2154 // kmp_critical_name *lck); 2155 llvm::Type *TypeParams[] = { 2156 getIdentTyPointerTy(), CGM.Int32Ty, 2157 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2158 auto *FnTy = 2159 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2160 RTLFn = 2161 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2162 break; 2163 } 2164 case OMPRTL__kmpc_omp_task_begin_if0: { 2165 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2166 // *new_task); 2167 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2168 CGM.VoidPtrTy}; 2169 auto *FnTy = 2170 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2171 RTLFn = 2172 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2173 break; 2174 } 2175 case OMPRTL__kmpc_omp_task_complete_if0: { 2176 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2177 // *new_task); 2178 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2179 CGM.VoidPtrTy}; 2180 auto *FnTy = 2181 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2182 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2183 /*Name=*/"__kmpc_omp_task_complete_if0"); 2184 break; 2185 } 2186 case OMPRTL__kmpc_ordered: { 2187 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2188 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2189 auto *FnTy = 2190 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2191 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2192 break; 2193 } 2194 case OMPRTL__kmpc_end_ordered: { 2195 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2196 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2197 auto *FnTy = 2198 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2199 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2200 break; 2201 } 2202 case OMPRTL__kmpc_omp_taskwait: { 2203 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2204 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2205 auto *FnTy = 2206 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2207 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2208 break; 2209 } 2210 case OMPRTL__kmpc_taskgroup: { 2211 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2212 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2213 auto *FnTy = 2214 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2215 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2216 break; 2217 } 2218 case OMPRTL__kmpc_end_taskgroup: { 2219 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2220 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2221 auto *FnTy = 2222 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2223 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2224 break; 2225 } 2226 case OMPRTL__kmpc_push_proc_bind: { 2227 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2228 // int proc_bind) 2229 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2230 auto *FnTy = 2231 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2232 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2233 break; 2234 } 2235 case OMPRTL__kmpc_omp_task_with_deps: { 2236 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2237 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2238 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2239 llvm::Type *TypeParams[] = { 2240 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2241 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2242 auto *FnTy = 2243 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2244 RTLFn = 2245 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2246 break; 2247 } 2248 case OMPRTL__kmpc_omp_wait_deps: { 2249 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2250 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2251 // kmp_depend_info_t *noalias_dep_list); 2252 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2253 CGM.Int32Ty, CGM.VoidPtrTy, 2254 CGM.Int32Ty, CGM.VoidPtrTy}; 2255 auto *FnTy = 2256 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2257 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2258 break; 2259 } 2260 case OMPRTL__kmpc_cancellationpoint: { 2261 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2262 // global_tid, kmp_int32 cncl_kind) 2263 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2264 auto *FnTy = 2265 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2266 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2267 break; 2268 } 2269 case OMPRTL__kmpc_cancel: { 2270 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2271 // kmp_int32 cncl_kind) 2272 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2273 auto *FnTy = 2274 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2275 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2276 break; 2277 } 2278 case OMPRTL__kmpc_push_num_teams: { 2279 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2280 // kmp_int32 num_teams, kmp_int32 num_threads) 2281 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2282 CGM.Int32Ty}; 2283 auto *FnTy = 2284 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2285 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2286 break; 2287 } 2288 case OMPRTL__kmpc_fork_teams: { 2289 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2290 // microtask, ...); 2291 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2292 getKmpc_MicroPointerTy()}; 2293 auto *FnTy = 2294 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2295 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2296 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2297 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2298 llvm::LLVMContext &Ctx = F->getContext(); 2299 llvm::MDBuilder MDB(Ctx); 2300 // Annotate the callback behavior of the __kmpc_fork_teams: 2301 // - The callback callee is argument number 2 (microtask). 2302 // - The first two arguments of the callback callee are unknown (-1). 2303 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2304 // callback callee. 2305 F->addMetadata( 2306 llvm::LLVMContext::MD_callback, 2307 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2308 2, {-1, -1}, 2309 /* VarArgsArePassed */ true)})); 2310 } 2311 } 2312 break; 2313 } 2314 case OMPRTL__kmpc_taskloop: { 2315 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2316 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2317 // sched, kmp_uint64 grainsize, void *task_dup); 2318 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2319 CGM.IntTy, 2320 CGM.VoidPtrTy, 2321 CGM.IntTy, 2322 CGM.Int64Ty->getPointerTo(), 2323 CGM.Int64Ty->getPointerTo(), 2324 CGM.Int64Ty, 2325 CGM.IntTy, 2326 CGM.IntTy, 2327 CGM.Int64Ty, 2328 CGM.VoidPtrTy}; 2329 auto *FnTy = 2330 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2331 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2332 break; 2333 } 2334 case OMPRTL__kmpc_doacross_init: { 2335 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2336 // num_dims, struct kmp_dim *dims); 2337 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2338 CGM.Int32Ty, 2339 CGM.Int32Ty, 2340 CGM.VoidPtrTy}; 2341 auto *FnTy = 2342 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2343 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2344 break; 2345 } 2346 case OMPRTL__kmpc_doacross_fini: { 2347 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2348 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2349 auto *FnTy = 2350 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2351 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2352 break; 2353 } 2354 case OMPRTL__kmpc_doacross_post: { 2355 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2356 // *vec); 2357 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2358 CGM.Int64Ty->getPointerTo()}; 2359 auto *FnTy = 2360 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2361 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2362 break; 2363 } 2364 case OMPRTL__kmpc_doacross_wait: { 2365 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2366 // *vec); 2367 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2368 CGM.Int64Ty->getPointerTo()}; 2369 auto *FnTy = 2370 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2371 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2372 break; 2373 } 2374 case OMPRTL__kmpc_task_reduction_init: { 2375 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2376 // *data); 2377 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2378 auto *FnTy = 2379 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2380 RTLFn = 2381 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2382 break; 2383 } 2384 case OMPRTL__kmpc_task_reduction_get_th_data: { 2385 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2386 // *d); 2387 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2388 auto *FnTy = 2389 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2390 RTLFn = CGM.CreateRuntimeFunction( 2391 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2392 break; 2393 } 2394 case OMPRTL__kmpc_alloc: { 2395 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2396 // al); omp_allocator_handle_t type is void *. 2397 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2398 auto *FnTy = 2399 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2400 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2401 break; 2402 } 2403 case OMPRTL__kmpc_free: { 2404 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2405 // al); omp_allocator_handle_t type is void *. 2406 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2407 auto *FnTy = 2408 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2409 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2410 break; 2411 } 2412 case OMPRTL__kmpc_push_target_tripcount: { 2413 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2414 // size); 2415 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2416 llvm::FunctionType *FnTy = 2417 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2418 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2419 break; 2420 } 2421 case OMPRTL__tgt_target: { 2422 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2423 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2424 // *arg_types); 2425 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2426 CGM.VoidPtrTy, 2427 CGM.Int32Ty, 2428 CGM.VoidPtrPtrTy, 2429 CGM.VoidPtrPtrTy, 2430 CGM.Int64Ty->getPointerTo(), 2431 CGM.Int64Ty->getPointerTo()}; 2432 auto *FnTy = 2433 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2434 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2435 break; 2436 } 2437 case OMPRTL__tgt_target_nowait: { 2438 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2439 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2440 // int64_t *arg_types); 2441 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2442 CGM.VoidPtrTy, 2443 CGM.Int32Ty, 2444 CGM.VoidPtrPtrTy, 2445 CGM.VoidPtrPtrTy, 2446 CGM.Int64Ty->getPointerTo(), 2447 CGM.Int64Ty->getPointerTo()}; 2448 auto *FnTy = 2449 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2450 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2451 break; 2452 } 2453 case OMPRTL__tgt_target_teams: { 2454 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2455 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2456 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2457 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2458 CGM.VoidPtrTy, 2459 CGM.Int32Ty, 2460 CGM.VoidPtrPtrTy, 2461 CGM.VoidPtrPtrTy, 2462 CGM.Int64Ty->getPointerTo(), 2463 CGM.Int64Ty->getPointerTo(), 2464 CGM.Int32Ty, 2465 CGM.Int32Ty}; 2466 auto *FnTy = 2467 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2468 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2469 break; 2470 } 2471 case OMPRTL__tgt_target_teams_nowait: { 2472 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2473 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2474 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2475 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2476 CGM.VoidPtrTy, 2477 CGM.Int32Ty, 2478 CGM.VoidPtrPtrTy, 2479 CGM.VoidPtrPtrTy, 2480 CGM.Int64Ty->getPointerTo(), 2481 CGM.Int64Ty->getPointerTo(), 2482 CGM.Int32Ty, 2483 CGM.Int32Ty}; 2484 auto *FnTy = 2485 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2486 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2487 break; 2488 } 2489 case OMPRTL__tgt_register_requires: { 2490 // Build void __tgt_register_requires(int64_t flags); 2491 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2492 auto *FnTy = 2493 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2494 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2495 break; 2496 } 2497 case OMPRTL__tgt_target_data_begin: { 2498 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2499 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2500 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2501 CGM.Int32Ty, 2502 CGM.VoidPtrPtrTy, 2503 CGM.VoidPtrPtrTy, 2504 CGM.Int64Ty->getPointerTo(), 2505 CGM.Int64Ty->getPointerTo()}; 2506 auto *FnTy = 2507 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2508 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2509 break; 2510 } 2511 case OMPRTL__tgt_target_data_begin_nowait: { 2512 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2513 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2514 // *arg_types); 2515 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2516 CGM.Int32Ty, 2517 CGM.VoidPtrPtrTy, 2518 CGM.VoidPtrPtrTy, 2519 CGM.Int64Ty->getPointerTo(), 2520 CGM.Int64Ty->getPointerTo()}; 2521 auto *FnTy = 2522 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2523 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2524 break; 2525 } 2526 case OMPRTL__tgt_target_data_end: { 2527 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2528 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2529 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2530 CGM.Int32Ty, 2531 CGM.VoidPtrPtrTy, 2532 CGM.VoidPtrPtrTy, 2533 CGM.Int64Ty->getPointerTo(), 2534 CGM.Int64Ty->getPointerTo()}; 2535 auto *FnTy = 2536 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2537 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2538 break; 2539 } 2540 case OMPRTL__tgt_target_data_end_nowait: { 2541 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2542 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2543 // *arg_types); 2544 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2545 CGM.Int32Ty, 2546 CGM.VoidPtrPtrTy, 2547 CGM.VoidPtrPtrTy, 2548 CGM.Int64Ty->getPointerTo(), 2549 CGM.Int64Ty->getPointerTo()}; 2550 auto *FnTy = 2551 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2552 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2553 break; 2554 } 2555 case OMPRTL__tgt_target_data_update: { 2556 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2557 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2558 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2559 CGM.Int32Ty, 2560 CGM.VoidPtrPtrTy, 2561 CGM.VoidPtrPtrTy, 2562 CGM.Int64Ty->getPointerTo(), 2563 CGM.Int64Ty->getPointerTo()}; 2564 auto *FnTy = 2565 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2566 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2567 break; 2568 } 2569 case OMPRTL__tgt_target_data_update_nowait: { 2570 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2571 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2572 // *arg_types); 2573 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2574 CGM.Int32Ty, 2575 CGM.VoidPtrPtrTy, 2576 CGM.VoidPtrPtrTy, 2577 CGM.Int64Ty->getPointerTo(), 2578 CGM.Int64Ty->getPointerTo()}; 2579 auto *FnTy = 2580 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2581 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2582 break; 2583 } 2584 case OMPRTL__tgt_mapper_num_components: { 2585 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2586 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2587 auto *FnTy = 2588 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2589 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2590 break; 2591 } 2592 case OMPRTL__tgt_push_mapper_component: { 2593 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2594 // *base, void *begin, int64_t size, int64_t type); 2595 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2596 CGM.Int64Ty, CGM.Int64Ty}; 2597 auto *FnTy = 2598 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2599 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2600 break; 2601 } 2602 case OMPRTL__kmpc_task_allow_completion_event: { 2603 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 2604 // int gtid, kmp_task_t *task); 2605 auto *FnTy = llvm::FunctionType::get( 2606 CGM.VoidPtrTy, {getIdentTyPointerTy(), CGM.IntTy, CGM.VoidPtrTy}, 2607 /*isVarArg=*/false); 2608 RTLFn = 2609 CGM.CreateRuntimeFunction(FnTy, "__kmpc_task_allow_completion_event"); 2610 break; 2611 } 2612 } 2613 assert(RTLFn && "Unable to find OpenMP runtime function"); 2614 return RTLFn; 2615 } 2616 2617 llvm::FunctionCallee 2618 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2619 assert((IVSize == 32 || IVSize == 64) && 2620 "IV size is not compatible with the omp runtime"); 2621 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2622 : "__kmpc_for_static_init_4u") 2623 : (IVSigned ? "__kmpc_for_static_init_8" 2624 : "__kmpc_for_static_init_8u"); 2625 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2626 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2627 llvm::Type *TypeParams[] = { 2628 getIdentTyPointerTy(), // loc 2629 CGM.Int32Ty, // tid 2630 CGM.Int32Ty, // schedtype 2631 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2632 PtrTy, // p_lower 2633 PtrTy, // p_upper 2634 PtrTy, // p_stride 2635 ITy, // incr 2636 ITy // chunk 2637 }; 2638 auto *FnTy = 2639 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2640 return CGM.CreateRuntimeFunction(FnTy, Name); 2641 } 2642 2643 llvm::FunctionCallee 2644 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2645 assert((IVSize == 32 || IVSize == 64) && 2646 "IV size is not compatible with the omp runtime"); 2647 StringRef Name = 2648 IVSize == 32 2649 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2650 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2651 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2652 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2653 CGM.Int32Ty, // tid 2654 CGM.Int32Ty, // schedtype 2655 ITy, // lower 2656 ITy, // upper 2657 ITy, // stride 2658 ITy // chunk 2659 }; 2660 auto *FnTy = 2661 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2662 return CGM.CreateRuntimeFunction(FnTy, Name); 2663 } 2664 2665 llvm::FunctionCallee 2666 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2667 assert((IVSize == 32 || IVSize == 64) && 2668 "IV size is not compatible with the omp runtime"); 2669 StringRef Name = 2670 IVSize == 32 2671 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2672 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2673 llvm::Type *TypeParams[] = { 2674 getIdentTyPointerTy(), // loc 2675 CGM.Int32Ty, // tid 2676 }; 2677 auto *FnTy = 2678 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2679 return CGM.CreateRuntimeFunction(FnTy, Name); 2680 } 2681 2682 llvm::FunctionCallee 2683 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2684 assert((IVSize == 32 || IVSize == 64) && 2685 "IV size is not compatible with the omp runtime"); 2686 StringRef Name = 2687 IVSize == 32 2688 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2689 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2690 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2691 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2692 llvm::Type *TypeParams[] = { 2693 getIdentTyPointerTy(), // loc 2694 CGM.Int32Ty, // tid 2695 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2696 PtrTy, // p_lower 2697 PtrTy, // p_upper 2698 PtrTy // p_stride 2699 }; 2700 auto *FnTy = 2701 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2702 return CGM.CreateRuntimeFunction(FnTy, Name); 2703 } 2704 2705 /// Obtain information that uniquely identifies a target entry. This 2706 /// consists of the file and device IDs as well as line number associated with 2707 /// the relevant entry source location. 2708 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2709 unsigned &DeviceID, unsigned &FileID, 2710 unsigned &LineNum) { 2711 SourceManager &SM = C.getSourceManager(); 2712 2713 // The loc should be always valid and have a file ID (the user cannot use 2714 // #pragma directives in macros) 2715 2716 assert(Loc.isValid() && "Source location is expected to be always valid."); 2717 2718 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2719 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2720 2721 llvm::sys::fs::UniqueID ID; 2722 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2723 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2724 << PLoc.getFilename() << EC.message(); 2725 2726 DeviceID = ID.getDevice(); 2727 FileID = ID.getFile(); 2728 LineNum = PLoc.getLine(); 2729 } 2730 2731 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2732 if (CGM.getLangOpts().OpenMPSimd) 2733 return Address::invalid(); 2734 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2735 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2736 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2737 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2738 HasRequiresUnifiedSharedMemory))) { 2739 SmallString<64> PtrName; 2740 { 2741 llvm::raw_svector_ostream OS(PtrName); 2742 OS << CGM.getMangledName(GlobalDecl(VD)); 2743 if (!VD->isExternallyVisible()) { 2744 unsigned DeviceID, FileID, Line; 2745 getTargetEntryUniqueInfo(CGM.getContext(), 2746 VD->getCanonicalDecl()->getBeginLoc(), 2747 DeviceID, FileID, Line); 2748 OS << llvm::format("_%x", FileID); 2749 } 2750 OS << "_decl_tgt_ref_ptr"; 2751 } 2752 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2753 if (!Ptr) { 2754 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2755 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2756 PtrName); 2757 2758 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2759 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2760 2761 if (!CGM.getLangOpts().OpenMPIsDevice) 2762 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2763 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2764 } 2765 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2766 } 2767 return Address::invalid(); 2768 } 2769 2770 llvm::Constant * 2771 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2772 assert(!CGM.getLangOpts().OpenMPUseTLS || 2773 !CGM.getContext().getTargetInfo().isTLSSupported()); 2774 // Lookup the entry, lazily creating it if necessary. 2775 std::string Suffix = getName({"cache", ""}); 2776 return getOrCreateInternalVariable( 2777 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2778 } 2779 2780 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2781 const VarDecl *VD, 2782 Address VDAddr, 2783 SourceLocation Loc) { 2784 if (CGM.getLangOpts().OpenMPUseTLS && 2785 CGM.getContext().getTargetInfo().isTLSSupported()) 2786 return VDAddr; 2787 2788 llvm::Type *VarTy = VDAddr.getElementType(); 2789 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2790 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2791 CGM.Int8PtrTy), 2792 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2793 getOrCreateThreadPrivateCache(VD)}; 2794 return Address(CGF.EmitRuntimeCall( 2795 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2796 VDAddr.getAlignment()); 2797 } 2798 2799 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2800 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2801 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2802 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2803 // library. 2804 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2805 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2806 OMPLoc); 2807 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2808 // to register constructor/destructor for variable. 2809 llvm::Value *Args[] = { 2810 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2811 Ctor, CopyCtor, Dtor}; 2812 CGF.EmitRuntimeCall( 2813 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2814 } 2815 2816 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2817 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2818 bool PerformInit, CodeGenFunction *CGF) { 2819 if (CGM.getLangOpts().OpenMPUseTLS && 2820 CGM.getContext().getTargetInfo().isTLSSupported()) 2821 return nullptr; 2822 2823 VD = VD->getDefinition(CGM.getContext()); 2824 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2825 QualType ASTTy = VD->getType(); 2826 2827 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2828 const Expr *Init = VD->getAnyInitializer(); 2829 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2830 // Generate function that re-emits the declaration's initializer into the 2831 // threadprivate copy of the variable VD 2832 CodeGenFunction CtorCGF(CGM); 2833 FunctionArgList Args; 2834 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2835 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2836 ImplicitParamDecl::Other); 2837 Args.push_back(&Dst); 2838 2839 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2840 CGM.getContext().VoidPtrTy, Args); 2841 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2842 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2843 llvm::Function *Fn = 2844 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2845 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2846 Args, Loc, Loc); 2847 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2848 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2849 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2850 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2851 Arg = CtorCGF.Builder.CreateElementBitCast( 2852 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2853 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2854 /*IsInitializer=*/true); 2855 ArgVal = CtorCGF.EmitLoadOfScalar( 2856 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2857 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2858 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2859 CtorCGF.FinishFunction(); 2860 Ctor = Fn; 2861 } 2862 if (VD->getType().isDestructedType() != QualType::DK_none) { 2863 // Generate function that emits destructor call for the threadprivate copy 2864 // of the variable VD 2865 CodeGenFunction DtorCGF(CGM); 2866 FunctionArgList Args; 2867 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2868 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2869 ImplicitParamDecl::Other); 2870 Args.push_back(&Dst); 2871 2872 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2873 CGM.getContext().VoidTy, Args); 2874 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2875 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2876 llvm::Function *Fn = 2877 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2878 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2879 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2880 Loc, Loc); 2881 // Create a scope with an artificial location for the body of this function. 2882 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2883 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2884 DtorCGF.GetAddrOfLocalVar(&Dst), 2885 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2886 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2887 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2888 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2889 DtorCGF.FinishFunction(); 2890 Dtor = Fn; 2891 } 2892 // Do not emit init function if it is not required. 2893 if (!Ctor && !Dtor) 2894 return nullptr; 2895 2896 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2897 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2898 /*isVarArg=*/false) 2899 ->getPointerTo(); 2900 // Copying constructor for the threadprivate variable. 2901 // Must be NULL - reserved by runtime, but currently it requires that this 2902 // parameter is always NULL. Otherwise it fires assertion. 2903 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2904 if (Ctor == nullptr) { 2905 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2906 /*isVarArg=*/false) 2907 ->getPointerTo(); 2908 Ctor = llvm::Constant::getNullValue(CtorTy); 2909 } 2910 if (Dtor == nullptr) { 2911 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2912 /*isVarArg=*/false) 2913 ->getPointerTo(); 2914 Dtor = llvm::Constant::getNullValue(DtorTy); 2915 } 2916 if (!CGF) { 2917 auto *InitFunctionTy = 2918 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2919 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2920 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2921 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2922 CodeGenFunction InitCGF(CGM); 2923 FunctionArgList ArgList; 2924 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2925 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2926 Loc, Loc); 2927 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2928 InitCGF.FinishFunction(); 2929 return InitFunction; 2930 } 2931 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2932 } 2933 return nullptr; 2934 } 2935 2936 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2937 llvm::GlobalVariable *Addr, 2938 bool PerformInit) { 2939 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2940 !CGM.getLangOpts().OpenMPIsDevice) 2941 return false; 2942 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2943 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2944 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2945 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2946 HasRequiresUnifiedSharedMemory)) 2947 return CGM.getLangOpts().OpenMPIsDevice; 2948 VD = VD->getDefinition(CGM.getContext()); 2949 assert(VD && "Unknown VarDecl"); 2950 2951 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2952 return CGM.getLangOpts().OpenMPIsDevice; 2953 2954 QualType ASTTy = VD->getType(); 2955 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2956 2957 // Produce the unique prefix to identify the new target regions. We use 2958 // the source location of the variable declaration which we know to not 2959 // conflict with any target region. 2960 unsigned DeviceID; 2961 unsigned FileID; 2962 unsigned Line; 2963 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2964 SmallString<128> Buffer, Out; 2965 { 2966 llvm::raw_svector_ostream OS(Buffer); 2967 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2968 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2969 } 2970 2971 const Expr *Init = VD->getAnyInitializer(); 2972 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2973 llvm::Constant *Ctor; 2974 llvm::Constant *ID; 2975 if (CGM.getLangOpts().OpenMPIsDevice) { 2976 // Generate function that re-emits the declaration's initializer into 2977 // the threadprivate copy of the variable VD 2978 CodeGenFunction CtorCGF(CGM); 2979 2980 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2981 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2982 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2983 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2984 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2985 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2986 FunctionArgList(), Loc, Loc); 2987 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2988 CtorCGF.EmitAnyExprToMem(Init, 2989 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2990 Init->getType().getQualifiers(), 2991 /*IsInitializer=*/true); 2992 CtorCGF.FinishFunction(); 2993 Ctor = Fn; 2994 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2995 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2996 } else { 2997 Ctor = new llvm::GlobalVariable( 2998 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2999 llvm::GlobalValue::PrivateLinkage, 3000 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 3001 ID = Ctor; 3002 } 3003 3004 // Register the information for the entry associated with the constructor. 3005 Out.clear(); 3006 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 3007 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 3008 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 3009 } 3010 if (VD->getType().isDestructedType() != QualType::DK_none) { 3011 llvm::Constant *Dtor; 3012 llvm::Constant *ID; 3013 if (CGM.getLangOpts().OpenMPIsDevice) { 3014 // Generate function that emits destructor call for the threadprivate 3015 // copy of the variable VD 3016 CodeGenFunction DtorCGF(CGM); 3017 3018 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 3019 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 3020 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 3021 FTy, Twine(Buffer, "_dtor"), FI, Loc); 3022 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 3023 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 3024 FunctionArgList(), Loc, Loc); 3025 // Create a scope with an artificial location for the body of this 3026 // function. 3027 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 3028 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 3029 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 3030 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 3031 DtorCGF.FinishFunction(); 3032 Dtor = Fn; 3033 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 3034 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 3035 } else { 3036 Dtor = new llvm::GlobalVariable( 3037 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 3038 llvm::GlobalValue::PrivateLinkage, 3039 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 3040 ID = Dtor; 3041 } 3042 // Register the information for the entry associated with the destructor. 3043 Out.clear(); 3044 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 3045 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 3046 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 3047 } 3048 return CGM.getLangOpts().OpenMPIsDevice; 3049 } 3050 3051 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 3052 QualType VarType, 3053 StringRef Name) { 3054 std::string Suffix = getName({"artificial", ""}); 3055 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 3056 llvm::Value *GAddr = 3057 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 3058 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 3059 CGM.getTarget().isTLSSupported()) { 3060 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 3061 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 3062 } 3063 std::string CacheSuffix = getName({"cache", ""}); 3064 llvm::Value *Args[] = { 3065 emitUpdateLocation(CGF, SourceLocation()), 3066 getThreadID(CGF, SourceLocation()), 3067 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 3068 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 3069 /*isSigned=*/false), 3070 getOrCreateInternalVariable( 3071 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 3072 return Address( 3073 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3074 CGF.EmitRuntimeCall( 3075 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3076 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3077 CGM.getContext().getTypeAlignInChars(VarType)); 3078 } 3079 3080 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 3081 const RegionCodeGenTy &ThenGen, 3082 const RegionCodeGenTy &ElseGen) { 3083 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3084 3085 // If the condition constant folds and can be elided, try to avoid emitting 3086 // the condition and the dead arm of the if/else. 3087 bool CondConstant; 3088 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3089 if (CondConstant) 3090 ThenGen(CGF); 3091 else 3092 ElseGen(CGF); 3093 return; 3094 } 3095 3096 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3097 // emit the conditional branch. 3098 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3099 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3100 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3101 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3102 3103 // Emit the 'then' code. 3104 CGF.EmitBlock(ThenBlock); 3105 ThenGen(CGF); 3106 CGF.EmitBranch(ContBlock); 3107 // Emit the 'else' code if present. 3108 // There is no need to emit line number for unconditional branch. 3109 (void)ApplyDebugLocation::CreateEmpty(CGF); 3110 CGF.EmitBlock(ElseBlock); 3111 ElseGen(CGF); 3112 // There is no need to emit line number for unconditional branch. 3113 (void)ApplyDebugLocation::CreateEmpty(CGF); 3114 CGF.EmitBranch(ContBlock); 3115 // Emit the continuation block for code after the if. 3116 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3117 } 3118 3119 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3120 llvm::Function *OutlinedFn, 3121 ArrayRef<llvm::Value *> CapturedVars, 3122 const Expr *IfCond) { 3123 if (!CGF.HaveInsertPoint()) 3124 return; 3125 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3126 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3127 PrePostActionTy &) { 3128 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3129 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3130 llvm::Value *Args[] = { 3131 RTLoc, 3132 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3133 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3134 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3135 RealArgs.append(std::begin(Args), std::end(Args)); 3136 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3137 3138 llvm::FunctionCallee RTLFn = 3139 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3140 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3141 }; 3142 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3143 PrePostActionTy &) { 3144 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3145 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3146 // Build calls: 3147 // __kmpc_serialized_parallel(&Loc, GTid); 3148 llvm::Value *Args[] = {RTLoc, ThreadID}; 3149 CGF.EmitRuntimeCall( 3150 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3151 3152 // OutlinedFn(>id, &zero_bound, CapturedStruct); 3153 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 3154 Address ZeroAddrBound = 3155 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3156 /*Name=*/".bound.zero.addr"); 3157 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 3158 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3159 // ThreadId for serialized parallels is 0. 3160 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 3161 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 3162 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3163 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3164 3165 // __kmpc_end_serialized_parallel(&Loc, GTid); 3166 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3167 CGF.EmitRuntimeCall( 3168 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3169 EndArgs); 3170 }; 3171 if (IfCond) { 3172 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 3173 } else { 3174 RegionCodeGenTy ThenRCG(ThenGen); 3175 ThenRCG(CGF); 3176 } 3177 } 3178 3179 // If we're inside an (outlined) parallel region, use the region info's 3180 // thread-ID variable (it is passed in a first argument of the outlined function 3181 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3182 // regular serial code region, get thread ID by calling kmp_int32 3183 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3184 // return the address of that temp. 3185 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3186 SourceLocation Loc) { 3187 if (auto *OMPRegionInfo = 3188 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3189 if (OMPRegionInfo->getThreadIDVariable()) 3190 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 3191 3192 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3193 QualType Int32Ty = 3194 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3195 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3196 CGF.EmitStoreOfScalar(ThreadID, 3197 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3198 3199 return ThreadIDTemp; 3200 } 3201 3202 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3203 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3204 SmallString<256> Buffer; 3205 llvm::raw_svector_ostream Out(Buffer); 3206 Out << Name; 3207 StringRef RuntimeName = Out.str(); 3208 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3209 if (Elem.second) { 3210 assert(Elem.second->getType()->getPointerElementType() == Ty && 3211 "OMP internal variable has different type than requested"); 3212 return &*Elem.second; 3213 } 3214 3215 return Elem.second = new llvm::GlobalVariable( 3216 CGM.getModule(), Ty, /*IsConstant*/ false, 3217 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3218 Elem.first(), /*InsertBefore=*/nullptr, 3219 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3220 } 3221 3222 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3223 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3224 std::string Name = getName({Prefix, "var"}); 3225 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3226 } 3227 3228 namespace { 3229 /// Common pre(post)-action for different OpenMP constructs. 3230 class CommonActionTy final : public PrePostActionTy { 3231 llvm::FunctionCallee EnterCallee; 3232 ArrayRef<llvm::Value *> EnterArgs; 3233 llvm::FunctionCallee ExitCallee; 3234 ArrayRef<llvm::Value *> ExitArgs; 3235 bool Conditional; 3236 llvm::BasicBlock *ContBlock = nullptr; 3237 3238 public: 3239 CommonActionTy(llvm::FunctionCallee EnterCallee, 3240 ArrayRef<llvm::Value *> EnterArgs, 3241 llvm::FunctionCallee ExitCallee, 3242 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3243 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3244 ExitArgs(ExitArgs), Conditional(Conditional) {} 3245 void Enter(CodeGenFunction &CGF) override { 3246 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3247 if (Conditional) { 3248 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3249 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3250 ContBlock = CGF.createBasicBlock("omp_if.end"); 3251 // Generate the branch (If-stmt) 3252 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3253 CGF.EmitBlock(ThenBlock); 3254 } 3255 } 3256 void Done(CodeGenFunction &CGF) { 3257 // Emit the rest of blocks/branches 3258 CGF.EmitBranch(ContBlock); 3259 CGF.EmitBlock(ContBlock, true); 3260 } 3261 void Exit(CodeGenFunction &CGF) override { 3262 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3263 } 3264 }; 3265 } // anonymous namespace 3266 3267 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3268 StringRef CriticalName, 3269 const RegionCodeGenTy &CriticalOpGen, 3270 SourceLocation Loc, const Expr *Hint) { 3271 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3272 // CriticalOpGen(); 3273 // __kmpc_end_critical(ident_t *, gtid, Lock); 3274 // Prepare arguments and build a call to __kmpc_critical 3275 if (!CGF.HaveInsertPoint()) 3276 return; 3277 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3278 getCriticalRegionLock(CriticalName)}; 3279 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3280 std::end(Args)); 3281 if (Hint) { 3282 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3283 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3284 } 3285 CommonActionTy Action( 3286 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3287 : OMPRTL__kmpc_critical), 3288 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3289 CriticalOpGen.setAction(Action); 3290 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3291 } 3292 3293 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3294 const RegionCodeGenTy &MasterOpGen, 3295 SourceLocation Loc) { 3296 if (!CGF.HaveInsertPoint()) 3297 return; 3298 // if(__kmpc_master(ident_t *, gtid)) { 3299 // MasterOpGen(); 3300 // __kmpc_end_master(ident_t *, gtid); 3301 // } 3302 // Prepare arguments and build a call to __kmpc_master 3303 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3304 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3305 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3306 /*Conditional=*/true); 3307 MasterOpGen.setAction(Action); 3308 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3309 Action.Done(CGF); 3310 } 3311 3312 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3313 SourceLocation Loc) { 3314 if (!CGF.HaveInsertPoint()) 3315 return; 3316 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3317 if (OMPBuilder) { 3318 OMPBuilder->CreateTaskyield(CGF.Builder); 3319 } else { 3320 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3321 llvm::Value *Args[] = { 3322 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3323 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3324 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), 3325 Args); 3326 } 3327 3328 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3329 Region->emitUntiedSwitch(CGF); 3330 } 3331 3332 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3333 const RegionCodeGenTy &TaskgroupOpGen, 3334 SourceLocation Loc) { 3335 if (!CGF.HaveInsertPoint()) 3336 return; 3337 // __kmpc_taskgroup(ident_t *, gtid); 3338 // TaskgroupOpGen(); 3339 // __kmpc_end_taskgroup(ident_t *, gtid); 3340 // Prepare arguments and build a call to __kmpc_taskgroup 3341 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3342 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3343 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3344 Args); 3345 TaskgroupOpGen.setAction(Action); 3346 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3347 } 3348 3349 /// Given an array of pointers to variables, project the address of a 3350 /// given variable. 3351 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3352 unsigned Index, const VarDecl *Var) { 3353 // Pull out the pointer to the variable. 3354 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3355 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3356 3357 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3358 Addr = CGF.Builder.CreateElementBitCast( 3359 Addr, CGF.ConvertTypeForMem(Var->getType())); 3360 return Addr; 3361 } 3362 3363 static llvm::Value *emitCopyprivateCopyFunction( 3364 CodeGenModule &CGM, llvm::Type *ArgsType, 3365 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3366 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3367 SourceLocation Loc) { 3368 ASTContext &C = CGM.getContext(); 3369 // void copy_func(void *LHSArg, void *RHSArg); 3370 FunctionArgList Args; 3371 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3372 ImplicitParamDecl::Other); 3373 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3374 ImplicitParamDecl::Other); 3375 Args.push_back(&LHSArg); 3376 Args.push_back(&RHSArg); 3377 const auto &CGFI = 3378 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3379 std::string Name = 3380 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3381 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3382 llvm::GlobalValue::InternalLinkage, Name, 3383 &CGM.getModule()); 3384 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3385 Fn->setDoesNotRecurse(); 3386 CodeGenFunction CGF(CGM); 3387 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3388 // Dest = (void*[n])(LHSArg); 3389 // Src = (void*[n])(RHSArg); 3390 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3391 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3392 ArgsType), CGF.getPointerAlign()); 3393 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3394 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3395 ArgsType), CGF.getPointerAlign()); 3396 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3397 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3398 // ... 3399 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3400 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3401 const auto *DestVar = 3402 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3403 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3404 3405 const auto *SrcVar = 3406 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3407 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3408 3409 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3410 QualType Type = VD->getType(); 3411 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3412 } 3413 CGF.FinishFunction(); 3414 return Fn; 3415 } 3416 3417 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3418 const RegionCodeGenTy &SingleOpGen, 3419 SourceLocation Loc, 3420 ArrayRef<const Expr *> CopyprivateVars, 3421 ArrayRef<const Expr *> SrcExprs, 3422 ArrayRef<const Expr *> DstExprs, 3423 ArrayRef<const Expr *> AssignmentOps) { 3424 if (!CGF.HaveInsertPoint()) 3425 return; 3426 assert(CopyprivateVars.size() == SrcExprs.size() && 3427 CopyprivateVars.size() == DstExprs.size() && 3428 CopyprivateVars.size() == AssignmentOps.size()); 3429 ASTContext &C = CGM.getContext(); 3430 // int32 did_it = 0; 3431 // if(__kmpc_single(ident_t *, gtid)) { 3432 // SingleOpGen(); 3433 // __kmpc_end_single(ident_t *, gtid); 3434 // did_it = 1; 3435 // } 3436 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3437 // <copy_func>, did_it); 3438 3439 Address DidIt = Address::invalid(); 3440 if (!CopyprivateVars.empty()) { 3441 // int32 did_it = 0; 3442 QualType KmpInt32Ty = 3443 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3444 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3445 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3446 } 3447 // Prepare arguments and build a call to __kmpc_single 3448 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3449 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3450 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3451 /*Conditional=*/true); 3452 SingleOpGen.setAction(Action); 3453 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3454 if (DidIt.isValid()) { 3455 // did_it = 1; 3456 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3457 } 3458 Action.Done(CGF); 3459 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3460 // <copy_func>, did_it); 3461 if (DidIt.isValid()) { 3462 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3463 QualType CopyprivateArrayTy = C.getConstantArrayType( 3464 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3465 /*IndexTypeQuals=*/0); 3466 // Create a list of all private variables for copyprivate. 3467 Address CopyprivateList = 3468 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3469 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3470 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3471 CGF.Builder.CreateStore( 3472 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3473 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 3474 CGF.VoidPtrTy), 3475 Elem); 3476 } 3477 // Build function that copies private values from single region to all other 3478 // threads in the corresponding parallel region. 3479 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3480 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3481 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3482 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3483 Address CL = 3484 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3485 CGF.VoidPtrTy); 3486 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3487 llvm::Value *Args[] = { 3488 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3489 getThreadID(CGF, Loc), // i32 <gtid> 3490 BufSize, // size_t <buf_size> 3491 CL.getPointer(), // void *<copyprivate list> 3492 CpyFn, // void (*) (void *, void *) <copy_func> 3493 DidItVal // i32 did_it 3494 }; 3495 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3496 } 3497 } 3498 3499 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3500 const RegionCodeGenTy &OrderedOpGen, 3501 SourceLocation Loc, bool IsThreads) { 3502 if (!CGF.HaveInsertPoint()) 3503 return; 3504 // __kmpc_ordered(ident_t *, gtid); 3505 // OrderedOpGen(); 3506 // __kmpc_end_ordered(ident_t *, gtid); 3507 // Prepare arguments and build a call to __kmpc_ordered 3508 if (IsThreads) { 3509 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3510 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3511 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3512 Args); 3513 OrderedOpGen.setAction(Action); 3514 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3515 return; 3516 } 3517 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3518 } 3519 3520 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3521 unsigned Flags; 3522 if (Kind == OMPD_for) 3523 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3524 else if (Kind == OMPD_sections) 3525 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3526 else if (Kind == OMPD_single) 3527 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3528 else if (Kind == OMPD_barrier) 3529 Flags = OMP_IDENT_BARRIER_EXPL; 3530 else 3531 Flags = OMP_IDENT_BARRIER_IMPL; 3532 return Flags; 3533 } 3534 3535 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3536 CodeGenFunction &CGF, const OMPLoopDirective &S, 3537 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3538 // Check if the loop directive is actually a doacross loop directive. In this 3539 // case choose static, 1 schedule. 3540 if (llvm::any_of( 3541 S.getClausesOfKind<OMPOrderedClause>(), 3542 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3543 ScheduleKind = OMPC_SCHEDULE_static; 3544 // Chunk size is 1 in this case. 3545 llvm::APInt ChunkSize(32, 1); 3546 ChunkExpr = IntegerLiteral::Create( 3547 CGF.getContext(), ChunkSize, 3548 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3549 SourceLocation()); 3550 } 3551 } 3552 3553 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3554 OpenMPDirectiveKind Kind, bool EmitChecks, 3555 bool ForceSimpleCall) { 3556 // Check if we should use the OMPBuilder 3557 auto *OMPRegionInfo = 3558 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 3559 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3560 if (OMPBuilder) { 3561 CGF.Builder.restoreIP(OMPBuilder->CreateBarrier( 3562 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 3563 return; 3564 } 3565 3566 if (!CGF.HaveInsertPoint()) 3567 return; 3568 // Build call __kmpc_cancel_barrier(loc, thread_id); 3569 // Build call __kmpc_barrier(loc, thread_id); 3570 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3571 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3572 // thread_id); 3573 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3574 getThreadID(CGF, Loc)}; 3575 if (OMPRegionInfo) { 3576 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3577 llvm::Value *Result = CGF.EmitRuntimeCall( 3578 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3579 if (EmitChecks) { 3580 // if (__kmpc_cancel_barrier()) { 3581 // exit from construct; 3582 // } 3583 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3584 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3585 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3586 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3587 CGF.EmitBlock(ExitBB); 3588 // exit from construct; 3589 CodeGenFunction::JumpDest CancelDestination = 3590 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3591 CGF.EmitBranchThroughCleanup(CancelDestination); 3592 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3593 } 3594 return; 3595 } 3596 } 3597 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3598 } 3599 3600 /// Map the OpenMP loop schedule to the runtime enumeration. 3601 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3602 bool Chunked, bool Ordered) { 3603 switch (ScheduleKind) { 3604 case OMPC_SCHEDULE_static: 3605 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3606 : (Ordered ? OMP_ord_static : OMP_sch_static); 3607 case OMPC_SCHEDULE_dynamic: 3608 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3609 case OMPC_SCHEDULE_guided: 3610 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3611 case OMPC_SCHEDULE_runtime: 3612 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3613 case OMPC_SCHEDULE_auto: 3614 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3615 case OMPC_SCHEDULE_unknown: 3616 assert(!Chunked && "chunk was specified but schedule kind not known"); 3617 return Ordered ? OMP_ord_static : OMP_sch_static; 3618 } 3619 llvm_unreachable("Unexpected runtime schedule"); 3620 } 3621 3622 /// Map the OpenMP distribute schedule to the runtime enumeration. 3623 static OpenMPSchedType 3624 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3625 // only static is allowed for dist_schedule 3626 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3627 } 3628 3629 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3630 bool Chunked) const { 3631 OpenMPSchedType Schedule = 3632 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3633 return Schedule == OMP_sch_static; 3634 } 3635 3636 bool CGOpenMPRuntime::isStaticNonchunked( 3637 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3638 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3639 return Schedule == OMP_dist_sch_static; 3640 } 3641 3642 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3643 bool Chunked) const { 3644 OpenMPSchedType Schedule = 3645 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3646 return Schedule == OMP_sch_static_chunked; 3647 } 3648 3649 bool CGOpenMPRuntime::isStaticChunked( 3650 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3651 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3652 return Schedule == OMP_dist_sch_static_chunked; 3653 } 3654 3655 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3656 OpenMPSchedType Schedule = 3657 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3658 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3659 return Schedule != OMP_sch_static; 3660 } 3661 3662 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3663 OpenMPScheduleClauseModifier M1, 3664 OpenMPScheduleClauseModifier M2) { 3665 int Modifier = 0; 3666 switch (M1) { 3667 case OMPC_SCHEDULE_MODIFIER_monotonic: 3668 Modifier = OMP_sch_modifier_monotonic; 3669 break; 3670 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3671 Modifier = OMP_sch_modifier_nonmonotonic; 3672 break; 3673 case OMPC_SCHEDULE_MODIFIER_simd: 3674 if (Schedule == OMP_sch_static_chunked) 3675 Schedule = OMP_sch_static_balanced_chunked; 3676 break; 3677 case OMPC_SCHEDULE_MODIFIER_last: 3678 case OMPC_SCHEDULE_MODIFIER_unknown: 3679 break; 3680 } 3681 switch (M2) { 3682 case OMPC_SCHEDULE_MODIFIER_monotonic: 3683 Modifier = OMP_sch_modifier_monotonic; 3684 break; 3685 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3686 Modifier = OMP_sch_modifier_nonmonotonic; 3687 break; 3688 case OMPC_SCHEDULE_MODIFIER_simd: 3689 if (Schedule == OMP_sch_static_chunked) 3690 Schedule = OMP_sch_static_balanced_chunked; 3691 break; 3692 case OMPC_SCHEDULE_MODIFIER_last: 3693 case OMPC_SCHEDULE_MODIFIER_unknown: 3694 break; 3695 } 3696 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3697 // If the static schedule kind is specified or if the ordered clause is 3698 // specified, and if the nonmonotonic modifier is not specified, the effect is 3699 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3700 // modifier is specified, the effect is as if the nonmonotonic modifier is 3701 // specified. 3702 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3703 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3704 Schedule == OMP_sch_static_balanced_chunked || 3705 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 3706 Schedule == OMP_dist_sch_static_chunked || 3707 Schedule == OMP_dist_sch_static)) 3708 Modifier = OMP_sch_modifier_nonmonotonic; 3709 } 3710 return Schedule | Modifier; 3711 } 3712 3713 void CGOpenMPRuntime::emitForDispatchInit( 3714 CodeGenFunction &CGF, SourceLocation Loc, 3715 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3716 bool Ordered, const DispatchRTInput &DispatchValues) { 3717 if (!CGF.HaveInsertPoint()) 3718 return; 3719 OpenMPSchedType Schedule = getRuntimeSchedule( 3720 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3721 assert(Ordered || 3722 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3723 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3724 Schedule != OMP_sch_static_balanced_chunked)); 3725 // Call __kmpc_dispatch_init( 3726 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3727 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3728 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3729 3730 // If the Chunk was not specified in the clause - use default value 1. 3731 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3732 : CGF.Builder.getIntN(IVSize, 1); 3733 llvm::Value *Args[] = { 3734 emitUpdateLocation(CGF, Loc), 3735 getThreadID(CGF, Loc), 3736 CGF.Builder.getInt32(addMonoNonMonoModifier( 3737 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3738 DispatchValues.LB, // Lower 3739 DispatchValues.UB, // Upper 3740 CGF.Builder.getIntN(IVSize, 1), // Stride 3741 Chunk // Chunk 3742 }; 3743 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3744 } 3745 3746 static void emitForStaticInitCall( 3747 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3748 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3749 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3750 const CGOpenMPRuntime::StaticRTInput &Values) { 3751 if (!CGF.HaveInsertPoint()) 3752 return; 3753 3754 assert(!Values.Ordered); 3755 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3756 Schedule == OMP_sch_static_balanced_chunked || 3757 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3758 Schedule == OMP_dist_sch_static || 3759 Schedule == OMP_dist_sch_static_chunked); 3760 3761 // Call __kmpc_for_static_init( 3762 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3763 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3764 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3765 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3766 llvm::Value *Chunk = Values.Chunk; 3767 if (Chunk == nullptr) { 3768 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3769 Schedule == OMP_dist_sch_static) && 3770 "expected static non-chunked schedule"); 3771 // If the Chunk was not specified in the clause - use default value 1. 3772 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3773 } else { 3774 assert((Schedule == OMP_sch_static_chunked || 3775 Schedule == OMP_sch_static_balanced_chunked || 3776 Schedule == OMP_ord_static_chunked || 3777 Schedule == OMP_dist_sch_static_chunked) && 3778 "expected static chunked schedule"); 3779 } 3780 llvm::Value *Args[] = { 3781 UpdateLocation, 3782 ThreadId, 3783 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3784 M2)), // Schedule type 3785 Values.IL.getPointer(), // &isLastIter 3786 Values.LB.getPointer(), // &LB 3787 Values.UB.getPointer(), // &UB 3788 Values.ST.getPointer(), // &Stride 3789 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3790 Chunk // Chunk 3791 }; 3792 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3793 } 3794 3795 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3796 SourceLocation Loc, 3797 OpenMPDirectiveKind DKind, 3798 const OpenMPScheduleTy &ScheduleKind, 3799 const StaticRTInput &Values) { 3800 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3801 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3802 assert(isOpenMPWorksharingDirective(DKind) && 3803 "Expected loop-based or sections-based directive."); 3804 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3805 isOpenMPLoopDirective(DKind) 3806 ? OMP_IDENT_WORK_LOOP 3807 : OMP_IDENT_WORK_SECTIONS); 3808 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3809 llvm::FunctionCallee StaticInitFunction = 3810 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3811 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3812 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3813 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3814 } 3815 3816 void CGOpenMPRuntime::emitDistributeStaticInit( 3817 CodeGenFunction &CGF, SourceLocation Loc, 3818 OpenMPDistScheduleClauseKind SchedKind, 3819 const CGOpenMPRuntime::StaticRTInput &Values) { 3820 OpenMPSchedType ScheduleNum = 3821 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3822 llvm::Value *UpdatedLocation = 3823 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3824 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3825 llvm::FunctionCallee StaticInitFunction = 3826 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3827 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3828 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3829 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3830 } 3831 3832 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3833 SourceLocation Loc, 3834 OpenMPDirectiveKind DKind) { 3835 if (!CGF.HaveInsertPoint()) 3836 return; 3837 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3838 llvm::Value *Args[] = { 3839 emitUpdateLocation(CGF, Loc, 3840 isOpenMPDistributeDirective(DKind) 3841 ? OMP_IDENT_WORK_DISTRIBUTE 3842 : isOpenMPLoopDirective(DKind) 3843 ? OMP_IDENT_WORK_LOOP 3844 : OMP_IDENT_WORK_SECTIONS), 3845 getThreadID(CGF, Loc)}; 3846 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3847 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3848 Args); 3849 } 3850 3851 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3852 SourceLocation Loc, 3853 unsigned IVSize, 3854 bool IVSigned) { 3855 if (!CGF.HaveInsertPoint()) 3856 return; 3857 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3858 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3859 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3860 } 3861 3862 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3863 SourceLocation Loc, unsigned IVSize, 3864 bool IVSigned, Address IL, 3865 Address LB, Address UB, 3866 Address ST) { 3867 // Call __kmpc_dispatch_next( 3868 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3869 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3870 // kmp_int[32|64] *p_stride); 3871 llvm::Value *Args[] = { 3872 emitUpdateLocation(CGF, Loc), 3873 getThreadID(CGF, Loc), 3874 IL.getPointer(), // &isLastIter 3875 LB.getPointer(), // &Lower 3876 UB.getPointer(), // &Upper 3877 ST.getPointer() // &Stride 3878 }; 3879 llvm::Value *Call = 3880 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3881 return CGF.EmitScalarConversion( 3882 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3883 CGF.getContext().BoolTy, Loc); 3884 } 3885 3886 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3887 llvm::Value *NumThreads, 3888 SourceLocation Loc) { 3889 if (!CGF.HaveInsertPoint()) 3890 return; 3891 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3892 llvm::Value *Args[] = { 3893 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3894 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3895 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3896 Args); 3897 } 3898 3899 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3900 ProcBindKind ProcBind, 3901 SourceLocation Loc) { 3902 if (!CGF.HaveInsertPoint()) 3903 return; 3904 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 3905 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3906 llvm::Value *Args[] = { 3907 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3908 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 3909 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3910 } 3911 3912 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3913 SourceLocation Loc, llvm::AtomicOrdering AO) { 3914 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3915 if (OMPBuilder) { 3916 OMPBuilder->CreateFlush(CGF.Builder); 3917 } else { 3918 if (!CGF.HaveInsertPoint()) 3919 return; 3920 // Build call void __kmpc_flush(ident_t *loc) 3921 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3922 emitUpdateLocation(CGF, Loc)); 3923 } 3924 } 3925 3926 namespace { 3927 /// Indexes of fields for type kmp_task_t. 3928 enum KmpTaskTFields { 3929 /// List of shared variables. 3930 KmpTaskTShareds, 3931 /// Task routine. 3932 KmpTaskTRoutine, 3933 /// Partition id for the untied tasks. 3934 KmpTaskTPartId, 3935 /// Function with call of destructors for private variables. 3936 Data1, 3937 /// Task priority. 3938 Data2, 3939 /// (Taskloops only) Lower bound. 3940 KmpTaskTLowerBound, 3941 /// (Taskloops only) Upper bound. 3942 KmpTaskTUpperBound, 3943 /// (Taskloops only) Stride. 3944 KmpTaskTStride, 3945 /// (Taskloops only) Is last iteration flag. 3946 KmpTaskTLastIter, 3947 /// (Taskloops only) Reduction data. 3948 KmpTaskTReductions, 3949 }; 3950 } // anonymous namespace 3951 3952 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3953 return OffloadEntriesTargetRegion.empty() && 3954 OffloadEntriesDeviceGlobalVar.empty(); 3955 } 3956 3957 /// Initialize target region entry. 3958 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3959 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3960 StringRef ParentName, unsigned LineNum, 3961 unsigned Order) { 3962 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3963 "only required for the device " 3964 "code generation."); 3965 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3966 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3967 OMPTargetRegionEntryTargetRegion); 3968 ++OffloadingEntriesNum; 3969 } 3970 3971 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3972 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3973 StringRef ParentName, unsigned LineNum, 3974 llvm::Constant *Addr, llvm::Constant *ID, 3975 OMPTargetRegionEntryKind Flags) { 3976 // If we are emitting code for a target, the entry is already initialized, 3977 // only has to be registered. 3978 if (CGM.getLangOpts().OpenMPIsDevice) { 3979 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3980 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3981 DiagnosticsEngine::Error, 3982 "Unable to find target region on line '%0' in the device code."); 3983 CGM.getDiags().Report(DiagID) << LineNum; 3984 return; 3985 } 3986 auto &Entry = 3987 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3988 assert(Entry.isValid() && "Entry not initialized!"); 3989 Entry.setAddress(Addr); 3990 Entry.setID(ID); 3991 Entry.setFlags(Flags); 3992 } else { 3993 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3994 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3995 ++OffloadingEntriesNum; 3996 } 3997 } 3998 3999 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 4000 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4001 unsigned LineNum) const { 4002 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 4003 if (PerDevice == OffloadEntriesTargetRegion.end()) 4004 return false; 4005 auto PerFile = PerDevice->second.find(FileID); 4006 if (PerFile == PerDevice->second.end()) 4007 return false; 4008 auto PerParentName = PerFile->second.find(ParentName); 4009 if (PerParentName == PerFile->second.end()) 4010 return false; 4011 auto PerLine = PerParentName->second.find(LineNum); 4012 if (PerLine == PerParentName->second.end()) 4013 return false; 4014 // Fail if this entry is already registered. 4015 if (PerLine->second.getAddress() || PerLine->second.getID()) 4016 return false; 4017 return true; 4018 } 4019 4020 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 4021 const OffloadTargetRegionEntryInfoActTy &Action) { 4022 // Scan all target region entries and perform the provided action. 4023 for (const auto &D : OffloadEntriesTargetRegion) 4024 for (const auto &F : D.second) 4025 for (const auto &P : F.second) 4026 for (const auto &L : P.second) 4027 Action(D.first, F.first, P.first(), L.first, L.second); 4028 } 4029 4030 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4031 initializeDeviceGlobalVarEntryInfo(StringRef Name, 4032 OMPTargetGlobalVarEntryKind Flags, 4033 unsigned Order) { 4034 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 4035 "only required for the device " 4036 "code generation."); 4037 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 4038 ++OffloadingEntriesNum; 4039 } 4040 4041 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4042 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 4043 CharUnits VarSize, 4044 OMPTargetGlobalVarEntryKind Flags, 4045 llvm::GlobalValue::LinkageTypes Linkage) { 4046 if (CGM.getLangOpts().OpenMPIsDevice) { 4047 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4048 assert(Entry.isValid() && Entry.getFlags() == Flags && 4049 "Entry not initialized!"); 4050 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4051 "Resetting with the new address."); 4052 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 4053 if (Entry.getVarSize().isZero()) { 4054 Entry.setVarSize(VarSize); 4055 Entry.setLinkage(Linkage); 4056 } 4057 return; 4058 } 4059 Entry.setVarSize(VarSize); 4060 Entry.setLinkage(Linkage); 4061 Entry.setAddress(Addr); 4062 } else { 4063 if (hasDeviceGlobalVarEntryInfo(VarName)) { 4064 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4065 assert(Entry.isValid() && Entry.getFlags() == Flags && 4066 "Entry not initialized!"); 4067 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4068 "Resetting with the new address."); 4069 if (Entry.getVarSize().isZero()) { 4070 Entry.setVarSize(VarSize); 4071 Entry.setLinkage(Linkage); 4072 } 4073 return; 4074 } 4075 OffloadEntriesDeviceGlobalVar.try_emplace( 4076 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 4077 ++OffloadingEntriesNum; 4078 } 4079 } 4080 4081 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4082 actOnDeviceGlobalVarEntriesInfo( 4083 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4084 // Scan all target region entries and perform the provided action. 4085 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4086 Action(E.getKey(), E.getValue()); 4087 } 4088 4089 void CGOpenMPRuntime::createOffloadEntry( 4090 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4091 llvm::GlobalValue::LinkageTypes Linkage) { 4092 StringRef Name = Addr->getName(); 4093 llvm::Module &M = CGM.getModule(); 4094 llvm::LLVMContext &C = M.getContext(); 4095 4096 // Create constant string with the name. 4097 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4098 4099 std::string StringName = getName({"omp_offloading", "entry_name"}); 4100 auto *Str = new llvm::GlobalVariable( 4101 M, StrPtrInit->getType(), /*isConstant=*/true, 4102 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4103 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4104 4105 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4106 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4107 llvm::ConstantInt::get(CGM.SizeTy, Size), 4108 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4109 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4110 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4111 llvm::GlobalVariable *Entry = createGlobalStruct( 4112 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4113 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4114 4115 // The entry has to be created in the section the linker expects it to be. 4116 Entry->setSection("omp_offloading_entries"); 4117 } 4118 4119 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4120 // Emit the offloading entries and metadata so that the device codegen side 4121 // can easily figure out what to emit. The produced metadata looks like 4122 // this: 4123 // 4124 // !omp_offload.info = !{!1, ...} 4125 // 4126 // Right now we only generate metadata for function that contain target 4127 // regions. 4128 4129 // If we are in simd mode or there are no entries, we don't need to do 4130 // anything. 4131 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 4132 return; 4133 4134 llvm::Module &M = CGM.getModule(); 4135 llvm::LLVMContext &C = M.getContext(); 4136 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4137 SourceLocation, StringRef>, 4138 16> 4139 OrderedEntries(OffloadEntriesInfoManager.size()); 4140 llvm::SmallVector<StringRef, 16> ParentFunctions( 4141 OffloadEntriesInfoManager.size()); 4142 4143 // Auxiliary methods to create metadata values and strings. 4144 auto &&GetMDInt = [this](unsigned V) { 4145 return llvm::ConstantAsMetadata::get( 4146 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4147 }; 4148 4149 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4150 4151 // Create the offloading info metadata node. 4152 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4153 4154 // Create function that emits metadata for each target region entry; 4155 auto &&TargetRegionMetadataEmitter = 4156 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4157 &GetMDString]( 4158 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4159 unsigned Line, 4160 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4161 // Generate metadata for target regions. Each entry of this metadata 4162 // contains: 4163 // - Entry 0 -> Kind of this type of metadata (0). 4164 // - Entry 1 -> Device ID of the file where the entry was identified. 4165 // - Entry 2 -> File ID of the file where the entry was identified. 4166 // - Entry 3 -> Mangled name of the function where the entry was 4167 // identified. 4168 // - Entry 4 -> Line in the file where the entry was identified. 4169 // - Entry 5 -> Order the entry was created. 4170 // The first element of the metadata node is the kind. 4171 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4172 GetMDInt(FileID), GetMDString(ParentName), 4173 GetMDInt(Line), GetMDInt(E.getOrder())}; 4174 4175 SourceLocation Loc; 4176 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4177 E = CGM.getContext().getSourceManager().fileinfo_end(); 4178 I != E; ++I) { 4179 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4180 I->getFirst()->getUniqueID().getFile() == FileID) { 4181 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4182 I->getFirst(), Line, 1); 4183 break; 4184 } 4185 } 4186 // Save this entry in the right position of the ordered entries array. 4187 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4188 ParentFunctions[E.getOrder()] = ParentName; 4189 4190 // Add metadata to the named metadata node. 4191 MD->addOperand(llvm::MDNode::get(C, Ops)); 4192 }; 4193 4194 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4195 TargetRegionMetadataEmitter); 4196 4197 // Create function that emits metadata for each device global variable entry; 4198 auto &&DeviceGlobalVarMetadataEmitter = 4199 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4200 MD](StringRef MangledName, 4201 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4202 &E) { 4203 // Generate metadata for global variables. Each entry of this metadata 4204 // contains: 4205 // - Entry 0 -> Kind of this type of metadata (1). 4206 // - Entry 1 -> Mangled name of the variable. 4207 // - Entry 2 -> Declare target kind. 4208 // - Entry 3 -> Order the entry was created. 4209 // The first element of the metadata node is the kind. 4210 llvm::Metadata *Ops[] = { 4211 GetMDInt(E.getKind()), GetMDString(MangledName), 4212 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4213 4214 // Save this entry in the right position of the ordered entries array. 4215 OrderedEntries[E.getOrder()] = 4216 std::make_tuple(&E, SourceLocation(), MangledName); 4217 4218 // Add metadata to the named metadata node. 4219 MD->addOperand(llvm::MDNode::get(C, Ops)); 4220 }; 4221 4222 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4223 DeviceGlobalVarMetadataEmitter); 4224 4225 for (const auto &E : OrderedEntries) { 4226 assert(std::get<0>(E) && "All ordered entries must exist!"); 4227 if (const auto *CE = 4228 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4229 std::get<0>(E))) { 4230 if (!CE->getID() || !CE->getAddress()) { 4231 // Do not blame the entry if the parent funtion is not emitted. 4232 StringRef FnName = ParentFunctions[CE->getOrder()]; 4233 if (!CGM.GetGlobalValue(FnName)) 4234 continue; 4235 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4236 DiagnosticsEngine::Error, 4237 "Offloading entry for target region in %0 is incorrect: either the " 4238 "address or the ID is invalid."); 4239 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4240 continue; 4241 } 4242 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4243 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4244 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4245 OffloadEntryInfoDeviceGlobalVar>( 4246 std::get<0>(E))) { 4247 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4248 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4249 CE->getFlags()); 4250 switch (Flags) { 4251 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4252 if (CGM.getLangOpts().OpenMPIsDevice && 4253 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4254 continue; 4255 if (!CE->getAddress()) { 4256 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4257 DiagnosticsEngine::Error, "Offloading entry for declare target " 4258 "variable %0 is incorrect: the " 4259 "address is invalid."); 4260 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4261 continue; 4262 } 4263 // The vaiable has no definition - no need to add the entry. 4264 if (CE->getVarSize().isZero()) 4265 continue; 4266 break; 4267 } 4268 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4269 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4270 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4271 "Declaret target link address is set."); 4272 if (CGM.getLangOpts().OpenMPIsDevice) 4273 continue; 4274 if (!CE->getAddress()) { 4275 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4276 DiagnosticsEngine::Error, 4277 "Offloading entry for declare target variable is incorrect: the " 4278 "address is invalid."); 4279 CGM.getDiags().Report(DiagID); 4280 continue; 4281 } 4282 break; 4283 } 4284 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4285 CE->getVarSize().getQuantity(), Flags, 4286 CE->getLinkage()); 4287 } else { 4288 llvm_unreachable("Unsupported entry kind."); 4289 } 4290 } 4291 } 4292 4293 /// Loads all the offload entries information from the host IR 4294 /// metadata. 4295 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4296 // If we are in target mode, load the metadata from the host IR. This code has 4297 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4298 4299 if (!CGM.getLangOpts().OpenMPIsDevice) 4300 return; 4301 4302 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4303 return; 4304 4305 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4306 if (auto EC = Buf.getError()) { 4307 CGM.getDiags().Report(diag::err_cannot_open_file) 4308 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4309 return; 4310 } 4311 4312 llvm::LLVMContext C; 4313 auto ME = expectedToErrorOrAndEmitErrors( 4314 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4315 4316 if (auto EC = ME.getError()) { 4317 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4318 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4319 CGM.getDiags().Report(DiagID) 4320 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4321 return; 4322 } 4323 4324 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4325 if (!MD) 4326 return; 4327 4328 for (llvm::MDNode *MN : MD->operands()) { 4329 auto &&GetMDInt = [MN](unsigned Idx) { 4330 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4331 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4332 }; 4333 4334 auto &&GetMDString = [MN](unsigned Idx) { 4335 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4336 return V->getString(); 4337 }; 4338 4339 switch (GetMDInt(0)) { 4340 default: 4341 llvm_unreachable("Unexpected metadata!"); 4342 break; 4343 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4344 OffloadingEntryInfoTargetRegion: 4345 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4346 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4347 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4348 /*Order=*/GetMDInt(5)); 4349 break; 4350 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4351 OffloadingEntryInfoDeviceGlobalVar: 4352 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4353 /*MangledName=*/GetMDString(1), 4354 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4355 /*Flags=*/GetMDInt(2)), 4356 /*Order=*/GetMDInt(3)); 4357 break; 4358 } 4359 } 4360 } 4361 4362 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4363 if (!KmpRoutineEntryPtrTy) { 4364 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4365 ASTContext &C = CGM.getContext(); 4366 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4367 FunctionProtoType::ExtProtoInfo EPI; 4368 KmpRoutineEntryPtrQTy = C.getPointerType( 4369 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4370 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4371 } 4372 } 4373 4374 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4375 // Make sure the type of the entry is already created. This is the type we 4376 // have to create: 4377 // struct __tgt_offload_entry{ 4378 // void *addr; // Pointer to the offload entry info. 4379 // // (function or global) 4380 // char *name; // Name of the function or global. 4381 // size_t size; // Size of the entry info (0 if it a function). 4382 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4383 // int32_t reserved; // Reserved, to use by the runtime library. 4384 // }; 4385 if (TgtOffloadEntryQTy.isNull()) { 4386 ASTContext &C = CGM.getContext(); 4387 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4388 RD->startDefinition(); 4389 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4390 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4391 addFieldToRecordDecl(C, RD, C.getSizeType()); 4392 addFieldToRecordDecl( 4393 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4394 addFieldToRecordDecl( 4395 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4396 RD->completeDefinition(); 4397 RD->addAttr(PackedAttr::CreateImplicit(C)); 4398 TgtOffloadEntryQTy = C.getRecordType(RD); 4399 } 4400 return TgtOffloadEntryQTy; 4401 } 4402 4403 namespace { 4404 struct PrivateHelpersTy { 4405 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original, 4406 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit) 4407 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy), 4408 PrivateElemInit(PrivateElemInit) {} 4409 const Expr *OriginalRef = nullptr; 4410 const VarDecl *Original = nullptr; 4411 const VarDecl *PrivateCopy = nullptr; 4412 const VarDecl *PrivateElemInit = nullptr; 4413 }; 4414 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4415 } // anonymous namespace 4416 4417 static RecordDecl * 4418 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4419 if (!Privates.empty()) { 4420 ASTContext &C = CGM.getContext(); 4421 // Build struct .kmp_privates_t. { 4422 // /* private vars */ 4423 // }; 4424 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4425 RD->startDefinition(); 4426 for (const auto &Pair : Privates) { 4427 const VarDecl *VD = Pair.second.Original; 4428 QualType Type = VD->getType().getNonReferenceType(); 4429 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4430 if (VD->hasAttrs()) { 4431 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4432 E(VD->getAttrs().end()); 4433 I != E; ++I) 4434 FD->addAttr(*I); 4435 } 4436 } 4437 RD->completeDefinition(); 4438 return RD; 4439 } 4440 return nullptr; 4441 } 4442 4443 static RecordDecl * 4444 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4445 QualType KmpInt32Ty, 4446 QualType KmpRoutineEntryPointerQTy) { 4447 ASTContext &C = CGM.getContext(); 4448 // Build struct kmp_task_t { 4449 // void * shareds; 4450 // kmp_routine_entry_t routine; 4451 // kmp_int32 part_id; 4452 // kmp_cmplrdata_t data1; 4453 // kmp_cmplrdata_t data2; 4454 // For taskloops additional fields: 4455 // kmp_uint64 lb; 4456 // kmp_uint64 ub; 4457 // kmp_int64 st; 4458 // kmp_int32 liter; 4459 // void * reductions; 4460 // }; 4461 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4462 UD->startDefinition(); 4463 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4464 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4465 UD->completeDefinition(); 4466 QualType KmpCmplrdataTy = C.getRecordType(UD); 4467 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4468 RD->startDefinition(); 4469 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4470 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4471 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4472 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4473 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4474 if (isOpenMPTaskLoopDirective(Kind)) { 4475 QualType KmpUInt64Ty = 4476 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4477 QualType KmpInt64Ty = 4478 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4479 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4480 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4481 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4482 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4483 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4484 } 4485 RD->completeDefinition(); 4486 return RD; 4487 } 4488 4489 static RecordDecl * 4490 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4491 ArrayRef<PrivateDataTy> Privates) { 4492 ASTContext &C = CGM.getContext(); 4493 // Build struct kmp_task_t_with_privates { 4494 // kmp_task_t task_data; 4495 // .kmp_privates_t. privates; 4496 // }; 4497 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4498 RD->startDefinition(); 4499 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4500 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4501 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4502 RD->completeDefinition(); 4503 return RD; 4504 } 4505 4506 /// Emit a proxy function which accepts kmp_task_t as the second 4507 /// argument. 4508 /// \code 4509 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4510 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4511 /// For taskloops: 4512 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4513 /// tt->reductions, tt->shareds); 4514 /// return 0; 4515 /// } 4516 /// \endcode 4517 static llvm::Function * 4518 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4519 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4520 QualType KmpTaskTWithPrivatesPtrQTy, 4521 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4522 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4523 llvm::Value *TaskPrivatesMap) { 4524 ASTContext &C = CGM.getContext(); 4525 FunctionArgList Args; 4526 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4527 ImplicitParamDecl::Other); 4528 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4529 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4530 ImplicitParamDecl::Other); 4531 Args.push_back(&GtidArg); 4532 Args.push_back(&TaskTypeArg); 4533 const auto &TaskEntryFnInfo = 4534 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4535 llvm::FunctionType *TaskEntryTy = 4536 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4537 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4538 auto *TaskEntry = llvm::Function::Create( 4539 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4540 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4541 TaskEntry->setDoesNotRecurse(); 4542 CodeGenFunction CGF(CGM); 4543 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4544 Loc, Loc); 4545 4546 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4547 // tt, 4548 // For taskloops: 4549 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4550 // tt->task_data.shareds); 4551 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4552 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4553 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4554 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4555 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4556 const auto *KmpTaskTWithPrivatesQTyRD = 4557 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4558 LValue Base = 4559 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4560 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4561 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4562 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4563 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 4564 4565 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4566 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4567 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4568 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4569 CGF.ConvertTypeForMem(SharedsPtrTy)); 4570 4571 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4572 llvm::Value *PrivatesParam; 4573 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4574 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4575 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4576 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 4577 } else { 4578 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4579 } 4580 4581 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4582 TaskPrivatesMap, 4583 CGF.Builder 4584 .CreatePointerBitCastOrAddrSpaceCast( 4585 TDBase.getAddress(CGF), CGF.VoidPtrTy) 4586 .getPointer()}; 4587 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4588 std::end(CommonArgs)); 4589 if (isOpenMPTaskLoopDirective(Kind)) { 4590 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4591 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4592 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4593 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4594 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4595 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4596 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4597 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4598 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4599 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4600 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4601 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4602 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4603 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4604 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4605 CallArgs.push_back(LBParam); 4606 CallArgs.push_back(UBParam); 4607 CallArgs.push_back(StParam); 4608 CallArgs.push_back(LIParam); 4609 CallArgs.push_back(RParam); 4610 } 4611 CallArgs.push_back(SharedsParam); 4612 4613 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4614 CallArgs); 4615 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4616 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4617 CGF.FinishFunction(); 4618 return TaskEntry; 4619 } 4620 4621 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4622 SourceLocation Loc, 4623 QualType KmpInt32Ty, 4624 QualType KmpTaskTWithPrivatesPtrQTy, 4625 QualType KmpTaskTWithPrivatesQTy) { 4626 ASTContext &C = CGM.getContext(); 4627 FunctionArgList Args; 4628 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4629 ImplicitParamDecl::Other); 4630 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4631 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4632 ImplicitParamDecl::Other); 4633 Args.push_back(&GtidArg); 4634 Args.push_back(&TaskTypeArg); 4635 const auto &DestructorFnInfo = 4636 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4637 llvm::FunctionType *DestructorFnTy = 4638 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4639 std::string Name = 4640 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4641 auto *DestructorFn = 4642 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4643 Name, &CGM.getModule()); 4644 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4645 DestructorFnInfo); 4646 DestructorFn->setDoesNotRecurse(); 4647 CodeGenFunction CGF(CGM); 4648 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4649 Args, Loc, Loc); 4650 4651 LValue Base = CGF.EmitLoadOfPointerLValue( 4652 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4653 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4654 const auto *KmpTaskTWithPrivatesQTyRD = 4655 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4656 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4657 Base = CGF.EmitLValueForField(Base, *FI); 4658 for (const auto *Field : 4659 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4660 if (QualType::DestructionKind DtorKind = 4661 Field->getType().isDestructedType()) { 4662 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4663 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 4664 } 4665 } 4666 CGF.FinishFunction(); 4667 return DestructorFn; 4668 } 4669 4670 /// Emit a privates mapping function for correct handling of private and 4671 /// firstprivate variables. 4672 /// \code 4673 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4674 /// **noalias priv1,..., <tyn> **noalias privn) { 4675 /// *priv1 = &.privates.priv1; 4676 /// ...; 4677 /// *privn = &.privates.privn; 4678 /// } 4679 /// \endcode 4680 static llvm::Value * 4681 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4682 ArrayRef<const Expr *> PrivateVars, 4683 ArrayRef<const Expr *> FirstprivateVars, 4684 ArrayRef<const Expr *> LastprivateVars, 4685 QualType PrivatesQTy, 4686 ArrayRef<PrivateDataTy> Privates) { 4687 ASTContext &C = CGM.getContext(); 4688 FunctionArgList Args; 4689 ImplicitParamDecl TaskPrivatesArg( 4690 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4691 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4692 ImplicitParamDecl::Other); 4693 Args.push_back(&TaskPrivatesArg); 4694 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4695 unsigned Counter = 1; 4696 for (const Expr *E : PrivateVars) { 4697 Args.push_back(ImplicitParamDecl::Create( 4698 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4699 C.getPointerType(C.getPointerType(E->getType())) 4700 .withConst() 4701 .withRestrict(), 4702 ImplicitParamDecl::Other)); 4703 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4704 PrivateVarsPos[VD] = Counter; 4705 ++Counter; 4706 } 4707 for (const Expr *E : FirstprivateVars) { 4708 Args.push_back(ImplicitParamDecl::Create( 4709 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4710 C.getPointerType(C.getPointerType(E->getType())) 4711 .withConst() 4712 .withRestrict(), 4713 ImplicitParamDecl::Other)); 4714 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4715 PrivateVarsPos[VD] = Counter; 4716 ++Counter; 4717 } 4718 for (const Expr *E : LastprivateVars) { 4719 Args.push_back(ImplicitParamDecl::Create( 4720 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4721 C.getPointerType(C.getPointerType(E->getType())) 4722 .withConst() 4723 .withRestrict(), 4724 ImplicitParamDecl::Other)); 4725 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4726 PrivateVarsPos[VD] = Counter; 4727 ++Counter; 4728 } 4729 const auto &TaskPrivatesMapFnInfo = 4730 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4731 llvm::FunctionType *TaskPrivatesMapTy = 4732 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4733 std::string Name = 4734 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4735 auto *TaskPrivatesMap = llvm::Function::Create( 4736 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4737 &CGM.getModule()); 4738 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4739 TaskPrivatesMapFnInfo); 4740 if (CGM.getLangOpts().Optimize) { 4741 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4742 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4743 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4744 } 4745 CodeGenFunction CGF(CGM); 4746 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4747 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4748 4749 // *privi = &.privates.privi; 4750 LValue Base = CGF.EmitLoadOfPointerLValue( 4751 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4752 TaskPrivatesArg.getType()->castAs<PointerType>()); 4753 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4754 Counter = 0; 4755 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4756 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4757 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4758 LValue RefLVal = 4759 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4760 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4761 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 4762 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 4763 ++Counter; 4764 } 4765 CGF.FinishFunction(); 4766 return TaskPrivatesMap; 4767 } 4768 4769 /// Emit initialization for private variables in task-based directives. 4770 static void emitPrivatesInit(CodeGenFunction &CGF, 4771 const OMPExecutableDirective &D, 4772 Address KmpTaskSharedsPtr, LValue TDBase, 4773 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4774 QualType SharedsTy, QualType SharedsPtrTy, 4775 const OMPTaskDataTy &Data, 4776 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4777 ASTContext &C = CGF.getContext(); 4778 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4779 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4780 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4781 ? OMPD_taskloop 4782 : OMPD_task; 4783 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4784 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4785 LValue SrcBase; 4786 bool IsTargetTask = 4787 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4788 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4789 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4790 // PointersArray and SizesArray. The original variables for these arrays are 4791 // not captured and we get their addresses explicitly. 4792 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) || 4793 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4794 SrcBase = CGF.MakeAddrLValue( 4795 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4796 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4797 SharedsTy); 4798 } 4799 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4800 for (const PrivateDataTy &Pair : Privates) { 4801 const VarDecl *VD = Pair.second.PrivateCopy; 4802 const Expr *Init = VD->getAnyInitializer(); 4803 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4804 !CGF.isTrivialInitializer(Init)))) { 4805 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4806 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4807 const VarDecl *OriginalVD = Pair.second.Original; 4808 // Check if the variable is the target-based BasePointersArray, 4809 // PointersArray or SizesArray. 4810 LValue SharedRefLValue; 4811 QualType Type = PrivateLValue.getType(); 4812 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4813 if (IsTargetTask && !SharedField) { 4814 assert(isa<ImplicitParamDecl>(OriginalVD) && 4815 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4816 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4817 ->getNumParams() == 0 && 4818 isa<TranslationUnitDecl>( 4819 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4820 ->getDeclContext()) && 4821 "Expected artificial target data variable."); 4822 SharedRefLValue = 4823 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4824 } else if (ForDup) { 4825 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4826 SharedRefLValue = CGF.MakeAddrLValue( 4827 Address(SharedRefLValue.getPointer(CGF), 4828 C.getDeclAlign(OriginalVD)), 4829 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4830 SharedRefLValue.getTBAAInfo()); 4831 } else { 4832 InlinedOpenMPRegionRAII Region( 4833 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown, 4834 /*HasCancel=*/false); 4835 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 4836 } 4837 if (Type->isArrayType()) { 4838 // Initialize firstprivate array. 4839 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4840 // Perform simple memcpy. 4841 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4842 } else { 4843 // Initialize firstprivate array using element-by-element 4844 // initialization. 4845 CGF.EmitOMPAggregateAssign( 4846 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 4847 Type, 4848 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4849 Address SrcElement) { 4850 // Clean up any temporaries needed by the initialization. 4851 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4852 InitScope.addPrivate( 4853 Elem, [SrcElement]() -> Address { return SrcElement; }); 4854 (void)InitScope.Privatize(); 4855 // Emit initialization for single element. 4856 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4857 CGF, &CapturesInfo); 4858 CGF.EmitAnyExprToMem(Init, DestElement, 4859 Init->getType().getQualifiers(), 4860 /*IsInitializer=*/false); 4861 }); 4862 } 4863 } else { 4864 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4865 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 4866 return SharedRefLValue.getAddress(CGF); 4867 }); 4868 (void)InitScope.Privatize(); 4869 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4870 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4871 /*capturedByInit=*/false); 4872 } 4873 } else { 4874 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4875 } 4876 } 4877 ++FI; 4878 } 4879 } 4880 4881 /// Check if duplication function is required for taskloops. 4882 static bool checkInitIsRequired(CodeGenFunction &CGF, 4883 ArrayRef<PrivateDataTy> Privates) { 4884 bool InitRequired = false; 4885 for (const PrivateDataTy &Pair : Privates) { 4886 const VarDecl *VD = Pair.second.PrivateCopy; 4887 const Expr *Init = VD->getAnyInitializer(); 4888 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4889 !CGF.isTrivialInitializer(Init)); 4890 if (InitRequired) 4891 break; 4892 } 4893 return InitRequired; 4894 } 4895 4896 4897 /// Emit task_dup function (for initialization of 4898 /// private/firstprivate/lastprivate vars and last_iter flag) 4899 /// \code 4900 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4901 /// lastpriv) { 4902 /// // setup lastprivate flag 4903 /// task_dst->last = lastpriv; 4904 /// // could be constructor calls here... 4905 /// } 4906 /// \endcode 4907 static llvm::Value * 4908 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4909 const OMPExecutableDirective &D, 4910 QualType KmpTaskTWithPrivatesPtrQTy, 4911 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4912 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4913 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4914 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4915 ASTContext &C = CGM.getContext(); 4916 FunctionArgList Args; 4917 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4918 KmpTaskTWithPrivatesPtrQTy, 4919 ImplicitParamDecl::Other); 4920 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4921 KmpTaskTWithPrivatesPtrQTy, 4922 ImplicitParamDecl::Other); 4923 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4924 ImplicitParamDecl::Other); 4925 Args.push_back(&DstArg); 4926 Args.push_back(&SrcArg); 4927 Args.push_back(&LastprivArg); 4928 const auto &TaskDupFnInfo = 4929 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4930 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4931 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4932 auto *TaskDup = llvm::Function::Create( 4933 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4934 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4935 TaskDup->setDoesNotRecurse(); 4936 CodeGenFunction CGF(CGM); 4937 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4938 Loc); 4939 4940 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4941 CGF.GetAddrOfLocalVar(&DstArg), 4942 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4943 // task_dst->liter = lastpriv; 4944 if (WithLastIter) { 4945 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4946 LValue Base = CGF.EmitLValueForField( 4947 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4948 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4949 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4950 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4951 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4952 } 4953 4954 // Emit initial values for private copies (if any). 4955 assert(!Privates.empty()); 4956 Address KmpTaskSharedsPtr = Address::invalid(); 4957 if (!Data.FirstprivateVars.empty()) { 4958 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4959 CGF.GetAddrOfLocalVar(&SrcArg), 4960 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4961 LValue Base = CGF.EmitLValueForField( 4962 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4963 KmpTaskSharedsPtr = Address( 4964 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4965 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4966 KmpTaskTShareds)), 4967 Loc), 4968 CGF.getNaturalTypeAlignment(SharedsTy)); 4969 } 4970 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4971 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4972 CGF.FinishFunction(); 4973 return TaskDup; 4974 } 4975 4976 /// Checks if destructor function is required to be generated. 4977 /// \return true if cleanups are required, false otherwise. 4978 static bool 4979 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4980 bool NeedsCleanup = false; 4981 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4982 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4983 for (const FieldDecl *FD : PrivateRD->fields()) { 4984 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4985 if (NeedsCleanup) 4986 break; 4987 } 4988 return NeedsCleanup; 4989 } 4990 4991 CGOpenMPRuntime::TaskResultTy 4992 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4993 const OMPExecutableDirective &D, 4994 llvm::Function *TaskFunction, QualType SharedsTy, 4995 Address Shareds, const OMPTaskDataTy &Data) { 4996 ASTContext &C = CGM.getContext(); 4997 llvm::SmallVector<PrivateDataTy, 4> Privates; 4998 // Aggregate privates and sort them by the alignment. 4999 const auto *I = Data.PrivateCopies.begin(); 5000 for (const Expr *E : Data.PrivateVars) { 5001 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5002 Privates.emplace_back( 5003 C.getDeclAlign(VD), 5004 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5005 /*PrivateElemInit=*/nullptr)); 5006 ++I; 5007 } 5008 I = Data.FirstprivateCopies.begin(); 5009 const auto *IElemInitRef = Data.FirstprivateInits.begin(); 5010 for (const Expr *E : Data.FirstprivateVars) { 5011 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5012 Privates.emplace_back( 5013 C.getDeclAlign(VD), 5014 PrivateHelpersTy( 5015 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5016 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 5017 ++I; 5018 ++IElemInitRef; 5019 } 5020 I = Data.LastprivateCopies.begin(); 5021 for (const Expr *E : Data.LastprivateVars) { 5022 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5023 Privates.emplace_back( 5024 C.getDeclAlign(VD), 5025 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5026 /*PrivateElemInit=*/nullptr)); 5027 ++I; 5028 } 5029 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 5030 return L.first > R.first; 5031 }); 5032 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 5033 // Build type kmp_routine_entry_t (if not built yet). 5034 emitKmpRoutineEntryT(KmpInt32Ty); 5035 // Build type kmp_task_t (if not built yet). 5036 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 5037 if (SavedKmpTaskloopTQTy.isNull()) { 5038 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5039 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5040 } 5041 KmpTaskTQTy = SavedKmpTaskloopTQTy; 5042 } else { 5043 assert((D.getDirectiveKind() == OMPD_task || 5044 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 5045 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5046 "Expected taskloop, task or target directive"); 5047 if (SavedKmpTaskTQTy.isNull()) { 5048 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5049 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5050 } 5051 KmpTaskTQTy = SavedKmpTaskTQTy; 5052 } 5053 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5054 // Build particular struct kmp_task_t for the given task. 5055 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5056 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5057 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5058 QualType KmpTaskTWithPrivatesPtrQTy = 5059 C.getPointerType(KmpTaskTWithPrivatesQTy); 5060 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5061 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5062 KmpTaskTWithPrivatesTy->getPointerTo(); 5063 llvm::Value *KmpTaskTWithPrivatesTySize = 5064 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5065 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5066 5067 // Emit initial values for private copies (if any). 5068 llvm::Value *TaskPrivatesMap = nullptr; 5069 llvm::Type *TaskPrivatesMapTy = 5070 std::next(TaskFunction->arg_begin(), 3)->getType(); 5071 if (!Privates.empty()) { 5072 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5073 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5074 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5075 FI->getType(), Privates); 5076 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5077 TaskPrivatesMap, TaskPrivatesMapTy); 5078 } else { 5079 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5080 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5081 } 5082 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5083 // kmp_task_t *tt); 5084 llvm::Function *TaskEntry = emitProxyTaskFunction( 5085 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5086 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5087 TaskPrivatesMap); 5088 5089 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5090 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5091 // kmp_routine_entry_t *task_entry); 5092 // Task flags. Format is taken from 5093 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5094 // description of kmp_tasking_flags struct. 5095 enum { 5096 TiedFlag = 0x1, 5097 FinalFlag = 0x2, 5098 DestructorsFlag = 0x8, 5099 PriorityFlag = 0x20, 5100 DetachableFlag = 0x40, 5101 }; 5102 unsigned Flags = Data.Tied ? TiedFlag : 0; 5103 bool NeedsCleanup = false; 5104 if (!Privates.empty()) { 5105 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5106 if (NeedsCleanup) 5107 Flags = Flags | DestructorsFlag; 5108 } 5109 if (Data.Priority.getInt()) 5110 Flags = Flags | PriorityFlag; 5111 if (D.hasClausesOfKind<OMPDetachClause>()) 5112 Flags = Flags | DetachableFlag; 5113 llvm::Value *TaskFlags = 5114 Data.Final.getPointer() 5115 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5116 CGF.Builder.getInt32(FinalFlag), 5117 CGF.Builder.getInt32(/*C=*/0)) 5118 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5119 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5120 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5121 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5122 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5123 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5124 TaskEntry, KmpRoutineEntryPtrTy)}; 5125 llvm::Value *NewTask; 5126 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5127 // Check if we have any device clause associated with the directive. 5128 const Expr *Device = nullptr; 5129 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5130 Device = C->getDevice(); 5131 // Emit device ID if any otherwise use default value. 5132 llvm::Value *DeviceID; 5133 if (Device) 5134 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5135 CGF.Int64Ty, /*isSigned=*/true); 5136 else 5137 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5138 AllocArgs.push_back(DeviceID); 5139 NewTask = CGF.EmitRuntimeCall( 5140 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5141 } else { 5142 NewTask = CGF.EmitRuntimeCall( 5143 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5144 } 5145 // Emit detach clause initialization. 5146 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid, 5147 // task_descriptor); 5148 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) { 5149 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts(); 5150 LValue EvtLVal = CGF.EmitLValue(Evt); 5151 5152 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 5153 // int gtid, kmp_task_t *task); 5154 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc()); 5155 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc()); 5156 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false); 5157 llvm::Value *EvtVal = CGF.EmitRuntimeCall( 5158 createRuntimeFunction(OMPRTL__kmpc_task_allow_completion_event), 5159 {Loc, Tid, NewTask}); 5160 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(), 5161 Evt->getExprLoc()); 5162 CGF.EmitStoreOfScalar(EvtVal, EvtLVal); 5163 } 5164 llvm::Value *NewTaskNewTaskTTy = 5165 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5166 NewTask, KmpTaskTWithPrivatesPtrTy); 5167 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5168 KmpTaskTWithPrivatesQTy); 5169 LValue TDBase = 5170 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5171 // Fill the data in the resulting kmp_task_t record. 5172 // Copy shareds if there are any. 5173 Address KmpTaskSharedsPtr = Address::invalid(); 5174 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5175 KmpTaskSharedsPtr = 5176 Address(CGF.EmitLoadOfScalar( 5177 CGF.EmitLValueForField( 5178 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5179 KmpTaskTShareds)), 5180 Loc), 5181 CGF.getNaturalTypeAlignment(SharedsTy)); 5182 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5183 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5184 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5185 } 5186 // Emit initial values for private copies (if any). 5187 TaskResultTy Result; 5188 if (!Privates.empty()) { 5189 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5190 SharedsTy, SharedsPtrTy, Data, Privates, 5191 /*ForDup=*/false); 5192 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5193 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5194 Result.TaskDupFn = emitTaskDupFunction( 5195 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5196 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5197 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5198 } 5199 } 5200 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5201 enum { Priority = 0, Destructors = 1 }; 5202 // Provide pointer to function with destructors for privates. 5203 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5204 const RecordDecl *KmpCmplrdataUD = 5205 (*FI)->getType()->getAsUnionType()->getDecl(); 5206 if (NeedsCleanup) { 5207 llvm::Value *DestructorFn = emitDestructorsFunction( 5208 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5209 KmpTaskTWithPrivatesQTy); 5210 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5211 LValue DestructorsLV = CGF.EmitLValueForField( 5212 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5213 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5214 DestructorFn, KmpRoutineEntryPtrTy), 5215 DestructorsLV); 5216 } 5217 // Set priority. 5218 if (Data.Priority.getInt()) { 5219 LValue Data2LV = CGF.EmitLValueForField( 5220 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5221 LValue PriorityLV = CGF.EmitLValueForField( 5222 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5223 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5224 } 5225 Result.NewTask = NewTask; 5226 Result.TaskEntry = TaskEntry; 5227 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5228 Result.TDBase = TDBase; 5229 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5230 return Result; 5231 } 5232 5233 namespace { 5234 /// Dependence kind for RTL. 5235 enum RTLDependenceKindTy { 5236 DepIn = 0x01, 5237 DepInOut = 0x3, 5238 DepMutexInOutSet = 0x4 5239 }; 5240 /// Fields ids in kmp_depend_info record. 5241 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5242 } // namespace 5243 5244 /// Translates internal dependency kind into the runtime kind. 5245 static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) { 5246 RTLDependenceKindTy DepKind; 5247 switch (K) { 5248 case OMPC_DEPEND_in: 5249 DepKind = DepIn; 5250 break; 5251 // Out and InOut dependencies must use the same code. 5252 case OMPC_DEPEND_out: 5253 case OMPC_DEPEND_inout: 5254 DepKind = DepInOut; 5255 break; 5256 case OMPC_DEPEND_mutexinoutset: 5257 DepKind = DepMutexInOutSet; 5258 break; 5259 case OMPC_DEPEND_source: 5260 case OMPC_DEPEND_sink: 5261 case OMPC_DEPEND_depobj: 5262 case OMPC_DEPEND_unknown: 5263 llvm_unreachable("Unknown task dependence type"); 5264 } 5265 return DepKind; 5266 } 5267 5268 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 5269 static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, 5270 QualType &FlagsTy) { 5271 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5272 if (KmpDependInfoTy.isNull()) { 5273 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5274 KmpDependInfoRD->startDefinition(); 5275 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5276 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5277 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5278 KmpDependInfoRD->completeDefinition(); 5279 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5280 } 5281 } 5282 5283 std::pair<llvm::Value *, LValue> 5284 CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, 5285 SourceLocation Loc) { 5286 ASTContext &C = CGM.getContext(); 5287 QualType FlagsTy; 5288 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5289 RecordDecl *KmpDependInfoRD = 5290 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5291 LValue Base = CGF.EmitLoadOfPointerLValue( 5292 DepobjLVal.getAddress(CGF), 5293 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5294 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5295 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5296 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 5297 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 5298 Base.getTBAAInfo()); 5299 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5300 Addr.getPointer(), 5301 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5302 LValue NumDepsBase = CGF.MakeAddrLValue( 5303 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 5304 Base.getBaseInfo(), Base.getTBAAInfo()); 5305 // NumDeps = deps[i].base_addr; 5306 LValue BaseAddrLVal = CGF.EmitLValueForField( 5307 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5308 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc); 5309 return std::make_pair(NumDeps, Base); 5310 } 5311 5312 std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause( 5313 CodeGenFunction &CGF, 5314 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependencies, 5315 bool ForDepobj, SourceLocation Loc) { 5316 // Process list of dependencies. 5317 ASTContext &C = CGM.getContext(); 5318 Address DependenciesArray = Address::invalid(); 5319 unsigned NumDependencies = Dependencies.size(); 5320 llvm::Value *NumOfElements = nullptr; 5321 if (NumDependencies) { 5322 QualType FlagsTy; 5323 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5324 RecordDecl *KmpDependInfoRD = 5325 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5326 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5327 unsigned NumDepobjDependecies = 0; 5328 SmallVector<std::pair<llvm::Value *, LValue>, 4> Depobjs; 5329 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0); 5330 // Calculate number of depobj dependecies. 5331 for (const std::pair<OpenMPDependClauseKind, const Expr *> &Pair : 5332 Dependencies) { 5333 if (Pair.first != OMPC_DEPEND_depobj) 5334 continue; 5335 LValue DepobjLVal = CGF.EmitLValue(Pair.second); 5336 llvm::Value *NumDeps; 5337 LValue Base; 5338 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 5339 NumOfDepobjElements = 5340 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumDeps); 5341 Depobjs.emplace_back(NumDeps, Base); 5342 ++NumDepobjDependecies; 5343 } 5344 5345 QualType KmpDependInfoArrayTy; 5346 // Define type kmp_depend_info[<Dependencies.size()>]; 5347 // For depobj reserve one extra element to store the number of elements. 5348 // It is required to handle depobj(x) update(in) construct. 5349 // kmp_depend_info[<Dependencies.size()>] deps; 5350 if (ForDepobj) { 5351 assert(NumDepobjDependecies == 0 && 5352 "depobj dependency kind is not expected in depobj directive."); 5353 KmpDependInfoArrayTy = C.getConstantArrayType( 5354 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1), 5355 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5356 // Need to allocate on the dynamic memory. 5357 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5358 // Use default allocator. 5359 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5360 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoArrayTy); 5361 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy); 5362 llvm::Value *Size = CGF.CGM.getSize(Sz.alignTo(Align)); 5363 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 5364 5365 llvm::Value *Addr = CGF.EmitRuntimeCall( 5366 createRuntimeFunction(OMPRTL__kmpc_alloc), Args, ".dep.arr.addr"); 5367 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5368 Addr, CGF.ConvertTypeForMem(KmpDependInfoArrayTy)->getPointerTo()); 5369 DependenciesArray = Address(Addr, Align); 5370 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 5371 /*isSigned=*/false); 5372 } else if (NumDepobjDependecies > 0) { 5373 NumOfElements = CGF.Builder.CreateNUWAdd( 5374 NumOfDepobjElements, 5375 llvm::ConstantInt::get(CGM.IntPtrTy, 5376 NumDependencies - NumDepobjDependecies, 5377 /*isSigned=*/false)); 5378 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 5379 /*isSigned=*/false); 5380 OpaqueValueExpr OVE( 5381 Loc, C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0), 5382 VK_RValue); 5383 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 5384 RValue::get(NumOfElements)); 5385 KmpDependInfoArrayTy = 5386 C.getVariableArrayType(KmpDependInfoTy, &OVE, ArrayType::Normal, 5387 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 5388 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy); 5389 // Properly emit variable-sized array. 5390 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy, 5391 ImplicitParamDecl::Other); 5392 CGF.EmitVarDecl(*PD); 5393 DependenciesArray = CGF.GetAddrOfLocalVar(PD); 5394 } else { 5395 KmpDependInfoArrayTy = C.getConstantArrayType( 5396 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5397 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5398 DependenciesArray = 5399 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5400 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 5401 /*isSigned=*/false); 5402 } 5403 if (ForDepobj) { 5404 // Write number of elements in the first element of array for depobj. 5405 llvm::Value *NumVal = 5406 llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies); 5407 LValue Base = CGF.MakeAddrLValue( 5408 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), 5409 KmpDependInfoTy); 5410 // deps[i].base_addr = NumDependencies; 5411 LValue BaseAddrLVal = CGF.EmitLValueForField( 5412 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5413 CGF.EmitStoreOfScalar(NumVal, BaseAddrLVal); 5414 } 5415 unsigned Pos = ForDepobj ? 1 : 0; 5416 for (unsigned I = 0; I < NumDependencies; ++I) { 5417 if (Dependencies[I].first == OMPC_DEPEND_depobj) 5418 continue; 5419 const Expr *E = Dependencies[I].second; 5420 LValue Addr = CGF.EmitLValue(E); 5421 llvm::Value *Size; 5422 QualType Ty = E->getType(); 5423 if (const auto *ASE = 5424 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5425 LValue UpAddrLVal = 5426 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5427 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 5428 UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 5429 llvm::Value *LowIntPtr = 5430 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy); 5431 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5432 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5433 } else { 5434 Size = CGF.getTypeSize(Ty); 5435 } 5436 LValue Base; 5437 if (NumDepobjDependecies > 0) { 5438 Base = CGF.MakeAddrLValue( 5439 CGF.Builder.CreateConstGEP(DependenciesArray, Pos), 5440 KmpDependInfoTy); 5441 } else { 5442 Base = CGF.MakeAddrLValue( 5443 CGF.Builder.CreateConstArrayGEP(DependenciesArray, Pos), 5444 KmpDependInfoTy); 5445 } 5446 // deps[i].base_addr = &<Dependencies[i].second>; 5447 LValue BaseAddrLVal = CGF.EmitLValueForField( 5448 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5449 CGF.EmitStoreOfScalar( 5450 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy), 5451 BaseAddrLVal); 5452 // deps[i].len = sizeof(<Dependencies[i].second>); 5453 LValue LenLVal = CGF.EmitLValueForField( 5454 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5455 CGF.EmitStoreOfScalar(Size, LenLVal); 5456 // deps[i].flags = <Dependencies[i].first>; 5457 RTLDependenceKindTy DepKind = 5458 translateDependencyKind(Dependencies[I].first); 5459 LValue FlagsLVal = CGF.EmitLValueForField( 5460 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5461 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5462 FlagsLVal); 5463 ++Pos; 5464 } 5465 // Copy final depobj arrays. 5466 if (NumDepobjDependecies > 0) { 5467 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy); 5468 Address Addr = CGF.Builder.CreateConstGEP(DependenciesArray, Pos); 5469 for (const std::pair<llvm::Value *, LValue> &Pair : Depobjs) { 5470 llvm::Value *Size = CGF.Builder.CreateNUWMul(ElSize, Pair.first); 5471 CGF.Builder.CreateMemCpy(Addr, Pair.second.getAddress(CGF), Size); 5472 Addr = 5473 Address(CGF.Builder.CreateGEP( 5474 Addr.getElementType(), Addr.getPointer(), Pair.first), 5475 DependenciesArray.getAlignment().alignmentOfArrayElement( 5476 C.getTypeSizeInChars(KmpDependInfoTy))); 5477 } 5478 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5479 DependenciesArray, CGF.VoidPtrTy); 5480 } else { 5481 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5482 CGF.Builder.CreateConstArrayGEP(DependenciesArray, ForDepobj ? 1 : 0), 5483 CGF.VoidPtrTy); 5484 } 5485 } 5486 return std::make_pair(NumOfElements, DependenciesArray); 5487 } 5488 5489 void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, 5490 SourceLocation Loc) { 5491 ASTContext &C = CGM.getContext(); 5492 QualType FlagsTy; 5493 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5494 LValue Base = CGF.EmitLoadOfPointerLValue( 5495 DepobjLVal.getAddress(CGF), 5496 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5497 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5498 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5499 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 5500 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5501 Addr.getPointer(), 5502 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5503 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, 5504 CGF.VoidPtrTy); 5505 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5506 // Use default allocator. 5507 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5508 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator}; 5509 5510 // _kmpc_free(gtid, addr, nullptr); 5511 (void)CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_free), Args); 5512 } 5513 5514 void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, 5515 OpenMPDependClauseKind NewDepKind, 5516 SourceLocation Loc) { 5517 ASTContext &C = CGM.getContext(); 5518 QualType FlagsTy; 5519 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5520 RecordDecl *KmpDependInfoRD = 5521 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5522 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5523 llvm::Value *NumDeps; 5524 LValue Base; 5525 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 5526 5527 Address Begin = Base.getAddress(CGF); 5528 // Cast from pointer to array type to pointer to single element. 5529 llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps); 5530 // The basic structure here is a while-do loop. 5531 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); 5532 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); 5533 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5534 CGF.EmitBlock(BodyBB); 5535 llvm::PHINode *ElementPHI = 5536 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); 5537 ElementPHI->addIncoming(Begin.getPointer(), EntryBB); 5538 Begin = Address(ElementPHI, Begin.getAlignment()); 5539 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), 5540 Base.getTBAAInfo()); 5541 // deps[i].flags = NewDepKind; 5542 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind); 5543 LValue FlagsLVal = CGF.EmitLValueForField( 5544 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5545 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5546 FlagsLVal); 5547 5548 // Shift the address forward by one element. 5549 Address ElementNext = 5550 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); 5551 ElementPHI->addIncoming(ElementNext.getPointer(), 5552 CGF.Builder.GetInsertBlock()); 5553 llvm::Value *IsEmpty = 5554 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); 5555 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5556 // Done. 5557 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5558 } 5559 5560 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5561 const OMPExecutableDirective &D, 5562 llvm::Function *TaskFunction, 5563 QualType SharedsTy, Address Shareds, 5564 const Expr *IfCond, 5565 const OMPTaskDataTy &Data) { 5566 if (!CGF.HaveInsertPoint()) 5567 return; 5568 5569 TaskResultTy Result = 5570 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5571 llvm::Value *NewTask = Result.NewTask; 5572 llvm::Function *TaskEntry = Result.TaskEntry; 5573 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5574 LValue TDBase = Result.TDBase; 5575 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5576 // Process list of dependences. 5577 Address DependenciesArray = Address::invalid(); 5578 llvm::Value *NumOfElements; 5579 std::tie(NumOfElements, DependenciesArray) = 5580 emitDependClause(CGF, Data.Dependences, /*ForDepobj=*/false, Loc); 5581 5582 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5583 // libcall. 5584 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5585 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5586 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5587 // list is not empty 5588 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5589 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5590 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5591 llvm::Value *DepTaskArgs[7]; 5592 if (!Data.Dependences.empty()) { 5593 DepTaskArgs[0] = UpLoc; 5594 DepTaskArgs[1] = ThreadID; 5595 DepTaskArgs[2] = NewTask; 5596 DepTaskArgs[3] = NumOfElements; 5597 DepTaskArgs[4] = DependenciesArray.getPointer(); 5598 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5599 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5600 } 5601 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs, 5602 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5603 if (!Data.Tied) { 5604 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5605 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5606 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5607 } 5608 if (!Data.Dependences.empty()) { 5609 CGF.EmitRuntimeCall( 5610 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5611 } else { 5612 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5613 TaskArgs); 5614 } 5615 // Check if parent region is untied and build return for untied task; 5616 if (auto *Region = 5617 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5618 Region->emitUntiedSwitch(CGF); 5619 }; 5620 5621 llvm::Value *DepWaitTaskArgs[6]; 5622 if (!Data.Dependences.empty()) { 5623 DepWaitTaskArgs[0] = UpLoc; 5624 DepWaitTaskArgs[1] = ThreadID; 5625 DepWaitTaskArgs[2] = NumOfElements; 5626 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5627 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5628 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5629 } 5630 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5631 &Data, &DepWaitTaskArgs, 5632 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5633 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5634 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5635 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5636 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5637 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5638 // is specified. 5639 if (!Data.Dependences.empty()) 5640 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5641 DepWaitTaskArgs); 5642 // Call proxy_task_entry(gtid, new_task); 5643 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5644 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5645 Action.Enter(CGF); 5646 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5647 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5648 OutlinedFnArgs); 5649 }; 5650 5651 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5652 // kmp_task_t *new_task); 5653 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5654 // kmp_task_t *new_task); 5655 RegionCodeGenTy RCG(CodeGen); 5656 CommonActionTy Action( 5657 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5658 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5659 RCG.setAction(Action); 5660 RCG(CGF); 5661 }; 5662 5663 if (IfCond) { 5664 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5665 } else { 5666 RegionCodeGenTy ThenRCG(ThenCodeGen); 5667 ThenRCG(CGF); 5668 } 5669 } 5670 5671 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5672 const OMPLoopDirective &D, 5673 llvm::Function *TaskFunction, 5674 QualType SharedsTy, Address Shareds, 5675 const Expr *IfCond, 5676 const OMPTaskDataTy &Data) { 5677 if (!CGF.HaveInsertPoint()) 5678 return; 5679 TaskResultTy Result = 5680 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5681 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5682 // libcall. 5683 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5684 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5685 // sched, kmp_uint64 grainsize, void *task_dup); 5686 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5687 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5688 llvm::Value *IfVal; 5689 if (IfCond) { 5690 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5691 /*isSigned=*/true); 5692 } else { 5693 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5694 } 5695 5696 LValue LBLVal = CGF.EmitLValueForField( 5697 Result.TDBase, 5698 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5699 const auto *LBVar = 5700 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5701 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5702 LBLVal.getQuals(), 5703 /*IsInitializer=*/true); 5704 LValue UBLVal = CGF.EmitLValueForField( 5705 Result.TDBase, 5706 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5707 const auto *UBVar = 5708 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5709 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5710 UBLVal.getQuals(), 5711 /*IsInitializer=*/true); 5712 LValue StLVal = CGF.EmitLValueForField( 5713 Result.TDBase, 5714 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5715 const auto *StVar = 5716 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5717 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5718 StLVal.getQuals(), 5719 /*IsInitializer=*/true); 5720 // Store reductions address. 5721 LValue RedLVal = CGF.EmitLValueForField( 5722 Result.TDBase, 5723 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5724 if (Data.Reductions) { 5725 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5726 } else { 5727 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5728 CGF.getContext().VoidPtrTy); 5729 } 5730 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5731 llvm::Value *TaskArgs[] = { 5732 UpLoc, 5733 ThreadID, 5734 Result.NewTask, 5735 IfVal, 5736 LBLVal.getPointer(CGF), 5737 UBLVal.getPointer(CGF), 5738 CGF.EmitLoadOfScalar(StLVal, Loc), 5739 llvm::ConstantInt::getSigned( 5740 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5741 llvm::ConstantInt::getSigned( 5742 CGF.IntTy, Data.Schedule.getPointer() 5743 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5744 : NoSchedule), 5745 Data.Schedule.getPointer() 5746 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5747 /*isSigned=*/false) 5748 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5749 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5750 Result.TaskDupFn, CGF.VoidPtrTy) 5751 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5752 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5753 } 5754 5755 /// Emit reduction operation for each element of array (required for 5756 /// array sections) LHS op = RHS. 5757 /// \param Type Type of array. 5758 /// \param LHSVar Variable on the left side of the reduction operation 5759 /// (references element of array in original variable). 5760 /// \param RHSVar Variable on the right side of the reduction operation 5761 /// (references element of array in original variable). 5762 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5763 /// RHSVar. 5764 static void EmitOMPAggregateReduction( 5765 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5766 const VarDecl *RHSVar, 5767 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5768 const Expr *, const Expr *)> &RedOpGen, 5769 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5770 const Expr *UpExpr = nullptr) { 5771 // Perform element-by-element initialization. 5772 QualType ElementTy; 5773 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5774 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5775 5776 // Drill down to the base element type on both arrays. 5777 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5778 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5779 5780 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5781 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5782 // Cast from pointer to array type to pointer to single element. 5783 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5784 // The basic structure here is a while-do loop. 5785 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5786 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5787 llvm::Value *IsEmpty = 5788 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5789 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5790 5791 // Enter the loop body, making that address the current address. 5792 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5793 CGF.EmitBlock(BodyBB); 5794 5795 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5796 5797 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5798 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5799 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5800 Address RHSElementCurrent = 5801 Address(RHSElementPHI, 5802 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5803 5804 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5805 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5806 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5807 Address LHSElementCurrent = 5808 Address(LHSElementPHI, 5809 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5810 5811 // Emit copy. 5812 CodeGenFunction::OMPPrivateScope Scope(CGF); 5813 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5814 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5815 Scope.Privatize(); 5816 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5817 Scope.ForceCleanup(); 5818 5819 // Shift the address forward by one element. 5820 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5821 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5822 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5823 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5824 // Check whether we've reached the end. 5825 llvm::Value *Done = 5826 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5827 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5828 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5829 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5830 5831 // Done. 5832 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5833 } 5834 5835 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5836 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5837 /// UDR combiner function. 5838 static void emitReductionCombiner(CodeGenFunction &CGF, 5839 const Expr *ReductionOp) { 5840 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5841 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5842 if (const auto *DRE = 5843 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5844 if (const auto *DRD = 5845 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5846 std::pair<llvm::Function *, llvm::Function *> Reduction = 5847 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5848 RValue Func = RValue::get(Reduction.first); 5849 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5850 CGF.EmitIgnoredExpr(ReductionOp); 5851 return; 5852 } 5853 CGF.EmitIgnoredExpr(ReductionOp); 5854 } 5855 5856 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5857 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5858 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5859 ArrayRef<const Expr *> ReductionOps) { 5860 ASTContext &C = CGM.getContext(); 5861 5862 // void reduction_func(void *LHSArg, void *RHSArg); 5863 FunctionArgList Args; 5864 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5865 ImplicitParamDecl::Other); 5866 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5867 ImplicitParamDecl::Other); 5868 Args.push_back(&LHSArg); 5869 Args.push_back(&RHSArg); 5870 const auto &CGFI = 5871 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5872 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5873 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5874 llvm::GlobalValue::InternalLinkage, Name, 5875 &CGM.getModule()); 5876 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5877 Fn->setDoesNotRecurse(); 5878 CodeGenFunction CGF(CGM); 5879 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5880 5881 // Dst = (void*[n])(LHSArg); 5882 // Src = (void*[n])(RHSArg); 5883 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5884 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5885 ArgsType), CGF.getPointerAlign()); 5886 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5887 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5888 ArgsType), CGF.getPointerAlign()); 5889 5890 // ... 5891 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5892 // ... 5893 CodeGenFunction::OMPPrivateScope Scope(CGF); 5894 auto IPriv = Privates.begin(); 5895 unsigned Idx = 0; 5896 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5897 const auto *RHSVar = 5898 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5899 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5900 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5901 }); 5902 const auto *LHSVar = 5903 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5904 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5905 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5906 }); 5907 QualType PrivTy = (*IPriv)->getType(); 5908 if (PrivTy->isVariablyModifiedType()) { 5909 // Get array size and emit VLA type. 5910 ++Idx; 5911 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5912 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5913 const VariableArrayType *VLA = 5914 CGF.getContext().getAsVariableArrayType(PrivTy); 5915 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5916 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5917 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5918 CGF.EmitVariablyModifiedType(PrivTy); 5919 } 5920 } 5921 Scope.Privatize(); 5922 IPriv = Privates.begin(); 5923 auto ILHS = LHSExprs.begin(); 5924 auto IRHS = RHSExprs.begin(); 5925 for (const Expr *E : ReductionOps) { 5926 if ((*IPriv)->getType()->isArrayType()) { 5927 // Emit reduction for array section. 5928 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5929 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5930 EmitOMPAggregateReduction( 5931 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5932 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5933 emitReductionCombiner(CGF, E); 5934 }); 5935 } else { 5936 // Emit reduction for array subscript or single variable. 5937 emitReductionCombiner(CGF, E); 5938 } 5939 ++IPriv; 5940 ++ILHS; 5941 ++IRHS; 5942 } 5943 Scope.ForceCleanup(); 5944 CGF.FinishFunction(); 5945 return Fn; 5946 } 5947 5948 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5949 const Expr *ReductionOp, 5950 const Expr *PrivateRef, 5951 const DeclRefExpr *LHS, 5952 const DeclRefExpr *RHS) { 5953 if (PrivateRef->getType()->isArrayType()) { 5954 // Emit reduction for array section. 5955 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5956 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5957 EmitOMPAggregateReduction( 5958 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5959 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5960 emitReductionCombiner(CGF, ReductionOp); 5961 }); 5962 } else { 5963 // Emit reduction for array subscript or single variable. 5964 emitReductionCombiner(CGF, ReductionOp); 5965 } 5966 } 5967 5968 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5969 ArrayRef<const Expr *> Privates, 5970 ArrayRef<const Expr *> LHSExprs, 5971 ArrayRef<const Expr *> RHSExprs, 5972 ArrayRef<const Expr *> ReductionOps, 5973 ReductionOptionsTy Options) { 5974 if (!CGF.HaveInsertPoint()) 5975 return; 5976 5977 bool WithNowait = Options.WithNowait; 5978 bool SimpleReduction = Options.SimpleReduction; 5979 5980 // Next code should be emitted for reduction: 5981 // 5982 // static kmp_critical_name lock = { 0 }; 5983 // 5984 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5985 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5986 // ... 5987 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5988 // *(Type<n>-1*)rhs[<n>-1]); 5989 // } 5990 // 5991 // ... 5992 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5993 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5994 // RedList, reduce_func, &<lock>)) { 5995 // case 1: 5996 // ... 5997 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5998 // ... 5999 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 6000 // break; 6001 // case 2: 6002 // ... 6003 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 6004 // ... 6005 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 6006 // break; 6007 // default:; 6008 // } 6009 // 6010 // if SimpleReduction is true, only the next code is generated: 6011 // ... 6012 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 6013 // ... 6014 6015 ASTContext &C = CGM.getContext(); 6016 6017 if (SimpleReduction) { 6018 CodeGenFunction::RunCleanupsScope Scope(CGF); 6019 auto IPriv = Privates.begin(); 6020 auto ILHS = LHSExprs.begin(); 6021 auto IRHS = RHSExprs.begin(); 6022 for (const Expr *E : ReductionOps) { 6023 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 6024 cast<DeclRefExpr>(*IRHS)); 6025 ++IPriv; 6026 ++ILHS; 6027 ++IRHS; 6028 } 6029 return; 6030 } 6031 6032 // 1. Build a list of reduction variables. 6033 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 6034 auto Size = RHSExprs.size(); 6035 for (const Expr *E : Privates) { 6036 if (E->getType()->isVariablyModifiedType()) 6037 // Reserve place for array size. 6038 ++Size; 6039 } 6040 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 6041 QualType ReductionArrayTy = 6042 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 6043 /*IndexTypeQuals=*/0); 6044 Address ReductionList = 6045 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 6046 auto IPriv = Privates.begin(); 6047 unsigned Idx = 0; 6048 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 6049 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 6050 CGF.Builder.CreateStore( 6051 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6052 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 6053 Elem); 6054 if ((*IPriv)->getType()->isVariablyModifiedType()) { 6055 // Store array size. 6056 ++Idx; 6057 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 6058 llvm::Value *Size = CGF.Builder.CreateIntCast( 6059 CGF.getVLASize( 6060 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 6061 .NumElts, 6062 CGF.SizeTy, /*isSigned=*/false); 6063 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 6064 Elem); 6065 } 6066 } 6067 6068 // 2. Emit reduce_func(). 6069 llvm::Function *ReductionFn = emitReductionFunction( 6070 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 6071 LHSExprs, RHSExprs, ReductionOps); 6072 6073 // 3. Create static kmp_critical_name lock = { 0 }; 6074 std::string Name = getName({"reduction"}); 6075 llvm::Value *Lock = getCriticalRegionLock(Name); 6076 6077 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 6078 // RedList, reduce_func, &<lock>); 6079 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 6080 llvm::Value *ThreadId = getThreadID(CGF, Loc); 6081 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 6082 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6083 ReductionList.getPointer(), CGF.VoidPtrTy); 6084 llvm::Value *Args[] = { 6085 IdentTLoc, // ident_t *<loc> 6086 ThreadId, // i32 <gtid> 6087 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 6088 ReductionArrayTySize, // size_type sizeof(RedList) 6089 RL, // void *RedList 6090 ReductionFn, // void (*) (void *, void *) <reduce_func> 6091 Lock // kmp_critical_name *&<lock> 6092 }; 6093 llvm::Value *Res = CGF.EmitRuntimeCall( 6094 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 6095 : OMPRTL__kmpc_reduce), 6096 Args); 6097 6098 // 5. Build switch(res) 6099 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 6100 llvm::SwitchInst *SwInst = 6101 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 6102 6103 // 6. Build case 1: 6104 // ... 6105 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 6106 // ... 6107 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 6108 // break; 6109 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 6110 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 6111 CGF.EmitBlock(Case1BB); 6112 6113 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 6114 llvm::Value *EndArgs[] = { 6115 IdentTLoc, // ident_t *<loc> 6116 ThreadId, // i32 <gtid> 6117 Lock // kmp_critical_name *&<lock> 6118 }; 6119 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 6120 CodeGenFunction &CGF, PrePostActionTy &Action) { 6121 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6122 auto IPriv = Privates.begin(); 6123 auto ILHS = LHSExprs.begin(); 6124 auto IRHS = RHSExprs.begin(); 6125 for (const Expr *E : ReductionOps) { 6126 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 6127 cast<DeclRefExpr>(*IRHS)); 6128 ++IPriv; 6129 ++ILHS; 6130 ++IRHS; 6131 } 6132 }; 6133 RegionCodeGenTy RCG(CodeGen); 6134 CommonActionTy Action( 6135 nullptr, llvm::None, 6136 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 6137 : OMPRTL__kmpc_end_reduce), 6138 EndArgs); 6139 RCG.setAction(Action); 6140 RCG(CGF); 6141 6142 CGF.EmitBranch(DefaultBB); 6143 6144 // 7. Build case 2: 6145 // ... 6146 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 6147 // ... 6148 // break; 6149 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 6150 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 6151 CGF.EmitBlock(Case2BB); 6152 6153 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 6154 CodeGenFunction &CGF, PrePostActionTy &Action) { 6155 auto ILHS = LHSExprs.begin(); 6156 auto IRHS = RHSExprs.begin(); 6157 auto IPriv = Privates.begin(); 6158 for (const Expr *E : ReductionOps) { 6159 const Expr *XExpr = nullptr; 6160 const Expr *EExpr = nullptr; 6161 const Expr *UpExpr = nullptr; 6162 BinaryOperatorKind BO = BO_Comma; 6163 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 6164 if (BO->getOpcode() == BO_Assign) { 6165 XExpr = BO->getLHS(); 6166 UpExpr = BO->getRHS(); 6167 } 6168 } 6169 // Try to emit update expression as a simple atomic. 6170 const Expr *RHSExpr = UpExpr; 6171 if (RHSExpr) { 6172 // Analyze RHS part of the whole expression. 6173 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 6174 RHSExpr->IgnoreParenImpCasts())) { 6175 // If this is a conditional operator, analyze its condition for 6176 // min/max reduction operator. 6177 RHSExpr = ACO->getCond(); 6178 } 6179 if (const auto *BORHS = 6180 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 6181 EExpr = BORHS->getRHS(); 6182 BO = BORHS->getOpcode(); 6183 } 6184 } 6185 if (XExpr) { 6186 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 6187 auto &&AtomicRedGen = [BO, VD, 6188 Loc](CodeGenFunction &CGF, const Expr *XExpr, 6189 const Expr *EExpr, const Expr *UpExpr) { 6190 LValue X = CGF.EmitLValue(XExpr); 6191 RValue E; 6192 if (EExpr) 6193 E = CGF.EmitAnyExpr(EExpr); 6194 CGF.EmitOMPAtomicSimpleUpdateExpr( 6195 X, E, BO, /*IsXLHSInRHSPart=*/true, 6196 llvm::AtomicOrdering::Monotonic, Loc, 6197 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 6198 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6199 PrivateScope.addPrivate( 6200 VD, [&CGF, VD, XRValue, Loc]() { 6201 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 6202 CGF.emitOMPSimpleStore( 6203 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 6204 VD->getType().getNonReferenceType(), Loc); 6205 return LHSTemp; 6206 }); 6207 (void)PrivateScope.Privatize(); 6208 return CGF.EmitAnyExpr(UpExpr); 6209 }); 6210 }; 6211 if ((*IPriv)->getType()->isArrayType()) { 6212 // Emit atomic reduction for array section. 6213 const auto *RHSVar = 6214 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 6215 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 6216 AtomicRedGen, XExpr, EExpr, UpExpr); 6217 } else { 6218 // Emit atomic reduction for array subscript or single variable. 6219 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 6220 } 6221 } else { 6222 // Emit as a critical region. 6223 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 6224 const Expr *, const Expr *) { 6225 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6226 std::string Name = RT.getName({"atomic_reduction"}); 6227 RT.emitCriticalRegion( 6228 CGF, Name, 6229 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 6230 Action.Enter(CGF); 6231 emitReductionCombiner(CGF, E); 6232 }, 6233 Loc); 6234 }; 6235 if ((*IPriv)->getType()->isArrayType()) { 6236 const auto *LHSVar = 6237 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 6238 const auto *RHSVar = 6239 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 6240 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 6241 CritRedGen); 6242 } else { 6243 CritRedGen(CGF, nullptr, nullptr, nullptr); 6244 } 6245 } 6246 ++ILHS; 6247 ++IRHS; 6248 ++IPriv; 6249 } 6250 }; 6251 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 6252 if (!WithNowait) { 6253 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 6254 llvm::Value *EndArgs[] = { 6255 IdentTLoc, // ident_t *<loc> 6256 ThreadId, // i32 <gtid> 6257 Lock // kmp_critical_name *&<lock> 6258 }; 6259 CommonActionTy Action(nullptr, llvm::None, 6260 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 6261 EndArgs); 6262 AtomicRCG.setAction(Action); 6263 AtomicRCG(CGF); 6264 } else { 6265 AtomicRCG(CGF); 6266 } 6267 6268 CGF.EmitBranch(DefaultBB); 6269 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 6270 } 6271 6272 /// Generates unique name for artificial threadprivate variables. 6273 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 6274 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 6275 const Expr *Ref) { 6276 SmallString<256> Buffer; 6277 llvm::raw_svector_ostream Out(Buffer); 6278 const clang::DeclRefExpr *DE; 6279 const VarDecl *D = ::getBaseDecl(Ref, DE); 6280 if (!D) 6281 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 6282 D = D->getCanonicalDecl(); 6283 std::string Name = CGM.getOpenMPRuntime().getName( 6284 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 6285 Out << Prefix << Name << "_" 6286 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 6287 return std::string(Out.str()); 6288 } 6289 6290 /// Emits reduction initializer function: 6291 /// \code 6292 /// void @.red_init(void* %arg) { 6293 /// %0 = bitcast void* %arg to <type>* 6294 /// store <type> <init>, <type>* %0 6295 /// ret void 6296 /// } 6297 /// \endcode 6298 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 6299 SourceLocation Loc, 6300 ReductionCodeGen &RCG, unsigned N) { 6301 ASTContext &C = CGM.getContext(); 6302 FunctionArgList Args; 6303 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6304 ImplicitParamDecl::Other); 6305 Args.emplace_back(&Param); 6306 const auto &FnInfo = 6307 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6308 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6309 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6310 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6311 Name, &CGM.getModule()); 6312 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6313 Fn->setDoesNotRecurse(); 6314 CodeGenFunction CGF(CGM); 6315 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6316 Address PrivateAddr = CGF.EmitLoadOfPointer( 6317 CGF.GetAddrOfLocalVar(&Param), 6318 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6319 llvm::Value *Size = nullptr; 6320 // If the size of the reduction item is non-constant, load it from global 6321 // threadprivate variable. 6322 if (RCG.getSizes(N).second) { 6323 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6324 CGF, CGM.getContext().getSizeType(), 6325 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6326 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6327 CGM.getContext().getSizeType(), Loc); 6328 } 6329 RCG.emitAggregateType(CGF, N, Size); 6330 LValue SharedLVal; 6331 // If initializer uses initializer from declare reduction construct, emit a 6332 // pointer to the address of the original reduction item (reuired by reduction 6333 // initializer) 6334 if (RCG.usesReductionInitializer(N)) { 6335 Address SharedAddr = 6336 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6337 CGF, CGM.getContext().VoidPtrTy, 6338 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6339 SharedAddr = CGF.EmitLoadOfPointer( 6340 SharedAddr, 6341 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6342 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6343 } else { 6344 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6345 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6346 CGM.getContext().VoidPtrTy); 6347 } 6348 // Emit the initializer: 6349 // %0 = bitcast void* %arg to <type>* 6350 // store <type> <init>, <type>* %0 6351 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6352 [](CodeGenFunction &) { return false; }); 6353 CGF.FinishFunction(); 6354 return Fn; 6355 } 6356 6357 /// Emits reduction combiner function: 6358 /// \code 6359 /// void @.red_comb(void* %arg0, void* %arg1) { 6360 /// %lhs = bitcast void* %arg0 to <type>* 6361 /// %rhs = bitcast void* %arg1 to <type>* 6362 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6363 /// store <type> %2, <type>* %lhs 6364 /// ret void 6365 /// } 6366 /// \endcode 6367 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6368 SourceLocation Loc, 6369 ReductionCodeGen &RCG, unsigned N, 6370 const Expr *ReductionOp, 6371 const Expr *LHS, const Expr *RHS, 6372 const Expr *PrivateRef) { 6373 ASTContext &C = CGM.getContext(); 6374 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6375 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6376 FunctionArgList Args; 6377 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6378 C.VoidPtrTy, ImplicitParamDecl::Other); 6379 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6380 ImplicitParamDecl::Other); 6381 Args.emplace_back(&ParamInOut); 6382 Args.emplace_back(&ParamIn); 6383 const auto &FnInfo = 6384 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6385 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6386 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6387 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6388 Name, &CGM.getModule()); 6389 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6390 Fn->setDoesNotRecurse(); 6391 CodeGenFunction CGF(CGM); 6392 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6393 llvm::Value *Size = nullptr; 6394 // If the size of the reduction item is non-constant, load it from global 6395 // threadprivate variable. 6396 if (RCG.getSizes(N).second) { 6397 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6398 CGF, CGM.getContext().getSizeType(), 6399 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6400 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6401 CGM.getContext().getSizeType(), Loc); 6402 } 6403 RCG.emitAggregateType(CGF, N, Size); 6404 // Remap lhs and rhs variables to the addresses of the function arguments. 6405 // %lhs = bitcast void* %arg0 to <type>* 6406 // %rhs = bitcast void* %arg1 to <type>* 6407 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6408 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6409 // Pull out the pointer to the variable. 6410 Address PtrAddr = CGF.EmitLoadOfPointer( 6411 CGF.GetAddrOfLocalVar(&ParamInOut), 6412 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6413 return CGF.Builder.CreateElementBitCast( 6414 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6415 }); 6416 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6417 // Pull out the pointer to the variable. 6418 Address PtrAddr = CGF.EmitLoadOfPointer( 6419 CGF.GetAddrOfLocalVar(&ParamIn), 6420 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6421 return CGF.Builder.CreateElementBitCast( 6422 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6423 }); 6424 PrivateScope.Privatize(); 6425 // Emit the combiner body: 6426 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6427 // store <type> %2, <type>* %lhs 6428 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6429 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6430 cast<DeclRefExpr>(RHS)); 6431 CGF.FinishFunction(); 6432 return Fn; 6433 } 6434 6435 /// Emits reduction finalizer function: 6436 /// \code 6437 /// void @.red_fini(void* %arg) { 6438 /// %0 = bitcast void* %arg to <type>* 6439 /// <destroy>(<type>* %0) 6440 /// ret void 6441 /// } 6442 /// \endcode 6443 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6444 SourceLocation Loc, 6445 ReductionCodeGen &RCG, unsigned N) { 6446 if (!RCG.needCleanups(N)) 6447 return nullptr; 6448 ASTContext &C = CGM.getContext(); 6449 FunctionArgList Args; 6450 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6451 ImplicitParamDecl::Other); 6452 Args.emplace_back(&Param); 6453 const auto &FnInfo = 6454 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6455 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6456 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6457 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6458 Name, &CGM.getModule()); 6459 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6460 Fn->setDoesNotRecurse(); 6461 CodeGenFunction CGF(CGM); 6462 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6463 Address PrivateAddr = CGF.EmitLoadOfPointer( 6464 CGF.GetAddrOfLocalVar(&Param), 6465 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6466 llvm::Value *Size = nullptr; 6467 // If the size of the reduction item is non-constant, load it from global 6468 // threadprivate variable. 6469 if (RCG.getSizes(N).second) { 6470 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6471 CGF, CGM.getContext().getSizeType(), 6472 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6473 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6474 CGM.getContext().getSizeType(), Loc); 6475 } 6476 RCG.emitAggregateType(CGF, N, Size); 6477 // Emit the finalizer body: 6478 // <destroy>(<type>* %0) 6479 RCG.emitCleanups(CGF, N, PrivateAddr); 6480 CGF.FinishFunction(Loc); 6481 return Fn; 6482 } 6483 6484 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6485 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6486 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6487 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6488 return nullptr; 6489 6490 // Build typedef struct: 6491 // kmp_task_red_input { 6492 // void *reduce_shar; // shared reduction item 6493 // size_t reduce_size; // size of data item 6494 // void *reduce_init; // data initialization routine 6495 // void *reduce_fini; // data finalization routine 6496 // void *reduce_comb; // data combiner routine 6497 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6498 // } kmp_task_red_input_t; 6499 ASTContext &C = CGM.getContext(); 6500 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6501 RD->startDefinition(); 6502 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6503 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6504 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6505 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6506 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6507 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6508 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6509 RD->completeDefinition(); 6510 QualType RDType = C.getRecordType(RD); 6511 unsigned Size = Data.ReductionVars.size(); 6512 llvm::APInt ArraySize(/*numBits=*/64, Size); 6513 QualType ArrayRDType = C.getConstantArrayType( 6514 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6515 // kmp_task_red_input_t .rd_input.[Size]; 6516 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6517 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6518 Data.ReductionOps); 6519 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6520 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6521 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6522 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6523 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6524 TaskRedInput.getPointer(), Idxs, 6525 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6526 ".rd_input.gep."); 6527 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6528 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6529 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6530 RCG.emitSharedLValue(CGF, Cnt); 6531 llvm::Value *CastedShared = 6532 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6533 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6534 RCG.emitAggregateType(CGF, Cnt); 6535 llvm::Value *SizeValInChars; 6536 llvm::Value *SizeVal; 6537 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6538 // We use delayed creation/initialization for VLAs, array sections and 6539 // custom reduction initializations. It is required because runtime does not 6540 // provide the way to pass the sizes of VLAs/array sections to 6541 // initializer/combiner/finalizer functions and does not pass the pointer to 6542 // original reduction item to the initializer. Instead threadprivate global 6543 // variables are used to store these values and use them in the functions. 6544 bool DelayedCreation = !!SizeVal; 6545 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6546 /*isSigned=*/false); 6547 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6548 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6549 // ElemLVal.reduce_init = init; 6550 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6551 llvm::Value *InitAddr = 6552 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6553 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6554 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6555 // ElemLVal.reduce_fini = fini; 6556 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6557 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6558 llvm::Value *FiniAddr = Fini 6559 ? CGF.EmitCastToVoidPtr(Fini) 6560 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6561 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6562 // ElemLVal.reduce_comb = comb; 6563 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6564 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6565 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6566 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6567 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6568 // ElemLVal.flags = 0; 6569 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6570 if (DelayedCreation) { 6571 CGF.EmitStoreOfScalar( 6572 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6573 FlagsLVal); 6574 } else 6575 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6576 FlagsLVal.getType()); 6577 } 6578 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6579 // *data); 6580 llvm::Value *Args[] = { 6581 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6582 /*isSigned=*/true), 6583 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6584 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6585 CGM.VoidPtrTy)}; 6586 return CGF.EmitRuntimeCall( 6587 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6588 } 6589 6590 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6591 SourceLocation Loc, 6592 ReductionCodeGen &RCG, 6593 unsigned N) { 6594 auto Sizes = RCG.getSizes(N); 6595 // Emit threadprivate global variable if the type is non-constant 6596 // (Sizes.second = nullptr). 6597 if (Sizes.second) { 6598 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6599 /*isSigned=*/false); 6600 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6601 CGF, CGM.getContext().getSizeType(), 6602 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6603 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6604 } 6605 // Store address of the original reduction item if custom initializer is used. 6606 if (RCG.usesReductionInitializer(N)) { 6607 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6608 CGF, CGM.getContext().VoidPtrTy, 6609 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6610 CGF.Builder.CreateStore( 6611 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6612 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy), 6613 SharedAddr, /*IsVolatile=*/false); 6614 } 6615 } 6616 6617 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6618 SourceLocation Loc, 6619 llvm::Value *ReductionsPtr, 6620 LValue SharedLVal) { 6621 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6622 // *d); 6623 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6624 CGM.IntTy, 6625 /*isSigned=*/true), 6626 ReductionsPtr, 6627 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6628 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6629 return Address( 6630 CGF.EmitRuntimeCall( 6631 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6632 SharedLVal.getAlignment()); 6633 } 6634 6635 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6636 SourceLocation Loc) { 6637 if (!CGF.HaveInsertPoint()) 6638 return; 6639 6640 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 6641 if (OMPBuilder) { 6642 OMPBuilder->CreateTaskwait(CGF.Builder); 6643 } else { 6644 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6645 // global_tid); 6646 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6647 // Ignore return result until untied tasks are supported. 6648 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6649 } 6650 6651 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6652 Region->emitUntiedSwitch(CGF); 6653 } 6654 6655 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6656 OpenMPDirectiveKind InnerKind, 6657 const RegionCodeGenTy &CodeGen, 6658 bool HasCancel) { 6659 if (!CGF.HaveInsertPoint()) 6660 return; 6661 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6662 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6663 } 6664 6665 namespace { 6666 enum RTCancelKind { 6667 CancelNoreq = 0, 6668 CancelParallel = 1, 6669 CancelLoop = 2, 6670 CancelSections = 3, 6671 CancelTaskgroup = 4 6672 }; 6673 } // anonymous namespace 6674 6675 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6676 RTCancelKind CancelKind = CancelNoreq; 6677 if (CancelRegion == OMPD_parallel) 6678 CancelKind = CancelParallel; 6679 else if (CancelRegion == OMPD_for) 6680 CancelKind = CancelLoop; 6681 else if (CancelRegion == OMPD_sections) 6682 CancelKind = CancelSections; 6683 else { 6684 assert(CancelRegion == OMPD_taskgroup); 6685 CancelKind = CancelTaskgroup; 6686 } 6687 return CancelKind; 6688 } 6689 6690 void CGOpenMPRuntime::emitCancellationPointCall( 6691 CodeGenFunction &CGF, SourceLocation Loc, 6692 OpenMPDirectiveKind CancelRegion) { 6693 if (!CGF.HaveInsertPoint()) 6694 return; 6695 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6696 // global_tid, kmp_int32 cncl_kind); 6697 if (auto *OMPRegionInfo = 6698 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6699 // For 'cancellation point taskgroup', the task region info may not have a 6700 // cancel. This may instead happen in another adjacent task. 6701 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6702 llvm::Value *Args[] = { 6703 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6704 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6705 // Ignore return result until untied tasks are supported. 6706 llvm::Value *Result = CGF.EmitRuntimeCall( 6707 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6708 // if (__kmpc_cancellationpoint()) { 6709 // exit from construct; 6710 // } 6711 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6712 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6713 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6714 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6715 CGF.EmitBlock(ExitBB); 6716 // exit from construct; 6717 CodeGenFunction::JumpDest CancelDest = 6718 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6719 CGF.EmitBranchThroughCleanup(CancelDest); 6720 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6721 } 6722 } 6723 } 6724 6725 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6726 const Expr *IfCond, 6727 OpenMPDirectiveKind CancelRegion) { 6728 if (!CGF.HaveInsertPoint()) 6729 return; 6730 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6731 // kmp_int32 cncl_kind); 6732 if (auto *OMPRegionInfo = 6733 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6734 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6735 PrePostActionTy &) { 6736 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6737 llvm::Value *Args[] = { 6738 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6739 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6740 // Ignore return result until untied tasks are supported. 6741 llvm::Value *Result = CGF.EmitRuntimeCall( 6742 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6743 // if (__kmpc_cancel()) { 6744 // exit from construct; 6745 // } 6746 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6747 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6748 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6749 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6750 CGF.EmitBlock(ExitBB); 6751 // exit from construct; 6752 CodeGenFunction::JumpDest CancelDest = 6753 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6754 CGF.EmitBranchThroughCleanup(CancelDest); 6755 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6756 }; 6757 if (IfCond) { 6758 emitIfClause(CGF, IfCond, ThenGen, 6759 [](CodeGenFunction &, PrePostActionTy &) {}); 6760 } else { 6761 RegionCodeGenTy ThenRCG(ThenGen); 6762 ThenRCG(CGF); 6763 } 6764 } 6765 } 6766 6767 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6768 const OMPExecutableDirective &D, StringRef ParentName, 6769 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6770 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6771 assert(!ParentName.empty() && "Invalid target region parent name!"); 6772 HasEmittedTargetRegion = true; 6773 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6774 IsOffloadEntry, CodeGen); 6775 } 6776 6777 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6778 const OMPExecutableDirective &D, StringRef ParentName, 6779 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6780 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6781 // Create a unique name for the entry function using the source location 6782 // information of the current target region. The name will be something like: 6783 // 6784 // __omp_offloading_DD_FFFF_PP_lBB 6785 // 6786 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6787 // mangled name of the function that encloses the target region and BB is the 6788 // line number of the target region. 6789 6790 unsigned DeviceID; 6791 unsigned FileID; 6792 unsigned Line; 6793 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6794 Line); 6795 SmallString<64> EntryFnName; 6796 { 6797 llvm::raw_svector_ostream OS(EntryFnName); 6798 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6799 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6800 } 6801 6802 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6803 6804 CodeGenFunction CGF(CGM, true); 6805 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6806 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6807 6808 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6809 6810 // If this target outline function is not an offload entry, we don't need to 6811 // register it. 6812 if (!IsOffloadEntry) 6813 return; 6814 6815 // The target region ID is used by the runtime library to identify the current 6816 // target region, so it only has to be unique and not necessarily point to 6817 // anything. It could be the pointer to the outlined function that implements 6818 // the target region, but we aren't using that so that the compiler doesn't 6819 // need to keep that, and could therefore inline the host function if proven 6820 // worthwhile during optimization. In the other hand, if emitting code for the 6821 // device, the ID has to be the function address so that it can retrieved from 6822 // the offloading entry and launched by the runtime library. We also mark the 6823 // outlined function to have external linkage in case we are emitting code for 6824 // the device, because these functions will be entry points to the device. 6825 6826 if (CGM.getLangOpts().OpenMPIsDevice) { 6827 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6828 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6829 OutlinedFn->setDSOLocal(false); 6830 } else { 6831 std::string Name = getName({EntryFnName, "region_id"}); 6832 OutlinedFnID = new llvm::GlobalVariable( 6833 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6834 llvm::GlobalValue::WeakAnyLinkage, 6835 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6836 } 6837 6838 // Register the information for the entry associated with this target region. 6839 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6840 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6841 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6842 } 6843 6844 /// Checks if the expression is constant or does not have non-trivial function 6845 /// calls. 6846 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6847 // We can skip constant expressions. 6848 // We can skip expressions with trivial calls or simple expressions. 6849 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6850 !E->hasNonTrivialCall(Ctx)) && 6851 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6852 } 6853 6854 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6855 const Stmt *Body) { 6856 const Stmt *Child = Body->IgnoreContainers(); 6857 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6858 Child = nullptr; 6859 for (const Stmt *S : C->body()) { 6860 if (const auto *E = dyn_cast<Expr>(S)) { 6861 if (isTrivial(Ctx, E)) 6862 continue; 6863 } 6864 // Some of the statements can be ignored. 6865 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6866 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6867 continue; 6868 // Analyze declarations. 6869 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6870 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6871 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6872 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6873 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6874 isa<UsingDirectiveDecl>(D) || 6875 isa<OMPDeclareReductionDecl>(D) || 6876 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6877 return true; 6878 const auto *VD = dyn_cast<VarDecl>(D); 6879 if (!VD) 6880 return false; 6881 return VD->isConstexpr() || 6882 ((VD->getType().isTrivialType(Ctx) || 6883 VD->getType()->isReferenceType()) && 6884 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6885 })) 6886 continue; 6887 } 6888 // Found multiple children - cannot get the one child only. 6889 if (Child) 6890 return nullptr; 6891 Child = S; 6892 } 6893 if (Child) 6894 Child = Child->IgnoreContainers(); 6895 } 6896 return Child; 6897 } 6898 6899 /// Emit the number of teams for a target directive. Inspect the num_teams 6900 /// clause associated with a teams construct combined or closely nested 6901 /// with the target directive. 6902 /// 6903 /// Emit a team of size one for directives such as 'target parallel' that 6904 /// have no associated teams construct. 6905 /// 6906 /// Otherwise, return nullptr. 6907 static llvm::Value * 6908 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6909 const OMPExecutableDirective &D) { 6910 assert(!CGF.getLangOpts().OpenMPIsDevice && 6911 "Clauses associated with the teams directive expected to be emitted " 6912 "only for the host!"); 6913 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6914 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6915 "Expected target-based executable directive."); 6916 CGBuilderTy &Bld = CGF.Builder; 6917 switch (DirectiveKind) { 6918 case OMPD_target: { 6919 const auto *CS = D.getInnermostCapturedStmt(); 6920 const auto *Body = 6921 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6922 const Stmt *ChildStmt = 6923 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6924 if (const auto *NestedDir = 6925 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6926 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6927 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6928 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6929 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6930 const Expr *NumTeams = 6931 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6932 llvm::Value *NumTeamsVal = 6933 CGF.EmitScalarExpr(NumTeams, 6934 /*IgnoreResultAssign*/ true); 6935 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6936 /*isSigned=*/true); 6937 } 6938 return Bld.getInt32(0); 6939 } 6940 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6941 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6942 return Bld.getInt32(1); 6943 return Bld.getInt32(0); 6944 } 6945 return nullptr; 6946 } 6947 case OMPD_target_teams: 6948 case OMPD_target_teams_distribute: 6949 case OMPD_target_teams_distribute_simd: 6950 case OMPD_target_teams_distribute_parallel_for: 6951 case OMPD_target_teams_distribute_parallel_for_simd: { 6952 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6953 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6954 const Expr *NumTeams = 6955 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6956 llvm::Value *NumTeamsVal = 6957 CGF.EmitScalarExpr(NumTeams, 6958 /*IgnoreResultAssign*/ true); 6959 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6960 /*isSigned=*/true); 6961 } 6962 return Bld.getInt32(0); 6963 } 6964 case OMPD_target_parallel: 6965 case OMPD_target_parallel_for: 6966 case OMPD_target_parallel_for_simd: 6967 case OMPD_target_simd: 6968 return Bld.getInt32(1); 6969 case OMPD_parallel: 6970 case OMPD_for: 6971 case OMPD_parallel_for: 6972 case OMPD_parallel_master: 6973 case OMPD_parallel_sections: 6974 case OMPD_for_simd: 6975 case OMPD_parallel_for_simd: 6976 case OMPD_cancel: 6977 case OMPD_cancellation_point: 6978 case OMPD_ordered: 6979 case OMPD_threadprivate: 6980 case OMPD_allocate: 6981 case OMPD_task: 6982 case OMPD_simd: 6983 case OMPD_sections: 6984 case OMPD_section: 6985 case OMPD_single: 6986 case OMPD_master: 6987 case OMPD_critical: 6988 case OMPD_taskyield: 6989 case OMPD_barrier: 6990 case OMPD_taskwait: 6991 case OMPD_taskgroup: 6992 case OMPD_atomic: 6993 case OMPD_flush: 6994 case OMPD_depobj: 6995 case OMPD_scan: 6996 case OMPD_teams: 6997 case OMPD_target_data: 6998 case OMPD_target_exit_data: 6999 case OMPD_target_enter_data: 7000 case OMPD_distribute: 7001 case OMPD_distribute_simd: 7002 case OMPD_distribute_parallel_for: 7003 case OMPD_distribute_parallel_for_simd: 7004 case OMPD_teams_distribute: 7005 case OMPD_teams_distribute_simd: 7006 case OMPD_teams_distribute_parallel_for: 7007 case OMPD_teams_distribute_parallel_for_simd: 7008 case OMPD_target_update: 7009 case OMPD_declare_simd: 7010 case OMPD_declare_variant: 7011 case OMPD_declare_target: 7012 case OMPD_end_declare_target: 7013 case OMPD_declare_reduction: 7014 case OMPD_declare_mapper: 7015 case OMPD_taskloop: 7016 case OMPD_taskloop_simd: 7017 case OMPD_master_taskloop: 7018 case OMPD_master_taskloop_simd: 7019 case OMPD_parallel_master_taskloop: 7020 case OMPD_parallel_master_taskloop_simd: 7021 case OMPD_requires: 7022 case OMPD_unknown: 7023 break; 7024 } 7025 llvm_unreachable("Unexpected directive kind."); 7026 } 7027 7028 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 7029 llvm::Value *DefaultThreadLimitVal) { 7030 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7031 CGF.getContext(), CS->getCapturedStmt()); 7032 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7033 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 7034 llvm::Value *NumThreads = nullptr; 7035 llvm::Value *CondVal = nullptr; 7036 // Handle if clause. If if clause present, the number of threads is 7037 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 7038 if (Dir->hasClausesOfKind<OMPIfClause>()) { 7039 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7040 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7041 const OMPIfClause *IfClause = nullptr; 7042 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 7043 if (C->getNameModifier() == OMPD_unknown || 7044 C->getNameModifier() == OMPD_parallel) { 7045 IfClause = C; 7046 break; 7047 } 7048 } 7049 if (IfClause) { 7050 const Expr *Cond = IfClause->getCondition(); 7051 bool Result; 7052 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 7053 if (!Result) 7054 return CGF.Builder.getInt32(1); 7055 } else { 7056 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 7057 if (const auto *PreInit = 7058 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 7059 for (const auto *I : PreInit->decls()) { 7060 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7061 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7062 } else { 7063 CodeGenFunction::AutoVarEmission Emission = 7064 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7065 CGF.EmitAutoVarCleanups(Emission); 7066 } 7067 } 7068 } 7069 CondVal = CGF.EvaluateExprAsBool(Cond); 7070 } 7071 } 7072 } 7073 // Check the value of num_threads clause iff if clause was not specified 7074 // or is not evaluated to false. 7075 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 7076 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7077 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7078 const auto *NumThreadsClause = 7079 Dir->getSingleClause<OMPNumThreadsClause>(); 7080 CodeGenFunction::LexicalScope Scope( 7081 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 7082 if (const auto *PreInit = 7083 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 7084 for (const auto *I : PreInit->decls()) { 7085 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7086 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7087 } else { 7088 CodeGenFunction::AutoVarEmission Emission = 7089 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7090 CGF.EmitAutoVarCleanups(Emission); 7091 } 7092 } 7093 } 7094 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 7095 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 7096 /*isSigned=*/false); 7097 if (DefaultThreadLimitVal) 7098 NumThreads = CGF.Builder.CreateSelect( 7099 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 7100 DefaultThreadLimitVal, NumThreads); 7101 } else { 7102 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 7103 : CGF.Builder.getInt32(0); 7104 } 7105 // Process condition of the if clause. 7106 if (CondVal) { 7107 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 7108 CGF.Builder.getInt32(1)); 7109 } 7110 return NumThreads; 7111 } 7112 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 7113 return CGF.Builder.getInt32(1); 7114 return DefaultThreadLimitVal; 7115 } 7116 return DefaultThreadLimitVal ? DefaultThreadLimitVal 7117 : CGF.Builder.getInt32(0); 7118 } 7119 7120 /// Emit the number of threads for a target directive. Inspect the 7121 /// thread_limit clause associated with a teams construct combined or closely 7122 /// nested with the target directive. 7123 /// 7124 /// Emit the num_threads clause for directives such as 'target parallel' that 7125 /// have no associated teams construct. 7126 /// 7127 /// Otherwise, return nullptr. 7128 static llvm::Value * 7129 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 7130 const OMPExecutableDirective &D) { 7131 assert(!CGF.getLangOpts().OpenMPIsDevice && 7132 "Clauses associated with the teams directive expected to be emitted " 7133 "only for the host!"); 7134 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 7135 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 7136 "Expected target-based executable directive."); 7137 CGBuilderTy &Bld = CGF.Builder; 7138 llvm::Value *ThreadLimitVal = nullptr; 7139 llvm::Value *NumThreadsVal = nullptr; 7140 switch (DirectiveKind) { 7141 case OMPD_target: { 7142 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7143 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7144 return NumThreads; 7145 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7146 CGF.getContext(), CS->getCapturedStmt()); 7147 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7148 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 7149 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7150 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7151 const auto *ThreadLimitClause = 7152 Dir->getSingleClause<OMPThreadLimitClause>(); 7153 CodeGenFunction::LexicalScope Scope( 7154 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 7155 if (const auto *PreInit = 7156 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 7157 for (const auto *I : PreInit->decls()) { 7158 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7159 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7160 } else { 7161 CodeGenFunction::AutoVarEmission Emission = 7162 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7163 CGF.EmitAutoVarCleanups(Emission); 7164 } 7165 } 7166 } 7167 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7168 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7169 ThreadLimitVal = 7170 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7171 } 7172 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 7173 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 7174 CS = Dir->getInnermostCapturedStmt(); 7175 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7176 CGF.getContext(), CS->getCapturedStmt()); 7177 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 7178 } 7179 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 7180 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 7181 CS = Dir->getInnermostCapturedStmt(); 7182 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7183 return NumThreads; 7184 } 7185 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 7186 return Bld.getInt32(1); 7187 } 7188 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7189 } 7190 case OMPD_target_teams: { 7191 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7192 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7193 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7194 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7195 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7196 ThreadLimitVal = 7197 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7198 } 7199 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7200 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7201 return NumThreads; 7202 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7203 CGF.getContext(), CS->getCapturedStmt()); 7204 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7205 if (Dir->getDirectiveKind() == OMPD_distribute) { 7206 CS = Dir->getInnermostCapturedStmt(); 7207 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7208 return NumThreads; 7209 } 7210 } 7211 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7212 } 7213 case OMPD_target_teams_distribute: 7214 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7215 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7216 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7217 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7218 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7219 ThreadLimitVal = 7220 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7221 } 7222 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 7223 case OMPD_target_parallel: 7224 case OMPD_target_parallel_for: 7225 case OMPD_target_parallel_for_simd: 7226 case OMPD_target_teams_distribute_parallel_for: 7227 case OMPD_target_teams_distribute_parallel_for_simd: { 7228 llvm::Value *CondVal = nullptr; 7229 // Handle if clause. If if clause present, the number of threads is 7230 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 7231 if (D.hasClausesOfKind<OMPIfClause>()) { 7232 const OMPIfClause *IfClause = nullptr; 7233 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 7234 if (C->getNameModifier() == OMPD_unknown || 7235 C->getNameModifier() == OMPD_parallel) { 7236 IfClause = C; 7237 break; 7238 } 7239 } 7240 if (IfClause) { 7241 const Expr *Cond = IfClause->getCondition(); 7242 bool Result; 7243 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 7244 if (!Result) 7245 return Bld.getInt32(1); 7246 } else { 7247 CodeGenFunction::RunCleanupsScope Scope(CGF); 7248 CondVal = CGF.EvaluateExprAsBool(Cond); 7249 } 7250 } 7251 } 7252 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7253 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7254 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7255 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7256 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7257 ThreadLimitVal = 7258 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7259 } 7260 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 7261 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 7262 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 7263 llvm::Value *NumThreads = CGF.EmitScalarExpr( 7264 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 7265 NumThreadsVal = 7266 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 7267 ThreadLimitVal = ThreadLimitVal 7268 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 7269 ThreadLimitVal), 7270 NumThreadsVal, ThreadLimitVal) 7271 : NumThreadsVal; 7272 } 7273 if (!ThreadLimitVal) 7274 ThreadLimitVal = Bld.getInt32(0); 7275 if (CondVal) 7276 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 7277 return ThreadLimitVal; 7278 } 7279 case OMPD_target_teams_distribute_simd: 7280 case OMPD_target_simd: 7281 return Bld.getInt32(1); 7282 case OMPD_parallel: 7283 case OMPD_for: 7284 case OMPD_parallel_for: 7285 case OMPD_parallel_master: 7286 case OMPD_parallel_sections: 7287 case OMPD_for_simd: 7288 case OMPD_parallel_for_simd: 7289 case OMPD_cancel: 7290 case OMPD_cancellation_point: 7291 case OMPD_ordered: 7292 case OMPD_threadprivate: 7293 case OMPD_allocate: 7294 case OMPD_task: 7295 case OMPD_simd: 7296 case OMPD_sections: 7297 case OMPD_section: 7298 case OMPD_single: 7299 case OMPD_master: 7300 case OMPD_critical: 7301 case OMPD_taskyield: 7302 case OMPD_barrier: 7303 case OMPD_taskwait: 7304 case OMPD_taskgroup: 7305 case OMPD_atomic: 7306 case OMPD_flush: 7307 case OMPD_depobj: 7308 case OMPD_scan: 7309 case OMPD_teams: 7310 case OMPD_target_data: 7311 case OMPD_target_exit_data: 7312 case OMPD_target_enter_data: 7313 case OMPD_distribute: 7314 case OMPD_distribute_simd: 7315 case OMPD_distribute_parallel_for: 7316 case OMPD_distribute_parallel_for_simd: 7317 case OMPD_teams_distribute: 7318 case OMPD_teams_distribute_simd: 7319 case OMPD_teams_distribute_parallel_for: 7320 case OMPD_teams_distribute_parallel_for_simd: 7321 case OMPD_target_update: 7322 case OMPD_declare_simd: 7323 case OMPD_declare_variant: 7324 case OMPD_declare_target: 7325 case OMPD_end_declare_target: 7326 case OMPD_declare_reduction: 7327 case OMPD_declare_mapper: 7328 case OMPD_taskloop: 7329 case OMPD_taskloop_simd: 7330 case OMPD_master_taskloop: 7331 case OMPD_master_taskloop_simd: 7332 case OMPD_parallel_master_taskloop: 7333 case OMPD_parallel_master_taskloop_simd: 7334 case OMPD_requires: 7335 case OMPD_unknown: 7336 break; 7337 } 7338 llvm_unreachable("Unsupported directive kind."); 7339 } 7340 7341 namespace { 7342 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7343 7344 // Utility to handle information from clauses associated with a given 7345 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7346 // It provides a convenient interface to obtain the information and generate 7347 // code for that information. 7348 class MappableExprsHandler { 7349 public: 7350 /// Values for bit flags used to specify the mapping type for 7351 /// offloading. 7352 enum OpenMPOffloadMappingFlags : uint64_t { 7353 /// No flags 7354 OMP_MAP_NONE = 0x0, 7355 /// Allocate memory on the device and move data from host to device. 7356 OMP_MAP_TO = 0x01, 7357 /// Allocate memory on the device and move data from device to host. 7358 OMP_MAP_FROM = 0x02, 7359 /// Always perform the requested mapping action on the element, even 7360 /// if it was already mapped before. 7361 OMP_MAP_ALWAYS = 0x04, 7362 /// Delete the element from the device environment, ignoring the 7363 /// current reference count associated with the element. 7364 OMP_MAP_DELETE = 0x08, 7365 /// The element being mapped is a pointer-pointee pair; both the 7366 /// pointer and the pointee should be mapped. 7367 OMP_MAP_PTR_AND_OBJ = 0x10, 7368 /// This flags signals that the base address of an entry should be 7369 /// passed to the target kernel as an argument. 7370 OMP_MAP_TARGET_PARAM = 0x20, 7371 /// Signal that the runtime library has to return the device pointer 7372 /// in the current position for the data being mapped. Used when we have the 7373 /// use_device_ptr clause. 7374 OMP_MAP_RETURN_PARAM = 0x40, 7375 /// This flag signals that the reference being passed is a pointer to 7376 /// private data. 7377 OMP_MAP_PRIVATE = 0x80, 7378 /// Pass the element to the device by value. 7379 OMP_MAP_LITERAL = 0x100, 7380 /// Implicit map 7381 OMP_MAP_IMPLICIT = 0x200, 7382 /// Close is a hint to the runtime to allocate memory close to 7383 /// the target device. 7384 OMP_MAP_CLOSE = 0x400, 7385 /// The 16 MSBs of the flags indicate whether the entry is member of some 7386 /// struct/class. 7387 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7388 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7389 }; 7390 7391 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7392 static unsigned getFlagMemberOffset() { 7393 unsigned Offset = 0; 7394 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7395 Remain = Remain >> 1) 7396 Offset++; 7397 return Offset; 7398 } 7399 7400 /// Class that associates information with a base pointer to be passed to the 7401 /// runtime library. 7402 class BasePointerInfo { 7403 /// The base pointer. 7404 llvm::Value *Ptr = nullptr; 7405 /// The base declaration that refers to this device pointer, or null if 7406 /// there is none. 7407 const ValueDecl *DevPtrDecl = nullptr; 7408 7409 public: 7410 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7411 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7412 llvm::Value *operator*() const { return Ptr; } 7413 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7414 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7415 }; 7416 7417 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7418 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7419 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7420 7421 /// Map between a struct and the its lowest & highest elements which have been 7422 /// mapped. 7423 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7424 /// HE(FieldIndex, Pointer)} 7425 struct StructRangeInfoTy { 7426 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7427 0, Address::invalid()}; 7428 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7429 0, Address::invalid()}; 7430 Address Base = Address::invalid(); 7431 }; 7432 7433 private: 7434 /// Kind that defines how a device pointer has to be returned. 7435 struct MapInfo { 7436 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7437 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7438 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7439 bool ReturnDevicePointer = false; 7440 bool IsImplicit = false; 7441 7442 MapInfo() = default; 7443 MapInfo( 7444 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7445 OpenMPMapClauseKind MapType, 7446 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7447 bool ReturnDevicePointer, bool IsImplicit) 7448 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7449 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7450 }; 7451 7452 /// If use_device_ptr is used on a pointer which is a struct member and there 7453 /// is no map information about it, then emission of that entry is deferred 7454 /// until the whole struct has been processed. 7455 struct DeferredDevicePtrEntryTy { 7456 const Expr *IE = nullptr; 7457 const ValueDecl *VD = nullptr; 7458 7459 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7460 : IE(IE), VD(VD) {} 7461 }; 7462 7463 /// The target directive from where the mappable clauses were extracted. It 7464 /// is either a executable directive or a user-defined mapper directive. 7465 llvm::PointerUnion<const OMPExecutableDirective *, 7466 const OMPDeclareMapperDecl *> 7467 CurDir; 7468 7469 /// Function the directive is being generated for. 7470 CodeGenFunction &CGF; 7471 7472 /// Set of all first private variables in the current directive. 7473 /// bool data is set to true if the variable is implicitly marked as 7474 /// firstprivate, false otherwise. 7475 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7476 7477 /// Map between device pointer declarations and their expression components. 7478 /// The key value for declarations in 'this' is null. 7479 llvm::DenseMap< 7480 const ValueDecl *, 7481 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7482 DevPointersMap; 7483 7484 llvm::Value *getExprTypeSize(const Expr *E) const { 7485 QualType ExprTy = E->getType().getCanonicalType(); 7486 7487 // Reference types are ignored for mapping purposes. 7488 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7489 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7490 7491 // Given that an array section is considered a built-in type, we need to 7492 // do the calculation based on the length of the section instead of relying 7493 // on CGF.getTypeSize(E->getType()). 7494 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7495 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7496 OAE->getBase()->IgnoreParenImpCasts()) 7497 .getCanonicalType(); 7498 7499 // If there is no length associated with the expression and lower bound is 7500 // not specified too, that means we are using the whole length of the 7501 // base. 7502 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7503 !OAE->getLowerBound()) 7504 return CGF.getTypeSize(BaseTy); 7505 7506 llvm::Value *ElemSize; 7507 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7508 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7509 } else { 7510 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7511 assert(ATy && "Expecting array type if not a pointer type."); 7512 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7513 } 7514 7515 // If we don't have a length at this point, that is because we have an 7516 // array section with a single element. 7517 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7518 return ElemSize; 7519 7520 if (const Expr *LenExpr = OAE->getLength()) { 7521 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7522 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7523 CGF.getContext().getSizeType(), 7524 LenExpr->getExprLoc()); 7525 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7526 } 7527 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7528 OAE->getLowerBound() && "expected array_section[lb:]."); 7529 // Size = sizetype - lb * elemtype; 7530 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7531 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7532 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7533 CGF.getContext().getSizeType(), 7534 OAE->getLowerBound()->getExprLoc()); 7535 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7536 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7537 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7538 LengthVal = CGF.Builder.CreateSelect( 7539 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7540 return LengthVal; 7541 } 7542 return CGF.getTypeSize(ExprTy); 7543 } 7544 7545 /// Return the corresponding bits for a given map clause modifier. Add 7546 /// a flag marking the map as a pointer if requested. Add a flag marking the 7547 /// map as the first one of a series of maps that relate to the same map 7548 /// expression. 7549 OpenMPOffloadMappingFlags getMapTypeBits( 7550 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7551 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7552 OpenMPOffloadMappingFlags Bits = 7553 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7554 switch (MapType) { 7555 case OMPC_MAP_alloc: 7556 case OMPC_MAP_release: 7557 // alloc and release is the default behavior in the runtime library, i.e. 7558 // if we don't pass any bits alloc/release that is what the runtime is 7559 // going to do. Therefore, we don't need to signal anything for these two 7560 // type modifiers. 7561 break; 7562 case OMPC_MAP_to: 7563 Bits |= OMP_MAP_TO; 7564 break; 7565 case OMPC_MAP_from: 7566 Bits |= OMP_MAP_FROM; 7567 break; 7568 case OMPC_MAP_tofrom: 7569 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7570 break; 7571 case OMPC_MAP_delete: 7572 Bits |= OMP_MAP_DELETE; 7573 break; 7574 case OMPC_MAP_unknown: 7575 llvm_unreachable("Unexpected map type!"); 7576 } 7577 if (AddPtrFlag) 7578 Bits |= OMP_MAP_PTR_AND_OBJ; 7579 if (AddIsTargetParamFlag) 7580 Bits |= OMP_MAP_TARGET_PARAM; 7581 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7582 != MapModifiers.end()) 7583 Bits |= OMP_MAP_ALWAYS; 7584 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7585 != MapModifiers.end()) 7586 Bits |= OMP_MAP_CLOSE; 7587 return Bits; 7588 } 7589 7590 /// Return true if the provided expression is a final array section. A 7591 /// final array section, is one whose length can't be proved to be one. 7592 bool isFinalArraySectionExpression(const Expr *E) const { 7593 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7594 7595 // It is not an array section and therefore not a unity-size one. 7596 if (!OASE) 7597 return false; 7598 7599 // An array section with no colon always refer to a single element. 7600 if (OASE->getColonLoc().isInvalid()) 7601 return false; 7602 7603 const Expr *Length = OASE->getLength(); 7604 7605 // If we don't have a length we have to check if the array has size 1 7606 // for this dimension. Also, we should always expect a length if the 7607 // base type is pointer. 7608 if (!Length) { 7609 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7610 OASE->getBase()->IgnoreParenImpCasts()) 7611 .getCanonicalType(); 7612 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7613 return ATy->getSize().getSExtValue() != 1; 7614 // If we don't have a constant dimension length, we have to consider 7615 // the current section as having any size, so it is not necessarily 7616 // unitary. If it happen to be unity size, that's user fault. 7617 return true; 7618 } 7619 7620 // Check if the length evaluates to 1. 7621 Expr::EvalResult Result; 7622 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7623 return true; // Can have more that size 1. 7624 7625 llvm::APSInt ConstLength = Result.Val.getInt(); 7626 return ConstLength.getSExtValue() != 1; 7627 } 7628 7629 /// Generate the base pointers, section pointers, sizes and map type 7630 /// bits for the provided map type, map modifier, and expression components. 7631 /// \a IsFirstComponent should be set to true if the provided set of 7632 /// components is the first associated with a capture. 7633 void generateInfoForComponentList( 7634 OpenMPMapClauseKind MapType, 7635 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7636 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7637 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7638 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7639 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7640 bool IsImplicit, 7641 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7642 OverlappedElements = llvm::None) const { 7643 // The following summarizes what has to be generated for each map and the 7644 // types below. The generated information is expressed in this order: 7645 // base pointer, section pointer, size, flags 7646 // (to add to the ones that come from the map type and modifier). 7647 // 7648 // double d; 7649 // int i[100]; 7650 // float *p; 7651 // 7652 // struct S1 { 7653 // int i; 7654 // float f[50]; 7655 // } 7656 // struct S2 { 7657 // int i; 7658 // float f[50]; 7659 // S1 s; 7660 // double *p; 7661 // struct S2 *ps; 7662 // } 7663 // S2 s; 7664 // S2 *ps; 7665 // 7666 // map(d) 7667 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7668 // 7669 // map(i) 7670 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7671 // 7672 // map(i[1:23]) 7673 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7674 // 7675 // map(p) 7676 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7677 // 7678 // map(p[1:24]) 7679 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7680 // 7681 // map(s) 7682 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7683 // 7684 // map(s.i) 7685 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7686 // 7687 // map(s.s.f) 7688 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7689 // 7690 // map(s.p) 7691 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7692 // 7693 // map(to: s.p[:22]) 7694 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7695 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7696 // &(s.p), &(s.p[0]), 22*sizeof(double), 7697 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7698 // (*) alloc space for struct members, only this is a target parameter 7699 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7700 // optimizes this entry out, same in the examples below) 7701 // (***) map the pointee (map: to) 7702 // 7703 // map(s.ps) 7704 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7705 // 7706 // map(from: s.ps->s.i) 7707 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7708 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7709 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7710 // 7711 // map(to: s.ps->ps) 7712 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7713 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7714 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7715 // 7716 // map(s.ps->ps->ps) 7717 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7718 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7719 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7720 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7721 // 7722 // map(to: s.ps->ps->s.f[:22]) 7723 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7724 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7725 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7726 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7727 // 7728 // map(ps) 7729 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7730 // 7731 // map(ps->i) 7732 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7733 // 7734 // map(ps->s.f) 7735 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7736 // 7737 // map(from: ps->p) 7738 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7739 // 7740 // map(to: ps->p[:22]) 7741 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7742 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7743 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7744 // 7745 // map(ps->ps) 7746 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7747 // 7748 // map(from: ps->ps->s.i) 7749 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7750 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7751 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7752 // 7753 // map(from: ps->ps->ps) 7754 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7755 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7756 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7757 // 7758 // map(ps->ps->ps->ps) 7759 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7760 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7761 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7762 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7763 // 7764 // map(to: ps->ps->ps->s.f[:22]) 7765 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7766 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7767 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7768 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7769 // 7770 // map(to: s.f[:22]) map(from: s.p[:33]) 7771 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7772 // sizeof(double*) (**), TARGET_PARAM 7773 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7774 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7775 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7776 // (*) allocate contiguous space needed to fit all mapped members even if 7777 // we allocate space for members not mapped (in this example, 7778 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7779 // them as well because they fall between &s.f[0] and &s.p) 7780 // 7781 // map(from: s.f[:22]) map(to: ps->p[:33]) 7782 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7783 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7784 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7785 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7786 // (*) the struct this entry pertains to is the 2nd element in the list of 7787 // arguments, hence MEMBER_OF(2) 7788 // 7789 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7790 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7791 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7792 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7793 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7794 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7795 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7796 // (*) the struct this entry pertains to is the 4th element in the list 7797 // of arguments, hence MEMBER_OF(4) 7798 7799 // Track if the map information being generated is the first for a capture. 7800 bool IsCaptureFirstInfo = IsFirstComponentList; 7801 // When the variable is on a declare target link or in a to clause with 7802 // unified memory, a reference is needed to hold the host/device address 7803 // of the variable. 7804 bool RequiresReference = false; 7805 7806 // Scan the components from the base to the complete expression. 7807 auto CI = Components.rbegin(); 7808 auto CE = Components.rend(); 7809 auto I = CI; 7810 7811 // Track if the map information being generated is the first for a list of 7812 // components. 7813 bool IsExpressionFirstInfo = true; 7814 Address BP = Address::invalid(); 7815 const Expr *AssocExpr = I->getAssociatedExpression(); 7816 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7817 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7818 7819 if (isa<MemberExpr>(AssocExpr)) { 7820 // The base is the 'this' pointer. The content of the pointer is going 7821 // to be the base of the field being mapped. 7822 BP = CGF.LoadCXXThisAddress(); 7823 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7824 (OASE && 7825 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7826 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7827 } else { 7828 // The base is the reference to the variable. 7829 // BP = &Var. 7830 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7831 if (const auto *VD = 7832 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7833 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7834 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7835 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7836 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7837 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7838 RequiresReference = true; 7839 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7840 } 7841 } 7842 } 7843 7844 // If the variable is a pointer and is being dereferenced (i.e. is not 7845 // the last component), the base has to be the pointer itself, not its 7846 // reference. References are ignored for mapping purposes. 7847 QualType Ty = 7848 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7849 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7850 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7851 7852 // We do not need to generate individual map information for the 7853 // pointer, it can be associated with the combined storage. 7854 ++I; 7855 } 7856 } 7857 7858 // Track whether a component of the list should be marked as MEMBER_OF some 7859 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7860 // in a component list should be marked as MEMBER_OF, all subsequent entries 7861 // do not belong to the base struct. E.g. 7862 // struct S2 s; 7863 // s.ps->ps->ps->f[:] 7864 // (1) (2) (3) (4) 7865 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7866 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7867 // is the pointee of ps(2) which is not member of struct s, so it should not 7868 // be marked as such (it is still PTR_AND_OBJ). 7869 // The variable is initialized to false so that PTR_AND_OBJ entries which 7870 // are not struct members are not considered (e.g. array of pointers to 7871 // data). 7872 bool ShouldBeMemberOf = false; 7873 7874 // Variable keeping track of whether or not we have encountered a component 7875 // in the component list which is a member expression. Useful when we have a 7876 // pointer or a final array section, in which case it is the previous 7877 // component in the list which tells us whether we have a member expression. 7878 // E.g. X.f[:] 7879 // While processing the final array section "[:]" it is "f" which tells us 7880 // whether we are dealing with a member of a declared struct. 7881 const MemberExpr *EncounteredME = nullptr; 7882 7883 for (; I != CE; ++I) { 7884 // If the current component is member of a struct (parent struct) mark it. 7885 if (!EncounteredME) { 7886 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7887 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7888 // as MEMBER_OF the parent struct. 7889 if (EncounteredME) 7890 ShouldBeMemberOf = true; 7891 } 7892 7893 auto Next = std::next(I); 7894 7895 // We need to generate the addresses and sizes if this is the last 7896 // component, if the component is a pointer or if it is an array section 7897 // whose length can't be proved to be one. If this is a pointer, it 7898 // becomes the base address for the following components. 7899 7900 // A final array section, is one whose length can't be proved to be one. 7901 bool IsFinalArraySection = 7902 isFinalArraySectionExpression(I->getAssociatedExpression()); 7903 7904 // Get information on whether the element is a pointer. Have to do a 7905 // special treatment for array sections given that they are built-in 7906 // types. 7907 const auto *OASE = 7908 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7909 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression()); 7910 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression()); 7911 bool IsPointer = 7912 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7913 .getCanonicalType() 7914 ->isAnyPointerType()) || 7915 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7916 bool IsNonDerefPointer = IsPointer && !UO && !BO; 7917 7918 if (Next == CE || IsNonDerefPointer || IsFinalArraySection) { 7919 // If this is not the last component, we expect the pointer to be 7920 // associated with an array expression or member expression. 7921 assert((Next == CE || 7922 isa<MemberExpr>(Next->getAssociatedExpression()) || 7923 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7924 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || 7925 isa<UnaryOperator>(Next->getAssociatedExpression()) || 7926 isa<BinaryOperator>(Next->getAssociatedExpression())) && 7927 "Unexpected expression"); 7928 7929 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7930 .getAddress(CGF); 7931 7932 // If this component is a pointer inside the base struct then we don't 7933 // need to create any entry for it - it will be combined with the object 7934 // it is pointing to into a single PTR_AND_OBJ entry. 7935 bool IsMemberPointer = 7936 IsPointer && EncounteredME && 7937 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7938 EncounteredME); 7939 if (!OverlappedElements.empty()) { 7940 // Handle base element with the info for overlapped elements. 7941 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7942 assert(Next == CE && 7943 "Expected last element for the overlapped elements."); 7944 assert(!IsPointer && 7945 "Unexpected base element with the pointer type."); 7946 // Mark the whole struct as the struct that requires allocation on the 7947 // device. 7948 PartialStruct.LowestElem = {0, LB}; 7949 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7950 I->getAssociatedExpression()->getType()); 7951 Address HB = CGF.Builder.CreateConstGEP( 7952 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7953 CGF.VoidPtrTy), 7954 TypeSize.getQuantity() - 1); 7955 PartialStruct.HighestElem = { 7956 std::numeric_limits<decltype( 7957 PartialStruct.HighestElem.first)>::max(), 7958 HB}; 7959 PartialStruct.Base = BP; 7960 // Emit data for non-overlapped data. 7961 OpenMPOffloadMappingFlags Flags = 7962 OMP_MAP_MEMBER_OF | 7963 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7964 /*AddPtrFlag=*/false, 7965 /*AddIsTargetParamFlag=*/false); 7966 LB = BP; 7967 llvm::Value *Size = nullptr; 7968 // Do bitcopy of all non-overlapped structure elements. 7969 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7970 Component : OverlappedElements) { 7971 Address ComponentLB = Address::invalid(); 7972 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7973 Component) { 7974 if (MC.getAssociatedDeclaration()) { 7975 ComponentLB = 7976 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7977 .getAddress(CGF); 7978 Size = CGF.Builder.CreatePtrDiff( 7979 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7980 CGF.EmitCastToVoidPtr(LB.getPointer())); 7981 break; 7982 } 7983 } 7984 BasePointers.push_back(BP.getPointer()); 7985 Pointers.push_back(LB.getPointer()); 7986 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7987 /*isSigned=*/true)); 7988 Types.push_back(Flags); 7989 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7990 } 7991 BasePointers.push_back(BP.getPointer()); 7992 Pointers.push_back(LB.getPointer()); 7993 Size = CGF.Builder.CreatePtrDiff( 7994 CGF.EmitCastToVoidPtr( 7995 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7996 CGF.EmitCastToVoidPtr(LB.getPointer())); 7997 Sizes.push_back( 7998 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7999 Types.push_back(Flags); 8000 break; 8001 } 8002 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 8003 if (!IsMemberPointer) { 8004 BasePointers.push_back(BP.getPointer()); 8005 Pointers.push_back(LB.getPointer()); 8006 Sizes.push_back( 8007 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 8008 8009 // We need to add a pointer flag for each map that comes from the 8010 // same expression except for the first one. We also need to signal 8011 // this map is the first one that relates with the current capture 8012 // (there is a set of entries for each capture). 8013 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 8014 MapType, MapModifiers, IsImplicit, 8015 !IsExpressionFirstInfo || RequiresReference, 8016 IsCaptureFirstInfo && !RequiresReference); 8017 8018 if (!IsExpressionFirstInfo) { 8019 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 8020 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 8021 if (IsPointer) 8022 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 8023 OMP_MAP_DELETE | OMP_MAP_CLOSE); 8024 8025 if (ShouldBeMemberOf) { 8026 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 8027 // should be later updated with the correct value of MEMBER_OF. 8028 Flags |= OMP_MAP_MEMBER_OF; 8029 // From now on, all subsequent PTR_AND_OBJ entries should not be 8030 // marked as MEMBER_OF. 8031 ShouldBeMemberOf = false; 8032 } 8033 } 8034 8035 Types.push_back(Flags); 8036 } 8037 8038 // If we have encountered a member expression so far, keep track of the 8039 // mapped member. If the parent is "*this", then the value declaration 8040 // is nullptr. 8041 if (EncounteredME) { 8042 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl()); 8043 unsigned FieldIndex = FD->getFieldIndex(); 8044 8045 // Update info about the lowest and highest elements for this struct 8046 if (!PartialStruct.Base.isValid()) { 8047 PartialStruct.LowestElem = {FieldIndex, LB}; 8048 PartialStruct.HighestElem = {FieldIndex, LB}; 8049 PartialStruct.Base = BP; 8050 } else if (FieldIndex < PartialStruct.LowestElem.first) { 8051 PartialStruct.LowestElem = {FieldIndex, LB}; 8052 } else if (FieldIndex > PartialStruct.HighestElem.first) { 8053 PartialStruct.HighestElem = {FieldIndex, LB}; 8054 } 8055 } 8056 8057 // If we have a final array section, we are done with this expression. 8058 if (IsFinalArraySection) 8059 break; 8060 8061 // The pointer becomes the base for the next element. 8062 if (Next != CE) 8063 BP = LB; 8064 8065 IsExpressionFirstInfo = false; 8066 IsCaptureFirstInfo = false; 8067 } 8068 } 8069 } 8070 8071 /// Return the adjusted map modifiers if the declaration a capture refers to 8072 /// appears in a first-private clause. This is expected to be used only with 8073 /// directives that start with 'target'. 8074 MappableExprsHandler::OpenMPOffloadMappingFlags 8075 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 8076 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 8077 8078 // A first private variable captured by reference will use only the 8079 // 'private ptr' and 'map to' flag. Return the right flags if the captured 8080 // declaration is known as first-private in this handler. 8081 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 8082 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 8083 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 8084 return MappableExprsHandler::OMP_MAP_ALWAYS | 8085 MappableExprsHandler::OMP_MAP_TO; 8086 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 8087 return MappableExprsHandler::OMP_MAP_TO | 8088 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 8089 return MappableExprsHandler::OMP_MAP_PRIVATE | 8090 MappableExprsHandler::OMP_MAP_TO; 8091 } 8092 return MappableExprsHandler::OMP_MAP_TO | 8093 MappableExprsHandler::OMP_MAP_FROM; 8094 } 8095 8096 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 8097 // Rotate by getFlagMemberOffset() bits. 8098 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 8099 << getFlagMemberOffset()); 8100 } 8101 8102 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 8103 OpenMPOffloadMappingFlags MemberOfFlag) { 8104 // If the entry is PTR_AND_OBJ but has not been marked with the special 8105 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 8106 // marked as MEMBER_OF. 8107 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 8108 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 8109 return; 8110 8111 // Reset the placeholder value to prepare the flag for the assignment of the 8112 // proper MEMBER_OF value. 8113 Flags &= ~OMP_MAP_MEMBER_OF; 8114 Flags |= MemberOfFlag; 8115 } 8116 8117 void getPlainLayout(const CXXRecordDecl *RD, 8118 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 8119 bool AsBase) const { 8120 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 8121 8122 llvm::StructType *St = 8123 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 8124 8125 unsigned NumElements = St->getNumElements(); 8126 llvm::SmallVector< 8127 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 8128 RecordLayout(NumElements); 8129 8130 // Fill bases. 8131 for (const auto &I : RD->bases()) { 8132 if (I.isVirtual()) 8133 continue; 8134 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8135 // Ignore empty bases. 8136 if (Base->isEmpty() || CGF.getContext() 8137 .getASTRecordLayout(Base) 8138 .getNonVirtualSize() 8139 .isZero()) 8140 continue; 8141 8142 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 8143 RecordLayout[FieldIndex] = Base; 8144 } 8145 // Fill in virtual bases. 8146 for (const auto &I : RD->vbases()) { 8147 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8148 // Ignore empty bases. 8149 if (Base->isEmpty()) 8150 continue; 8151 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 8152 if (RecordLayout[FieldIndex]) 8153 continue; 8154 RecordLayout[FieldIndex] = Base; 8155 } 8156 // Fill in all the fields. 8157 assert(!RD->isUnion() && "Unexpected union."); 8158 for (const auto *Field : RD->fields()) { 8159 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 8160 // will fill in later.) 8161 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 8162 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 8163 RecordLayout[FieldIndex] = Field; 8164 } 8165 } 8166 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 8167 &Data : RecordLayout) { 8168 if (Data.isNull()) 8169 continue; 8170 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 8171 getPlainLayout(Base, Layout, /*AsBase=*/true); 8172 else 8173 Layout.push_back(Data.get<const FieldDecl *>()); 8174 } 8175 } 8176 8177 public: 8178 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 8179 : CurDir(&Dir), CGF(CGF) { 8180 // Extract firstprivate clause information. 8181 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 8182 for (const auto *D : C->varlists()) 8183 FirstPrivateDecls.try_emplace( 8184 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 8185 // Extract device pointer clause information. 8186 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 8187 for (auto L : C->component_lists()) 8188 DevPointersMap[L.first].push_back(L.second); 8189 } 8190 8191 /// Constructor for the declare mapper directive. 8192 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 8193 : CurDir(&Dir), CGF(CGF) {} 8194 8195 /// Generate code for the combined entry if we have a partially mapped struct 8196 /// and take care of the mapping flags of the arguments corresponding to 8197 /// individual struct members. 8198 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 8199 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8200 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 8201 const StructRangeInfoTy &PartialStruct) const { 8202 // Base is the base of the struct 8203 BasePointers.push_back(PartialStruct.Base.getPointer()); 8204 // Pointer is the address of the lowest element 8205 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 8206 Pointers.push_back(LB); 8207 // Size is (addr of {highest+1} element) - (addr of lowest element) 8208 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 8209 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 8210 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 8211 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 8212 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 8213 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 8214 /*isSigned=*/false); 8215 Sizes.push_back(Size); 8216 // Map type is always TARGET_PARAM 8217 Types.push_back(OMP_MAP_TARGET_PARAM); 8218 // Remove TARGET_PARAM flag from the first element 8219 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 8220 8221 // All other current entries will be MEMBER_OF the combined entry 8222 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8223 // 0xFFFF in the MEMBER_OF field). 8224 OpenMPOffloadMappingFlags MemberOfFlag = 8225 getMemberOfFlag(BasePointers.size() - 1); 8226 for (auto &M : CurTypes) 8227 setCorrectMemberOfFlag(M, MemberOfFlag); 8228 } 8229 8230 /// Generate all the base pointers, section pointers, sizes and map 8231 /// types for the extracted mappable expressions. Also, for each item that 8232 /// relates with a device pointer, a pair of the relevant declaration and 8233 /// index where it occurs is appended to the device pointers info array. 8234 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 8235 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8236 MapFlagsArrayTy &Types) const { 8237 // We have to process the component lists that relate with the same 8238 // declaration in a single chunk so that we can generate the map flags 8239 // correctly. Therefore, we organize all lists in a map. 8240 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8241 8242 // Helper function to fill the information map for the different supported 8243 // clauses. 8244 auto &&InfoGen = [&Info]( 8245 const ValueDecl *D, 8246 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8247 OpenMPMapClauseKind MapType, 8248 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8249 bool ReturnDevicePointer, bool IsImplicit) { 8250 const ValueDecl *VD = 8251 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8252 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8253 IsImplicit); 8254 }; 8255 8256 assert(CurDir.is<const OMPExecutableDirective *>() && 8257 "Expect a executable directive"); 8258 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8259 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 8260 for (const auto L : C->component_lists()) { 8261 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 8262 /*ReturnDevicePointer=*/false, C->isImplicit()); 8263 } 8264 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 8265 for (const auto L : C->component_lists()) { 8266 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 8267 /*ReturnDevicePointer=*/false, C->isImplicit()); 8268 } 8269 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 8270 for (const auto L : C->component_lists()) { 8271 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 8272 /*ReturnDevicePointer=*/false, C->isImplicit()); 8273 } 8274 8275 // Look at the use_device_ptr clause information and mark the existing map 8276 // entries as such. If there is no map information for an entry in the 8277 // use_device_ptr list, we create one with map type 'alloc' and zero size 8278 // section. It is the user fault if that was not mapped before. If there is 8279 // no map information and the pointer is a struct member, then we defer the 8280 // emission of that entry until the whole struct has been processed. 8281 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 8282 DeferredInfo; 8283 8284 for (const auto *C : 8285 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 8286 for (const auto L : C->component_lists()) { 8287 assert(!L.second.empty() && "Not expecting empty list of components!"); 8288 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 8289 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8290 const Expr *IE = L.second.back().getAssociatedExpression(); 8291 // If the first component is a member expression, we have to look into 8292 // 'this', which maps to null in the map of map information. Otherwise 8293 // look directly for the information. 8294 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8295 8296 // We potentially have map information for this declaration already. 8297 // Look for the first set of components that refer to it. 8298 if (It != Info.end()) { 8299 auto CI = std::find_if( 8300 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 8301 return MI.Components.back().getAssociatedDeclaration() == VD; 8302 }); 8303 // If we found a map entry, signal that the pointer has to be returned 8304 // and move on to the next declaration. 8305 if (CI != It->second.end()) { 8306 CI->ReturnDevicePointer = true; 8307 continue; 8308 } 8309 } 8310 8311 // We didn't find any match in our map information - generate a zero 8312 // size array section - if the pointer is a struct member we defer this 8313 // action until the whole struct has been processed. 8314 if (isa<MemberExpr>(IE)) { 8315 // Insert the pointer into Info to be processed by 8316 // generateInfoForComponentList. Because it is a member pointer 8317 // without a pointee, no entry will be generated for it, therefore 8318 // we need to generate one after the whole struct has been processed. 8319 // Nonetheless, generateInfoForComponentList must be called to take 8320 // the pointer into account for the calculation of the range of the 8321 // partial struct. 8322 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 8323 /*ReturnDevicePointer=*/false, C->isImplicit()); 8324 DeferredInfo[nullptr].emplace_back(IE, VD); 8325 } else { 8326 llvm::Value *Ptr = 8327 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8328 BasePointers.emplace_back(Ptr, VD); 8329 Pointers.push_back(Ptr); 8330 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8331 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8332 } 8333 } 8334 } 8335 8336 for (const auto &M : Info) { 8337 // We need to know when we generate information for the first component 8338 // associated with a capture, because the mapping flags depend on it. 8339 bool IsFirstComponentList = true; 8340 8341 // Temporary versions of arrays 8342 MapBaseValuesArrayTy CurBasePointers; 8343 MapValuesArrayTy CurPointers; 8344 MapValuesArrayTy CurSizes; 8345 MapFlagsArrayTy CurTypes; 8346 StructRangeInfoTy PartialStruct; 8347 8348 for (const MapInfo &L : M.second) { 8349 assert(!L.Components.empty() && 8350 "Not expecting declaration with no component lists."); 8351 8352 // Remember the current base pointer index. 8353 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8354 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8355 CurBasePointers, CurPointers, CurSizes, 8356 CurTypes, PartialStruct, 8357 IsFirstComponentList, L.IsImplicit); 8358 8359 // If this entry relates with a device pointer, set the relevant 8360 // declaration and add the 'return pointer' flag. 8361 if (L.ReturnDevicePointer) { 8362 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8363 "Unexpected number of mapped base pointers."); 8364 8365 const ValueDecl *RelevantVD = 8366 L.Components.back().getAssociatedDeclaration(); 8367 assert(RelevantVD && 8368 "No relevant declaration related with device pointer??"); 8369 8370 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8371 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8372 } 8373 IsFirstComponentList = false; 8374 } 8375 8376 // Append any pending zero-length pointers which are struct members and 8377 // used with use_device_ptr. 8378 auto CI = DeferredInfo.find(M.first); 8379 if (CI != DeferredInfo.end()) { 8380 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8381 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8382 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8383 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8384 CurBasePointers.emplace_back(BasePtr, L.VD); 8385 CurPointers.push_back(Ptr); 8386 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8387 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8388 // value MEMBER_OF=FFFF so that the entry is later updated with the 8389 // correct value of MEMBER_OF. 8390 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8391 OMP_MAP_MEMBER_OF); 8392 } 8393 } 8394 8395 // If there is an entry in PartialStruct it means we have a struct with 8396 // individual members mapped. Emit an extra combined entry. 8397 if (PartialStruct.Base.isValid()) 8398 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8399 PartialStruct); 8400 8401 // We need to append the results of this capture to what we already have. 8402 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8403 Pointers.append(CurPointers.begin(), CurPointers.end()); 8404 Sizes.append(CurSizes.begin(), CurSizes.end()); 8405 Types.append(CurTypes.begin(), CurTypes.end()); 8406 } 8407 } 8408 8409 /// Generate all the base pointers, section pointers, sizes and map types for 8410 /// the extracted map clauses of user-defined mapper. 8411 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8412 MapValuesArrayTy &Pointers, 8413 MapValuesArrayTy &Sizes, 8414 MapFlagsArrayTy &Types) const { 8415 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8416 "Expect a declare mapper directive"); 8417 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8418 // We have to process the component lists that relate with the same 8419 // declaration in a single chunk so that we can generate the map flags 8420 // correctly. Therefore, we organize all lists in a map. 8421 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8422 8423 // Helper function to fill the information map for the different supported 8424 // clauses. 8425 auto &&InfoGen = [&Info]( 8426 const ValueDecl *D, 8427 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8428 OpenMPMapClauseKind MapType, 8429 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8430 bool ReturnDevicePointer, bool IsImplicit) { 8431 const ValueDecl *VD = 8432 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8433 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8434 IsImplicit); 8435 }; 8436 8437 for (const auto *C : CurMapperDir->clauselists()) { 8438 const auto *MC = cast<OMPMapClause>(C); 8439 for (const auto L : MC->component_lists()) { 8440 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8441 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8442 } 8443 } 8444 8445 for (const auto &M : Info) { 8446 // We need to know when we generate information for the first component 8447 // associated with a capture, because the mapping flags depend on it. 8448 bool IsFirstComponentList = true; 8449 8450 // Temporary versions of arrays 8451 MapBaseValuesArrayTy CurBasePointers; 8452 MapValuesArrayTy CurPointers; 8453 MapValuesArrayTy CurSizes; 8454 MapFlagsArrayTy CurTypes; 8455 StructRangeInfoTy PartialStruct; 8456 8457 for (const MapInfo &L : M.second) { 8458 assert(!L.Components.empty() && 8459 "Not expecting declaration with no component lists."); 8460 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8461 CurBasePointers, CurPointers, CurSizes, 8462 CurTypes, PartialStruct, 8463 IsFirstComponentList, L.IsImplicit); 8464 IsFirstComponentList = false; 8465 } 8466 8467 // If there is an entry in PartialStruct it means we have a struct with 8468 // individual members mapped. Emit an extra combined entry. 8469 if (PartialStruct.Base.isValid()) 8470 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8471 PartialStruct); 8472 8473 // We need to append the results of this capture to what we already have. 8474 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8475 Pointers.append(CurPointers.begin(), CurPointers.end()); 8476 Sizes.append(CurSizes.begin(), CurSizes.end()); 8477 Types.append(CurTypes.begin(), CurTypes.end()); 8478 } 8479 } 8480 8481 /// Emit capture info for lambdas for variables captured by reference. 8482 void generateInfoForLambdaCaptures( 8483 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8484 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8485 MapFlagsArrayTy &Types, 8486 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8487 const auto *RD = VD->getType() 8488 .getCanonicalType() 8489 .getNonReferenceType() 8490 ->getAsCXXRecordDecl(); 8491 if (!RD || !RD->isLambda()) 8492 return; 8493 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8494 LValue VDLVal = CGF.MakeAddrLValue( 8495 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8496 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8497 FieldDecl *ThisCapture = nullptr; 8498 RD->getCaptureFields(Captures, ThisCapture); 8499 if (ThisCapture) { 8500 LValue ThisLVal = 8501 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8502 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8503 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8504 VDLVal.getPointer(CGF)); 8505 BasePointers.push_back(ThisLVal.getPointer(CGF)); 8506 Pointers.push_back(ThisLValVal.getPointer(CGF)); 8507 Sizes.push_back( 8508 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8509 CGF.Int64Ty, /*isSigned=*/true)); 8510 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8511 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8512 } 8513 for (const LambdaCapture &LC : RD->captures()) { 8514 if (!LC.capturesVariable()) 8515 continue; 8516 const VarDecl *VD = LC.getCapturedVar(); 8517 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8518 continue; 8519 auto It = Captures.find(VD); 8520 assert(It != Captures.end() && "Found lambda capture without field."); 8521 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8522 if (LC.getCaptureKind() == LCK_ByRef) { 8523 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8524 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8525 VDLVal.getPointer(CGF)); 8526 BasePointers.push_back(VarLVal.getPointer(CGF)); 8527 Pointers.push_back(VarLValVal.getPointer(CGF)); 8528 Sizes.push_back(CGF.Builder.CreateIntCast( 8529 CGF.getTypeSize( 8530 VD->getType().getCanonicalType().getNonReferenceType()), 8531 CGF.Int64Ty, /*isSigned=*/true)); 8532 } else { 8533 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8534 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8535 VDLVal.getPointer(CGF)); 8536 BasePointers.push_back(VarLVal.getPointer(CGF)); 8537 Pointers.push_back(VarRVal.getScalarVal()); 8538 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8539 } 8540 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8541 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8542 } 8543 } 8544 8545 /// Set correct indices for lambdas captures. 8546 void adjustMemberOfForLambdaCaptures( 8547 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8548 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8549 MapFlagsArrayTy &Types) const { 8550 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8551 // Set correct member_of idx for all implicit lambda captures. 8552 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8553 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8554 continue; 8555 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8556 assert(BasePtr && "Unable to find base lambda address."); 8557 int TgtIdx = -1; 8558 for (unsigned J = I; J > 0; --J) { 8559 unsigned Idx = J - 1; 8560 if (Pointers[Idx] != BasePtr) 8561 continue; 8562 TgtIdx = Idx; 8563 break; 8564 } 8565 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8566 // All other current entries will be MEMBER_OF the combined entry 8567 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8568 // 0xFFFF in the MEMBER_OF field). 8569 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8570 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8571 } 8572 } 8573 8574 /// Generate the base pointers, section pointers, sizes and map types 8575 /// associated to a given capture. 8576 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8577 llvm::Value *Arg, 8578 MapBaseValuesArrayTy &BasePointers, 8579 MapValuesArrayTy &Pointers, 8580 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8581 StructRangeInfoTy &PartialStruct) const { 8582 assert(!Cap->capturesVariableArrayType() && 8583 "Not expecting to generate map info for a variable array type!"); 8584 8585 // We need to know when we generating information for the first component 8586 const ValueDecl *VD = Cap->capturesThis() 8587 ? nullptr 8588 : Cap->getCapturedVar()->getCanonicalDecl(); 8589 8590 // If this declaration appears in a is_device_ptr clause we just have to 8591 // pass the pointer by value. If it is a reference to a declaration, we just 8592 // pass its value. 8593 if (DevPointersMap.count(VD)) { 8594 BasePointers.emplace_back(Arg, VD); 8595 Pointers.push_back(Arg); 8596 Sizes.push_back( 8597 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8598 CGF.Int64Ty, /*isSigned=*/true)); 8599 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8600 return; 8601 } 8602 8603 using MapData = 8604 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8605 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8606 SmallVector<MapData, 4> DeclComponentLists; 8607 assert(CurDir.is<const OMPExecutableDirective *>() && 8608 "Expect a executable directive"); 8609 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8610 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8611 for (const auto L : C->decl_component_lists(VD)) { 8612 assert(L.first == VD && 8613 "We got information for the wrong declaration??"); 8614 assert(!L.second.empty() && 8615 "Not expecting declaration with no component lists."); 8616 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8617 C->getMapTypeModifiers(), 8618 C->isImplicit()); 8619 } 8620 } 8621 8622 // Find overlapping elements (including the offset from the base element). 8623 llvm::SmallDenseMap< 8624 const MapData *, 8625 llvm::SmallVector< 8626 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8627 4> 8628 OverlappedData; 8629 size_t Count = 0; 8630 for (const MapData &L : DeclComponentLists) { 8631 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8632 OpenMPMapClauseKind MapType; 8633 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8634 bool IsImplicit; 8635 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8636 ++Count; 8637 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8638 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8639 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8640 auto CI = Components.rbegin(); 8641 auto CE = Components.rend(); 8642 auto SI = Components1.rbegin(); 8643 auto SE = Components1.rend(); 8644 for (; CI != CE && SI != SE; ++CI, ++SI) { 8645 if (CI->getAssociatedExpression()->getStmtClass() != 8646 SI->getAssociatedExpression()->getStmtClass()) 8647 break; 8648 // Are we dealing with different variables/fields? 8649 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8650 break; 8651 } 8652 // Found overlapping if, at least for one component, reached the head of 8653 // the components list. 8654 if (CI == CE || SI == SE) { 8655 assert((CI != CE || SI != SE) && 8656 "Unexpected full match of the mapping components."); 8657 const MapData &BaseData = CI == CE ? L : L1; 8658 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8659 SI == SE ? Components : Components1; 8660 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8661 OverlappedElements.getSecond().push_back(SubData); 8662 } 8663 } 8664 } 8665 // Sort the overlapped elements for each item. 8666 llvm::SmallVector<const FieldDecl *, 4> Layout; 8667 if (!OverlappedData.empty()) { 8668 if (const auto *CRD = 8669 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8670 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8671 else { 8672 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8673 Layout.append(RD->field_begin(), RD->field_end()); 8674 } 8675 } 8676 for (auto &Pair : OverlappedData) { 8677 llvm::sort( 8678 Pair.getSecond(), 8679 [&Layout]( 8680 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8681 OMPClauseMappableExprCommon::MappableExprComponentListRef 8682 Second) { 8683 auto CI = First.rbegin(); 8684 auto CE = First.rend(); 8685 auto SI = Second.rbegin(); 8686 auto SE = Second.rend(); 8687 for (; CI != CE && SI != SE; ++CI, ++SI) { 8688 if (CI->getAssociatedExpression()->getStmtClass() != 8689 SI->getAssociatedExpression()->getStmtClass()) 8690 break; 8691 // Are we dealing with different variables/fields? 8692 if (CI->getAssociatedDeclaration() != 8693 SI->getAssociatedDeclaration()) 8694 break; 8695 } 8696 8697 // Lists contain the same elements. 8698 if (CI == CE && SI == SE) 8699 return false; 8700 8701 // List with less elements is less than list with more elements. 8702 if (CI == CE || SI == SE) 8703 return CI == CE; 8704 8705 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8706 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8707 if (FD1->getParent() == FD2->getParent()) 8708 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8709 const auto It = 8710 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8711 return FD == FD1 || FD == FD2; 8712 }); 8713 return *It == FD1; 8714 }); 8715 } 8716 8717 // Associated with a capture, because the mapping flags depend on it. 8718 // Go through all of the elements with the overlapped elements. 8719 for (const auto &Pair : OverlappedData) { 8720 const MapData &L = *Pair.getFirst(); 8721 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8722 OpenMPMapClauseKind MapType; 8723 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8724 bool IsImplicit; 8725 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8726 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8727 OverlappedComponents = Pair.getSecond(); 8728 bool IsFirstComponentList = true; 8729 generateInfoForComponentList(MapType, MapModifiers, Components, 8730 BasePointers, Pointers, Sizes, Types, 8731 PartialStruct, IsFirstComponentList, 8732 IsImplicit, OverlappedComponents); 8733 } 8734 // Go through other elements without overlapped elements. 8735 bool IsFirstComponentList = OverlappedData.empty(); 8736 for (const MapData &L : DeclComponentLists) { 8737 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8738 OpenMPMapClauseKind MapType; 8739 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8740 bool IsImplicit; 8741 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8742 auto It = OverlappedData.find(&L); 8743 if (It == OverlappedData.end()) 8744 generateInfoForComponentList(MapType, MapModifiers, Components, 8745 BasePointers, Pointers, Sizes, Types, 8746 PartialStruct, IsFirstComponentList, 8747 IsImplicit); 8748 IsFirstComponentList = false; 8749 } 8750 } 8751 8752 /// Generate the base pointers, section pointers, sizes and map types 8753 /// associated with the declare target link variables. 8754 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8755 MapValuesArrayTy &Pointers, 8756 MapValuesArrayTy &Sizes, 8757 MapFlagsArrayTy &Types) const { 8758 assert(CurDir.is<const OMPExecutableDirective *>() && 8759 "Expect a executable directive"); 8760 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8761 // Map other list items in the map clause which are not captured variables 8762 // but "declare target link" global variables. 8763 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8764 for (const auto L : C->component_lists()) { 8765 if (!L.first) 8766 continue; 8767 const auto *VD = dyn_cast<VarDecl>(L.first); 8768 if (!VD) 8769 continue; 8770 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8771 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8772 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8773 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8774 continue; 8775 StructRangeInfoTy PartialStruct; 8776 generateInfoForComponentList( 8777 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8778 Pointers, Sizes, Types, PartialStruct, 8779 /*IsFirstComponentList=*/true, C->isImplicit()); 8780 assert(!PartialStruct.Base.isValid() && 8781 "No partial structs for declare target link expected."); 8782 } 8783 } 8784 } 8785 8786 /// Generate the default map information for a given capture \a CI, 8787 /// record field declaration \a RI and captured value \a CV. 8788 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8789 const FieldDecl &RI, llvm::Value *CV, 8790 MapBaseValuesArrayTy &CurBasePointers, 8791 MapValuesArrayTy &CurPointers, 8792 MapValuesArrayTy &CurSizes, 8793 MapFlagsArrayTy &CurMapTypes) const { 8794 bool IsImplicit = true; 8795 // Do the default mapping. 8796 if (CI.capturesThis()) { 8797 CurBasePointers.push_back(CV); 8798 CurPointers.push_back(CV); 8799 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8800 CurSizes.push_back( 8801 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8802 CGF.Int64Ty, /*isSigned=*/true)); 8803 // Default map type. 8804 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8805 } else if (CI.capturesVariableByCopy()) { 8806 CurBasePointers.push_back(CV); 8807 CurPointers.push_back(CV); 8808 if (!RI.getType()->isAnyPointerType()) { 8809 // We have to signal to the runtime captures passed by value that are 8810 // not pointers. 8811 CurMapTypes.push_back(OMP_MAP_LITERAL); 8812 CurSizes.push_back(CGF.Builder.CreateIntCast( 8813 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8814 } else { 8815 // Pointers are implicitly mapped with a zero size and no flags 8816 // (other than first map that is added for all implicit maps). 8817 CurMapTypes.push_back(OMP_MAP_NONE); 8818 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8819 } 8820 const VarDecl *VD = CI.getCapturedVar(); 8821 auto I = FirstPrivateDecls.find(VD); 8822 if (I != FirstPrivateDecls.end()) 8823 IsImplicit = I->getSecond(); 8824 } else { 8825 assert(CI.capturesVariable() && "Expected captured reference."); 8826 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8827 QualType ElementType = PtrTy->getPointeeType(); 8828 CurSizes.push_back(CGF.Builder.CreateIntCast( 8829 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8830 // The default map type for a scalar/complex type is 'to' because by 8831 // default the value doesn't have to be retrieved. For an aggregate 8832 // type, the default is 'tofrom'. 8833 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8834 const VarDecl *VD = CI.getCapturedVar(); 8835 auto I = FirstPrivateDecls.find(VD); 8836 if (I != FirstPrivateDecls.end() && 8837 VD->getType().isConstant(CGF.getContext())) { 8838 llvm::Constant *Addr = 8839 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8840 // Copy the value of the original variable to the new global copy. 8841 CGF.Builder.CreateMemCpy( 8842 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 8843 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8844 CurSizes.back(), /*IsVolatile=*/false); 8845 // Use new global variable as the base pointers. 8846 CurBasePointers.push_back(Addr); 8847 CurPointers.push_back(Addr); 8848 } else { 8849 CurBasePointers.push_back(CV); 8850 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8851 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8852 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8853 AlignmentSource::Decl)); 8854 CurPointers.push_back(PtrAddr.getPointer()); 8855 } else { 8856 CurPointers.push_back(CV); 8857 } 8858 } 8859 if (I != FirstPrivateDecls.end()) 8860 IsImplicit = I->getSecond(); 8861 } 8862 // Every default map produces a single argument which is a target parameter. 8863 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8864 8865 // Add flag stating this is an implicit map. 8866 if (IsImplicit) 8867 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8868 } 8869 }; 8870 } // anonymous namespace 8871 8872 /// Emit the arrays used to pass the captures and map information to the 8873 /// offloading runtime library. If there is no map or capture information, 8874 /// return nullptr by reference. 8875 static void 8876 emitOffloadingArrays(CodeGenFunction &CGF, 8877 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8878 MappableExprsHandler::MapValuesArrayTy &Pointers, 8879 MappableExprsHandler::MapValuesArrayTy &Sizes, 8880 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8881 CGOpenMPRuntime::TargetDataInfo &Info) { 8882 CodeGenModule &CGM = CGF.CGM; 8883 ASTContext &Ctx = CGF.getContext(); 8884 8885 // Reset the array information. 8886 Info.clearArrayInfo(); 8887 Info.NumberOfPtrs = BasePointers.size(); 8888 8889 if (Info.NumberOfPtrs) { 8890 // Detect if we have any capture size requiring runtime evaluation of the 8891 // size so that a constant array could be eventually used. 8892 bool hasRuntimeEvaluationCaptureSize = false; 8893 for (llvm::Value *S : Sizes) 8894 if (!isa<llvm::Constant>(S)) { 8895 hasRuntimeEvaluationCaptureSize = true; 8896 break; 8897 } 8898 8899 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8900 QualType PointerArrayType = Ctx.getConstantArrayType( 8901 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8902 /*IndexTypeQuals=*/0); 8903 8904 Info.BasePointersArray = 8905 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8906 Info.PointersArray = 8907 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8908 8909 // If we don't have any VLA types or other types that require runtime 8910 // evaluation, we can use a constant array for the map sizes, otherwise we 8911 // need to fill up the arrays as we do for the pointers. 8912 QualType Int64Ty = 8913 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8914 if (hasRuntimeEvaluationCaptureSize) { 8915 QualType SizeArrayType = Ctx.getConstantArrayType( 8916 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8917 /*IndexTypeQuals=*/0); 8918 Info.SizesArray = 8919 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8920 } else { 8921 // We expect all the sizes to be constant, so we collect them to create 8922 // a constant array. 8923 SmallVector<llvm::Constant *, 16> ConstSizes; 8924 for (llvm::Value *S : Sizes) 8925 ConstSizes.push_back(cast<llvm::Constant>(S)); 8926 8927 auto *SizesArrayInit = llvm::ConstantArray::get( 8928 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8929 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8930 auto *SizesArrayGbl = new llvm::GlobalVariable( 8931 CGM.getModule(), SizesArrayInit->getType(), 8932 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8933 SizesArrayInit, Name); 8934 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8935 Info.SizesArray = SizesArrayGbl; 8936 } 8937 8938 // The map types are always constant so we don't need to generate code to 8939 // fill arrays. Instead, we create an array constant. 8940 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8941 llvm::copy(MapTypes, Mapping.begin()); 8942 llvm::Constant *MapTypesArrayInit = 8943 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8944 std::string MaptypesName = 8945 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8946 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8947 CGM.getModule(), MapTypesArrayInit->getType(), 8948 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8949 MapTypesArrayInit, MaptypesName); 8950 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8951 Info.MapTypesArray = MapTypesArrayGbl; 8952 8953 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8954 llvm::Value *BPVal = *BasePointers[I]; 8955 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8956 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8957 Info.BasePointersArray, 0, I); 8958 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8959 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8960 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8961 CGF.Builder.CreateStore(BPVal, BPAddr); 8962 8963 if (Info.requiresDevicePointerInfo()) 8964 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8965 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8966 8967 llvm::Value *PVal = Pointers[I]; 8968 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8969 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8970 Info.PointersArray, 0, I); 8971 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8972 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8973 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8974 CGF.Builder.CreateStore(PVal, PAddr); 8975 8976 if (hasRuntimeEvaluationCaptureSize) { 8977 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8978 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8979 Info.SizesArray, 8980 /*Idx0=*/0, 8981 /*Idx1=*/I); 8982 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8983 CGF.Builder.CreateStore( 8984 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8985 SAddr); 8986 } 8987 } 8988 } 8989 } 8990 8991 /// Emit the arguments to be passed to the runtime library based on the 8992 /// arrays of pointers, sizes and map types. 8993 static void emitOffloadingArraysArgument( 8994 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8995 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8996 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8997 CodeGenModule &CGM = CGF.CGM; 8998 if (Info.NumberOfPtrs) { 8999 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9000 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9001 Info.BasePointersArray, 9002 /*Idx0=*/0, /*Idx1=*/0); 9003 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9004 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9005 Info.PointersArray, 9006 /*Idx0=*/0, 9007 /*Idx1=*/0); 9008 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9009 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 9010 /*Idx0=*/0, /*Idx1=*/0); 9011 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9012 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9013 Info.MapTypesArray, 9014 /*Idx0=*/0, 9015 /*Idx1=*/0); 9016 } else { 9017 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9018 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9019 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9020 MapTypesArrayArg = 9021 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9022 } 9023 } 9024 9025 /// Check for inner distribute directive. 9026 static const OMPExecutableDirective * 9027 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 9028 const auto *CS = D.getInnermostCapturedStmt(); 9029 const auto *Body = 9030 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 9031 const Stmt *ChildStmt = 9032 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9033 9034 if (const auto *NestedDir = 9035 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9036 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 9037 switch (D.getDirectiveKind()) { 9038 case OMPD_target: 9039 if (isOpenMPDistributeDirective(DKind)) 9040 return NestedDir; 9041 if (DKind == OMPD_teams) { 9042 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 9043 /*IgnoreCaptured=*/true); 9044 if (!Body) 9045 return nullptr; 9046 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9047 if (const auto *NND = 9048 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9049 DKind = NND->getDirectiveKind(); 9050 if (isOpenMPDistributeDirective(DKind)) 9051 return NND; 9052 } 9053 } 9054 return nullptr; 9055 case OMPD_target_teams: 9056 if (isOpenMPDistributeDirective(DKind)) 9057 return NestedDir; 9058 return nullptr; 9059 case OMPD_target_parallel: 9060 case OMPD_target_simd: 9061 case OMPD_target_parallel_for: 9062 case OMPD_target_parallel_for_simd: 9063 return nullptr; 9064 case OMPD_target_teams_distribute: 9065 case OMPD_target_teams_distribute_simd: 9066 case OMPD_target_teams_distribute_parallel_for: 9067 case OMPD_target_teams_distribute_parallel_for_simd: 9068 case OMPD_parallel: 9069 case OMPD_for: 9070 case OMPD_parallel_for: 9071 case OMPD_parallel_master: 9072 case OMPD_parallel_sections: 9073 case OMPD_for_simd: 9074 case OMPD_parallel_for_simd: 9075 case OMPD_cancel: 9076 case OMPD_cancellation_point: 9077 case OMPD_ordered: 9078 case OMPD_threadprivate: 9079 case OMPD_allocate: 9080 case OMPD_task: 9081 case OMPD_simd: 9082 case OMPD_sections: 9083 case OMPD_section: 9084 case OMPD_single: 9085 case OMPD_master: 9086 case OMPD_critical: 9087 case OMPD_taskyield: 9088 case OMPD_barrier: 9089 case OMPD_taskwait: 9090 case OMPD_taskgroup: 9091 case OMPD_atomic: 9092 case OMPD_flush: 9093 case OMPD_depobj: 9094 case OMPD_scan: 9095 case OMPD_teams: 9096 case OMPD_target_data: 9097 case OMPD_target_exit_data: 9098 case OMPD_target_enter_data: 9099 case OMPD_distribute: 9100 case OMPD_distribute_simd: 9101 case OMPD_distribute_parallel_for: 9102 case OMPD_distribute_parallel_for_simd: 9103 case OMPD_teams_distribute: 9104 case OMPD_teams_distribute_simd: 9105 case OMPD_teams_distribute_parallel_for: 9106 case OMPD_teams_distribute_parallel_for_simd: 9107 case OMPD_target_update: 9108 case OMPD_declare_simd: 9109 case OMPD_declare_variant: 9110 case OMPD_declare_target: 9111 case OMPD_end_declare_target: 9112 case OMPD_declare_reduction: 9113 case OMPD_declare_mapper: 9114 case OMPD_taskloop: 9115 case OMPD_taskloop_simd: 9116 case OMPD_master_taskloop: 9117 case OMPD_master_taskloop_simd: 9118 case OMPD_parallel_master_taskloop: 9119 case OMPD_parallel_master_taskloop_simd: 9120 case OMPD_requires: 9121 case OMPD_unknown: 9122 llvm_unreachable("Unexpected directive."); 9123 } 9124 } 9125 9126 return nullptr; 9127 } 9128 9129 /// Emit the user-defined mapper function. The code generation follows the 9130 /// pattern in the example below. 9131 /// \code 9132 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 9133 /// void *base, void *begin, 9134 /// int64_t size, int64_t type) { 9135 /// // Allocate space for an array section first. 9136 /// if (size > 1 && !maptype.IsDelete) 9137 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9138 /// size*sizeof(Ty), clearToFrom(type)); 9139 /// // Map members. 9140 /// for (unsigned i = 0; i < size; i++) { 9141 /// // For each component specified by this mapper: 9142 /// for (auto c : all_components) { 9143 /// if (c.hasMapper()) 9144 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 9145 /// c.arg_type); 9146 /// else 9147 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 9148 /// c.arg_begin, c.arg_size, c.arg_type); 9149 /// } 9150 /// } 9151 /// // Delete the array section. 9152 /// if (size > 1 && maptype.IsDelete) 9153 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9154 /// size*sizeof(Ty), clearToFrom(type)); 9155 /// } 9156 /// \endcode 9157 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 9158 CodeGenFunction *CGF) { 9159 if (UDMMap.count(D) > 0) 9160 return; 9161 ASTContext &C = CGM.getContext(); 9162 QualType Ty = D->getType(); 9163 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 9164 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 9165 auto *MapperVarDecl = 9166 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 9167 SourceLocation Loc = D->getLocation(); 9168 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 9169 9170 // Prepare mapper function arguments and attributes. 9171 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9172 C.VoidPtrTy, ImplicitParamDecl::Other); 9173 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9174 ImplicitParamDecl::Other); 9175 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9176 C.VoidPtrTy, ImplicitParamDecl::Other); 9177 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9178 ImplicitParamDecl::Other); 9179 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9180 ImplicitParamDecl::Other); 9181 FunctionArgList Args; 9182 Args.push_back(&HandleArg); 9183 Args.push_back(&BaseArg); 9184 Args.push_back(&BeginArg); 9185 Args.push_back(&SizeArg); 9186 Args.push_back(&TypeArg); 9187 const CGFunctionInfo &FnInfo = 9188 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 9189 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 9190 SmallString<64> TyStr; 9191 llvm::raw_svector_ostream Out(TyStr); 9192 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 9193 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 9194 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 9195 Name, &CGM.getModule()); 9196 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 9197 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 9198 // Start the mapper function code generation. 9199 CodeGenFunction MapperCGF(CGM); 9200 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 9201 // Compute the starting and end addreses of array elements. 9202 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 9203 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 9204 C.getPointerType(Int64Ty), Loc); 9205 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 9206 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 9207 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 9208 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 9209 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 9210 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 9211 C.getPointerType(Int64Ty), Loc); 9212 // Prepare common arguments for array initiation and deletion. 9213 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 9214 MapperCGF.GetAddrOfLocalVar(&HandleArg), 9215 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9216 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 9217 MapperCGF.GetAddrOfLocalVar(&BaseArg), 9218 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9219 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 9220 MapperCGF.GetAddrOfLocalVar(&BeginArg), 9221 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9222 9223 // Emit array initiation if this is an array section and \p MapType indicates 9224 // that memory allocation is required. 9225 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 9226 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9227 ElementSize, HeadBB, /*IsInit=*/true); 9228 9229 // Emit a for loop to iterate through SizeArg of elements and map all of them. 9230 9231 // Emit the loop header block. 9232 MapperCGF.EmitBlock(HeadBB); 9233 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 9234 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 9235 // Evaluate whether the initial condition is satisfied. 9236 llvm::Value *IsEmpty = 9237 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 9238 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 9239 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 9240 9241 // Emit the loop body block. 9242 MapperCGF.EmitBlock(BodyBB); 9243 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 9244 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 9245 PtrPHI->addIncoming(PtrBegin, EntryBB); 9246 Address PtrCurrent = 9247 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 9248 .getAlignment() 9249 .alignmentOfArrayElement(ElementSize)); 9250 // Privatize the declared variable of mapper to be the current array element. 9251 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 9252 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 9253 return MapperCGF 9254 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 9255 .getAddress(MapperCGF); 9256 }); 9257 (void)Scope.Privatize(); 9258 9259 // Get map clause information. Fill up the arrays with all mapped variables. 9260 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9261 MappableExprsHandler::MapValuesArrayTy Pointers; 9262 MappableExprsHandler::MapValuesArrayTy Sizes; 9263 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9264 MappableExprsHandler MEHandler(*D, MapperCGF); 9265 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 9266 9267 // Call the runtime API __tgt_mapper_num_components to get the number of 9268 // pre-existing components. 9269 llvm::Value *OffloadingArgs[] = {Handle}; 9270 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 9271 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 9272 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 9273 PreviousSize, 9274 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 9275 9276 // Fill up the runtime mapper handle for all components. 9277 for (unsigned I = 0; I < BasePointers.size(); ++I) { 9278 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 9279 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9280 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 9281 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9282 llvm::Value *CurSizeArg = Sizes[I]; 9283 9284 // Extract the MEMBER_OF field from the map type. 9285 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 9286 MapperCGF.EmitBlock(MemberBB); 9287 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 9288 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 9289 OriMapType, 9290 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 9291 llvm::BasicBlock *MemberCombineBB = 9292 MapperCGF.createBasicBlock("omp.member.combine"); 9293 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 9294 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 9295 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 9296 // Add the number of pre-existing components to the MEMBER_OF field if it 9297 // is valid. 9298 MapperCGF.EmitBlock(MemberCombineBB); 9299 llvm::Value *CombinedMember = 9300 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 9301 // Do nothing if it is not a member of previous components. 9302 MapperCGF.EmitBlock(TypeBB); 9303 llvm::PHINode *MemberMapType = 9304 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 9305 MemberMapType->addIncoming(OriMapType, MemberBB); 9306 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 9307 9308 // Combine the map type inherited from user-defined mapper with that 9309 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9310 // bits of the \a MapType, which is the input argument of the mapper 9311 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9312 // bits of MemberMapType. 9313 // [OpenMP 5.0], 1.2.6. map-type decay. 9314 // | alloc | to | from | tofrom | release | delete 9315 // ---------------------------------------------------------- 9316 // alloc | alloc | alloc | alloc | alloc | release | delete 9317 // to | alloc | to | alloc | to | release | delete 9318 // from | alloc | alloc | from | from | release | delete 9319 // tofrom | alloc | to | from | tofrom | release | delete 9320 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9321 MapType, 9322 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9323 MappableExprsHandler::OMP_MAP_FROM)); 9324 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9325 llvm::BasicBlock *AllocElseBB = 9326 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9327 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9328 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9329 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9330 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9331 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9332 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9333 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9334 MapperCGF.EmitBlock(AllocBB); 9335 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9336 MemberMapType, 9337 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9338 MappableExprsHandler::OMP_MAP_FROM))); 9339 MapperCGF.Builder.CreateBr(EndBB); 9340 MapperCGF.EmitBlock(AllocElseBB); 9341 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9342 LeftToFrom, 9343 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9344 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9345 // In case of to, clear OMP_MAP_FROM. 9346 MapperCGF.EmitBlock(ToBB); 9347 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9348 MemberMapType, 9349 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9350 MapperCGF.Builder.CreateBr(EndBB); 9351 MapperCGF.EmitBlock(ToElseBB); 9352 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9353 LeftToFrom, 9354 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9355 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9356 // In case of from, clear OMP_MAP_TO. 9357 MapperCGF.EmitBlock(FromBB); 9358 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9359 MemberMapType, 9360 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9361 // In case of tofrom, do nothing. 9362 MapperCGF.EmitBlock(EndBB); 9363 llvm::PHINode *CurMapType = 9364 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9365 CurMapType->addIncoming(AllocMapType, AllocBB); 9366 CurMapType->addIncoming(ToMapType, ToBB); 9367 CurMapType->addIncoming(FromMapType, FromBB); 9368 CurMapType->addIncoming(MemberMapType, ToElseBB); 9369 9370 // TODO: call the corresponding mapper function if a user-defined mapper is 9371 // associated with this map clause. 9372 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9373 // data structure. 9374 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9375 CurSizeArg, CurMapType}; 9376 MapperCGF.EmitRuntimeCall( 9377 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9378 OffloadingArgs); 9379 } 9380 9381 // Update the pointer to point to the next element that needs to be mapped, 9382 // and check whether we have mapped all elements. 9383 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9384 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9385 PtrPHI->addIncoming(PtrNext, BodyBB); 9386 llvm::Value *IsDone = 9387 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9388 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9389 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9390 9391 MapperCGF.EmitBlock(ExitBB); 9392 // Emit array deletion if this is an array section and \p MapType indicates 9393 // that deletion is required. 9394 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9395 ElementSize, DoneBB, /*IsInit=*/false); 9396 9397 // Emit the function exit block. 9398 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9399 MapperCGF.FinishFunction(); 9400 UDMMap.try_emplace(D, Fn); 9401 if (CGF) { 9402 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9403 Decls.second.push_back(D); 9404 } 9405 } 9406 9407 /// Emit the array initialization or deletion portion for user-defined mapper 9408 /// code generation. First, it evaluates whether an array section is mapped and 9409 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9410 /// true, and \a MapType indicates to not delete this array, array 9411 /// initialization code is generated. If \a IsInit is false, and \a MapType 9412 /// indicates to not this array, array deletion code is generated. 9413 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9414 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9415 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9416 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9417 StringRef Prefix = IsInit ? ".init" : ".del"; 9418 9419 // Evaluate if this is an array section. 9420 llvm::BasicBlock *IsDeleteBB = 9421 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"})); 9422 llvm::BasicBlock *BodyBB = 9423 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 9424 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9425 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9426 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9427 9428 // Evaluate if we are going to delete this section. 9429 MapperCGF.EmitBlock(IsDeleteBB); 9430 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9431 MapType, 9432 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9433 llvm::Value *DeleteCond; 9434 if (IsInit) { 9435 DeleteCond = MapperCGF.Builder.CreateIsNull( 9436 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9437 } else { 9438 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9439 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9440 } 9441 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9442 9443 MapperCGF.EmitBlock(BodyBB); 9444 // Get the array size by multiplying element size and element number (i.e., \p 9445 // Size). 9446 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9447 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9448 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9449 // memory allocation/deletion purpose only. 9450 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9451 MapType, 9452 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9453 MappableExprsHandler::OMP_MAP_FROM))); 9454 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9455 // data structure. 9456 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9457 MapperCGF.EmitRuntimeCall( 9458 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9459 } 9460 9461 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9462 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9463 llvm::Value *DeviceID, 9464 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9465 const OMPLoopDirective &D)> 9466 SizeEmitter) { 9467 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9468 const OMPExecutableDirective *TD = &D; 9469 // Get nested teams distribute kind directive, if any. 9470 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9471 TD = getNestedDistributeDirective(CGM.getContext(), D); 9472 if (!TD) 9473 return; 9474 const auto *LD = cast<OMPLoopDirective>(TD); 9475 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9476 PrePostActionTy &) { 9477 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9478 llvm::Value *Args[] = {DeviceID, NumIterations}; 9479 CGF.EmitRuntimeCall( 9480 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9481 } 9482 }; 9483 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9484 } 9485 9486 void CGOpenMPRuntime::emitTargetCall( 9487 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9488 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9489 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 9490 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9491 const OMPLoopDirective &D)> 9492 SizeEmitter) { 9493 if (!CGF.HaveInsertPoint()) 9494 return; 9495 9496 assert(OutlinedFn && "Invalid outlined function!"); 9497 9498 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9499 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9500 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9501 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9502 PrePostActionTy &) { 9503 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9504 }; 9505 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9506 9507 CodeGenFunction::OMPTargetDataInfo InputInfo; 9508 llvm::Value *MapTypesArray = nullptr; 9509 // Fill up the pointer arrays and transfer execution to the device. 9510 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9511 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9512 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9513 if (Device.getInt() == OMPC_DEVICE_ancestor) { 9514 // Reverse offloading is not supported, so just execute on the host. 9515 if (RequiresOuterTask) { 9516 CapturedVars.clear(); 9517 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9518 } 9519 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9520 return; 9521 } 9522 9523 // On top of the arrays that were filled up, the target offloading call 9524 // takes as arguments the device id as well as the host pointer. The host 9525 // pointer is used by the runtime library to identify the current target 9526 // region, so it only has to be unique and not necessarily point to 9527 // anything. It could be the pointer to the outlined function that 9528 // implements the target region, but we aren't using that so that the 9529 // compiler doesn't need to keep that, and could therefore inline the host 9530 // function if proven worthwhile during optimization. 9531 9532 // From this point on, we need to have an ID of the target region defined. 9533 assert(OutlinedFnID && "Invalid outlined function ID!"); 9534 9535 // Emit device ID if any. 9536 llvm::Value *DeviceID; 9537 if (Device.getPointer()) { 9538 assert((Device.getInt() == OMPC_DEVICE_unknown || 9539 Device.getInt() == OMPC_DEVICE_device_num) && 9540 "Expected device_num modifier."); 9541 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer()); 9542 DeviceID = 9543 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true); 9544 } else { 9545 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9546 } 9547 9548 // Emit the number of elements in the offloading arrays. 9549 llvm::Value *PointerNum = 9550 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9551 9552 // Return value of the runtime offloading call. 9553 llvm::Value *Return; 9554 9555 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9556 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9557 9558 // Emit tripcount for the target loop-based directive. 9559 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9560 9561 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9562 // The target region is an outlined function launched by the runtime 9563 // via calls __tgt_target() or __tgt_target_teams(). 9564 // 9565 // __tgt_target() launches a target region with one team and one thread, 9566 // executing a serial region. This master thread may in turn launch 9567 // more threads within its team upon encountering a parallel region, 9568 // however, no additional teams can be launched on the device. 9569 // 9570 // __tgt_target_teams() launches a target region with one or more teams, 9571 // each with one or more threads. This call is required for target 9572 // constructs such as: 9573 // 'target teams' 9574 // 'target' / 'teams' 9575 // 'target teams distribute parallel for' 9576 // 'target parallel' 9577 // and so on. 9578 // 9579 // Note that on the host and CPU targets, the runtime implementation of 9580 // these calls simply call the outlined function without forking threads. 9581 // The outlined functions themselves have runtime calls to 9582 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9583 // the compiler in emitTeamsCall() and emitParallelCall(). 9584 // 9585 // In contrast, on the NVPTX target, the implementation of 9586 // __tgt_target_teams() launches a GPU kernel with the requested number 9587 // of teams and threads so no additional calls to the runtime are required. 9588 if (NumTeams) { 9589 // If we have NumTeams defined this means that we have an enclosed teams 9590 // region. Therefore we also expect to have NumThreads defined. These two 9591 // values should be defined in the presence of a teams directive, 9592 // regardless of having any clauses associated. If the user is using teams 9593 // but no clauses, these two values will be the default that should be 9594 // passed to the runtime library - a 32-bit integer with the value zero. 9595 assert(NumThreads && "Thread limit expression should be available along " 9596 "with number of teams."); 9597 llvm::Value *OffloadingArgs[] = {DeviceID, 9598 OutlinedFnID, 9599 PointerNum, 9600 InputInfo.BasePointersArray.getPointer(), 9601 InputInfo.PointersArray.getPointer(), 9602 InputInfo.SizesArray.getPointer(), 9603 MapTypesArray, 9604 NumTeams, 9605 NumThreads}; 9606 Return = CGF.EmitRuntimeCall( 9607 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9608 : OMPRTL__tgt_target_teams), 9609 OffloadingArgs); 9610 } else { 9611 llvm::Value *OffloadingArgs[] = {DeviceID, 9612 OutlinedFnID, 9613 PointerNum, 9614 InputInfo.BasePointersArray.getPointer(), 9615 InputInfo.PointersArray.getPointer(), 9616 InputInfo.SizesArray.getPointer(), 9617 MapTypesArray}; 9618 Return = CGF.EmitRuntimeCall( 9619 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9620 : OMPRTL__tgt_target), 9621 OffloadingArgs); 9622 } 9623 9624 // Check the error code and execute the host version if required. 9625 llvm::BasicBlock *OffloadFailedBlock = 9626 CGF.createBasicBlock("omp_offload.failed"); 9627 llvm::BasicBlock *OffloadContBlock = 9628 CGF.createBasicBlock("omp_offload.cont"); 9629 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9630 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9631 9632 CGF.EmitBlock(OffloadFailedBlock); 9633 if (RequiresOuterTask) { 9634 CapturedVars.clear(); 9635 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9636 } 9637 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9638 CGF.EmitBranch(OffloadContBlock); 9639 9640 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9641 }; 9642 9643 // Notify that the host version must be executed. 9644 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9645 RequiresOuterTask](CodeGenFunction &CGF, 9646 PrePostActionTy &) { 9647 if (RequiresOuterTask) { 9648 CapturedVars.clear(); 9649 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9650 } 9651 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9652 }; 9653 9654 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9655 &CapturedVars, RequiresOuterTask, 9656 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9657 // Fill up the arrays with all the captured variables. 9658 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9659 MappableExprsHandler::MapValuesArrayTy Pointers; 9660 MappableExprsHandler::MapValuesArrayTy Sizes; 9661 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9662 9663 // Get mappable expression information. 9664 MappableExprsHandler MEHandler(D, CGF); 9665 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9666 9667 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9668 auto CV = CapturedVars.begin(); 9669 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9670 CE = CS.capture_end(); 9671 CI != CE; ++CI, ++RI, ++CV) { 9672 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9673 MappableExprsHandler::MapValuesArrayTy CurPointers; 9674 MappableExprsHandler::MapValuesArrayTy CurSizes; 9675 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9676 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9677 9678 // VLA sizes are passed to the outlined region by copy and do not have map 9679 // information associated. 9680 if (CI->capturesVariableArrayType()) { 9681 CurBasePointers.push_back(*CV); 9682 CurPointers.push_back(*CV); 9683 CurSizes.push_back(CGF.Builder.CreateIntCast( 9684 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9685 // Copy to the device as an argument. No need to retrieve it. 9686 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9687 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9688 MappableExprsHandler::OMP_MAP_IMPLICIT); 9689 } else { 9690 // If we have any information in the map clause, we use it, otherwise we 9691 // just do a default mapping. 9692 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9693 CurSizes, CurMapTypes, PartialStruct); 9694 if (CurBasePointers.empty()) 9695 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9696 CurPointers, CurSizes, CurMapTypes); 9697 // Generate correct mapping for variables captured by reference in 9698 // lambdas. 9699 if (CI->capturesVariable()) 9700 MEHandler.generateInfoForLambdaCaptures( 9701 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9702 CurMapTypes, LambdaPointers); 9703 } 9704 // We expect to have at least an element of information for this capture. 9705 assert(!CurBasePointers.empty() && 9706 "Non-existing map pointer for capture!"); 9707 assert(CurBasePointers.size() == CurPointers.size() && 9708 CurBasePointers.size() == CurSizes.size() && 9709 CurBasePointers.size() == CurMapTypes.size() && 9710 "Inconsistent map information sizes!"); 9711 9712 // If there is an entry in PartialStruct it means we have a struct with 9713 // individual members mapped. Emit an extra combined entry. 9714 if (PartialStruct.Base.isValid()) 9715 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9716 CurMapTypes, PartialStruct); 9717 9718 // We need to append the results of this capture to what we already have. 9719 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9720 Pointers.append(CurPointers.begin(), CurPointers.end()); 9721 Sizes.append(CurSizes.begin(), CurSizes.end()); 9722 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9723 } 9724 // Adjust MEMBER_OF flags for the lambdas captures. 9725 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9726 Pointers, MapTypes); 9727 // Map other list items in the map clause which are not captured variables 9728 // but "declare target link" global variables. 9729 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9730 MapTypes); 9731 9732 TargetDataInfo Info; 9733 // Fill up the arrays and create the arguments. 9734 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9735 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9736 Info.PointersArray, Info.SizesArray, 9737 Info.MapTypesArray, Info); 9738 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9739 InputInfo.BasePointersArray = 9740 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9741 InputInfo.PointersArray = 9742 Address(Info.PointersArray, CGM.getPointerAlign()); 9743 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9744 MapTypesArray = Info.MapTypesArray; 9745 if (RequiresOuterTask) 9746 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9747 else 9748 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9749 }; 9750 9751 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9752 CodeGenFunction &CGF, PrePostActionTy &) { 9753 if (RequiresOuterTask) { 9754 CodeGenFunction::OMPTargetDataInfo InputInfo; 9755 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9756 } else { 9757 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9758 } 9759 }; 9760 9761 // If we have a target function ID it means that we need to support 9762 // offloading, otherwise, just execute on the host. We need to execute on host 9763 // regardless of the conditional in the if clause if, e.g., the user do not 9764 // specify target triples. 9765 if (OutlinedFnID) { 9766 if (IfCond) { 9767 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9768 } else { 9769 RegionCodeGenTy ThenRCG(TargetThenGen); 9770 ThenRCG(CGF); 9771 } 9772 } else { 9773 RegionCodeGenTy ElseRCG(TargetElseGen); 9774 ElseRCG(CGF); 9775 } 9776 } 9777 9778 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9779 StringRef ParentName) { 9780 if (!S) 9781 return; 9782 9783 // Codegen OMP target directives that offload compute to the device. 9784 bool RequiresDeviceCodegen = 9785 isa<OMPExecutableDirective>(S) && 9786 isOpenMPTargetExecutionDirective( 9787 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9788 9789 if (RequiresDeviceCodegen) { 9790 const auto &E = *cast<OMPExecutableDirective>(S); 9791 unsigned DeviceID; 9792 unsigned FileID; 9793 unsigned Line; 9794 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9795 FileID, Line); 9796 9797 // Is this a target region that should not be emitted as an entry point? If 9798 // so just signal we are done with this target region. 9799 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9800 ParentName, Line)) 9801 return; 9802 9803 switch (E.getDirectiveKind()) { 9804 case OMPD_target: 9805 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9806 cast<OMPTargetDirective>(E)); 9807 break; 9808 case OMPD_target_parallel: 9809 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9810 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9811 break; 9812 case OMPD_target_teams: 9813 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9814 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9815 break; 9816 case OMPD_target_teams_distribute: 9817 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9818 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9819 break; 9820 case OMPD_target_teams_distribute_simd: 9821 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9822 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9823 break; 9824 case OMPD_target_parallel_for: 9825 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9826 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9827 break; 9828 case OMPD_target_parallel_for_simd: 9829 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9830 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9831 break; 9832 case OMPD_target_simd: 9833 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9834 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9835 break; 9836 case OMPD_target_teams_distribute_parallel_for: 9837 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9838 CGM, ParentName, 9839 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9840 break; 9841 case OMPD_target_teams_distribute_parallel_for_simd: 9842 CodeGenFunction:: 9843 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9844 CGM, ParentName, 9845 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9846 break; 9847 case OMPD_parallel: 9848 case OMPD_for: 9849 case OMPD_parallel_for: 9850 case OMPD_parallel_master: 9851 case OMPD_parallel_sections: 9852 case OMPD_for_simd: 9853 case OMPD_parallel_for_simd: 9854 case OMPD_cancel: 9855 case OMPD_cancellation_point: 9856 case OMPD_ordered: 9857 case OMPD_threadprivate: 9858 case OMPD_allocate: 9859 case OMPD_task: 9860 case OMPD_simd: 9861 case OMPD_sections: 9862 case OMPD_section: 9863 case OMPD_single: 9864 case OMPD_master: 9865 case OMPD_critical: 9866 case OMPD_taskyield: 9867 case OMPD_barrier: 9868 case OMPD_taskwait: 9869 case OMPD_taskgroup: 9870 case OMPD_atomic: 9871 case OMPD_flush: 9872 case OMPD_depobj: 9873 case OMPD_scan: 9874 case OMPD_teams: 9875 case OMPD_target_data: 9876 case OMPD_target_exit_data: 9877 case OMPD_target_enter_data: 9878 case OMPD_distribute: 9879 case OMPD_distribute_simd: 9880 case OMPD_distribute_parallel_for: 9881 case OMPD_distribute_parallel_for_simd: 9882 case OMPD_teams_distribute: 9883 case OMPD_teams_distribute_simd: 9884 case OMPD_teams_distribute_parallel_for: 9885 case OMPD_teams_distribute_parallel_for_simd: 9886 case OMPD_target_update: 9887 case OMPD_declare_simd: 9888 case OMPD_declare_variant: 9889 case OMPD_declare_target: 9890 case OMPD_end_declare_target: 9891 case OMPD_declare_reduction: 9892 case OMPD_declare_mapper: 9893 case OMPD_taskloop: 9894 case OMPD_taskloop_simd: 9895 case OMPD_master_taskloop: 9896 case OMPD_master_taskloop_simd: 9897 case OMPD_parallel_master_taskloop: 9898 case OMPD_parallel_master_taskloop_simd: 9899 case OMPD_requires: 9900 case OMPD_unknown: 9901 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9902 } 9903 return; 9904 } 9905 9906 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9907 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9908 return; 9909 9910 scanForTargetRegionsFunctions( 9911 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9912 return; 9913 } 9914 9915 // If this is a lambda function, look into its body. 9916 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9917 S = L->getBody(); 9918 9919 // Keep looking for target regions recursively. 9920 for (const Stmt *II : S->children()) 9921 scanForTargetRegionsFunctions(II, ParentName); 9922 } 9923 9924 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9925 // If emitting code for the host, we do not process FD here. Instead we do 9926 // the normal code generation. 9927 if (!CGM.getLangOpts().OpenMPIsDevice) { 9928 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9929 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9930 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9931 // Do not emit device_type(nohost) functions for the host. 9932 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9933 return true; 9934 } 9935 return false; 9936 } 9937 9938 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9939 // Try to detect target regions in the function. 9940 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9941 StringRef Name = CGM.getMangledName(GD); 9942 scanForTargetRegionsFunctions(FD->getBody(), Name); 9943 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9944 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9945 // Do not emit device_type(nohost) functions for the host. 9946 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9947 return true; 9948 } 9949 9950 // Do not to emit function if it is not marked as declare target. 9951 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9952 AlreadyEmittedTargetDecls.count(VD) == 0; 9953 } 9954 9955 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9956 if (!CGM.getLangOpts().OpenMPIsDevice) 9957 return false; 9958 9959 // Check if there are Ctors/Dtors in this declaration and look for target 9960 // regions in it. We use the complete variant to produce the kernel name 9961 // mangling. 9962 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9963 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9964 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9965 StringRef ParentName = 9966 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9967 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9968 } 9969 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9970 StringRef ParentName = 9971 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9972 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9973 } 9974 } 9975 9976 // Do not to emit variable if it is not marked as declare target. 9977 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9978 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9979 cast<VarDecl>(GD.getDecl())); 9980 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9981 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9982 HasRequiresUnifiedSharedMemory)) { 9983 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9984 return true; 9985 } 9986 return false; 9987 } 9988 9989 llvm::Constant * 9990 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9991 const VarDecl *VD) { 9992 assert(VD->getType().isConstant(CGM.getContext()) && 9993 "Expected constant variable."); 9994 StringRef VarName; 9995 llvm::Constant *Addr; 9996 llvm::GlobalValue::LinkageTypes Linkage; 9997 QualType Ty = VD->getType(); 9998 SmallString<128> Buffer; 9999 { 10000 unsigned DeviceID; 10001 unsigned FileID; 10002 unsigned Line; 10003 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 10004 FileID, Line); 10005 llvm::raw_svector_ostream OS(Buffer); 10006 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 10007 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 10008 VarName = OS.str(); 10009 } 10010 Linkage = llvm::GlobalValue::InternalLinkage; 10011 Addr = 10012 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 10013 getDefaultFirstprivateAddressSpace()); 10014 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 10015 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 10016 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 10017 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10018 VarName, Addr, VarSize, 10019 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 10020 return Addr; 10021 } 10022 10023 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 10024 llvm::Constant *Addr) { 10025 if (CGM.getLangOpts().OMPTargetTriples.empty() && 10026 !CGM.getLangOpts().OpenMPIsDevice) 10027 return; 10028 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10029 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10030 if (!Res) { 10031 if (CGM.getLangOpts().OpenMPIsDevice) { 10032 // Register non-target variables being emitted in device code (debug info 10033 // may cause this). 10034 StringRef VarName = CGM.getMangledName(VD); 10035 EmittedNonTargetVariables.try_emplace(VarName, Addr); 10036 } 10037 return; 10038 } 10039 // Register declare target variables. 10040 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 10041 StringRef VarName; 10042 CharUnits VarSize; 10043 llvm::GlobalValue::LinkageTypes Linkage; 10044 10045 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10046 !HasRequiresUnifiedSharedMemory) { 10047 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10048 VarName = CGM.getMangledName(VD); 10049 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 10050 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 10051 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 10052 } else { 10053 VarSize = CharUnits::Zero(); 10054 } 10055 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 10056 // Temp solution to prevent optimizations of the internal variables. 10057 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 10058 std::string RefName = getName({VarName, "ref"}); 10059 if (!CGM.GetGlobalValue(RefName)) { 10060 llvm::Constant *AddrRef = 10061 getOrCreateInternalVariable(Addr->getType(), RefName); 10062 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 10063 GVAddrRef->setConstant(/*Val=*/true); 10064 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 10065 GVAddrRef->setInitializer(Addr); 10066 CGM.addCompilerUsedGlobal(GVAddrRef); 10067 } 10068 } 10069 } else { 10070 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 10071 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10072 HasRequiresUnifiedSharedMemory)) && 10073 "Declare target attribute must link or to with unified memory."); 10074 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 10075 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 10076 else 10077 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10078 10079 if (CGM.getLangOpts().OpenMPIsDevice) { 10080 VarName = Addr->getName(); 10081 Addr = nullptr; 10082 } else { 10083 VarName = getAddrOfDeclareTargetVar(VD).getName(); 10084 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 10085 } 10086 VarSize = CGM.getPointerSize(); 10087 Linkage = llvm::GlobalValue::WeakAnyLinkage; 10088 } 10089 10090 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10091 VarName, Addr, VarSize, Flags, Linkage); 10092 } 10093 10094 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 10095 if (isa<FunctionDecl>(GD.getDecl()) || 10096 isa<OMPDeclareReductionDecl>(GD.getDecl())) 10097 return emitTargetFunctions(GD); 10098 10099 return emitTargetGlobalVariable(GD); 10100 } 10101 10102 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 10103 for (const VarDecl *VD : DeferredGlobalVariables) { 10104 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10105 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10106 if (!Res) 10107 continue; 10108 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10109 !HasRequiresUnifiedSharedMemory) { 10110 CGM.EmitGlobal(VD); 10111 } else { 10112 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 10113 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10114 HasRequiresUnifiedSharedMemory)) && 10115 "Expected link clause or to clause with unified memory."); 10116 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 10117 } 10118 } 10119 } 10120 10121 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 10122 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 10123 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 10124 " Expected target-based directive."); 10125 } 10126 10127 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 10128 for (const OMPClause *Clause : D->clauselists()) { 10129 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 10130 HasRequiresUnifiedSharedMemory = true; 10131 } else if (const auto *AC = 10132 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 10133 switch (AC->getAtomicDefaultMemOrderKind()) { 10134 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 10135 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 10136 break; 10137 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 10138 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 10139 break; 10140 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 10141 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 10142 break; 10143 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 10144 break; 10145 } 10146 } 10147 } 10148 } 10149 10150 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 10151 return RequiresAtomicOrdering; 10152 } 10153 10154 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 10155 LangAS &AS) { 10156 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 10157 return false; 10158 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 10159 switch(A->getAllocatorType()) { 10160 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 10161 // Not supported, fallback to the default mem space. 10162 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 10163 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 10164 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 10165 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 10166 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 10167 case OMPAllocateDeclAttr::OMPConstMemAlloc: 10168 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 10169 AS = LangAS::Default; 10170 return true; 10171 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 10172 llvm_unreachable("Expected predefined allocator for the variables with the " 10173 "static storage."); 10174 } 10175 return false; 10176 } 10177 10178 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 10179 return HasRequiresUnifiedSharedMemory; 10180 } 10181 10182 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 10183 CodeGenModule &CGM) 10184 : CGM(CGM) { 10185 if (CGM.getLangOpts().OpenMPIsDevice) { 10186 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 10187 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 10188 } 10189 } 10190 10191 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 10192 if (CGM.getLangOpts().OpenMPIsDevice) 10193 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 10194 } 10195 10196 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 10197 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 10198 return true; 10199 10200 const auto *D = cast<FunctionDecl>(GD.getDecl()); 10201 // Do not to emit function if it is marked as declare target as it was already 10202 // emitted. 10203 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 10204 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 10205 if (auto *F = dyn_cast_or_null<llvm::Function>( 10206 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 10207 return !F->isDeclaration(); 10208 return false; 10209 } 10210 return true; 10211 } 10212 10213 return !AlreadyEmittedTargetDecls.insert(D).second; 10214 } 10215 10216 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 10217 // If we don't have entries or if we are emitting code for the device, we 10218 // don't need to do anything. 10219 if (CGM.getLangOpts().OMPTargetTriples.empty() || 10220 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 10221 (OffloadEntriesInfoManager.empty() && 10222 !HasEmittedDeclareTargetRegion && 10223 !HasEmittedTargetRegion)) 10224 return nullptr; 10225 10226 // Create and register the function that handles the requires directives. 10227 ASTContext &C = CGM.getContext(); 10228 10229 llvm::Function *RequiresRegFn; 10230 { 10231 CodeGenFunction CGF(CGM); 10232 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 10233 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 10234 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 10235 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 10236 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 10237 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 10238 // TODO: check for other requires clauses. 10239 // The requires directive takes effect only when a target region is 10240 // present in the compilation unit. Otherwise it is ignored and not 10241 // passed to the runtime. This avoids the runtime from throwing an error 10242 // for mismatching requires clauses across compilation units that don't 10243 // contain at least 1 target region. 10244 assert((HasEmittedTargetRegion || 10245 HasEmittedDeclareTargetRegion || 10246 !OffloadEntriesInfoManager.empty()) && 10247 "Target or declare target region expected."); 10248 if (HasRequiresUnifiedSharedMemory) 10249 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 10250 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 10251 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 10252 CGF.FinishFunction(); 10253 } 10254 return RequiresRegFn; 10255 } 10256 10257 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 10258 const OMPExecutableDirective &D, 10259 SourceLocation Loc, 10260 llvm::Function *OutlinedFn, 10261 ArrayRef<llvm::Value *> CapturedVars) { 10262 if (!CGF.HaveInsertPoint()) 10263 return; 10264 10265 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10266 CodeGenFunction::RunCleanupsScope Scope(CGF); 10267 10268 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 10269 llvm::Value *Args[] = { 10270 RTLoc, 10271 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 10272 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 10273 llvm::SmallVector<llvm::Value *, 16> RealArgs; 10274 RealArgs.append(std::begin(Args), std::end(Args)); 10275 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 10276 10277 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 10278 CGF.EmitRuntimeCall(RTLFn, RealArgs); 10279 } 10280 10281 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 10282 const Expr *NumTeams, 10283 const Expr *ThreadLimit, 10284 SourceLocation Loc) { 10285 if (!CGF.HaveInsertPoint()) 10286 return; 10287 10288 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10289 10290 llvm::Value *NumTeamsVal = 10291 NumTeams 10292 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 10293 CGF.CGM.Int32Ty, /* isSigned = */ true) 10294 : CGF.Builder.getInt32(0); 10295 10296 llvm::Value *ThreadLimitVal = 10297 ThreadLimit 10298 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 10299 CGF.CGM.Int32Ty, /* isSigned = */ true) 10300 : CGF.Builder.getInt32(0); 10301 10302 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 10303 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 10304 ThreadLimitVal}; 10305 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 10306 PushNumTeamsArgs); 10307 } 10308 10309 void CGOpenMPRuntime::emitTargetDataCalls( 10310 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10311 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 10312 if (!CGF.HaveInsertPoint()) 10313 return; 10314 10315 // Action used to replace the default codegen action and turn privatization 10316 // off. 10317 PrePostActionTy NoPrivAction; 10318 10319 // Generate the code for the opening of the data environment. Capture all the 10320 // arguments of the runtime call by reference because they are used in the 10321 // closing of the region. 10322 auto &&BeginThenGen = [this, &D, Device, &Info, 10323 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 10324 // Fill up the arrays with all the mapped variables. 10325 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10326 MappableExprsHandler::MapValuesArrayTy Pointers; 10327 MappableExprsHandler::MapValuesArrayTy Sizes; 10328 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10329 10330 // Get map clause information. 10331 MappableExprsHandler MCHandler(D, CGF); 10332 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10333 10334 // Fill up the arrays and create the arguments. 10335 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10336 10337 llvm::Value *BasePointersArrayArg = nullptr; 10338 llvm::Value *PointersArrayArg = nullptr; 10339 llvm::Value *SizesArrayArg = nullptr; 10340 llvm::Value *MapTypesArrayArg = nullptr; 10341 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10342 SizesArrayArg, MapTypesArrayArg, Info); 10343 10344 // Emit device ID if any. 10345 llvm::Value *DeviceID = nullptr; 10346 if (Device) { 10347 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10348 CGF.Int64Ty, /*isSigned=*/true); 10349 } else { 10350 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10351 } 10352 10353 // Emit the number of elements in the offloading arrays. 10354 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10355 10356 llvm::Value *OffloadingArgs[] = { 10357 DeviceID, PointerNum, BasePointersArrayArg, 10358 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10359 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 10360 OffloadingArgs); 10361 10362 // If device pointer privatization is required, emit the body of the region 10363 // here. It will have to be duplicated: with and without privatization. 10364 if (!Info.CaptureDeviceAddrMap.empty()) 10365 CodeGen(CGF); 10366 }; 10367 10368 // Generate code for the closing of the data region. 10369 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10370 PrePostActionTy &) { 10371 assert(Info.isValid() && "Invalid data environment closing arguments."); 10372 10373 llvm::Value *BasePointersArrayArg = nullptr; 10374 llvm::Value *PointersArrayArg = nullptr; 10375 llvm::Value *SizesArrayArg = nullptr; 10376 llvm::Value *MapTypesArrayArg = nullptr; 10377 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10378 SizesArrayArg, MapTypesArrayArg, Info); 10379 10380 // Emit device ID if any. 10381 llvm::Value *DeviceID = nullptr; 10382 if (Device) { 10383 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10384 CGF.Int64Ty, /*isSigned=*/true); 10385 } else { 10386 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10387 } 10388 10389 // Emit the number of elements in the offloading arrays. 10390 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10391 10392 llvm::Value *OffloadingArgs[] = { 10393 DeviceID, PointerNum, BasePointersArrayArg, 10394 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10395 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10396 OffloadingArgs); 10397 }; 10398 10399 // If we need device pointer privatization, we need to emit the body of the 10400 // region with no privatization in the 'else' branch of the conditional. 10401 // Otherwise, we don't have to do anything. 10402 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10403 PrePostActionTy &) { 10404 if (!Info.CaptureDeviceAddrMap.empty()) { 10405 CodeGen.setAction(NoPrivAction); 10406 CodeGen(CGF); 10407 } 10408 }; 10409 10410 // We don't have to do anything to close the region if the if clause evaluates 10411 // to false. 10412 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10413 10414 if (IfCond) { 10415 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10416 } else { 10417 RegionCodeGenTy RCG(BeginThenGen); 10418 RCG(CGF); 10419 } 10420 10421 // If we don't require privatization of device pointers, we emit the body in 10422 // between the runtime calls. This avoids duplicating the body code. 10423 if (Info.CaptureDeviceAddrMap.empty()) { 10424 CodeGen.setAction(NoPrivAction); 10425 CodeGen(CGF); 10426 } 10427 10428 if (IfCond) { 10429 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10430 } else { 10431 RegionCodeGenTy RCG(EndThenGen); 10432 RCG(CGF); 10433 } 10434 } 10435 10436 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10437 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10438 const Expr *Device) { 10439 if (!CGF.HaveInsertPoint()) 10440 return; 10441 10442 assert((isa<OMPTargetEnterDataDirective>(D) || 10443 isa<OMPTargetExitDataDirective>(D) || 10444 isa<OMPTargetUpdateDirective>(D)) && 10445 "Expecting either target enter, exit data, or update directives."); 10446 10447 CodeGenFunction::OMPTargetDataInfo InputInfo; 10448 llvm::Value *MapTypesArray = nullptr; 10449 // Generate the code for the opening of the data environment. 10450 auto &&ThenGen = [this, &D, Device, &InputInfo, 10451 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10452 // Emit device ID if any. 10453 llvm::Value *DeviceID = nullptr; 10454 if (Device) { 10455 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10456 CGF.Int64Ty, /*isSigned=*/true); 10457 } else { 10458 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10459 } 10460 10461 // Emit the number of elements in the offloading arrays. 10462 llvm::Constant *PointerNum = 10463 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10464 10465 llvm::Value *OffloadingArgs[] = {DeviceID, 10466 PointerNum, 10467 InputInfo.BasePointersArray.getPointer(), 10468 InputInfo.PointersArray.getPointer(), 10469 InputInfo.SizesArray.getPointer(), 10470 MapTypesArray}; 10471 10472 // Select the right runtime function call for each expected standalone 10473 // directive. 10474 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10475 OpenMPRTLFunction RTLFn; 10476 switch (D.getDirectiveKind()) { 10477 case OMPD_target_enter_data: 10478 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10479 : OMPRTL__tgt_target_data_begin; 10480 break; 10481 case OMPD_target_exit_data: 10482 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10483 : OMPRTL__tgt_target_data_end; 10484 break; 10485 case OMPD_target_update: 10486 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10487 : OMPRTL__tgt_target_data_update; 10488 break; 10489 case OMPD_parallel: 10490 case OMPD_for: 10491 case OMPD_parallel_for: 10492 case OMPD_parallel_master: 10493 case OMPD_parallel_sections: 10494 case OMPD_for_simd: 10495 case OMPD_parallel_for_simd: 10496 case OMPD_cancel: 10497 case OMPD_cancellation_point: 10498 case OMPD_ordered: 10499 case OMPD_threadprivate: 10500 case OMPD_allocate: 10501 case OMPD_task: 10502 case OMPD_simd: 10503 case OMPD_sections: 10504 case OMPD_section: 10505 case OMPD_single: 10506 case OMPD_master: 10507 case OMPD_critical: 10508 case OMPD_taskyield: 10509 case OMPD_barrier: 10510 case OMPD_taskwait: 10511 case OMPD_taskgroup: 10512 case OMPD_atomic: 10513 case OMPD_flush: 10514 case OMPD_depobj: 10515 case OMPD_scan: 10516 case OMPD_teams: 10517 case OMPD_target_data: 10518 case OMPD_distribute: 10519 case OMPD_distribute_simd: 10520 case OMPD_distribute_parallel_for: 10521 case OMPD_distribute_parallel_for_simd: 10522 case OMPD_teams_distribute: 10523 case OMPD_teams_distribute_simd: 10524 case OMPD_teams_distribute_parallel_for: 10525 case OMPD_teams_distribute_parallel_for_simd: 10526 case OMPD_declare_simd: 10527 case OMPD_declare_variant: 10528 case OMPD_declare_target: 10529 case OMPD_end_declare_target: 10530 case OMPD_declare_reduction: 10531 case OMPD_declare_mapper: 10532 case OMPD_taskloop: 10533 case OMPD_taskloop_simd: 10534 case OMPD_master_taskloop: 10535 case OMPD_master_taskloop_simd: 10536 case OMPD_parallel_master_taskloop: 10537 case OMPD_parallel_master_taskloop_simd: 10538 case OMPD_target: 10539 case OMPD_target_simd: 10540 case OMPD_target_teams_distribute: 10541 case OMPD_target_teams_distribute_simd: 10542 case OMPD_target_teams_distribute_parallel_for: 10543 case OMPD_target_teams_distribute_parallel_for_simd: 10544 case OMPD_target_teams: 10545 case OMPD_target_parallel: 10546 case OMPD_target_parallel_for: 10547 case OMPD_target_parallel_for_simd: 10548 case OMPD_requires: 10549 case OMPD_unknown: 10550 llvm_unreachable("Unexpected standalone target data directive."); 10551 break; 10552 } 10553 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10554 }; 10555 10556 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10557 CodeGenFunction &CGF, PrePostActionTy &) { 10558 // Fill up the arrays with all the mapped variables. 10559 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10560 MappableExprsHandler::MapValuesArrayTy Pointers; 10561 MappableExprsHandler::MapValuesArrayTy Sizes; 10562 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10563 10564 // Get map clause information. 10565 MappableExprsHandler MEHandler(D, CGF); 10566 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10567 10568 TargetDataInfo Info; 10569 // Fill up the arrays and create the arguments. 10570 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10571 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10572 Info.PointersArray, Info.SizesArray, 10573 Info.MapTypesArray, Info); 10574 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10575 InputInfo.BasePointersArray = 10576 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10577 InputInfo.PointersArray = 10578 Address(Info.PointersArray, CGM.getPointerAlign()); 10579 InputInfo.SizesArray = 10580 Address(Info.SizesArray, CGM.getPointerAlign()); 10581 MapTypesArray = Info.MapTypesArray; 10582 if (D.hasClausesOfKind<OMPDependClause>()) 10583 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10584 else 10585 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10586 }; 10587 10588 if (IfCond) { 10589 emitIfClause(CGF, IfCond, TargetThenGen, 10590 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10591 } else { 10592 RegionCodeGenTy ThenRCG(TargetThenGen); 10593 ThenRCG(CGF); 10594 } 10595 } 10596 10597 namespace { 10598 /// Kind of parameter in a function with 'declare simd' directive. 10599 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10600 /// Attribute set of the parameter. 10601 struct ParamAttrTy { 10602 ParamKindTy Kind = Vector; 10603 llvm::APSInt StrideOrArg; 10604 llvm::APSInt Alignment; 10605 }; 10606 } // namespace 10607 10608 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10609 ArrayRef<ParamAttrTy> ParamAttrs) { 10610 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10611 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10612 // of that clause. The VLEN value must be power of 2. 10613 // In other case the notion of the function`s "characteristic data type" (CDT) 10614 // is used to compute the vector length. 10615 // CDT is defined in the following order: 10616 // a) For non-void function, the CDT is the return type. 10617 // b) If the function has any non-uniform, non-linear parameters, then the 10618 // CDT is the type of the first such parameter. 10619 // c) If the CDT determined by a) or b) above is struct, union, or class 10620 // type which is pass-by-value (except for the type that maps to the 10621 // built-in complex data type), the characteristic data type is int. 10622 // d) If none of the above three cases is applicable, the CDT is int. 10623 // The VLEN is then determined based on the CDT and the size of vector 10624 // register of that ISA for which current vector version is generated. The 10625 // VLEN is computed using the formula below: 10626 // VLEN = sizeof(vector_register) / sizeof(CDT), 10627 // where vector register size specified in section 3.2.1 Registers and the 10628 // Stack Frame of original AMD64 ABI document. 10629 QualType RetType = FD->getReturnType(); 10630 if (RetType.isNull()) 10631 return 0; 10632 ASTContext &C = FD->getASTContext(); 10633 QualType CDT; 10634 if (!RetType.isNull() && !RetType->isVoidType()) { 10635 CDT = RetType; 10636 } else { 10637 unsigned Offset = 0; 10638 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10639 if (ParamAttrs[Offset].Kind == Vector) 10640 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10641 ++Offset; 10642 } 10643 if (CDT.isNull()) { 10644 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10645 if (ParamAttrs[I + Offset].Kind == Vector) { 10646 CDT = FD->getParamDecl(I)->getType(); 10647 break; 10648 } 10649 } 10650 } 10651 } 10652 if (CDT.isNull()) 10653 CDT = C.IntTy; 10654 CDT = CDT->getCanonicalTypeUnqualified(); 10655 if (CDT->isRecordType() || CDT->isUnionType()) 10656 CDT = C.IntTy; 10657 return C.getTypeSize(CDT); 10658 } 10659 10660 static void 10661 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10662 const llvm::APSInt &VLENVal, 10663 ArrayRef<ParamAttrTy> ParamAttrs, 10664 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10665 struct ISADataTy { 10666 char ISA; 10667 unsigned VecRegSize; 10668 }; 10669 ISADataTy ISAData[] = { 10670 { 10671 'b', 128 10672 }, // SSE 10673 { 10674 'c', 256 10675 }, // AVX 10676 { 10677 'd', 256 10678 }, // AVX2 10679 { 10680 'e', 512 10681 }, // AVX512 10682 }; 10683 llvm::SmallVector<char, 2> Masked; 10684 switch (State) { 10685 case OMPDeclareSimdDeclAttr::BS_Undefined: 10686 Masked.push_back('N'); 10687 Masked.push_back('M'); 10688 break; 10689 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10690 Masked.push_back('N'); 10691 break; 10692 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10693 Masked.push_back('M'); 10694 break; 10695 } 10696 for (char Mask : Masked) { 10697 for (const ISADataTy &Data : ISAData) { 10698 SmallString<256> Buffer; 10699 llvm::raw_svector_ostream Out(Buffer); 10700 Out << "_ZGV" << Data.ISA << Mask; 10701 if (!VLENVal) { 10702 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10703 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10704 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10705 } else { 10706 Out << VLENVal; 10707 } 10708 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10709 switch (ParamAttr.Kind){ 10710 case LinearWithVarStride: 10711 Out << 's' << ParamAttr.StrideOrArg; 10712 break; 10713 case Linear: 10714 Out << 'l'; 10715 if (!!ParamAttr.StrideOrArg) 10716 Out << ParamAttr.StrideOrArg; 10717 break; 10718 case Uniform: 10719 Out << 'u'; 10720 break; 10721 case Vector: 10722 Out << 'v'; 10723 break; 10724 } 10725 if (!!ParamAttr.Alignment) 10726 Out << 'a' << ParamAttr.Alignment; 10727 } 10728 Out << '_' << Fn->getName(); 10729 Fn->addFnAttr(Out.str()); 10730 } 10731 } 10732 } 10733 10734 // This are the Functions that are needed to mangle the name of the 10735 // vector functions generated by the compiler, according to the rules 10736 // defined in the "Vector Function ABI specifications for AArch64", 10737 // available at 10738 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10739 10740 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10741 /// 10742 /// TODO: Need to implement the behavior for reference marked with a 10743 /// var or no linear modifiers (1.b in the section). For this, we 10744 /// need to extend ParamKindTy to support the linear modifiers. 10745 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10746 QT = QT.getCanonicalType(); 10747 10748 if (QT->isVoidType()) 10749 return false; 10750 10751 if (Kind == ParamKindTy::Uniform) 10752 return false; 10753 10754 if (Kind == ParamKindTy::Linear) 10755 return false; 10756 10757 // TODO: Handle linear references with modifiers 10758 10759 if (Kind == ParamKindTy::LinearWithVarStride) 10760 return false; 10761 10762 return true; 10763 } 10764 10765 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10766 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10767 QT = QT.getCanonicalType(); 10768 unsigned Size = C.getTypeSize(QT); 10769 10770 // Only scalars and complex within 16 bytes wide set PVB to true. 10771 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10772 return false; 10773 10774 if (QT->isFloatingType()) 10775 return true; 10776 10777 if (QT->isIntegerType()) 10778 return true; 10779 10780 if (QT->isPointerType()) 10781 return true; 10782 10783 // TODO: Add support for complex types (section 3.1.2, item 2). 10784 10785 return false; 10786 } 10787 10788 /// Computes the lane size (LS) of a return type or of an input parameter, 10789 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10790 /// TODO: Add support for references, section 3.2.1, item 1. 10791 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10792 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10793 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10794 if (getAArch64PBV(PTy, C)) 10795 return C.getTypeSize(PTy); 10796 } 10797 if (getAArch64PBV(QT, C)) 10798 return C.getTypeSize(QT); 10799 10800 return C.getTypeSize(C.getUIntPtrType()); 10801 } 10802 10803 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10804 // signature of the scalar function, as defined in 3.2.2 of the 10805 // AAVFABI. 10806 static std::tuple<unsigned, unsigned, bool> 10807 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10808 QualType RetType = FD->getReturnType().getCanonicalType(); 10809 10810 ASTContext &C = FD->getASTContext(); 10811 10812 bool OutputBecomesInput = false; 10813 10814 llvm::SmallVector<unsigned, 8> Sizes; 10815 if (!RetType->isVoidType()) { 10816 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10817 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10818 OutputBecomesInput = true; 10819 } 10820 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10821 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10822 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10823 } 10824 10825 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10826 // The LS of a function parameter / return value can only be a power 10827 // of 2, starting from 8 bits, up to 128. 10828 assert(std::all_of(Sizes.begin(), Sizes.end(), 10829 [](unsigned Size) { 10830 return Size == 8 || Size == 16 || Size == 32 || 10831 Size == 64 || Size == 128; 10832 }) && 10833 "Invalid size"); 10834 10835 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10836 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10837 OutputBecomesInput); 10838 } 10839 10840 /// Mangle the parameter part of the vector function name according to 10841 /// their OpenMP classification. The mangling function is defined in 10842 /// section 3.5 of the AAVFABI. 10843 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10844 SmallString<256> Buffer; 10845 llvm::raw_svector_ostream Out(Buffer); 10846 for (const auto &ParamAttr : ParamAttrs) { 10847 switch (ParamAttr.Kind) { 10848 case LinearWithVarStride: 10849 Out << "ls" << ParamAttr.StrideOrArg; 10850 break; 10851 case Linear: 10852 Out << 'l'; 10853 // Don't print the step value if it is not present or if it is 10854 // equal to 1. 10855 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10856 Out << ParamAttr.StrideOrArg; 10857 break; 10858 case Uniform: 10859 Out << 'u'; 10860 break; 10861 case Vector: 10862 Out << 'v'; 10863 break; 10864 } 10865 10866 if (!!ParamAttr.Alignment) 10867 Out << 'a' << ParamAttr.Alignment; 10868 } 10869 10870 return std::string(Out.str()); 10871 } 10872 10873 // Function used to add the attribute. The parameter `VLEN` is 10874 // templated to allow the use of "x" when targeting scalable functions 10875 // for SVE. 10876 template <typename T> 10877 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10878 char ISA, StringRef ParSeq, 10879 StringRef MangledName, bool OutputBecomesInput, 10880 llvm::Function *Fn) { 10881 SmallString<256> Buffer; 10882 llvm::raw_svector_ostream Out(Buffer); 10883 Out << Prefix << ISA << LMask << VLEN; 10884 if (OutputBecomesInput) 10885 Out << "v"; 10886 Out << ParSeq << "_" << MangledName; 10887 Fn->addFnAttr(Out.str()); 10888 } 10889 10890 // Helper function to generate the Advanced SIMD names depending on 10891 // the value of the NDS when simdlen is not present. 10892 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10893 StringRef Prefix, char ISA, 10894 StringRef ParSeq, StringRef MangledName, 10895 bool OutputBecomesInput, 10896 llvm::Function *Fn) { 10897 switch (NDS) { 10898 case 8: 10899 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10900 OutputBecomesInput, Fn); 10901 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10902 OutputBecomesInput, Fn); 10903 break; 10904 case 16: 10905 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10906 OutputBecomesInput, Fn); 10907 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10908 OutputBecomesInput, Fn); 10909 break; 10910 case 32: 10911 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10912 OutputBecomesInput, Fn); 10913 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10914 OutputBecomesInput, Fn); 10915 break; 10916 case 64: 10917 case 128: 10918 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10919 OutputBecomesInput, Fn); 10920 break; 10921 default: 10922 llvm_unreachable("Scalar type is too wide."); 10923 } 10924 } 10925 10926 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10927 static void emitAArch64DeclareSimdFunction( 10928 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10929 ArrayRef<ParamAttrTy> ParamAttrs, 10930 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10931 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10932 10933 // Get basic data for building the vector signature. 10934 const auto Data = getNDSWDS(FD, ParamAttrs); 10935 const unsigned NDS = std::get<0>(Data); 10936 const unsigned WDS = std::get<1>(Data); 10937 const bool OutputBecomesInput = std::get<2>(Data); 10938 10939 // Check the values provided via `simdlen` by the user. 10940 // 1. A `simdlen(1)` doesn't produce vector signatures, 10941 if (UserVLEN == 1) { 10942 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10943 DiagnosticsEngine::Warning, 10944 "The clause simdlen(1) has no effect when targeting aarch64."); 10945 CGM.getDiags().Report(SLoc, DiagID); 10946 return; 10947 } 10948 10949 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10950 // Advanced SIMD output. 10951 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10952 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10953 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10954 "power of 2 when targeting Advanced SIMD."); 10955 CGM.getDiags().Report(SLoc, DiagID); 10956 return; 10957 } 10958 10959 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10960 // limits. 10961 if (ISA == 's' && UserVLEN != 0) { 10962 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10963 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10964 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10965 "lanes in the architectural constraints " 10966 "for SVE (min is 128-bit, max is " 10967 "2048-bit, by steps of 128-bit)"); 10968 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10969 return; 10970 } 10971 } 10972 10973 // Sort out parameter sequence. 10974 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10975 StringRef Prefix = "_ZGV"; 10976 // Generate simdlen from user input (if any). 10977 if (UserVLEN) { 10978 if (ISA == 's') { 10979 // SVE generates only a masked function. 10980 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10981 OutputBecomesInput, Fn); 10982 } else { 10983 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10984 // Advanced SIMD generates one or two functions, depending on 10985 // the `[not]inbranch` clause. 10986 switch (State) { 10987 case OMPDeclareSimdDeclAttr::BS_Undefined: 10988 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10989 OutputBecomesInput, Fn); 10990 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10991 OutputBecomesInput, Fn); 10992 break; 10993 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10994 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10995 OutputBecomesInput, Fn); 10996 break; 10997 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10998 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10999 OutputBecomesInput, Fn); 11000 break; 11001 } 11002 } 11003 } else { 11004 // If no user simdlen is provided, follow the AAVFABI rules for 11005 // generating the vector length. 11006 if (ISA == 's') { 11007 // SVE, section 3.4.1, item 1. 11008 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 11009 OutputBecomesInput, Fn); 11010 } else { 11011 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11012 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 11013 // two vector names depending on the use of the clause 11014 // `[not]inbranch`. 11015 switch (State) { 11016 case OMPDeclareSimdDeclAttr::BS_Undefined: 11017 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11018 OutputBecomesInput, Fn); 11019 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11020 OutputBecomesInput, Fn); 11021 break; 11022 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11023 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11024 OutputBecomesInput, Fn); 11025 break; 11026 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11027 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11028 OutputBecomesInput, Fn); 11029 break; 11030 } 11031 } 11032 } 11033 } 11034 11035 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 11036 llvm::Function *Fn) { 11037 ASTContext &C = CGM.getContext(); 11038 FD = FD->getMostRecentDecl(); 11039 // Map params to their positions in function decl. 11040 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 11041 if (isa<CXXMethodDecl>(FD)) 11042 ParamPositions.try_emplace(FD, 0); 11043 unsigned ParamPos = ParamPositions.size(); 11044 for (const ParmVarDecl *P : FD->parameters()) { 11045 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 11046 ++ParamPos; 11047 } 11048 while (FD) { 11049 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 11050 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 11051 // Mark uniform parameters. 11052 for (const Expr *E : Attr->uniforms()) { 11053 E = E->IgnoreParenImpCasts(); 11054 unsigned Pos; 11055 if (isa<CXXThisExpr>(E)) { 11056 Pos = ParamPositions[FD]; 11057 } else { 11058 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11059 ->getCanonicalDecl(); 11060 Pos = ParamPositions[PVD]; 11061 } 11062 ParamAttrs[Pos].Kind = Uniform; 11063 } 11064 // Get alignment info. 11065 auto NI = Attr->alignments_begin(); 11066 for (const Expr *E : Attr->aligneds()) { 11067 E = E->IgnoreParenImpCasts(); 11068 unsigned Pos; 11069 QualType ParmTy; 11070 if (isa<CXXThisExpr>(E)) { 11071 Pos = ParamPositions[FD]; 11072 ParmTy = E->getType(); 11073 } else { 11074 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11075 ->getCanonicalDecl(); 11076 Pos = ParamPositions[PVD]; 11077 ParmTy = PVD->getType(); 11078 } 11079 ParamAttrs[Pos].Alignment = 11080 (*NI) 11081 ? (*NI)->EvaluateKnownConstInt(C) 11082 : llvm::APSInt::getUnsigned( 11083 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 11084 .getQuantity()); 11085 ++NI; 11086 } 11087 // Mark linear parameters. 11088 auto SI = Attr->steps_begin(); 11089 auto MI = Attr->modifiers_begin(); 11090 for (const Expr *E : Attr->linears()) { 11091 E = E->IgnoreParenImpCasts(); 11092 unsigned Pos; 11093 if (isa<CXXThisExpr>(E)) { 11094 Pos = ParamPositions[FD]; 11095 } else { 11096 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11097 ->getCanonicalDecl(); 11098 Pos = ParamPositions[PVD]; 11099 } 11100 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 11101 ParamAttr.Kind = Linear; 11102 if (*SI) { 11103 Expr::EvalResult Result; 11104 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 11105 if (const auto *DRE = 11106 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 11107 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 11108 ParamAttr.Kind = LinearWithVarStride; 11109 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 11110 ParamPositions[StridePVD->getCanonicalDecl()]); 11111 } 11112 } 11113 } else { 11114 ParamAttr.StrideOrArg = Result.Val.getInt(); 11115 } 11116 } 11117 ++SI; 11118 ++MI; 11119 } 11120 llvm::APSInt VLENVal; 11121 SourceLocation ExprLoc; 11122 const Expr *VLENExpr = Attr->getSimdlen(); 11123 if (VLENExpr) { 11124 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 11125 ExprLoc = VLENExpr->getExprLoc(); 11126 } 11127 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 11128 if (CGM.getTriple().isX86()) { 11129 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 11130 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 11131 unsigned VLEN = VLENVal.getExtValue(); 11132 StringRef MangledName = Fn->getName(); 11133 if (CGM.getTarget().hasFeature("sve")) 11134 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11135 MangledName, 's', 128, Fn, ExprLoc); 11136 if (CGM.getTarget().hasFeature("neon")) 11137 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11138 MangledName, 'n', 128, Fn, ExprLoc); 11139 } 11140 } 11141 FD = FD->getPreviousDecl(); 11142 } 11143 } 11144 11145 namespace { 11146 /// Cleanup action for doacross support. 11147 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 11148 public: 11149 static const int DoacrossFinArgs = 2; 11150 11151 private: 11152 llvm::FunctionCallee RTLFn; 11153 llvm::Value *Args[DoacrossFinArgs]; 11154 11155 public: 11156 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 11157 ArrayRef<llvm::Value *> CallArgs) 11158 : RTLFn(RTLFn) { 11159 assert(CallArgs.size() == DoacrossFinArgs); 11160 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11161 } 11162 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11163 if (!CGF.HaveInsertPoint()) 11164 return; 11165 CGF.EmitRuntimeCall(RTLFn, Args); 11166 } 11167 }; 11168 } // namespace 11169 11170 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11171 const OMPLoopDirective &D, 11172 ArrayRef<Expr *> NumIterations) { 11173 if (!CGF.HaveInsertPoint()) 11174 return; 11175 11176 ASTContext &C = CGM.getContext(); 11177 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 11178 RecordDecl *RD; 11179 if (KmpDimTy.isNull()) { 11180 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 11181 // kmp_int64 lo; // lower 11182 // kmp_int64 up; // upper 11183 // kmp_int64 st; // stride 11184 // }; 11185 RD = C.buildImplicitRecord("kmp_dim"); 11186 RD->startDefinition(); 11187 addFieldToRecordDecl(C, RD, Int64Ty); 11188 addFieldToRecordDecl(C, RD, Int64Ty); 11189 addFieldToRecordDecl(C, RD, Int64Ty); 11190 RD->completeDefinition(); 11191 KmpDimTy = C.getRecordType(RD); 11192 } else { 11193 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 11194 } 11195 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 11196 QualType ArrayTy = 11197 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 11198 11199 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 11200 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 11201 enum { LowerFD = 0, UpperFD, StrideFD }; 11202 // Fill dims with data. 11203 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 11204 LValue DimsLVal = CGF.MakeAddrLValue( 11205 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 11206 // dims.upper = num_iterations; 11207 LValue UpperLVal = CGF.EmitLValueForField( 11208 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 11209 llvm::Value *NumIterVal = 11210 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 11211 D.getNumIterations()->getType(), Int64Ty, 11212 D.getNumIterations()->getExprLoc()); 11213 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 11214 // dims.stride = 1; 11215 LValue StrideLVal = CGF.EmitLValueForField( 11216 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 11217 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 11218 StrideLVal); 11219 } 11220 11221 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 11222 // kmp_int32 num_dims, struct kmp_dim * dims); 11223 llvm::Value *Args[] = { 11224 emitUpdateLocation(CGF, D.getBeginLoc()), 11225 getThreadID(CGF, D.getBeginLoc()), 11226 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 11227 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11228 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 11229 CGM.VoidPtrTy)}; 11230 11231 llvm::FunctionCallee RTLFn = 11232 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 11233 CGF.EmitRuntimeCall(RTLFn, Args); 11234 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 11235 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 11236 llvm::FunctionCallee FiniRTLFn = 11237 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 11238 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11239 llvm::makeArrayRef(FiniArgs)); 11240 } 11241 11242 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11243 const OMPDependClause *C) { 11244 QualType Int64Ty = 11245 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 11246 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 11247 QualType ArrayTy = CGM.getContext().getConstantArrayType( 11248 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 11249 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 11250 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 11251 const Expr *CounterVal = C->getLoopData(I); 11252 assert(CounterVal); 11253 llvm::Value *CntVal = CGF.EmitScalarConversion( 11254 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 11255 CounterVal->getExprLoc()); 11256 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 11257 /*Volatile=*/false, Int64Ty); 11258 } 11259 llvm::Value *Args[] = { 11260 emitUpdateLocation(CGF, C->getBeginLoc()), 11261 getThreadID(CGF, C->getBeginLoc()), 11262 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 11263 llvm::FunctionCallee RTLFn; 11264 if (C->getDependencyKind() == OMPC_DEPEND_source) { 11265 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 11266 } else { 11267 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 11268 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 11269 } 11270 CGF.EmitRuntimeCall(RTLFn, Args); 11271 } 11272 11273 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 11274 llvm::FunctionCallee Callee, 11275 ArrayRef<llvm::Value *> Args) const { 11276 assert(Loc.isValid() && "Outlined function call location must be valid."); 11277 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 11278 11279 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 11280 if (Fn->doesNotThrow()) { 11281 CGF.EmitNounwindRuntimeCall(Fn, Args); 11282 return; 11283 } 11284 } 11285 CGF.EmitRuntimeCall(Callee, Args); 11286 } 11287 11288 void CGOpenMPRuntime::emitOutlinedFunctionCall( 11289 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 11290 ArrayRef<llvm::Value *> Args) const { 11291 emitCall(CGF, Loc, OutlinedFn, Args); 11292 } 11293 11294 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 11295 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 11296 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 11297 HasEmittedDeclareTargetRegion = true; 11298 } 11299 11300 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 11301 const VarDecl *NativeParam, 11302 const VarDecl *TargetParam) const { 11303 return CGF.GetAddrOfLocalVar(NativeParam); 11304 } 11305 11306 namespace { 11307 /// Cleanup action for allocate support. 11308 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 11309 public: 11310 static const int CleanupArgs = 3; 11311 11312 private: 11313 llvm::FunctionCallee RTLFn; 11314 llvm::Value *Args[CleanupArgs]; 11315 11316 public: 11317 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 11318 ArrayRef<llvm::Value *> CallArgs) 11319 : RTLFn(RTLFn) { 11320 assert(CallArgs.size() == CleanupArgs && 11321 "Size of arguments does not match."); 11322 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11323 } 11324 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11325 if (!CGF.HaveInsertPoint()) 11326 return; 11327 CGF.EmitRuntimeCall(RTLFn, Args); 11328 } 11329 }; 11330 } // namespace 11331 11332 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 11333 const VarDecl *VD) { 11334 if (!VD) 11335 return Address::invalid(); 11336 const VarDecl *CVD = VD->getCanonicalDecl(); 11337 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 11338 return Address::invalid(); 11339 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 11340 // Use the default allocation. 11341 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 11342 !AA->getAllocator()) 11343 return Address::invalid(); 11344 llvm::Value *Size; 11345 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11346 if (CVD->getType()->isVariablyModifiedType()) { 11347 Size = CGF.getTypeSize(CVD->getType()); 11348 // Align the size: ((size + align - 1) / align) * align 11349 Size = CGF.Builder.CreateNUWAdd( 11350 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11351 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11352 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11353 } else { 11354 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 11355 Size = CGM.getSize(Sz.alignTo(Align)); 11356 } 11357 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11358 assert(AA->getAllocator() && 11359 "Expected allocator expression for non-default allocator."); 11360 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11361 // According to the standard, the original allocator type is a enum (integer). 11362 // Convert to pointer type, if required. 11363 if (Allocator->getType()->isIntegerTy()) 11364 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11365 else if (Allocator->getType()->isPointerTy()) 11366 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11367 CGM.VoidPtrTy); 11368 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11369 11370 llvm::Value *Addr = 11371 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11372 getName({CVD->getName(), ".void.addr"})); 11373 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11374 Allocator}; 11375 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11376 11377 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11378 llvm::makeArrayRef(FiniArgs)); 11379 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11380 Addr, 11381 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11382 getName({CVD->getName(), ".addr"})); 11383 return Address(Addr, Align); 11384 } 11385 11386 /// Finds the variant function that matches current context with its context 11387 /// selector. 11388 static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM, 11389 const FunctionDecl *FD) { 11390 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) 11391 return FD; 11392 11393 SmallVector<Expr *, 8> VariantExprs; 11394 SmallVector<VariantMatchInfo, 8> VMIs; 11395 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { 11396 const OMPTraitInfo &TI = *A->getTraitInfos(); 11397 VMIs.push_back(VariantMatchInfo()); 11398 TI.getAsVariantMatchInfo(CGM.getContext(), VMIs.back()); 11399 VariantExprs.push_back(A->getVariantFuncRef()); 11400 } 11401 11402 OMPContext Ctx(CGM.getLangOpts().OpenMPIsDevice, CGM.getTriple()); 11403 // FIXME: Keep the context in the OMPIRBuilder so we can add constructs as we 11404 // build them. 11405 11406 int BestMatchIdx = getBestVariantMatchForContext(VMIs, Ctx); 11407 if (BestMatchIdx < 0) 11408 return FD; 11409 11410 return cast<FunctionDecl>( 11411 cast<DeclRefExpr>(VariantExprs[BestMatchIdx]->IgnoreParenImpCasts()) 11412 ->getDecl()); 11413 } 11414 11415 bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { 11416 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11417 // If the original function is defined already, use its definition. 11418 StringRef MangledName = CGM.getMangledName(GD); 11419 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); 11420 if (Orig && !Orig->isDeclaration()) 11421 return false; 11422 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D); 11423 // Emit original function if it does not have declare variant attribute or the 11424 // context does not match. 11425 if (NewFD == D) 11426 return false; 11427 GlobalDecl NewGD = GD.getWithDecl(NewFD); 11428 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) { 11429 DeferredVariantFunction.erase(D); 11430 return true; 11431 } 11432 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD))); 11433 return true; 11434 } 11435 11436 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 11437 CodeGenModule &CGM, const OMPLoopDirective &S) 11438 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 11439 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11440 if (!NeedToPush) 11441 return; 11442 NontemporalDeclsSet &DS = 11443 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 11444 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 11445 for (const Stmt *Ref : C->private_refs()) { 11446 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 11447 const ValueDecl *VD; 11448 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 11449 VD = DRE->getDecl(); 11450 } else { 11451 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 11452 assert((ME->isImplicitCXXThis() || 11453 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 11454 "Expected member of current class."); 11455 VD = ME->getMemberDecl(); 11456 } 11457 DS.insert(VD); 11458 } 11459 } 11460 } 11461 11462 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 11463 if (!NeedToPush) 11464 return; 11465 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 11466 } 11467 11468 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 11469 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11470 11471 return llvm::any_of( 11472 CGM.getOpenMPRuntime().NontemporalDeclsStack, 11473 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 11474 } 11475 11476 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 11477 const OMPExecutableDirective &S, 11478 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 11479 const { 11480 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 11481 // Vars in target/task regions must be excluded completely. 11482 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 11483 isOpenMPTaskingDirective(S.getDirectiveKind())) { 11484 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11485 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 11486 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 11487 for (const CapturedStmt::Capture &Cap : CS->captures()) { 11488 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 11489 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 11490 } 11491 } 11492 // Exclude vars in private clauses. 11493 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 11494 for (const Expr *Ref : C->varlists()) { 11495 if (!Ref->getType()->isScalarType()) 11496 continue; 11497 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11498 if (!DRE) 11499 continue; 11500 NeedToCheckForLPCs.insert(DRE->getDecl()); 11501 } 11502 } 11503 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 11504 for (const Expr *Ref : C->varlists()) { 11505 if (!Ref->getType()->isScalarType()) 11506 continue; 11507 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11508 if (!DRE) 11509 continue; 11510 NeedToCheckForLPCs.insert(DRE->getDecl()); 11511 } 11512 } 11513 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11514 for (const Expr *Ref : C->varlists()) { 11515 if (!Ref->getType()->isScalarType()) 11516 continue; 11517 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11518 if (!DRE) 11519 continue; 11520 NeedToCheckForLPCs.insert(DRE->getDecl()); 11521 } 11522 } 11523 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 11524 for (const Expr *Ref : C->varlists()) { 11525 if (!Ref->getType()->isScalarType()) 11526 continue; 11527 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11528 if (!DRE) 11529 continue; 11530 NeedToCheckForLPCs.insert(DRE->getDecl()); 11531 } 11532 } 11533 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 11534 for (const Expr *Ref : C->varlists()) { 11535 if (!Ref->getType()->isScalarType()) 11536 continue; 11537 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11538 if (!DRE) 11539 continue; 11540 NeedToCheckForLPCs.insert(DRE->getDecl()); 11541 } 11542 } 11543 for (const Decl *VD : NeedToCheckForLPCs) { 11544 for (const LastprivateConditionalData &Data : 11545 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 11546 if (Data.DeclToUniqueName.count(VD) > 0) { 11547 if (!Data.Disabled) 11548 NeedToAddForLPCsAsDisabled.insert(VD); 11549 break; 11550 } 11551 } 11552 } 11553 } 11554 11555 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11556 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 11557 : CGM(CGF.CGM), 11558 Action((CGM.getLangOpts().OpenMP >= 50 && 11559 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 11560 [](const OMPLastprivateClause *C) { 11561 return C->getKind() == 11562 OMPC_LASTPRIVATE_conditional; 11563 })) 11564 ? ActionToDo::PushAsLastprivateConditional 11565 : ActionToDo::DoNotPush) { 11566 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11567 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 11568 return; 11569 assert(Action == ActionToDo::PushAsLastprivateConditional && 11570 "Expected a push action."); 11571 LastprivateConditionalData &Data = 11572 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11573 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11574 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 11575 continue; 11576 11577 for (const Expr *Ref : C->varlists()) { 11578 Data.DeclToUniqueName.insert(std::make_pair( 11579 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 11580 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 11581 } 11582 } 11583 Data.IVLVal = IVLVal; 11584 Data.Fn = CGF.CurFn; 11585 } 11586 11587 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11588 CodeGenFunction &CGF, const OMPExecutableDirective &S) 11589 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 11590 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11591 if (CGM.getLangOpts().OpenMP < 50) 11592 return; 11593 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 11594 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 11595 if (!NeedToAddForLPCsAsDisabled.empty()) { 11596 Action = ActionToDo::DisableLastprivateConditional; 11597 LastprivateConditionalData &Data = 11598 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11599 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 11600 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 11601 Data.Fn = CGF.CurFn; 11602 Data.Disabled = true; 11603 } 11604 } 11605 11606 CGOpenMPRuntime::LastprivateConditionalRAII 11607 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 11608 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 11609 return LastprivateConditionalRAII(CGF, S); 11610 } 11611 11612 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 11613 if (CGM.getLangOpts().OpenMP < 50) 11614 return; 11615 if (Action == ActionToDo::DisableLastprivateConditional) { 11616 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11617 "Expected list of disabled private vars."); 11618 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11619 } 11620 if (Action == ActionToDo::PushAsLastprivateConditional) { 11621 assert( 11622 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11623 "Expected list of lastprivate conditional vars."); 11624 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11625 } 11626 } 11627 11628 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 11629 const VarDecl *VD) { 11630 ASTContext &C = CGM.getContext(); 11631 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 11632 if (I == LastprivateConditionalToTypes.end()) 11633 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 11634 QualType NewType; 11635 const FieldDecl *VDField; 11636 const FieldDecl *FiredField; 11637 LValue BaseLVal; 11638 auto VI = I->getSecond().find(VD); 11639 if (VI == I->getSecond().end()) { 11640 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 11641 RD->startDefinition(); 11642 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 11643 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 11644 RD->completeDefinition(); 11645 NewType = C.getRecordType(RD); 11646 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 11647 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 11648 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 11649 } else { 11650 NewType = std::get<0>(VI->getSecond()); 11651 VDField = std::get<1>(VI->getSecond()); 11652 FiredField = std::get<2>(VI->getSecond()); 11653 BaseLVal = std::get<3>(VI->getSecond()); 11654 } 11655 LValue FiredLVal = 11656 CGF.EmitLValueForField(BaseLVal, FiredField); 11657 CGF.EmitStoreOfScalar( 11658 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 11659 FiredLVal); 11660 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 11661 } 11662 11663 namespace { 11664 /// Checks if the lastprivate conditional variable is referenced in LHS. 11665 class LastprivateConditionalRefChecker final 11666 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 11667 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 11668 const Expr *FoundE = nullptr; 11669 const Decl *FoundD = nullptr; 11670 StringRef UniqueDeclName; 11671 LValue IVLVal; 11672 llvm::Function *FoundFn = nullptr; 11673 SourceLocation Loc; 11674 11675 public: 11676 bool VisitDeclRefExpr(const DeclRefExpr *E) { 11677 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11678 llvm::reverse(LPM)) { 11679 auto It = D.DeclToUniqueName.find(E->getDecl()); 11680 if (It == D.DeclToUniqueName.end()) 11681 continue; 11682 if (D.Disabled) 11683 return false; 11684 FoundE = E; 11685 FoundD = E->getDecl()->getCanonicalDecl(); 11686 UniqueDeclName = It->second; 11687 IVLVal = D.IVLVal; 11688 FoundFn = D.Fn; 11689 break; 11690 } 11691 return FoundE == E; 11692 } 11693 bool VisitMemberExpr(const MemberExpr *E) { 11694 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 11695 return false; 11696 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11697 llvm::reverse(LPM)) { 11698 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 11699 if (It == D.DeclToUniqueName.end()) 11700 continue; 11701 if (D.Disabled) 11702 return false; 11703 FoundE = E; 11704 FoundD = E->getMemberDecl()->getCanonicalDecl(); 11705 UniqueDeclName = It->second; 11706 IVLVal = D.IVLVal; 11707 FoundFn = D.Fn; 11708 break; 11709 } 11710 return FoundE == E; 11711 } 11712 bool VisitStmt(const Stmt *S) { 11713 for (const Stmt *Child : S->children()) { 11714 if (!Child) 11715 continue; 11716 if (const auto *E = dyn_cast<Expr>(Child)) 11717 if (!E->isGLValue()) 11718 continue; 11719 if (Visit(Child)) 11720 return true; 11721 } 11722 return false; 11723 } 11724 explicit LastprivateConditionalRefChecker( 11725 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 11726 : LPM(LPM) {} 11727 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 11728 getFoundData() const { 11729 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 11730 } 11731 }; 11732 } // namespace 11733 11734 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 11735 LValue IVLVal, 11736 StringRef UniqueDeclName, 11737 LValue LVal, 11738 SourceLocation Loc) { 11739 // Last updated loop counter for the lastprivate conditional var. 11740 // int<xx> last_iv = 0; 11741 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 11742 llvm::Constant *LastIV = 11743 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 11744 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 11745 IVLVal.getAlignment().getAsAlign()); 11746 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 11747 11748 // Last value of the lastprivate conditional. 11749 // decltype(priv_a) last_a; 11750 llvm::Constant *Last = getOrCreateInternalVariable( 11751 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 11752 cast<llvm::GlobalVariable>(Last)->setAlignment( 11753 LVal.getAlignment().getAsAlign()); 11754 LValue LastLVal = 11755 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 11756 11757 // Global loop counter. Required to handle inner parallel-for regions. 11758 // iv 11759 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 11760 11761 // #pragma omp critical(a) 11762 // if (last_iv <= iv) { 11763 // last_iv = iv; 11764 // last_a = priv_a; 11765 // } 11766 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 11767 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 11768 Action.Enter(CGF); 11769 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 11770 // (last_iv <= iv) ? Check if the variable is updated and store new 11771 // value in global var. 11772 llvm::Value *CmpRes; 11773 if (IVLVal.getType()->isSignedIntegerType()) { 11774 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 11775 } else { 11776 assert(IVLVal.getType()->isUnsignedIntegerType() && 11777 "Loop iteration variable must be integer."); 11778 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 11779 } 11780 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 11781 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 11782 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 11783 // { 11784 CGF.EmitBlock(ThenBB); 11785 11786 // last_iv = iv; 11787 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 11788 11789 // last_a = priv_a; 11790 switch (CGF.getEvaluationKind(LVal.getType())) { 11791 case TEK_Scalar: { 11792 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 11793 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 11794 break; 11795 } 11796 case TEK_Complex: { 11797 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 11798 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 11799 break; 11800 } 11801 case TEK_Aggregate: 11802 llvm_unreachable( 11803 "Aggregates are not supported in lastprivate conditional."); 11804 } 11805 // } 11806 CGF.EmitBranch(ExitBB); 11807 // There is no need to emit line number for unconditional branch. 11808 (void)ApplyDebugLocation::CreateEmpty(CGF); 11809 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 11810 }; 11811 11812 if (CGM.getLangOpts().OpenMPSimd) { 11813 // Do not emit as a critical region as no parallel region could be emitted. 11814 RegionCodeGenTy ThenRCG(CodeGen); 11815 ThenRCG(CGF); 11816 } else { 11817 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 11818 } 11819 } 11820 11821 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 11822 const Expr *LHS) { 11823 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11824 return; 11825 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 11826 if (!Checker.Visit(LHS)) 11827 return; 11828 const Expr *FoundE; 11829 const Decl *FoundD; 11830 StringRef UniqueDeclName; 11831 LValue IVLVal; 11832 llvm::Function *FoundFn; 11833 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 11834 Checker.getFoundData(); 11835 if (FoundFn != CGF.CurFn) { 11836 // Special codegen for inner parallel regions. 11837 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 11838 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 11839 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 11840 "Lastprivate conditional is not found in outer region."); 11841 QualType StructTy = std::get<0>(It->getSecond()); 11842 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 11843 LValue PrivLVal = CGF.EmitLValue(FoundE); 11844 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11845 PrivLVal.getAddress(CGF), 11846 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 11847 LValue BaseLVal = 11848 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 11849 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 11850 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 11851 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 11852 FiredLVal, llvm::AtomicOrdering::Unordered, 11853 /*IsVolatile=*/true, /*isInit=*/false); 11854 return; 11855 } 11856 11857 // Private address of the lastprivate conditional in the current context. 11858 // priv_a 11859 LValue LVal = CGF.EmitLValue(FoundE); 11860 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 11861 FoundE->getExprLoc()); 11862 } 11863 11864 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 11865 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11866 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 11867 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11868 return; 11869 auto Range = llvm::reverse(LastprivateConditionalStack); 11870 auto It = llvm::find_if( 11871 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 11872 if (It == Range.end() || It->Fn != CGF.CurFn) 11873 return; 11874 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 11875 assert(LPCI != LastprivateConditionalToTypes.end() && 11876 "Lastprivates must be registered already."); 11877 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11878 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 11879 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 11880 for (const auto &Pair : It->DeclToUniqueName) { 11881 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 11882 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 11883 continue; 11884 auto I = LPCI->getSecond().find(Pair.first); 11885 assert(I != LPCI->getSecond().end() && 11886 "Lastprivate must be rehistered already."); 11887 // bool Cmp = priv_a.Fired != 0; 11888 LValue BaseLVal = std::get<3>(I->getSecond()); 11889 LValue FiredLVal = 11890 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 11891 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 11892 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 11893 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 11894 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 11895 // if (Cmp) { 11896 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 11897 CGF.EmitBlock(ThenBB); 11898 Address Addr = CGF.GetAddrOfLocalVar(VD); 11899 LValue LVal; 11900 if (VD->getType()->isReferenceType()) 11901 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 11902 AlignmentSource::Decl); 11903 else 11904 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 11905 AlignmentSource::Decl); 11906 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 11907 D.getBeginLoc()); 11908 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 11909 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 11910 // } 11911 } 11912 } 11913 11914 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 11915 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 11916 SourceLocation Loc) { 11917 if (CGF.getLangOpts().OpenMP < 50) 11918 return; 11919 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 11920 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 11921 "Unknown lastprivate conditional variable."); 11922 StringRef UniqueName = It->second; 11923 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 11924 // The variable was not updated in the region - exit. 11925 if (!GV) 11926 return; 11927 LValue LPLVal = CGF.MakeAddrLValue( 11928 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 11929 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 11930 CGF.EmitStoreOfScalar(Res, PrivLVal); 11931 } 11932 11933 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11934 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11935 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11936 llvm_unreachable("Not supported in SIMD-only mode"); 11937 } 11938 11939 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11940 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11941 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11942 llvm_unreachable("Not supported in SIMD-only mode"); 11943 } 11944 11945 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11946 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11947 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11948 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11949 bool Tied, unsigned &NumberOfParts) { 11950 llvm_unreachable("Not supported in SIMD-only mode"); 11951 } 11952 11953 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11954 SourceLocation Loc, 11955 llvm::Function *OutlinedFn, 11956 ArrayRef<llvm::Value *> CapturedVars, 11957 const Expr *IfCond) { 11958 llvm_unreachable("Not supported in SIMD-only mode"); 11959 } 11960 11961 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11962 CodeGenFunction &CGF, StringRef CriticalName, 11963 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11964 const Expr *Hint) { 11965 llvm_unreachable("Not supported in SIMD-only mode"); 11966 } 11967 11968 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11969 const RegionCodeGenTy &MasterOpGen, 11970 SourceLocation Loc) { 11971 llvm_unreachable("Not supported in SIMD-only mode"); 11972 } 11973 11974 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11975 SourceLocation Loc) { 11976 llvm_unreachable("Not supported in SIMD-only mode"); 11977 } 11978 11979 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11980 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11981 SourceLocation Loc) { 11982 llvm_unreachable("Not supported in SIMD-only mode"); 11983 } 11984 11985 void CGOpenMPSIMDRuntime::emitSingleRegion( 11986 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11987 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11988 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11989 ArrayRef<const Expr *> AssignmentOps) { 11990 llvm_unreachable("Not supported in SIMD-only mode"); 11991 } 11992 11993 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11994 const RegionCodeGenTy &OrderedOpGen, 11995 SourceLocation Loc, 11996 bool IsThreads) { 11997 llvm_unreachable("Not supported in SIMD-only mode"); 11998 } 11999 12000 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 12001 SourceLocation Loc, 12002 OpenMPDirectiveKind Kind, 12003 bool EmitChecks, 12004 bool ForceSimpleCall) { 12005 llvm_unreachable("Not supported in SIMD-only mode"); 12006 } 12007 12008 void CGOpenMPSIMDRuntime::emitForDispatchInit( 12009 CodeGenFunction &CGF, SourceLocation Loc, 12010 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 12011 bool Ordered, const DispatchRTInput &DispatchValues) { 12012 llvm_unreachable("Not supported in SIMD-only mode"); 12013 } 12014 12015 void CGOpenMPSIMDRuntime::emitForStaticInit( 12016 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 12017 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 12018 llvm_unreachable("Not supported in SIMD-only mode"); 12019 } 12020 12021 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 12022 CodeGenFunction &CGF, SourceLocation Loc, 12023 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 12024 llvm_unreachable("Not supported in SIMD-only mode"); 12025 } 12026 12027 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 12028 SourceLocation Loc, 12029 unsigned IVSize, 12030 bool IVSigned) { 12031 llvm_unreachable("Not supported in SIMD-only mode"); 12032 } 12033 12034 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 12035 SourceLocation Loc, 12036 OpenMPDirectiveKind DKind) { 12037 llvm_unreachable("Not supported in SIMD-only mode"); 12038 } 12039 12040 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 12041 SourceLocation Loc, 12042 unsigned IVSize, bool IVSigned, 12043 Address IL, Address LB, 12044 Address UB, Address ST) { 12045 llvm_unreachable("Not supported in SIMD-only mode"); 12046 } 12047 12048 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 12049 llvm::Value *NumThreads, 12050 SourceLocation Loc) { 12051 llvm_unreachable("Not supported in SIMD-only mode"); 12052 } 12053 12054 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 12055 ProcBindKind ProcBind, 12056 SourceLocation Loc) { 12057 llvm_unreachable("Not supported in SIMD-only mode"); 12058 } 12059 12060 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 12061 const VarDecl *VD, 12062 Address VDAddr, 12063 SourceLocation Loc) { 12064 llvm_unreachable("Not supported in SIMD-only mode"); 12065 } 12066 12067 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 12068 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 12069 CodeGenFunction *CGF) { 12070 llvm_unreachable("Not supported in SIMD-only mode"); 12071 } 12072 12073 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 12074 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 12075 llvm_unreachable("Not supported in SIMD-only mode"); 12076 } 12077 12078 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 12079 ArrayRef<const Expr *> Vars, 12080 SourceLocation Loc, 12081 llvm::AtomicOrdering AO) { 12082 llvm_unreachable("Not supported in SIMD-only mode"); 12083 } 12084 12085 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 12086 const OMPExecutableDirective &D, 12087 llvm::Function *TaskFunction, 12088 QualType SharedsTy, Address Shareds, 12089 const Expr *IfCond, 12090 const OMPTaskDataTy &Data) { 12091 llvm_unreachable("Not supported in SIMD-only mode"); 12092 } 12093 12094 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 12095 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 12096 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 12097 const Expr *IfCond, const OMPTaskDataTy &Data) { 12098 llvm_unreachable("Not supported in SIMD-only mode"); 12099 } 12100 12101 void CGOpenMPSIMDRuntime::emitReduction( 12102 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 12103 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 12104 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 12105 assert(Options.SimpleReduction && "Only simple reduction is expected."); 12106 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 12107 ReductionOps, Options); 12108 } 12109 12110 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 12111 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 12112 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 12113 llvm_unreachable("Not supported in SIMD-only mode"); 12114 } 12115 12116 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 12117 SourceLocation Loc, 12118 ReductionCodeGen &RCG, 12119 unsigned N) { 12120 llvm_unreachable("Not supported in SIMD-only mode"); 12121 } 12122 12123 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 12124 SourceLocation Loc, 12125 llvm::Value *ReductionsPtr, 12126 LValue SharedLVal) { 12127 llvm_unreachable("Not supported in SIMD-only mode"); 12128 } 12129 12130 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 12131 SourceLocation Loc) { 12132 llvm_unreachable("Not supported in SIMD-only mode"); 12133 } 12134 12135 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 12136 CodeGenFunction &CGF, SourceLocation Loc, 12137 OpenMPDirectiveKind CancelRegion) { 12138 llvm_unreachable("Not supported in SIMD-only mode"); 12139 } 12140 12141 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 12142 SourceLocation Loc, const Expr *IfCond, 12143 OpenMPDirectiveKind CancelRegion) { 12144 llvm_unreachable("Not supported in SIMD-only mode"); 12145 } 12146 12147 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 12148 const OMPExecutableDirective &D, StringRef ParentName, 12149 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 12150 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 12151 llvm_unreachable("Not supported in SIMD-only mode"); 12152 } 12153 12154 void CGOpenMPSIMDRuntime::emitTargetCall( 12155 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12156 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 12157 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 12158 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 12159 const OMPLoopDirective &D)> 12160 SizeEmitter) { 12161 llvm_unreachable("Not supported in SIMD-only mode"); 12162 } 12163 12164 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 12165 llvm_unreachable("Not supported in SIMD-only mode"); 12166 } 12167 12168 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 12169 llvm_unreachable("Not supported in SIMD-only mode"); 12170 } 12171 12172 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 12173 return false; 12174 } 12175 12176 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 12177 const OMPExecutableDirective &D, 12178 SourceLocation Loc, 12179 llvm::Function *OutlinedFn, 12180 ArrayRef<llvm::Value *> CapturedVars) { 12181 llvm_unreachable("Not supported in SIMD-only mode"); 12182 } 12183 12184 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 12185 const Expr *NumTeams, 12186 const Expr *ThreadLimit, 12187 SourceLocation Loc) { 12188 llvm_unreachable("Not supported in SIMD-only mode"); 12189 } 12190 12191 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 12192 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12193 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 12194 llvm_unreachable("Not supported in SIMD-only mode"); 12195 } 12196 12197 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 12198 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12199 const Expr *Device) { 12200 llvm_unreachable("Not supported in SIMD-only mode"); 12201 } 12202 12203 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 12204 const OMPLoopDirective &D, 12205 ArrayRef<Expr *> NumIterations) { 12206 llvm_unreachable("Not supported in SIMD-only mode"); 12207 } 12208 12209 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12210 const OMPDependClause *C) { 12211 llvm_unreachable("Not supported in SIMD-only mode"); 12212 } 12213 12214 const VarDecl * 12215 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 12216 const VarDecl *NativeParam) const { 12217 llvm_unreachable("Not supported in SIMD-only mode"); 12218 } 12219 12220 Address 12221 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 12222 const VarDecl *NativeParam, 12223 const VarDecl *TargetParam) const { 12224 llvm_unreachable("Not supported in SIMD-only mode"); 12225 } 12226