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 #include <numeric> 42 43 using namespace clang; 44 using namespace CodeGen; 45 using namespace llvm::omp; 46 47 namespace { 48 /// Base class for handling code generation inside OpenMP regions. 49 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 50 public: 51 /// Kinds of OpenMP regions used in codegen. 52 enum CGOpenMPRegionKind { 53 /// Region with outlined function for standalone 'parallel' 54 /// directive. 55 ParallelOutlinedRegion, 56 /// Region with outlined function for standalone 'task' directive. 57 TaskOutlinedRegion, 58 /// Region for constructs that do not require function outlining, 59 /// like 'for', 'sections', 'atomic' etc. directives. 60 InlinedRegion, 61 /// Region with outlined function for standalone 'target' directive. 62 TargetRegion, 63 }; 64 65 CGOpenMPRegionInfo(const CapturedStmt &CS, 66 const CGOpenMPRegionKind RegionKind, 67 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 68 bool HasCancel) 69 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 70 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 71 72 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 73 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 74 bool HasCancel) 75 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 76 Kind(Kind), HasCancel(HasCancel) {} 77 78 /// Get a variable or parameter for storing global thread id 79 /// inside OpenMP construct. 80 virtual const VarDecl *getThreadIDVariable() const = 0; 81 82 /// Emit the captured statement body. 83 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 84 85 /// Get an LValue for the current ThreadID variable. 86 /// \return LValue for thread id variable. This LValue always has type int32*. 87 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 88 89 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 90 91 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 92 93 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 94 95 bool hasCancel() const { return HasCancel; } 96 97 static bool classof(const CGCapturedStmtInfo *Info) { 98 return Info->getKind() == CR_OpenMP; 99 } 100 101 ~CGOpenMPRegionInfo() override = default; 102 103 protected: 104 CGOpenMPRegionKind RegionKind; 105 RegionCodeGenTy CodeGen; 106 OpenMPDirectiveKind Kind; 107 bool HasCancel; 108 }; 109 110 /// API for captured statement code generation in OpenMP constructs. 111 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 112 public: 113 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 114 const RegionCodeGenTy &CodeGen, 115 OpenMPDirectiveKind Kind, bool HasCancel, 116 StringRef HelperName) 117 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 118 HasCancel), 119 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 120 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 121 } 122 123 /// Get a variable or parameter for storing global thread id 124 /// inside OpenMP construct. 125 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 126 127 /// Get the name of the capture helper. 128 StringRef getHelperName() const override { return HelperName; } 129 130 static bool classof(const CGCapturedStmtInfo *Info) { 131 return CGOpenMPRegionInfo::classof(Info) && 132 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 133 ParallelOutlinedRegion; 134 } 135 136 private: 137 /// A variable or parameter storing global thread id for OpenMP 138 /// constructs. 139 const VarDecl *ThreadIDVar; 140 StringRef HelperName; 141 }; 142 143 /// API for captured statement code generation in OpenMP constructs. 144 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 145 public: 146 class UntiedTaskActionTy final : public PrePostActionTy { 147 bool Untied; 148 const VarDecl *PartIDVar; 149 const RegionCodeGenTy UntiedCodeGen; 150 llvm::SwitchInst *UntiedSwitch = nullptr; 151 152 public: 153 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 154 const RegionCodeGenTy &UntiedCodeGen) 155 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 156 void Enter(CodeGenFunction &CGF) override { 157 if (Untied) { 158 // Emit task switching point. 159 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 160 CGF.GetAddrOfLocalVar(PartIDVar), 161 PartIDVar->getType()->castAs<PointerType>()); 162 llvm::Value *Res = 163 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 164 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 165 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 166 CGF.EmitBlock(DoneBB); 167 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 168 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 169 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 170 CGF.Builder.GetInsertBlock()); 171 emitUntiedSwitch(CGF); 172 } 173 } 174 void emitUntiedSwitch(CodeGenFunction &CGF) const { 175 if (Untied) { 176 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 177 CGF.GetAddrOfLocalVar(PartIDVar), 178 PartIDVar->getType()->castAs<PointerType>()); 179 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 180 PartIdLVal); 181 UntiedCodeGen(CGF); 182 CodeGenFunction::JumpDest CurPoint = 183 CGF.getJumpDestInCurrentScope(".untied.next."); 184 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 185 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 186 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 187 CGF.Builder.GetInsertBlock()); 188 CGF.EmitBranchThroughCleanup(CurPoint); 189 CGF.EmitBlock(CurPoint.getBlock()); 190 } 191 } 192 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 193 }; 194 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 195 const VarDecl *ThreadIDVar, 196 const RegionCodeGenTy &CodeGen, 197 OpenMPDirectiveKind Kind, bool HasCancel, 198 const UntiedTaskActionTy &Action) 199 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 200 ThreadIDVar(ThreadIDVar), Action(Action) { 201 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 202 } 203 204 /// Get a variable or parameter for storing global thread id 205 /// inside OpenMP construct. 206 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 207 208 /// Get an LValue for the current ThreadID variable. 209 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 210 211 /// Get the name of the capture helper. 212 StringRef getHelperName() const override { return ".omp_outlined."; } 213 214 void emitUntiedSwitch(CodeGenFunction &CGF) override { 215 Action.emitUntiedSwitch(CGF); 216 } 217 218 static bool classof(const CGCapturedStmtInfo *Info) { 219 return CGOpenMPRegionInfo::classof(Info) && 220 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 221 TaskOutlinedRegion; 222 } 223 224 private: 225 /// A variable or parameter storing global thread id for OpenMP 226 /// constructs. 227 const VarDecl *ThreadIDVar; 228 /// Action for emitting code for untied tasks. 229 const UntiedTaskActionTy &Action; 230 }; 231 232 /// API for inlined captured statement code generation in OpenMP 233 /// constructs. 234 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 235 public: 236 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 237 const RegionCodeGenTy &CodeGen, 238 OpenMPDirectiveKind Kind, bool HasCancel) 239 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 240 OldCSI(OldCSI), 241 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 242 243 // Retrieve the value of the context parameter. 244 llvm::Value *getContextValue() const override { 245 if (OuterRegionInfo) 246 return OuterRegionInfo->getContextValue(); 247 llvm_unreachable("No context value for inlined OpenMP region"); 248 } 249 250 void setContextValue(llvm::Value *V) override { 251 if (OuterRegionInfo) { 252 OuterRegionInfo->setContextValue(V); 253 return; 254 } 255 llvm_unreachable("No context value for inlined OpenMP region"); 256 } 257 258 /// Lookup the captured field decl for a variable. 259 const FieldDecl *lookup(const VarDecl *VD) const override { 260 if (OuterRegionInfo) 261 return OuterRegionInfo->lookup(VD); 262 // If there is no outer outlined region,no need to lookup in a list of 263 // captured variables, we can use the original one. 264 return nullptr; 265 } 266 267 FieldDecl *getThisFieldDecl() const override { 268 if (OuterRegionInfo) 269 return OuterRegionInfo->getThisFieldDecl(); 270 return nullptr; 271 } 272 273 /// Get a variable or parameter for storing global thread id 274 /// inside OpenMP construct. 275 const VarDecl *getThreadIDVariable() const override { 276 if (OuterRegionInfo) 277 return OuterRegionInfo->getThreadIDVariable(); 278 return nullptr; 279 } 280 281 /// Get an LValue for the current ThreadID variable. 282 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 283 if (OuterRegionInfo) 284 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 285 llvm_unreachable("No LValue for inlined OpenMP construct"); 286 } 287 288 /// Get the name of the capture helper. 289 StringRef getHelperName() const override { 290 if (auto *OuterRegionInfo = getOldCSI()) 291 return OuterRegionInfo->getHelperName(); 292 llvm_unreachable("No helper name for inlined OpenMP construct"); 293 } 294 295 void emitUntiedSwitch(CodeGenFunction &CGF) override { 296 if (OuterRegionInfo) 297 OuterRegionInfo->emitUntiedSwitch(CGF); 298 } 299 300 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 301 302 static bool classof(const CGCapturedStmtInfo *Info) { 303 return CGOpenMPRegionInfo::classof(Info) && 304 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 305 } 306 307 ~CGOpenMPInlinedRegionInfo() override = default; 308 309 private: 310 /// CodeGen info about outer OpenMP region. 311 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 312 CGOpenMPRegionInfo *OuterRegionInfo; 313 }; 314 315 /// API for captured statement code generation in OpenMP target 316 /// constructs. For this captures, implicit parameters are used instead of the 317 /// captured fields. The name of the target region has to be unique in a given 318 /// application so it is provided by the client, because only the client has 319 /// the information to generate that. 320 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 321 public: 322 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 323 const RegionCodeGenTy &CodeGen, StringRef HelperName) 324 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 325 /*HasCancel=*/false), 326 HelperName(HelperName) {} 327 328 /// This is unused for target regions because each starts executing 329 /// with a single thread. 330 const VarDecl *getThreadIDVariable() const override { return nullptr; } 331 332 /// Get the name of the capture helper. 333 StringRef getHelperName() const override { return HelperName; } 334 335 static bool classof(const CGCapturedStmtInfo *Info) { 336 return CGOpenMPRegionInfo::classof(Info) && 337 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 338 } 339 340 private: 341 StringRef HelperName; 342 }; 343 344 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 345 llvm_unreachable("No codegen for expressions"); 346 } 347 /// API for generation of expressions captured in a innermost OpenMP 348 /// region. 349 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 350 public: 351 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 352 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 353 OMPD_unknown, 354 /*HasCancel=*/false), 355 PrivScope(CGF) { 356 // Make sure the globals captured in the provided statement are local by 357 // using the privatization logic. We assume the same variable is not 358 // captured more than once. 359 for (const auto &C : CS.captures()) { 360 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 361 continue; 362 363 const VarDecl *VD = C.getCapturedVar(); 364 if (VD->isLocalVarDeclOrParm()) 365 continue; 366 367 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 368 /*RefersToEnclosingVariableOrCapture=*/false, 369 VD->getType().getNonReferenceType(), VK_LValue, 370 C.getLocation()); 371 PrivScope.addPrivate( 372 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 373 } 374 (void)PrivScope.Privatize(); 375 } 376 377 /// Lookup the captured field decl for a variable. 378 const FieldDecl *lookup(const VarDecl *VD) const override { 379 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 380 return FD; 381 return nullptr; 382 } 383 384 /// Emit the captured statement body. 385 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 386 llvm_unreachable("No body for expressions"); 387 } 388 389 /// Get a variable or parameter for storing global thread id 390 /// inside OpenMP construct. 391 const VarDecl *getThreadIDVariable() const override { 392 llvm_unreachable("No thread id for expressions"); 393 } 394 395 /// Get the name of the capture helper. 396 StringRef getHelperName() const override { 397 llvm_unreachable("No helper name for expressions"); 398 } 399 400 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 401 402 private: 403 /// Private scope to capture global variables. 404 CodeGenFunction::OMPPrivateScope PrivScope; 405 }; 406 407 /// RAII for emitting code of OpenMP constructs. 408 class InlinedOpenMPRegionRAII { 409 CodeGenFunction &CGF; 410 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 411 FieldDecl *LambdaThisCaptureField = nullptr; 412 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 413 414 public: 415 /// Constructs region for combined constructs. 416 /// \param CodeGen Code generation sequence for combined directives. Includes 417 /// a list of functions used for code generation of implicitly inlined 418 /// regions. 419 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 420 OpenMPDirectiveKind Kind, bool HasCancel) 421 : CGF(CGF) { 422 // Start emission for the construct. 423 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 424 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 425 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 426 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 427 CGF.LambdaThisCaptureField = nullptr; 428 BlockInfo = CGF.BlockInfo; 429 CGF.BlockInfo = nullptr; 430 } 431 432 ~InlinedOpenMPRegionRAII() { 433 // Restore original CapturedStmtInfo only if we're done with code emission. 434 auto *OldCSI = 435 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 436 delete CGF.CapturedStmtInfo; 437 CGF.CapturedStmtInfo = OldCSI; 438 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 439 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 440 CGF.BlockInfo = BlockInfo; 441 } 442 }; 443 444 /// Values for bit flags used in the ident_t to describe the fields. 445 /// All enumeric elements are named and described in accordance with the code 446 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 447 enum OpenMPLocationFlags : unsigned { 448 /// Use trampoline for internal microtask. 449 OMP_IDENT_IMD = 0x01, 450 /// Use c-style ident structure. 451 OMP_IDENT_KMPC = 0x02, 452 /// Atomic reduction option for kmpc_reduce. 453 OMP_ATOMIC_REDUCE = 0x10, 454 /// Explicit 'barrier' directive. 455 OMP_IDENT_BARRIER_EXPL = 0x20, 456 /// Implicit barrier in code. 457 OMP_IDENT_BARRIER_IMPL = 0x40, 458 /// Implicit barrier in 'for' directive. 459 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 460 /// Implicit barrier in 'sections' directive. 461 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 462 /// Implicit barrier in 'single' directive. 463 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 464 /// Call of __kmp_for_static_init for static loop. 465 OMP_IDENT_WORK_LOOP = 0x200, 466 /// Call of __kmp_for_static_init for sections. 467 OMP_IDENT_WORK_SECTIONS = 0x400, 468 /// Call of __kmp_for_static_init for distribute. 469 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 470 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 471 }; 472 473 namespace { 474 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 475 /// Values for bit flags for marking which requires clauses have been used. 476 enum OpenMPOffloadingRequiresDirFlags : int64_t { 477 /// flag undefined. 478 OMP_REQ_UNDEFINED = 0x000, 479 /// no requires clause present. 480 OMP_REQ_NONE = 0x001, 481 /// reverse_offload clause. 482 OMP_REQ_REVERSE_OFFLOAD = 0x002, 483 /// unified_address clause. 484 OMP_REQ_UNIFIED_ADDRESS = 0x004, 485 /// unified_shared_memory clause. 486 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 487 /// dynamic_allocators clause. 488 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 489 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 490 }; 491 492 enum OpenMPOffloadingReservedDeviceIDs { 493 /// Device ID if the device was not defined, runtime should get it 494 /// from environment variables in the spec. 495 OMP_DEVICEID_UNDEF = -1, 496 }; 497 } // anonymous namespace 498 499 /// Describes ident structure that describes a source location. 500 /// All descriptions are taken from 501 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 502 /// Original structure: 503 /// typedef struct ident { 504 /// kmp_int32 reserved_1; /**< might be used in Fortran; 505 /// see above */ 506 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 507 /// KMP_IDENT_KMPC identifies this union 508 /// member */ 509 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 510 /// see above */ 511 ///#if USE_ITT_BUILD 512 /// /* but currently used for storing 513 /// region-specific ITT */ 514 /// /* contextual information. */ 515 ///#endif /* USE_ITT_BUILD */ 516 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 517 /// C++ */ 518 /// char const *psource; /**< String describing the source location. 519 /// The string is composed of semi-colon separated 520 // fields which describe the source file, 521 /// the function and a pair of line numbers that 522 /// delimit the construct. 523 /// */ 524 /// } ident_t; 525 enum IdentFieldIndex { 526 /// might be used in Fortran 527 IdentField_Reserved_1, 528 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 529 IdentField_Flags, 530 /// Not really used in Fortran any more 531 IdentField_Reserved_2, 532 /// Source[4] in Fortran, do not use for C++ 533 IdentField_Reserved_3, 534 /// String describing the source location. The string is composed of 535 /// semi-colon separated fields which describe the source file, the function 536 /// and a pair of line numbers that delimit the construct. 537 IdentField_PSource 538 }; 539 540 /// Schedule types for 'omp for' loops (these enumerators are taken from 541 /// the enum sched_type in kmp.h). 542 enum OpenMPSchedType { 543 /// Lower bound for default (unordered) versions. 544 OMP_sch_lower = 32, 545 OMP_sch_static_chunked = 33, 546 OMP_sch_static = 34, 547 OMP_sch_dynamic_chunked = 35, 548 OMP_sch_guided_chunked = 36, 549 OMP_sch_runtime = 37, 550 OMP_sch_auto = 38, 551 /// static with chunk adjustment (e.g., simd) 552 OMP_sch_static_balanced_chunked = 45, 553 /// Lower bound for 'ordered' versions. 554 OMP_ord_lower = 64, 555 OMP_ord_static_chunked = 65, 556 OMP_ord_static = 66, 557 OMP_ord_dynamic_chunked = 67, 558 OMP_ord_guided_chunked = 68, 559 OMP_ord_runtime = 69, 560 OMP_ord_auto = 70, 561 OMP_sch_default = OMP_sch_static, 562 /// dist_schedule types 563 OMP_dist_sch_static_chunked = 91, 564 OMP_dist_sch_static = 92, 565 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 566 /// Set if the monotonic schedule modifier was present. 567 OMP_sch_modifier_monotonic = (1 << 29), 568 /// Set if the nonmonotonic schedule modifier was present. 569 OMP_sch_modifier_nonmonotonic = (1 << 30), 570 }; 571 572 enum OpenMPRTLFunction { 573 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 574 /// kmpc_micro microtask, ...); 575 OMPRTL__kmpc_fork_call, 576 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 577 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 578 OMPRTL__kmpc_threadprivate_cached, 579 /// Call to void __kmpc_threadprivate_register( ident_t *, 580 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 581 OMPRTL__kmpc_threadprivate_register, 582 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 583 OMPRTL__kmpc_global_thread_num, 584 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 585 // kmp_critical_name *crit); 586 OMPRTL__kmpc_critical, 587 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 588 // global_tid, kmp_critical_name *crit, uintptr_t hint); 589 OMPRTL__kmpc_critical_with_hint, 590 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 591 // kmp_critical_name *crit); 592 OMPRTL__kmpc_end_critical, 593 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 594 // global_tid); 595 OMPRTL__kmpc_cancel_barrier, 596 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 597 OMPRTL__kmpc_barrier, 598 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 599 OMPRTL__kmpc_for_static_fini, 600 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 601 // global_tid); 602 OMPRTL__kmpc_serialized_parallel, 603 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 604 // global_tid); 605 OMPRTL__kmpc_end_serialized_parallel, 606 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 607 // kmp_int32 num_threads); 608 OMPRTL__kmpc_push_num_threads, 609 // Call to void __kmpc_flush(ident_t *loc); 610 OMPRTL__kmpc_flush, 611 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 612 OMPRTL__kmpc_master, 613 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 614 OMPRTL__kmpc_end_master, 615 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 616 // int end_part); 617 OMPRTL__kmpc_omp_taskyield, 618 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 619 OMPRTL__kmpc_single, 620 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 621 OMPRTL__kmpc_end_single, 622 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 623 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 624 // kmp_routine_entry_t *task_entry); 625 OMPRTL__kmpc_omp_task_alloc, 626 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 627 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 628 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 629 // kmp_int64 device_id); 630 OMPRTL__kmpc_omp_target_task_alloc, 631 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 632 // new_task); 633 OMPRTL__kmpc_omp_task, 634 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 635 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 636 // kmp_int32 didit); 637 OMPRTL__kmpc_copyprivate, 638 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 639 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 640 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 641 OMPRTL__kmpc_reduce, 642 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 643 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 644 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 645 // *lck); 646 OMPRTL__kmpc_reduce_nowait, 647 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 648 // kmp_critical_name *lck); 649 OMPRTL__kmpc_end_reduce, 650 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 651 // kmp_critical_name *lck); 652 OMPRTL__kmpc_end_reduce_nowait, 653 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 654 // kmp_task_t * new_task); 655 OMPRTL__kmpc_omp_task_begin_if0, 656 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 657 // kmp_task_t * new_task); 658 OMPRTL__kmpc_omp_task_complete_if0, 659 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 660 OMPRTL__kmpc_ordered, 661 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 662 OMPRTL__kmpc_end_ordered, 663 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 664 // global_tid); 665 OMPRTL__kmpc_omp_taskwait, 666 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 667 OMPRTL__kmpc_taskgroup, 668 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 669 OMPRTL__kmpc_end_taskgroup, 670 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 671 // int proc_bind); 672 OMPRTL__kmpc_push_proc_bind, 673 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 674 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 675 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 676 OMPRTL__kmpc_omp_task_with_deps, 677 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 678 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 679 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 680 OMPRTL__kmpc_omp_wait_deps, 681 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 682 // global_tid, kmp_int32 cncl_kind); 683 OMPRTL__kmpc_cancellationpoint, 684 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 685 // kmp_int32 cncl_kind); 686 OMPRTL__kmpc_cancel, 687 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 688 // kmp_int32 num_teams, kmp_int32 thread_limit); 689 OMPRTL__kmpc_push_num_teams, 690 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 691 // microtask, ...); 692 OMPRTL__kmpc_fork_teams, 693 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 694 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 695 // sched, kmp_uint64 grainsize, void *task_dup); 696 OMPRTL__kmpc_taskloop, 697 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 698 // num_dims, struct kmp_dim *dims); 699 OMPRTL__kmpc_doacross_init, 700 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 701 OMPRTL__kmpc_doacross_fini, 702 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 703 // *vec); 704 OMPRTL__kmpc_doacross_post, 705 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 706 // *vec); 707 OMPRTL__kmpc_doacross_wait, 708 // Call to void *__kmpc_taskred_init(int gtid, int num_data, void *data); 709 OMPRTL__kmpc_taskred_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 *> Origs, 984 ArrayRef<const Expr *> Privates, 985 ArrayRef<const Expr *> ReductionOps) { 986 ClausesData.reserve(Shareds.size()); 987 SharedAddresses.reserve(Shareds.size()); 988 Sizes.reserve(Shareds.size()); 989 BaseDecls.reserve(Shareds.size()); 990 const auto *IOrig = Origs.begin(); 991 const auto *IPriv = Privates.begin(); 992 const auto *IRed = ReductionOps.begin(); 993 for (const Expr *Ref : Shareds) { 994 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed); 995 std::advance(IOrig, 1); 996 std::advance(IPriv, 1); 997 std::advance(IRed, 1); 998 } 999 } 1000 1001 void ReductionCodeGen::emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N) { 1002 assert(SharedAddresses.size() == N && OrigAddresses.size() == N && 1003 "Number of generated lvalues must be exactly N."); 1004 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared); 1005 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared); 1006 SharedAddresses.emplace_back(First, Second); 1007 if (ClausesData[N].Shared == ClausesData[N].Ref) { 1008 OrigAddresses.emplace_back(First, Second); 1009 } else { 1010 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 1011 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 1012 OrigAddresses.emplace_back(First, Second); 1013 } 1014 } 1015 1016 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 1017 const auto *PrivateVD = 1018 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1019 QualType PrivateType = PrivateVD->getType(); 1020 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1021 if (!PrivateType->isVariablyModifiedType()) { 1022 Sizes.emplace_back( 1023 CGF.getTypeSize( 1024 SharedAddresses[N].first.getType().getNonReferenceType()), 1025 nullptr); 1026 return; 1027 } 1028 llvm::Value *Size; 1029 llvm::Value *SizeInChars; 1030 auto *ElemType = cast<llvm::PointerType>( 1031 SharedAddresses[N].first.getPointer(CGF)->getType()) 1032 ->getElementType(); 1033 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1034 if (AsArraySection) { 1035 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF), 1036 SharedAddresses[N].first.getPointer(CGF)); 1037 Size = CGF.Builder.CreateNUWAdd( 1038 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1039 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1040 } else { 1041 SizeInChars = CGF.getTypeSize( 1042 SharedAddresses[N].first.getType().getNonReferenceType()); 1043 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1044 } 1045 Sizes.emplace_back(SizeInChars, Size); 1046 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1047 CGF, 1048 cast<OpaqueValueExpr>( 1049 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1050 RValue::get(Size)); 1051 CGF.EmitVariablyModifiedType(PrivateType); 1052 } 1053 1054 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1055 llvm::Value *Size) { 1056 const auto *PrivateVD = 1057 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1058 QualType PrivateType = PrivateVD->getType(); 1059 if (!PrivateType->isVariablyModifiedType()) { 1060 assert(!Size && !Sizes[N].second && 1061 "Size should be nullptr for non-variably modified reduction " 1062 "items."); 1063 return; 1064 } 1065 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1066 CGF, 1067 cast<OpaqueValueExpr>( 1068 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1069 RValue::get(Size)); 1070 CGF.EmitVariablyModifiedType(PrivateType); 1071 } 1072 1073 void ReductionCodeGen::emitInitialization( 1074 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1075 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1076 assert(SharedAddresses.size() > N && "No variable was generated"); 1077 const auto *PrivateVD = 1078 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1079 const OMPDeclareReductionDecl *DRD = 1080 getReductionInit(ClausesData[N].ReductionOp); 1081 QualType PrivateType = PrivateVD->getType(); 1082 PrivateAddr = CGF.Builder.CreateElementBitCast( 1083 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1084 QualType SharedType = SharedAddresses[N].first.getType(); 1085 SharedLVal = CGF.MakeAddrLValue( 1086 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 1087 CGF.ConvertTypeForMem(SharedType)), 1088 SharedType, SharedAddresses[N].first.getBaseInfo(), 1089 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1090 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1091 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1092 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1093 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1094 PrivateAddr, SharedLVal.getAddress(CGF), 1095 SharedLVal.getType()); 1096 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1097 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1098 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1099 PrivateVD->getType().getQualifiers(), 1100 /*IsInitializer=*/false); 1101 } 1102 } 1103 1104 bool ReductionCodeGen::needCleanups(unsigned N) { 1105 const auto *PrivateVD = 1106 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1107 QualType PrivateType = PrivateVD->getType(); 1108 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1109 return DTorKind != QualType::DK_none; 1110 } 1111 1112 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1113 Address PrivateAddr) { 1114 const auto *PrivateVD = 1115 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1116 QualType PrivateType = PrivateVD->getType(); 1117 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1118 if (needCleanups(N)) { 1119 PrivateAddr = CGF.Builder.CreateElementBitCast( 1120 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1121 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1122 } 1123 } 1124 1125 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1126 LValue BaseLV) { 1127 BaseTy = BaseTy.getNonReferenceType(); 1128 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1129 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1130 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1131 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 1132 } else { 1133 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 1134 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1135 } 1136 BaseTy = BaseTy->getPointeeType(); 1137 } 1138 return CGF.MakeAddrLValue( 1139 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 1140 CGF.ConvertTypeForMem(ElTy)), 1141 BaseLV.getType(), BaseLV.getBaseInfo(), 1142 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1143 } 1144 1145 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1146 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1147 llvm::Value *Addr) { 1148 Address Tmp = Address::invalid(); 1149 Address TopTmp = Address::invalid(); 1150 Address MostTopTmp = Address::invalid(); 1151 BaseTy = BaseTy.getNonReferenceType(); 1152 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1153 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1154 Tmp = CGF.CreateMemTemp(BaseTy); 1155 if (TopTmp.isValid()) 1156 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1157 else 1158 MostTopTmp = Tmp; 1159 TopTmp = Tmp; 1160 BaseTy = BaseTy->getPointeeType(); 1161 } 1162 llvm::Type *Ty = BaseLVType; 1163 if (Tmp.isValid()) 1164 Ty = Tmp.getElementType(); 1165 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1166 if (Tmp.isValid()) { 1167 CGF.Builder.CreateStore(Addr, Tmp); 1168 return MostTopTmp; 1169 } 1170 return Address(Addr, BaseLVAlignment); 1171 } 1172 1173 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1174 const VarDecl *OrigVD = nullptr; 1175 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1176 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1177 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1178 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1179 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1180 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1181 DE = cast<DeclRefExpr>(Base); 1182 OrigVD = cast<VarDecl>(DE->getDecl()); 1183 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1184 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1185 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1186 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1187 DE = cast<DeclRefExpr>(Base); 1188 OrigVD = cast<VarDecl>(DE->getDecl()); 1189 } 1190 return OrigVD; 1191 } 1192 1193 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1194 Address PrivateAddr) { 1195 const DeclRefExpr *DE; 1196 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1197 BaseDecls.emplace_back(OrigVD); 1198 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1199 LValue BaseLValue = 1200 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1201 OriginalBaseLValue); 1202 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1203 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1204 llvm::Value *PrivatePointer = 1205 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1206 PrivateAddr.getPointer(), 1207 SharedAddresses[N].first.getAddress(CGF).getType()); 1208 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1209 return castToBase(CGF, OrigVD->getType(), 1210 SharedAddresses[N].first.getType(), 1211 OriginalBaseLValue.getAddress(CGF).getType(), 1212 OriginalBaseLValue.getAlignment(), Ptr); 1213 } 1214 BaseDecls.emplace_back( 1215 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1216 return PrivateAddr; 1217 } 1218 1219 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1220 const OMPDeclareReductionDecl *DRD = 1221 getReductionInit(ClausesData[N].ReductionOp); 1222 return DRD && DRD->getInitializer(); 1223 } 1224 1225 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1226 return CGF.EmitLoadOfPointerLValue( 1227 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1228 getThreadIDVariable()->getType()->castAs<PointerType>()); 1229 } 1230 1231 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1232 if (!CGF.HaveInsertPoint()) 1233 return; 1234 // 1.2.2 OpenMP Language Terminology 1235 // Structured block - An executable statement with a single entry at the 1236 // top and a single exit at the bottom. 1237 // The point of exit cannot be a branch out of the structured block. 1238 // longjmp() and throw() must not violate the entry/exit criteria. 1239 CGF.EHStack.pushTerminate(); 1240 CodeGen(CGF); 1241 CGF.EHStack.popTerminate(); 1242 } 1243 1244 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1245 CodeGenFunction &CGF) { 1246 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1247 getThreadIDVariable()->getType(), 1248 AlignmentSource::Decl); 1249 } 1250 1251 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1252 QualType FieldTy) { 1253 auto *Field = FieldDecl::Create( 1254 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1255 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1256 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1257 Field->setAccess(AS_public); 1258 DC->addDecl(Field); 1259 return Field; 1260 } 1261 1262 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1263 StringRef Separator) 1264 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1265 OffloadEntriesInfoManager(CGM) { 1266 ASTContext &C = CGM.getContext(); 1267 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1268 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1269 RD->startDefinition(); 1270 // reserved_1 1271 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1272 // flags 1273 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1274 // reserved_2 1275 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1276 // reserved_3 1277 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1278 // psource 1279 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1280 RD->completeDefinition(); 1281 IdentQTy = C.getRecordType(RD); 1282 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1283 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1284 1285 loadOffloadInfoMetadata(); 1286 } 1287 1288 void CGOpenMPRuntime::clear() { 1289 InternalVars.clear(); 1290 // Clean non-target variable declarations possibly used only in debug info. 1291 for (const auto &Data : EmittedNonTargetVariables) { 1292 if (!Data.getValue().pointsToAliveValue()) 1293 continue; 1294 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1295 if (!GV) 1296 continue; 1297 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1298 continue; 1299 GV->eraseFromParent(); 1300 } 1301 } 1302 1303 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1304 SmallString<128> Buffer; 1305 llvm::raw_svector_ostream OS(Buffer); 1306 StringRef Sep = FirstSeparator; 1307 for (StringRef Part : Parts) { 1308 OS << Sep << Part; 1309 Sep = Separator; 1310 } 1311 return std::string(OS.str()); 1312 } 1313 1314 static llvm::Function * 1315 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1316 const Expr *CombinerInitializer, const VarDecl *In, 1317 const VarDecl *Out, bool IsCombiner) { 1318 // void .omp_combiner.(Ty *in, Ty *out); 1319 ASTContext &C = CGM.getContext(); 1320 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1321 FunctionArgList Args; 1322 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1323 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1324 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1325 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1326 Args.push_back(&OmpOutParm); 1327 Args.push_back(&OmpInParm); 1328 const CGFunctionInfo &FnInfo = 1329 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1330 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1331 std::string Name = CGM.getOpenMPRuntime().getName( 1332 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1333 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1334 Name, &CGM.getModule()); 1335 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1336 if (CGM.getLangOpts().Optimize) { 1337 Fn->removeFnAttr(llvm::Attribute::NoInline); 1338 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1339 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1340 } 1341 CodeGenFunction CGF(CGM); 1342 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1343 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1344 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1345 Out->getLocation()); 1346 CodeGenFunction::OMPPrivateScope Scope(CGF); 1347 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1348 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1349 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1350 .getAddress(CGF); 1351 }); 1352 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1353 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1354 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1355 .getAddress(CGF); 1356 }); 1357 (void)Scope.Privatize(); 1358 if (!IsCombiner && Out->hasInit() && 1359 !CGF.isTrivialInitializer(Out->getInit())) { 1360 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1361 Out->getType().getQualifiers(), 1362 /*IsInitializer=*/true); 1363 } 1364 if (CombinerInitializer) 1365 CGF.EmitIgnoredExpr(CombinerInitializer); 1366 Scope.ForceCleanup(); 1367 CGF.FinishFunction(); 1368 return Fn; 1369 } 1370 1371 void CGOpenMPRuntime::emitUserDefinedReduction( 1372 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1373 if (UDRMap.count(D) > 0) 1374 return; 1375 llvm::Function *Combiner = emitCombinerOrInitializer( 1376 CGM, D->getType(), D->getCombiner(), 1377 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1378 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1379 /*IsCombiner=*/true); 1380 llvm::Function *Initializer = nullptr; 1381 if (const Expr *Init = D->getInitializer()) { 1382 Initializer = emitCombinerOrInitializer( 1383 CGM, D->getType(), 1384 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1385 : nullptr, 1386 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1387 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1388 /*IsCombiner=*/false); 1389 } 1390 UDRMap.try_emplace(D, Combiner, Initializer); 1391 if (CGF) { 1392 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1393 Decls.second.push_back(D); 1394 } 1395 } 1396 1397 std::pair<llvm::Function *, llvm::Function *> 1398 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1399 auto I = UDRMap.find(D); 1400 if (I != UDRMap.end()) 1401 return I->second; 1402 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1403 return UDRMap.lookup(D); 1404 } 1405 1406 namespace { 1407 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1408 // Builder if one is present. 1409 struct PushAndPopStackRAII { 1410 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1411 bool HasCancel) 1412 : OMPBuilder(OMPBuilder) { 1413 if (!OMPBuilder) 1414 return; 1415 1416 // The following callback is the crucial part of clangs cleanup process. 1417 // 1418 // NOTE: 1419 // Once the OpenMPIRBuilder is used to create parallel regions (and 1420 // similar), the cancellation destination (Dest below) is determined via 1421 // IP. That means if we have variables to finalize we split the block at IP, 1422 // use the new block (=BB) as destination to build a JumpDest (via 1423 // getJumpDestInCurrentScope(BB)) which then is fed to 1424 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1425 // to push & pop an FinalizationInfo object. 1426 // The FiniCB will still be needed but at the point where the 1427 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1428 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1429 assert(IP.getBlock()->end() == IP.getPoint() && 1430 "Clang CG should cause non-terminated block!"); 1431 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1432 CGF.Builder.restoreIP(IP); 1433 CodeGenFunction::JumpDest Dest = 1434 CGF.getOMPCancelDestination(OMPD_parallel); 1435 CGF.EmitBranchThroughCleanup(Dest); 1436 }; 1437 1438 // TODO: Remove this once we emit parallel regions through the 1439 // OpenMPIRBuilder as it can do this setup internally. 1440 llvm::OpenMPIRBuilder::FinalizationInfo FI( 1441 {FiniCB, OMPD_parallel, HasCancel}); 1442 OMPBuilder->pushFinalizationCB(std::move(FI)); 1443 } 1444 ~PushAndPopStackRAII() { 1445 if (OMPBuilder) 1446 OMPBuilder->popFinalizationCB(); 1447 } 1448 llvm::OpenMPIRBuilder *OMPBuilder; 1449 }; 1450 } // namespace 1451 1452 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1453 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1454 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1455 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1456 assert(ThreadIDVar->getType()->isPointerType() && 1457 "thread id variable must be of type kmp_int32 *"); 1458 CodeGenFunction CGF(CGM, true); 1459 bool HasCancel = false; 1460 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1461 HasCancel = OPD->hasCancel(); 1462 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1463 HasCancel = OPSD->hasCancel(); 1464 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1465 HasCancel = OPFD->hasCancel(); 1466 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1467 HasCancel = OPFD->hasCancel(); 1468 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1469 HasCancel = OPFD->hasCancel(); 1470 else if (const auto *OPFD = 1471 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1472 HasCancel = OPFD->hasCancel(); 1473 else if (const auto *OPFD = 1474 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1475 HasCancel = OPFD->hasCancel(); 1476 1477 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1478 // parallel region to make cancellation barriers work properly. 1479 llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder(); 1480 PushAndPopStackRAII PSR(OMPBuilder, CGF, HasCancel); 1481 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1482 HasCancel, OutlinedHelperName); 1483 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1484 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1485 } 1486 1487 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1488 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1489 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1490 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1491 return emitParallelOrTeamsOutlinedFunction( 1492 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1493 } 1494 1495 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1496 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1497 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1498 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1499 return emitParallelOrTeamsOutlinedFunction( 1500 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1501 } 1502 1503 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1504 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1505 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1506 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1507 bool Tied, unsigned &NumberOfParts) { 1508 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1509 PrePostActionTy &) { 1510 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1511 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1512 llvm::Value *TaskArgs[] = { 1513 UpLoc, ThreadID, 1514 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1515 TaskTVar->getType()->castAs<PointerType>()) 1516 .getPointer(CGF)}; 1517 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1518 }; 1519 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1520 UntiedCodeGen); 1521 CodeGen.setAction(Action); 1522 assert(!ThreadIDVar->getType()->isPointerType() && 1523 "thread id variable must be of type kmp_int32 for tasks"); 1524 const OpenMPDirectiveKind Region = 1525 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1526 : OMPD_task; 1527 const CapturedStmt *CS = D.getCapturedStmt(Region); 1528 bool HasCancel = false; 1529 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D)) 1530 HasCancel = TD->hasCancel(); 1531 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D)) 1532 HasCancel = TD->hasCancel(); 1533 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D)) 1534 HasCancel = TD->hasCancel(); 1535 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D)) 1536 HasCancel = TD->hasCancel(); 1537 1538 CodeGenFunction CGF(CGM, true); 1539 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1540 InnermostKind, HasCancel, Action); 1541 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1542 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1543 if (!Tied) 1544 NumberOfParts = Action.getNumberOfParts(); 1545 return Res; 1546 } 1547 1548 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1549 const RecordDecl *RD, const CGRecordLayout &RL, 1550 ArrayRef<llvm::Constant *> Data) { 1551 llvm::StructType *StructTy = RL.getLLVMType(); 1552 unsigned PrevIdx = 0; 1553 ConstantInitBuilder CIBuilder(CGM); 1554 auto DI = Data.begin(); 1555 for (const FieldDecl *FD : RD->fields()) { 1556 unsigned Idx = RL.getLLVMFieldNo(FD); 1557 // Fill the alignment. 1558 for (unsigned I = PrevIdx; I < Idx; ++I) 1559 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1560 PrevIdx = Idx + 1; 1561 Fields.add(*DI); 1562 ++DI; 1563 } 1564 } 1565 1566 template <class... As> 1567 static llvm::GlobalVariable * 1568 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1569 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1570 As &&... Args) { 1571 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1572 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1573 ConstantInitBuilder CIBuilder(CGM); 1574 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1575 buildStructValue(Fields, CGM, RD, RL, Data); 1576 return Fields.finishAndCreateGlobal( 1577 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1578 std::forward<As>(Args)...); 1579 } 1580 1581 template <typename T> 1582 static void 1583 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1584 ArrayRef<llvm::Constant *> Data, 1585 T &Parent) { 1586 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1587 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1588 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1589 buildStructValue(Fields, CGM, RD, RL, Data); 1590 Fields.finishAndAddTo(Parent); 1591 } 1592 1593 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1594 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1595 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1596 FlagsTy FlagsKey(Flags, Reserved2Flags); 1597 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1598 if (!Entry) { 1599 if (!DefaultOpenMPPSource) { 1600 // Initialize default location for psource field of ident_t structure of 1601 // all ident_t objects. Format is ";file;function;line;column;;". 1602 // Taken from 1603 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1604 DefaultOpenMPPSource = 1605 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1606 DefaultOpenMPPSource = 1607 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1608 } 1609 1610 llvm::Constant *Data[] = { 1611 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1612 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1613 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1614 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1615 llvm::GlobalValue *DefaultOpenMPLocation = 1616 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1617 llvm::GlobalValue::PrivateLinkage); 1618 DefaultOpenMPLocation->setUnnamedAddr( 1619 llvm::GlobalValue::UnnamedAddr::Global); 1620 1621 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1622 } 1623 return Address(Entry, Align); 1624 } 1625 1626 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1627 bool AtCurrentPoint) { 1628 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1629 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1630 1631 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1632 if (AtCurrentPoint) { 1633 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1634 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1635 } else { 1636 Elem.second.ServiceInsertPt = 1637 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1638 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1639 } 1640 } 1641 1642 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1643 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1644 if (Elem.second.ServiceInsertPt) { 1645 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1646 Elem.second.ServiceInsertPt = nullptr; 1647 Ptr->eraseFromParent(); 1648 } 1649 } 1650 1651 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1652 SourceLocation Loc, 1653 unsigned Flags) { 1654 Flags |= OMP_IDENT_KMPC; 1655 // If no debug info is generated - return global default location. 1656 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1657 Loc.isInvalid()) 1658 return getOrCreateDefaultLocation(Flags).getPointer(); 1659 1660 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1661 1662 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1663 Address LocValue = Address::invalid(); 1664 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1665 if (I != OpenMPLocThreadIDMap.end()) 1666 LocValue = Address(I->second.DebugLoc, Align); 1667 1668 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1669 // GetOpenMPThreadID was called before this routine. 1670 if (!LocValue.isValid()) { 1671 // Generate "ident_t .kmpc_loc.addr;" 1672 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1673 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1674 Elem.second.DebugLoc = AI.getPointer(); 1675 LocValue = AI; 1676 1677 if (!Elem.second.ServiceInsertPt) 1678 setLocThreadIdInsertPt(CGF); 1679 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1680 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1681 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1682 CGF.getTypeSize(IdentQTy)); 1683 } 1684 1685 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1686 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1687 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1688 LValue PSource = 1689 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1690 1691 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1692 if (OMPDebugLoc == nullptr) { 1693 SmallString<128> Buffer2; 1694 llvm::raw_svector_ostream OS2(Buffer2); 1695 // Build debug location 1696 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1697 OS2 << ";" << PLoc.getFilename() << ";"; 1698 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1699 OS2 << FD->getQualifiedNameAsString(); 1700 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1701 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1702 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1703 } 1704 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1705 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1706 1707 // Our callers always pass this to a runtime function, so for 1708 // convenience, go ahead and return a naked pointer. 1709 return LocValue.getPointer(); 1710 } 1711 1712 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1713 SourceLocation Loc) { 1714 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1715 1716 llvm::Value *ThreadID = nullptr; 1717 // Check whether we've already cached a load of the thread id in this 1718 // function. 1719 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1720 if (I != OpenMPLocThreadIDMap.end()) { 1721 ThreadID = I->second.ThreadID; 1722 if (ThreadID != nullptr) 1723 return ThreadID; 1724 } 1725 // If exceptions are enabled, do not use parameter to avoid possible crash. 1726 if (auto *OMPRegionInfo = 1727 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1728 if (OMPRegionInfo->getThreadIDVariable()) { 1729 // Check if this an outlined function with thread id passed as argument. 1730 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1731 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1732 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1733 !CGF.getLangOpts().CXXExceptions || 1734 CGF.Builder.GetInsertBlock() == TopBlock || 1735 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1736 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1737 TopBlock || 1738 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1739 CGF.Builder.GetInsertBlock()) { 1740 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1741 // If value loaded in entry block, cache it and use it everywhere in 1742 // function. 1743 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1744 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1745 Elem.second.ThreadID = ThreadID; 1746 } 1747 return ThreadID; 1748 } 1749 } 1750 } 1751 1752 // This is not an outlined function region - need to call __kmpc_int32 1753 // kmpc_global_thread_num(ident_t *loc). 1754 // Generate thread id value and cache this value for use across the 1755 // function. 1756 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1757 if (!Elem.second.ServiceInsertPt) 1758 setLocThreadIdInsertPt(CGF); 1759 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1760 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1761 llvm::CallInst *Call = CGF.Builder.CreateCall( 1762 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1763 emitUpdateLocation(CGF, Loc)); 1764 Call->setCallingConv(CGF.getRuntimeCC()); 1765 Elem.second.ThreadID = Call; 1766 return Call; 1767 } 1768 1769 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1770 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1771 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1772 clearLocThreadIdInsertPt(CGF); 1773 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1774 } 1775 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1776 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1777 UDRMap.erase(D); 1778 FunctionUDRMap.erase(CGF.CurFn); 1779 } 1780 auto I = FunctionUDMMap.find(CGF.CurFn); 1781 if (I != FunctionUDMMap.end()) { 1782 for(const auto *D : I->second) 1783 UDMMap.erase(D); 1784 FunctionUDMMap.erase(I); 1785 } 1786 LastprivateConditionalToTypes.erase(CGF.CurFn); 1787 } 1788 1789 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1790 return IdentTy->getPointerTo(); 1791 } 1792 1793 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1794 if (!Kmpc_MicroTy) { 1795 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1796 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1797 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1798 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1799 } 1800 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1801 } 1802 1803 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1804 llvm::FunctionCallee RTLFn = nullptr; 1805 switch (static_cast<OpenMPRTLFunction>(Function)) { 1806 case OMPRTL__kmpc_fork_call: { 1807 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1808 // microtask, ...); 1809 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1810 getKmpc_MicroPointerTy()}; 1811 auto *FnTy = 1812 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1813 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1814 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1815 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1816 llvm::LLVMContext &Ctx = F->getContext(); 1817 llvm::MDBuilder MDB(Ctx); 1818 // Annotate the callback behavior of the __kmpc_fork_call: 1819 // - The callback callee is argument number 2 (microtask). 1820 // - The first two arguments of the callback callee are unknown (-1). 1821 // - All variadic arguments to the __kmpc_fork_call are passed to the 1822 // callback callee. 1823 F->addMetadata( 1824 llvm::LLVMContext::MD_callback, 1825 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1826 2, {-1, -1}, 1827 /* VarArgsArePassed */ true)})); 1828 } 1829 } 1830 break; 1831 } 1832 case OMPRTL__kmpc_global_thread_num: { 1833 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1834 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1835 auto *FnTy = 1836 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1837 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1838 break; 1839 } 1840 case OMPRTL__kmpc_threadprivate_cached: { 1841 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1842 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1843 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1844 CGM.VoidPtrTy, CGM.SizeTy, 1845 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1846 auto *FnTy = 1847 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1848 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1849 break; 1850 } 1851 case OMPRTL__kmpc_critical: { 1852 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1853 // kmp_critical_name *crit); 1854 llvm::Type *TypeParams[] = { 1855 getIdentTyPointerTy(), CGM.Int32Ty, 1856 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1857 auto *FnTy = 1858 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1859 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1860 break; 1861 } 1862 case OMPRTL__kmpc_critical_with_hint: { 1863 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1864 // kmp_critical_name *crit, uintptr_t hint); 1865 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1866 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1867 CGM.IntPtrTy}; 1868 auto *FnTy = 1869 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1870 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1871 break; 1872 } 1873 case OMPRTL__kmpc_threadprivate_register: { 1874 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1875 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1876 // typedef void *(*kmpc_ctor)(void *); 1877 auto *KmpcCtorTy = 1878 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1879 /*isVarArg*/ false)->getPointerTo(); 1880 // typedef void *(*kmpc_cctor)(void *, void *); 1881 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1882 auto *KmpcCopyCtorTy = 1883 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1884 /*isVarArg*/ false) 1885 ->getPointerTo(); 1886 // typedef void (*kmpc_dtor)(void *); 1887 auto *KmpcDtorTy = 1888 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1889 ->getPointerTo(); 1890 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1891 KmpcCopyCtorTy, KmpcDtorTy}; 1892 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1893 /*isVarArg*/ false); 1894 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1895 break; 1896 } 1897 case OMPRTL__kmpc_end_critical: { 1898 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1899 // kmp_critical_name *crit); 1900 llvm::Type *TypeParams[] = { 1901 getIdentTyPointerTy(), CGM.Int32Ty, 1902 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1903 auto *FnTy = 1904 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1905 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1906 break; 1907 } 1908 case OMPRTL__kmpc_cancel_barrier: { 1909 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1910 // global_tid); 1911 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1912 auto *FnTy = 1913 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1914 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1915 break; 1916 } 1917 case OMPRTL__kmpc_barrier: { 1918 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1919 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1920 auto *FnTy = 1921 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1922 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1923 break; 1924 } 1925 case OMPRTL__kmpc_for_static_fini: { 1926 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1927 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1928 auto *FnTy = 1929 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1930 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1931 break; 1932 } 1933 case OMPRTL__kmpc_push_num_threads: { 1934 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1935 // kmp_int32 num_threads) 1936 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1937 CGM.Int32Ty}; 1938 auto *FnTy = 1939 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1940 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1941 break; 1942 } 1943 case OMPRTL__kmpc_serialized_parallel: { 1944 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1945 // global_tid); 1946 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1947 auto *FnTy = 1948 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1949 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1950 break; 1951 } 1952 case OMPRTL__kmpc_end_serialized_parallel: { 1953 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1954 // global_tid); 1955 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1956 auto *FnTy = 1957 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1958 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1959 break; 1960 } 1961 case OMPRTL__kmpc_flush: { 1962 // Build void __kmpc_flush(ident_t *loc); 1963 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1964 auto *FnTy = 1965 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1966 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1967 break; 1968 } 1969 case OMPRTL__kmpc_master: { 1970 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1971 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1972 auto *FnTy = 1973 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1974 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 1975 break; 1976 } 1977 case OMPRTL__kmpc_end_master: { 1978 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 1979 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1980 auto *FnTy = 1981 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1982 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 1983 break; 1984 } 1985 case OMPRTL__kmpc_omp_taskyield: { 1986 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 1987 // int end_part); 1988 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1989 auto *FnTy = 1990 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1991 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 1992 break; 1993 } 1994 case OMPRTL__kmpc_single: { 1995 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 1996 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1997 auto *FnTy = 1998 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1999 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 2000 break; 2001 } 2002 case OMPRTL__kmpc_end_single: { 2003 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 2004 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2005 auto *FnTy = 2006 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2007 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 2008 break; 2009 } 2010 case OMPRTL__kmpc_omp_task_alloc: { 2011 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 2012 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2013 // kmp_routine_entry_t *task_entry); 2014 assert(KmpRoutineEntryPtrTy != nullptr && 2015 "Type kmp_routine_entry_t must be created."); 2016 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2017 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 2018 // Return void * and then cast to particular kmp_task_t type. 2019 auto *FnTy = 2020 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2021 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 2022 break; 2023 } 2024 case OMPRTL__kmpc_omp_target_task_alloc: { 2025 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 2026 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2027 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 2028 assert(KmpRoutineEntryPtrTy != nullptr && 2029 "Type kmp_routine_entry_t must be created."); 2030 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2031 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 2032 CGM.Int64Ty}; 2033 // Return void * and then cast to particular kmp_task_t type. 2034 auto *FnTy = 2035 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2036 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2037 break; 2038 } 2039 case OMPRTL__kmpc_omp_task: { 2040 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2041 // *new_task); 2042 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2043 CGM.VoidPtrTy}; 2044 auto *FnTy = 2045 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2046 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2047 break; 2048 } 2049 case OMPRTL__kmpc_copyprivate: { 2050 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2051 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2052 // kmp_int32 didit); 2053 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2054 auto *CpyFnTy = 2055 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2056 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2057 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2058 CGM.Int32Ty}; 2059 auto *FnTy = 2060 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2061 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2062 break; 2063 } 2064 case OMPRTL__kmpc_reduce: { 2065 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2066 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2067 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2068 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2069 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2070 /*isVarArg=*/false); 2071 llvm::Type *TypeParams[] = { 2072 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2073 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2074 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2075 auto *FnTy = 2076 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2077 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2078 break; 2079 } 2080 case OMPRTL__kmpc_reduce_nowait: { 2081 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2082 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2083 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2084 // *lck); 2085 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2086 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2087 /*isVarArg=*/false); 2088 llvm::Type *TypeParams[] = { 2089 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2090 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2091 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2092 auto *FnTy = 2093 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2094 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2095 break; 2096 } 2097 case OMPRTL__kmpc_end_reduce: { 2098 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2099 // kmp_critical_name *lck); 2100 llvm::Type *TypeParams[] = { 2101 getIdentTyPointerTy(), CGM.Int32Ty, 2102 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2103 auto *FnTy = 2104 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2105 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2106 break; 2107 } 2108 case OMPRTL__kmpc_end_reduce_nowait: { 2109 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2110 // kmp_critical_name *lck); 2111 llvm::Type *TypeParams[] = { 2112 getIdentTyPointerTy(), CGM.Int32Ty, 2113 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2114 auto *FnTy = 2115 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2116 RTLFn = 2117 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2118 break; 2119 } 2120 case OMPRTL__kmpc_omp_task_begin_if0: { 2121 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2122 // *new_task); 2123 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2124 CGM.VoidPtrTy}; 2125 auto *FnTy = 2126 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2127 RTLFn = 2128 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2129 break; 2130 } 2131 case OMPRTL__kmpc_omp_task_complete_if0: { 2132 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2133 // *new_task); 2134 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2135 CGM.VoidPtrTy}; 2136 auto *FnTy = 2137 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2138 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2139 /*Name=*/"__kmpc_omp_task_complete_if0"); 2140 break; 2141 } 2142 case OMPRTL__kmpc_ordered: { 2143 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2144 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2145 auto *FnTy = 2146 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2147 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2148 break; 2149 } 2150 case OMPRTL__kmpc_end_ordered: { 2151 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2152 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2153 auto *FnTy = 2154 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2155 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2156 break; 2157 } 2158 case OMPRTL__kmpc_omp_taskwait: { 2159 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2160 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2161 auto *FnTy = 2162 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2163 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2164 break; 2165 } 2166 case OMPRTL__kmpc_taskgroup: { 2167 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2168 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2169 auto *FnTy = 2170 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2171 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2172 break; 2173 } 2174 case OMPRTL__kmpc_end_taskgroup: { 2175 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2176 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2177 auto *FnTy = 2178 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2179 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2180 break; 2181 } 2182 case OMPRTL__kmpc_push_proc_bind: { 2183 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2184 // int proc_bind) 2185 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2186 auto *FnTy = 2187 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2188 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2189 break; 2190 } 2191 case OMPRTL__kmpc_omp_task_with_deps: { 2192 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2193 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2194 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2195 llvm::Type *TypeParams[] = { 2196 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2197 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2198 auto *FnTy = 2199 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2200 RTLFn = 2201 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2202 break; 2203 } 2204 case OMPRTL__kmpc_omp_wait_deps: { 2205 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2206 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2207 // kmp_depend_info_t *noalias_dep_list); 2208 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2209 CGM.Int32Ty, CGM.VoidPtrTy, 2210 CGM.Int32Ty, CGM.VoidPtrTy}; 2211 auto *FnTy = 2212 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2213 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2214 break; 2215 } 2216 case OMPRTL__kmpc_cancellationpoint: { 2217 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2218 // global_tid, kmp_int32 cncl_kind) 2219 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2220 auto *FnTy = 2221 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2222 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2223 break; 2224 } 2225 case OMPRTL__kmpc_cancel: { 2226 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2227 // kmp_int32 cncl_kind) 2228 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2229 auto *FnTy = 2230 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2231 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2232 break; 2233 } 2234 case OMPRTL__kmpc_push_num_teams: { 2235 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2236 // kmp_int32 num_teams, kmp_int32 num_threads) 2237 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2238 CGM.Int32Ty}; 2239 auto *FnTy = 2240 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2241 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2242 break; 2243 } 2244 case OMPRTL__kmpc_fork_teams: { 2245 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2246 // microtask, ...); 2247 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2248 getKmpc_MicroPointerTy()}; 2249 auto *FnTy = 2250 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2251 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2252 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2253 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2254 llvm::LLVMContext &Ctx = F->getContext(); 2255 llvm::MDBuilder MDB(Ctx); 2256 // Annotate the callback behavior of the __kmpc_fork_teams: 2257 // - The callback callee is argument number 2 (microtask). 2258 // - The first two arguments of the callback callee are unknown (-1). 2259 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2260 // callback callee. 2261 F->addMetadata( 2262 llvm::LLVMContext::MD_callback, 2263 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2264 2, {-1, -1}, 2265 /* VarArgsArePassed */ true)})); 2266 } 2267 } 2268 break; 2269 } 2270 case OMPRTL__kmpc_taskloop: { 2271 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2272 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2273 // sched, kmp_uint64 grainsize, void *task_dup); 2274 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2275 CGM.IntTy, 2276 CGM.VoidPtrTy, 2277 CGM.IntTy, 2278 CGM.Int64Ty->getPointerTo(), 2279 CGM.Int64Ty->getPointerTo(), 2280 CGM.Int64Ty, 2281 CGM.IntTy, 2282 CGM.IntTy, 2283 CGM.Int64Ty, 2284 CGM.VoidPtrTy}; 2285 auto *FnTy = 2286 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2287 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2288 break; 2289 } 2290 case OMPRTL__kmpc_doacross_init: { 2291 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2292 // num_dims, struct kmp_dim *dims); 2293 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2294 CGM.Int32Ty, 2295 CGM.Int32Ty, 2296 CGM.VoidPtrTy}; 2297 auto *FnTy = 2298 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2299 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2300 break; 2301 } 2302 case OMPRTL__kmpc_doacross_fini: { 2303 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2304 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2305 auto *FnTy = 2306 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2307 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2308 break; 2309 } 2310 case OMPRTL__kmpc_doacross_post: { 2311 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2312 // *vec); 2313 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2314 CGM.Int64Ty->getPointerTo()}; 2315 auto *FnTy = 2316 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2317 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2318 break; 2319 } 2320 case OMPRTL__kmpc_doacross_wait: { 2321 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2322 // *vec); 2323 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2324 CGM.Int64Ty->getPointerTo()}; 2325 auto *FnTy = 2326 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2327 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2328 break; 2329 } 2330 case OMPRTL__kmpc_taskred_init: { 2331 // Build void *__kmpc_taskred_init(int gtid, int num_data, void *data); 2332 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2333 auto *FnTy = 2334 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2335 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskred_init"); 2336 break; 2337 } 2338 case OMPRTL__kmpc_task_reduction_get_th_data: { 2339 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2340 // *d); 2341 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2342 auto *FnTy = 2343 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2344 RTLFn = CGM.CreateRuntimeFunction( 2345 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2346 break; 2347 } 2348 case OMPRTL__kmpc_alloc: { 2349 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2350 // al); omp_allocator_handle_t type is void *. 2351 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2352 auto *FnTy = 2353 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2354 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2355 break; 2356 } 2357 case OMPRTL__kmpc_free: { 2358 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2359 // al); omp_allocator_handle_t type is void *. 2360 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2361 auto *FnTy = 2362 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2363 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2364 break; 2365 } 2366 case OMPRTL__kmpc_push_target_tripcount: { 2367 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2368 // size); 2369 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2370 llvm::FunctionType *FnTy = 2371 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2372 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2373 break; 2374 } 2375 case OMPRTL__tgt_target: { 2376 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2377 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2378 // *arg_types); 2379 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2380 CGM.VoidPtrTy, 2381 CGM.Int32Ty, 2382 CGM.VoidPtrPtrTy, 2383 CGM.VoidPtrPtrTy, 2384 CGM.Int64Ty->getPointerTo(), 2385 CGM.Int64Ty->getPointerTo()}; 2386 auto *FnTy = 2387 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2388 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2389 break; 2390 } 2391 case OMPRTL__tgt_target_nowait: { 2392 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2393 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2394 // int64_t *arg_types); 2395 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2396 CGM.VoidPtrTy, 2397 CGM.Int32Ty, 2398 CGM.VoidPtrPtrTy, 2399 CGM.VoidPtrPtrTy, 2400 CGM.Int64Ty->getPointerTo(), 2401 CGM.Int64Ty->getPointerTo()}; 2402 auto *FnTy = 2403 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2404 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2405 break; 2406 } 2407 case OMPRTL__tgt_target_teams: { 2408 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2409 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2410 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2411 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2412 CGM.VoidPtrTy, 2413 CGM.Int32Ty, 2414 CGM.VoidPtrPtrTy, 2415 CGM.VoidPtrPtrTy, 2416 CGM.Int64Ty->getPointerTo(), 2417 CGM.Int64Ty->getPointerTo(), 2418 CGM.Int32Ty, 2419 CGM.Int32Ty}; 2420 auto *FnTy = 2421 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2422 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2423 break; 2424 } 2425 case OMPRTL__tgt_target_teams_nowait: { 2426 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2427 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2428 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2429 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2430 CGM.VoidPtrTy, 2431 CGM.Int32Ty, 2432 CGM.VoidPtrPtrTy, 2433 CGM.VoidPtrPtrTy, 2434 CGM.Int64Ty->getPointerTo(), 2435 CGM.Int64Ty->getPointerTo(), 2436 CGM.Int32Ty, 2437 CGM.Int32Ty}; 2438 auto *FnTy = 2439 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2440 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2441 break; 2442 } 2443 case OMPRTL__tgt_register_requires: { 2444 // Build void __tgt_register_requires(int64_t flags); 2445 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2446 auto *FnTy = 2447 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2448 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2449 break; 2450 } 2451 case OMPRTL__tgt_target_data_begin: { 2452 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2453 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2454 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2455 CGM.Int32Ty, 2456 CGM.VoidPtrPtrTy, 2457 CGM.VoidPtrPtrTy, 2458 CGM.Int64Ty->getPointerTo(), 2459 CGM.Int64Ty->getPointerTo()}; 2460 auto *FnTy = 2461 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2462 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2463 break; 2464 } 2465 case OMPRTL__tgt_target_data_begin_nowait: { 2466 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2467 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2468 // *arg_types); 2469 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2470 CGM.Int32Ty, 2471 CGM.VoidPtrPtrTy, 2472 CGM.VoidPtrPtrTy, 2473 CGM.Int64Ty->getPointerTo(), 2474 CGM.Int64Ty->getPointerTo()}; 2475 auto *FnTy = 2476 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2477 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2478 break; 2479 } 2480 case OMPRTL__tgt_target_data_end: { 2481 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2482 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2483 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2484 CGM.Int32Ty, 2485 CGM.VoidPtrPtrTy, 2486 CGM.VoidPtrPtrTy, 2487 CGM.Int64Ty->getPointerTo(), 2488 CGM.Int64Ty->getPointerTo()}; 2489 auto *FnTy = 2490 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2491 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2492 break; 2493 } 2494 case OMPRTL__tgt_target_data_end_nowait: { 2495 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2496 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2497 // *arg_types); 2498 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2499 CGM.Int32Ty, 2500 CGM.VoidPtrPtrTy, 2501 CGM.VoidPtrPtrTy, 2502 CGM.Int64Ty->getPointerTo(), 2503 CGM.Int64Ty->getPointerTo()}; 2504 auto *FnTy = 2505 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2506 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2507 break; 2508 } 2509 case OMPRTL__tgt_target_data_update: { 2510 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2511 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2512 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2513 CGM.Int32Ty, 2514 CGM.VoidPtrPtrTy, 2515 CGM.VoidPtrPtrTy, 2516 CGM.Int64Ty->getPointerTo(), 2517 CGM.Int64Ty->getPointerTo()}; 2518 auto *FnTy = 2519 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2520 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2521 break; 2522 } 2523 case OMPRTL__tgt_target_data_update_nowait: { 2524 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2525 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2526 // *arg_types); 2527 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2528 CGM.Int32Ty, 2529 CGM.VoidPtrPtrTy, 2530 CGM.VoidPtrPtrTy, 2531 CGM.Int64Ty->getPointerTo(), 2532 CGM.Int64Ty->getPointerTo()}; 2533 auto *FnTy = 2534 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2535 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2536 break; 2537 } 2538 case OMPRTL__tgt_mapper_num_components: { 2539 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2540 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2541 auto *FnTy = 2542 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2543 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2544 break; 2545 } 2546 case OMPRTL__tgt_push_mapper_component: { 2547 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2548 // *base, void *begin, int64_t size, int64_t type); 2549 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2550 CGM.Int64Ty, CGM.Int64Ty}; 2551 auto *FnTy = 2552 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2553 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2554 break; 2555 } 2556 case OMPRTL__kmpc_task_allow_completion_event: { 2557 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 2558 // int gtid, kmp_task_t *task); 2559 auto *FnTy = llvm::FunctionType::get( 2560 CGM.VoidPtrTy, {getIdentTyPointerTy(), CGM.IntTy, CGM.VoidPtrTy}, 2561 /*isVarArg=*/false); 2562 RTLFn = 2563 CGM.CreateRuntimeFunction(FnTy, "__kmpc_task_allow_completion_event"); 2564 break; 2565 } 2566 } 2567 assert(RTLFn && "Unable to find OpenMP runtime function"); 2568 return RTLFn; 2569 } 2570 2571 llvm::FunctionCallee 2572 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2573 assert((IVSize == 32 || IVSize == 64) && 2574 "IV size is not compatible with the omp runtime"); 2575 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2576 : "__kmpc_for_static_init_4u") 2577 : (IVSigned ? "__kmpc_for_static_init_8" 2578 : "__kmpc_for_static_init_8u"); 2579 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2580 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2581 llvm::Type *TypeParams[] = { 2582 getIdentTyPointerTy(), // loc 2583 CGM.Int32Ty, // tid 2584 CGM.Int32Ty, // schedtype 2585 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2586 PtrTy, // p_lower 2587 PtrTy, // p_upper 2588 PtrTy, // p_stride 2589 ITy, // incr 2590 ITy // chunk 2591 }; 2592 auto *FnTy = 2593 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2594 return CGM.CreateRuntimeFunction(FnTy, Name); 2595 } 2596 2597 llvm::FunctionCallee 2598 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2599 assert((IVSize == 32 || IVSize == 64) && 2600 "IV size is not compatible with the omp runtime"); 2601 StringRef Name = 2602 IVSize == 32 2603 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2604 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2605 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2606 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2607 CGM.Int32Ty, // tid 2608 CGM.Int32Ty, // schedtype 2609 ITy, // lower 2610 ITy, // upper 2611 ITy, // stride 2612 ITy // chunk 2613 }; 2614 auto *FnTy = 2615 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2616 return CGM.CreateRuntimeFunction(FnTy, Name); 2617 } 2618 2619 llvm::FunctionCallee 2620 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2621 assert((IVSize == 32 || IVSize == 64) && 2622 "IV size is not compatible with the omp runtime"); 2623 StringRef Name = 2624 IVSize == 32 2625 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2626 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2627 llvm::Type *TypeParams[] = { 2628 getIdentTyPointerTy(), // loc 2629 CGM.Int32Ty, // tid 2630 }; 2631 auto *FnTy = 2632 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2633 return CGM.CreateRuntimeFunction(FnTy, Name); 2634 } 2635 2636 llvm::FunctionCallee 2637 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2638 assert((IVSize == 32 || IVSize == 64) && 2639 "IV size is not compatible with the omp runtime"); 2640 StringRef Name = 2641 IVSize == 32 2642 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2643 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2644 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2645 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2646 llvm::Type *TypeParams[] = { 2647 getIdentTyPointerTy(), // loc 2648 CGM.Int32Ty, // tid 2649 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2650 PtrTy, // p_lower 2651 PtrTy, // p_upper 2652 PtrTy // p_stride 2653 }; 2654 auto *FnTy = 2655 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2656 return CGM.CreateRuntimeFunction(FnTy, Name); 2657 } 2658 2659 /// Obtain information that uniquely identifies a target entry. This 2660 /// consists of the file and device IDs as well as line number associated with 2661 /// the relevant entry source location. 2662 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2663 unsigned &DeviceID, unsigned &FileID, 2664 unsigned &LineNum) { 2665 SourceManager &SM = C.getSourceManager(); 2666 2667 // The loc should be always valid and have a file ID (the user cannot use 2668 // #pragma directives in macros) 2669 2670 assert(Loc.isValid() && "Source location is expected to be always valid."); 2671 2672 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2673 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2674 2675 llvm::sys::fs::UniqueID ID; 2676 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2677 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2678 << PLoc.getFilename() << EC.message(); 2679 2680 DeviceID = ID.getDevice(); 2681 FileID = ID.getFile(); 2682 LineNum = PLoc.getLine(); 2683 } 2684 2685 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2686 if (CGM.getLangOpts().OpenMPSimd) 2687 return Address::invalid(); 2688 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2689 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2690 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2691 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2692 HasRequiresUnifiedSharedMemory))) { 2693 SmallString<64> PtrName; 2694 { 2695 llvm::raw_svector_ostream OS(PtrName); 2696 OS << CGM.getMangledName(GlobalDecl(VD)); 2697 if (!VD->isExternallyVisible()) { 2698 unsigned DeviceID, FileID, Line; 2699 getTargetEntryUniqueInfo(CGM.getContext(), 2700 VD->getCanonicalDecl()->getBeginLoc(), 2701 DeviceID, FileID, Line); 2702 OS << llvm::format("_%x", FileID); 2703 } 2704 OS << "_decl_tgt_ref_ptr"; 2705 } 2706 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2707 if (!Ptr) { 2708 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2709 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2710 PtrName); 2711 2712 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2713 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2714 2715 if (!CGM.getLangOpts().OpenMPIsDevice) 2716 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2717 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2718 } 2719 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2720 } 2721 return Address::invalid(); 2722 } 2723 2724 llvm::Constant * 2725 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2726 assert(!CGM.getLangOpts().OpenMPUseTLS || 2727 !CGM.getContext().getTargetInfo().isTLSSupported()); 2728 // Lookup the entry, lazily creating it if necessary. 2729 std::string Suffix = getName({"cache", ""}); 2730 return getOrCreateInternalVariable( 2731 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2732 } 2733 2734 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2735 const VarDecl *VD, 2736 Address VDAddr, 2737 SourceLocation Loc) { 2738 if (CGM.getLangOpts().OpenMPUseTLS && 2739 CGM.getContext().getTargetInfo().isTLSSupported()) 2740 return VDAddr; 2741 2742 llvm::Type *VarTy = VDAddr.getElementType(); 2743 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2744 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2745 CGM.Int8PtrTy), 2746 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2747 getOrCreateThreadPrivateCache(VD)}; 2748 return Address(CGF.EmitRuntimeCall( 2749 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2750 VDAddr.getAlignment()); 2751 } 2752 2753 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2754 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2755 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2756 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2757 // library. 2758 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2759 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2760 OMPLoc); 2761 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2762 // to register constructor/destructor for variable. 2763 llvm::Value *Args[] = { 2764 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2765 Ctor, CopyCtor, Dtor}; 2766 CGF.EmitRuntimeCall( 2767 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2768 } 2769 2770 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2771 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2772 bool PerformInit, CodeGenFunction *CGF) { 2773 if (CGM.getLangOpts().OpenMPUseTLS && 2774 CGM.getContext().getTargetInfo().isTLSSupported()) 2775 return nullptr; 2776 2777 VD = VD->getDefinition(CGM.getContext()); 2778 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2779 QualType ASTTy = VD->getType(); 2780 2781 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2782 const Expr *Init = VD->getAnyInitializer(); 2783 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2784 // Generate function that re-emits the declaration's initializer into the 2785 // threadprivate copy of the variable VD 2786 CodeGenFunction CtorCGF(CGM); 2787 FunctionArgList Args; 2788 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2789 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2790 ImplicitParamDecl::Other); 2791 Args.push_back(&Dst); 2792 2793 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2794 CGM.getContext().VoidPtrTy, Args); 2795 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2796 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2797 llvm::Function *Fn = 2798 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2799 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2800 Args, Loc, Loc); 2801 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2802 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2803 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2804 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2805 Arg = CtorCGF.Builder.CreateElementBitCast( 2806 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2807 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2808 /*IsInitializer=*/true); 2809 ArgVal = CtorCGF.EmitLoadOfScalar( 2810 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2811 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2812 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2813 CtorCGF.FinishFunction(); 2814 Ctor = Fn; 2815 } 2816 if (VD->getType().isDestructedType() != QualType::DK_none) { 2817 // Generate function that emits destructor call for the threadprivate copy 2818 // of the variable VD 2819 CodeGenFunction DtorCGF(CGM); 2820 FunctionArgList Args; 2821 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2822 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2823 ImplicitParamDecl::Other); 2824 Args.push_back(&Dst); 2825 2826 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2827 CGM.getContext().VoidTy, Args); 2828 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2829 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2830 llvm::Function *Fn = 2831 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2832 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2833 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2834 Loc, Loc); 2835 // Create a scope with an artificial location for the body of this function. 2836 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2837 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2838 DtorCGF.GetAddrOfLocalVar(&Dst), 2839 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2840 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2841 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2842 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2843 DtorCGF.FinishFunction(); 2844 Dtor = Fn; 2845 } 2846 // Do not emit init function if it is not required. 2847 if (!Ctor && !Dtor) 2848 return nullptr; 2849 2850 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2851 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2852 /*isVarArg=*/false) 2853 ->getPointerTo(); 2854 // Copying constructor for the threadprivate variable. 2855 // Must be NULL - reserved by runtime, but currently it requires that this 2856 // parameter is always NULL. Otherwise it fires assertion. 2857 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2858 if (Ctor == nullptr) { 2859 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2860 /*isVarArg=*/false) 2861 ->getPointerTo(); 2862 Ctor = llvm::Constant::getNullValue(CtorTy); 2863 } 2864 if (Dtor == nullptr) { 2865 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2866 /*isVarArg=*/false) 2867 ->getPointerTo(); 2868 Dtor = llvm::Constant::getNullValue(DtorTy); 2869 } 2870 if (!CGF) { 2871 auto *InitFunctionTy = 2872 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2873 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2874 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2875 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2876 CodeGenFunction InitCGF(CGM); 2877 FunctionArgList ArgList; 2878 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2879 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2880 Loc, Loc); 2881 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2882 InitCGF.FinishFunction(); 2883 return InitFunction; 2884 } 2885 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2886 } 2887 return nullptr; 2888 } 2889 2890 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2891 llvm::GlobalVariable *Addr, 2892 bool PerformInit) { 2893 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2894 !CGM.getLangOpts().OpenMPIsDevice) 2895 return false; 2896 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2897 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2898 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2899 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2900 HasRequiresUnifiedSharedMemory)) 2901 return CGM.getLangOpts().OpenMPIsDevice; 2902 VD = VD->getDefinition(CGM.getContext()); 2903 assert(VD && "Unknown VarDecl"); 2904 2905 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2906 return CGM.getLangOpts().OpenMPIsDevice; 2907 2908 QualType ASTTy = VD->getType(); 2909 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2910 2911 // Produce the unique prefix to identify the new target regions. We use 2912 // the source location of the variable declaration which we know to not 2913 // conflict with any target region. 2914 unsigned DeviceID; 2915 unsigned FileID; 2916 unsigned Line; 2917 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2918 SmallString<128> Buffer, Out; 2919 { 2920 llvm::raw_svector_ostream OS(Buffer); 2921 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2922 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2923 } 2924 2925 const Expr *Init = VD->getAnyInitializer(); 2926 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2927 llvm::Constant *Ctor; 2928 llvm::Constant *ID; 2929 if (CGM.getLangOpts().OpenMPIsDevice) { 2930 // Generate function that re-emits the declaration's initializer into 2931 // the threadprivate copy of the variable VD 2932 CodeGenFunction CtorCGF(CGM); 2933 2934 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2935 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2936 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2937 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2938 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2939 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2940 FunctionArgList(), Loc, Loc); 2941 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2942 CtorCGF.EmitAnyExprToMem(Init, 2943 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2944 Init->getType().getQualifiers(), 2945 /*IsInitializer=*/true); 2946 CtorCGF.FinishFunction(); 2947 Ctor = Fn; 2948 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2949 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2950 } else { 2951 Ctor = new llvm::GlobalVariable( 2952 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2953 llvm::GlobalValue::PrivateLinkage, 2954 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2955 ID = Ctor; 2956 } 2957 2958 // Register the information for the entry associated with the constructor. 2959 Out.clear(); 2960 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2961 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2962 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2963 } 2964 if (VD->getType().isDestructedType() != QualType::DK_none) { 2965 llvm::Constant *Dtor; 2966 llvm::Constant *ID; 2967 if (CGM.getLangOpts().OpenMPIsDevice) { 2968 // Generate function that emits destructor call for the threadprivate 2969 // copy of the variable VD 2970 CodeGenFunction DtorCGF(CGM); 2971 2972 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2973 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2974 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2975 FTy, Twine(Buffer, "_dtor"), FI, Loc); 2976 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2977 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2978 FunctionArgList(), Loc, Loc); 2979 // Create a scope with an artificial location for the body of this 2980 // function. 2981 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2982 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 2983 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2984 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2985 DtorCGF.FinishFunction(); 2986 Dtor = Fn; 2987 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2988 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 2989 } else { 2990 Dtor = new llvm::GlobalVariable( 2991 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2992 llvm::GlobalValue::PrivateLinkage, 2993 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 2994 ID = Dtor; 2995 } 2996 // Register the information for the entry associated with the destructor. 2997 Out.clear(); 2998 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2999 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 3000 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 3001 } 3002 return CGM.getLangOpts().OpenMPIsDevice; 3003 } 3004 3005 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 3006 QualType VarType, 3007 StringRef Name) { 3008 std::string Suffix = getName({"artificial", ""}); 3009 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 3010 llvm::Value *GAddr = 3011 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 3012 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 3013 CGM.getTarget().isTLSSupported()) { 3014 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 3015 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 3016 } 3017 std::string CacheSuffix = getName({"cache", ""}); 3018 llvm::Value *Args[] = { 3019 emitUpdateLocation(CGF, SourceLocation()), 3020 getThreadID(CGF, SourceLocation()), 3021 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 3022 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 3023 /*isSigned=*/false), 3024 getOrCreateInternalVariable( 3025 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 3026 return Address( 3027 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3028 CGF.EmitRuntimeCall( 3029 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3030 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3031 CGM.getContext().getTypeAlignInChars(VarType)); 3032 } 3033 3034 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 3035 const RegionCodeGenTy &ThenGen, 3036 const RegionCodeGenTy &ElseGen) { 3037 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3038 3039 // If the condition constant folds and can be elided, try to avoid emitting 3040 // the condition and the dead arm of the if/else. 3041 bool CondConstant; 3042 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3043 if (CondConstant) 3044 ThenGen(CGF); 3045 else 3046 ElseGen(CGF); 3047 return; 3048 } 3049 3050 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3051 // emit the conditional branch. 3052 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3053 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3054 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3055 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3056 3057 // Emit the 'then' code. 3058 CGF.EmitBlock(ThenBlock); 3059 ThenGen(CGF); 3060 CGF.EmitBranch(ContBlock); 3061 // Emit the 'else' code if present. 3062 // There is no need to emit line number for unconditional branch. 3063 (void)ApplyDebugLocation::CreateEmpty(CGF); 3064 CGF.EmitBlock(ElseBlock); 3065 ElseGen(CGF); 3066 // There is no need to emit line number for unconditional branch. 3067 (void)ApplyDebugLocation::CreateEmpty(CGF); 3068 CGF.EmitBranch(ContBlock); 3069 // Emit the continuation block for code after the if. 3070 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3071 } 3072 3073 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3074 llvm::Function *OutlinedFn, 3075 ArrayRef<llvm::Value *> CapturedVars, 3076 const Expr *IfCond) { 3077 if (!CGF.HaveInsertPoint()) 3078 return; 3079 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3080 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3081 PrePostActionTy &) { 3082 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3083 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3084 llvm::Value *Args[] = { 3085 RTLoc, 3086 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3087 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3088 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3089 RealArgs.append(std::begin(Args), std::end(Args)); 3090 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3091 3092 llvm::FunctionCallee RTLFn = 3093 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3094 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3095 }; 3096 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3097 PrePostActionTy &) { 3098 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3099 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3100 // Build calls: 3101 // __kmpc_serialized_parallel(&Loc, GTid); 3102 llvm::Value *Args[] = {RTLoc, ThreadID}; 3103 CGF.EmitRuntimeCall( 3104 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3105 3106 // OutlinedFn(>id, &zero_bound, CapturedStruct); 3107 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 3108 Address ZeroAddrBound = 3109 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3110 /*Name=*/".bound.zero.addr"); 3111 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 3112 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3113 // ThreadId for serialized parallels is 0. 3114 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 3115 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 3116 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3117 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3118 3119 // __kmpc_end_serialized_parallel(&Loc, GTid); 3120 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3121 CGF.EmitRuntimeCall( 3122 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3123 EndArgs); 3124 }; 3125 if (IfCond) { 3126 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 3127 } else { 3128 RegionCodeGenTy ThenRCG(ThenGen); 3129 ThenRCG(CGF); 3130 } 3131 } 3132 3133 // If we're inside an (outlined) parallel region, use the region info's 3134 // thread-ID variable (it is passed in a first argument of the outlined function 3135 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3136 // regular serial code region, get thread ID by calling kmp_int32 3137 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3138 // return the address of that temp. 3139 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3140 SourceLocation Loc) { 3141 if (auto *OMPRegionInfo = 3142 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3143 if (OMPRegionInfo->getThreadIDVariable()) 3144 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 3145 3146 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3147 QualType Int32Ty = 3148 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3149 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3150 CGF.EmitStoreOfScalar(ThreadID, 3151 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3152 3153 return ThreadIDTemp; 3154 } 3155 3156 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3157 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3158 SmallString<256> Buffer; 3159 llvm::raw_svector_ostream Out(Buffer); 3160 Out << Name; 3161 StringRef RuntimeName = Out.str(); 3162 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3163 if (Elem.second) { 3164 assert(Elem.second->getType()->getPointerElementType() == Ty && 3165 "OMP internal variable has different type than requested"); 3166 return &*Elem.second; 3167 } 3168 3169 return Elem.second = new llvm::GlobalVariable( 3170 CGM.getModule(), Ty, /*IsConstant*/ false, 3171 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3172 Elem.first(), /*InsertBefore=*/nullptr, 3173 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3174 } 3175 3176 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3177 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3178 std::string Name = getName({Prefix, "var"}); 3179 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3180 } 3181 3182 namespace { 3183 /// Common pre(post)-action for different OpenMP constructs. 3184 class CommonActionTy final : public PrePostActionTy { 3185 llvm::FunctionCallee EnterCallee; 3186 ArrayRef<llvm::Value *> EnterArgs; 3187 llvm::FunctionCallee ExitCallee; 3188 ArrayRef<llvm::Value *> ExitArgs; 3189 bool Conditional; 3190 llvm::BasicBlock *ContBlock = nullptr; 3191 3192 public: 3193 CommonActionTy(llvm::FunctionCallee EnterCallee, 3194 ArrayRef<llvm::Value *> EnterArgs, 3195 llvm::FunctionCallee ExitCallee, 3196 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3197 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3198 ExitArgs(ExitArgs), Conditional(Conditional) {} 3199 void Enter(CodeGenFunction &CGF) override { 3200 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3201 if (Conditional) { 3202 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3203 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3204 ContBlock = CGF.createBasicBlock("omp_if.end"); 3205 // Generate the branch (If-stmt) 3206 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3207 CGF.EmitBlock(ThenBlock); 3208 } 3209 } 3210 void Done(CodeGenFunction &CGF) { 3211 // Emit the rest of blocks/branches 3212 CGF.EmitBranch(ContBlock); 3213 CGF.EmitBlock(ContBlock, true); 3214 } 3215 void Exit(CodeGenFunction &CGF) override { 3216 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3217 } 3218 }; 3219 } // anonymous namespace 3220 3221 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3222 StringRef CriticalName, 3223 const RegionCodeGenTy &CriticalOpGen, 3224 SourceLocation Loc, const Expr *Hint) { 3225 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3226 // CriticalOpGen(); 3227 // __kmpc_end_critical(ident_t *, gtid, Lock); 3228 // Prepare arguments and build a call to __kmpc_critical 3229 if (!CGF.HaveInsertPoint()) 3230 return; 3231 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3232 getCriticalRegionLock(CriticalName)}; 3233 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3234 std::end(Args)); 3235 if (Hint) { 3236 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3237 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3238 } 3239 CommonActionTy Action( 3240 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3241 : OMPRTL__kmpc_critical), 3242 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3243 CriticalOpGen.setAction(Action); 3244 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3245 } 3246 3247 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3248 const RegionCodeGenTy &MasterOpGen, 3249 SourceLocation Loc) { 3250 if (!CGF.HaveInsertPoint()) 3251 return; 3252 // if(__kmpc_master(ident_t *, gtid)) { 3253 // MasterOpGen(); 3254 // __kmpc_end_master(ident_t *, gtid); 3255 // } 3256 // Prepare arguments and build a call to __kmpc_master 3257 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3258 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3259 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3260 /*Conditional=*/true); 3261 MasterOpGen.setAction(Action); 3262 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3263 Action.Done(CGF); 3264 } 3265 3266 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3267 SourceLocation Loc) { 3268 if (!CGF.HaveInsertPoint()) 3269 return; 3270 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3271 if (OMPBuilder) { 3272 OMPBuilder->CreateTaskyield(CGF.Builder); 3273 } else { 3274 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3275 llvm::Value *Args[] = { 3276 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3277 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3278 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), 3279 Args); 3280 } 3281 3282 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3283 Region->emitUntiedSwitch(CGF); 3284 } 3285 3286 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3287 const RegionCodeGenTy &TaskgroupOpGen, 3288 SourceLocation Loc) { 3289 if (!CGF.HaveInsertPoint()) 3290 return; 3291 // __kmpc_taskgroup(ident_t *, gtid); 3292 // TaskgroupOpGen(); 3293 // __kmpc_end_taskgroup(ident_t *, gtid); 3294 // Prepare arguments and build a call to __kmpc_taskgroup 3295 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3296 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3297 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3298 Args); 3299 TaskgroupOpGen.setAction(Action); 3300 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3301 } 3302 3303 /// Given an array of pointers to variables, project the address of a 3304 /// given variable. 3305 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3306 unsigned Index, const VarDecl *Var) { 3307 // Pull out the pointer to the variable. 3308 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3309 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3310 3311 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3312 Addr = CGF.Builder.CreateElementBitCast( 3313 Addr, CGF.ConvertTypeForMem(Var->getType())); 3314 return Addr; 3315 } 3316 3317 static llvm::Value *emitCopyprivateCopyFunction( 3318 CodeGenModule &CGM, llvm::Type *ArgsType, 3319 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3320 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3321 SourceLocation Loc) { 3322 ASTContext &C = CGM.getContext(); 3323 // void copy_func(void *LHSArg, void *RHSArg); 3324 FunctionArgList Args; 3325 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3326 ImplicitParamDecl::Other); 3327 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3328 ImplicitParamDecl::Other); 3329 Args.push_back(&LHSArg); 3330 Args.push_back(&RHSArg); 3331 const auto &CGFI = 3332 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3333 std::string Name = 3334 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3335 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3336 llvm::GlobalValue::InternalLinkage, Name, 3337 &CGM.getModule()); 3338 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3339 Fn->setDoesNotRecurse(); 3340 CodeGenFunction CGF(CGM); 3341 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3342 // Dest = (void*[n])(LHSArg); 3343 // Src = (void*[n])(RHSArg); 3344 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3345 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3346 ArgsType), CGF.getPointerAlign()); 3347 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3348 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3349 ArgsType), CGF.getPointerAlign()); 3350 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3351 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3352 // ... 3353 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3354 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3355 const auto *DestVar = 3356 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3357 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3358 3359 const auto *SrcVar = 3360 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3361 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3362 3363 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3364 QualType Type = VD->getType(); 3365 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3366 } 3367 CGF.FinishFunction(); 3368 return Fn; 3369 } 3370 3371 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3372 const RegionCodeGenTy &SingleOpGen, 3373 SourceLocation Loc, 3374 ArrayRef<const Expr *> CopyprivateVars, 3375 ArrayRef<const Expr *> SrcExprs, 3376 ArrayRef<const Expr *> DstExprs, 3377 ArrayRef<const Expr *> AssignmentOps) { 3378 if (!CGF.HaveInsertPoint()) 3379 return; 3380 assert(CopyprivateVars.size() == SrcExprs.size() && 3381 CopyprivateVars.size() == DstExprs.size() && 3382 CopyprivateVars.size() == AssignmentOps.size()); 3383 ASTContext &C = CGM.getContext(); 3384 // int32 did_it = 0; 3385 // if(__kmpc_single(ident_t *, gtid)) { 3386 // SingleOpGen(); 3387 // __kmpc_end_single(ident_t *, gtid); 3388 // did_it = 1; 3389 // } 3390 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3391 // <copy_func>, did_it); 3392 3393 Address DidIt = Address::invalid(); 3394 if (!CopyprivateVars.empty()) { 3395 // int32 did_it = 0; 3396 QualType KmpInt32Ty = 3397 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3398 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3399 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3400 } 3401 // Prepare arguments and build a call to __kmpc_single 3402 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3403 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3404 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3405 /*Conditional=*/true); 3406 SingleOpGen.setAction(Action); 3407 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3408 if (DidIt.isValid()) { 3409 // did_it = 1; 3410 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3411 } 3412 Action.Done(CGF); 3413 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3414 // <copy_func>, did_it); 3415 if (DidIt.isValid()) { 3416 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3417 QualType CopyprivateArrayTy = C.getConstantArrayType( 3418 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3419 /*IndexTypeQuals=*/0); 3420 // Create a list of all private variables for copyprivate. 3421 Address CopyprivateList = 3422 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3423 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3424 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3425 CGF.Builder.CreateStore( 3426 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3427 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 3428 CGF.VoidPtrTy), 3429 Elem); 3430 } 3431 // Build function that copies private values from single region to all other 3432 // threads in the corresponding parallel region. 3433 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3434 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3435 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3436 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3437 Address CL = 3438 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3439 CGF.VoidPtrTy); 3440 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3441 llvm::Value *Args[] = { 3442 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3443 getThreadID(CGF, Loc), // i32 <gtid> 3444 BufSize, // size_t <buf_size> 3445 CL.getPointer(), // void *<copyprivate list> 3446 CpyFn, // void (*) (void *, void *) <copy_func> 3447 DidItVal // i32 did_it 3448 }; 3449 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3450 } 3451 } 3452 3453 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3454 const RegionCodeGenTy &OrderedOpGen, 3455 SourceLocation Loc, bool IsThreads) { 3456 if (!CGF.HaveInsertPoint()) 3457 return; 3458 // __kmpc_ordered(ident_t *, gtid); 3459 // OrderedOpGen(); 3460 // __kmpc_end_ordered(ident_t *, gtid); 3461 // Prepare arguments and build a call to __kmpc_ordered 3462 if (IsThreads) { 3463 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3464 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3465 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3466 Args); 3467 OrderedOpGen.setAction(Action); 3468 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3469 return; 3470 } 3471 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3472 } 3473 3474 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3475 unsigned Flags; 3476 if (Kind == OMPD_for) 3477 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3478 else if (Kind == OMPD_sections) 3479 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3480 else if (Kind == OMPD_single) 3481 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3482 else if (Kind == OMPD_barrier) 3483 Flags = OMP_IDENT_BARRIER_EXPL; 3484 else 3485 Flags = OMP_IDENT_BARRIER_IMPL; 3486 return Flags; 3487 } 3488 3489 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3490 CodeGenFunction &CGF, const OMPLoopDirective &S, 3491 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3492 // Check if the loop directive is actually a doacross loop directive. In this 3493 // case choose static, 1 schedule. 3494 if (llvm::any_of( 3495 S.getClausesOfKind<OMPOrderedClause>(), 3496 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3497 ScheduleKind = OMPC_SCHEDULE_static; 3498 // Chunk size is 1 in this case. 3499 llvm::APInt ChunkSize(32, 1); 3500 ChunkExpr = IntegerLiteral::Create( 3501 CGF.getContext(), ChunkSize, 3502 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3503 SourceLocation()); 3504 } 3505 } 3506 3507 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3508 OpenMPDirectiveKind Kind, bool EmitChecks, 3509 bool ForceSimpleCall) { 3510 // Check if we should use the OMPBuilder 3511 auto *OMPRegionInfo = 3512 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 3513 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3514 if (OMPBuilder) { 3515 CGF.Builder.restoreIP(OMPBuilder->CreateBarrier( 3516 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 3517 return; 3518 } 3519 3520 if (!CGF.HaveInsertPoint()) 3521 return; 3522 // Build call __kmpc_cancel_barrier(loc, thread_id); 3523 // Build call __kmpc_barrier(loc, thread_id); 3524 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3525 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3526 // thread_id); 3527 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3528 getThreadID(CGF, Loc)}; 3529 if (OMPRegionInfo) { 3530 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3531 llvm::Value *Result = CGF.EmitRuntimeCall( 3532 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3533 if (EmitChecks) { 3534 // if (__kmpc_cancel_barrier()) { 3535 // exit from construct; 3536 // } 3537 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3538 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3539 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3540 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3541 CGF.EmitBlock(ExitBB); 3542 // exit from construct; 3543 CodeGenFunction::JumpDest CancelDestination = 3544 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3545 CGF.EmitBranchThroughCleanup(CancelDestination); 3546 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3547 } 3548 return; 3549 } 3550 } 3551 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3552 } 3553 3554 /// Map the OpenMP loop schedule to the runtime enumeration. 3555 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3556 bool Chunked, bool Ordered) { 3557 switch (ScheduleKind) { 3558 case OMPC_SCHEDULE_static: 3559 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3560 : (Ordered ? OMP_ord_static : OMP_sch_static); 3561 case OMPC_SCHEDULE_dynamic: 3562 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3563 case OMPC_SCHEDULE_guided: 3564 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3565 case OMPC_SCHEDULE_runtime: 3566 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3567 case OMPC_SCHEDULE_auto: 3568 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3569 case OMPC_SCHEDULE_unknown: 3570 assert(!Chunked && "chunk was specified but schedule kind not known"); 3571 return Ordered ? OMP_ord_static : OMP_sch_static; 3572 } 3573 llvm_unreachable("Unexpected runtime schedule"); 3574 } 3575 3576 /// Map the OpenMP distribute schedule to the runtime enumeration. 3577 static OpenMPSchedType 3578 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3579 // only static is allowed for dist_schedule 3580 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3581 } 3582 3583 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3584 bool Chunked) const { 3585 OpenMPSchedType Schedule = 3586 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3587 return Schedule == OMP_sch_static; 3588 } 3589 3590 bool CGOpenMPRuntime::isStaticNonchunked( 3591 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3592 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3593 return Schedule == OMP_dist_sch_static; 3594 } 3595 3596 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3597 bool Chunked) const { 3598 OpenMPSchedType Schedule = 3599 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3600 return Schedule == OMP_sch_static_chunked; 3601 } 3602 3603 bool CGOpenMPRuntime::isStaticChunked( 3604 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3605 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3606 return Schedule == OMP_dist_sch_static_chunked; 3607 } 3608 3609 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3610 OpenMPSchedType Schedule = 3611 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3612 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3613 return Schedule != OMP_sch_static; 3614 } 3615 3616 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3617 OpenMPScheduleClauseModifier M1, 3618 OpenMPScheduleClauseModifier M2) { 3619 int Modifier = 0; 3620 switch (M1) { 3621 case OMPC_SCHEDULE_MODIFIER_monotonic: 3622 Modifier = OMP_sch_modifier_monotonic; 3623 break; 3624 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3625 Modifier = OMP_sch_modifier_nonmonotonic; 3626 break; 3627 case OMPC_SCHEDULE_MODIFIER_simd: 3628 if (Schedule == OMP_sch_static_chunked) 3629 Schedule = OMP_sch_static_balanced_chunked; 3630 break; 3631 case OMPC_SCHEDULE_MODIFIER_last: 3632 case OMPC_SCHEDULE_MODIFIER_unknown: 3633 break; 3634 } 3635 switch (M2) { 3636 case OMPC_SCHEDULE_MODIFIER_monotonic: 3637 Modifier = OMP_sch_modifier_monotonic; 3638 break; 3639 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3640 Modifier = OMP_sch_modifier_nonmonotonic; 3641 break; 3642 case OMPC_SCHEDULE_MODIFIER_simd: 3643 if (Schedule == OMP_sch_static_chunked) 3644 Schedule = OMP_sch_static_balanced_chunked; 3645 break; 3646 case OMPC_SCHEDULE_MODIFIER_last: 3647 case OMPC_SCHEDULE_MODIFIER_unknown: 3648 break; 3649 } 3650 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3651 // If the static schedule kind is specified or if the ordered clause is 3652 // specified, and if the nonmonotonic modifier is not specified, the effect is 3653 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3654 // modifier is specified, the effect is as if the nonmonotonic modifier is 3655 // specified. 3656 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3657 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3658 Schedule == OMP_sch_static_balanced_chunked || 3659 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 3660 Schedule == OMP_dist_sch_static_chunked || 3661 Schedule == OMP_dist_sch_static)) 3662 Modifier = OMP_sch_modifier_nonmonotonic; 3663 } 3664 return Schedule | Modifier; 3665 } 3666 3667 void CGOpenMPRuntime::emitForDispatchInit( 3668 CodeGenFunction &CGF, SourceLocation Loc, 3669 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3670 bool Ordered, const DispatchRTInput &DispatchValues) { 3671 if (!CGF.HaveInsertPoint()) 3672 return; 3673 OpenMPSchedType Schedule = getRuntimeSchedule( 3674 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3675 assert(Ordered || 3676 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3677 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3678 Schedule != OMP_sch_static_balanced_chunked)); 3679 // Call __kmpc_dispatch_init( 3680 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3681 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3682 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3683 3684 // If the Chunk was not specified in the clause - use default value 1. 3685 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3686 : CGF.Builder.getIntN(IVSize, 1); 3687 llvm::Value *Args[] = { 3688 emitUpdateLocation(CGF, Loc), 3689 getThreadID(CGF, Loc), 3690 CGF.Builder.getInt32(addMonoNonMonoModifier( 3691 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3692 DispatchValues.LB, // Lower 3693 DispatchValues.UB, // Upper 3694 CGF.Builder.getIntN(IVSize, 1), // Stride 3695 Chunk // Chunk 3696 }; 3697 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3698 } 3699 3700 static void emitForStaticInitCall( 3701 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3702 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3703 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3704 const CGOpenMPRuntime::StaticRTInput &Values) { 3705 if (!CGF.HaveInsertPoint()) 3706 return; 3707 3708 assert(!Values.Ordered); 3709 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3710 Schedule == OMP_sch_static_balanced_chunked || 3711 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3712 Schedule == OMP_dist_sch_static || 3713 Schedule == OMP_dist_sch_static_chunked); 3714 3715 // Call __kmpc_for_static_init( 3716 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3717 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3718 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3719 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3720 llvm::Value *Chunk = Values.Chunk; 3721 if (Chunk == nullptr) { 3722 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3723 Schedule == OMP_dist_sch_static) && 3724 "expected static non-chunked schedule"); 3725 // If the Chunk was not specified in the clause - use default value 1. 3726 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3727 } else { 3728 assert((Schedule == OMP_sch_static_chunked || 3729 Schedule == OMP_sch_static_balanced_chunked || 3730 Schedule == OMP_ord_static_chunked || 3731 Schedule == OMP_dist_sch_static_chunked) && 3732 "expected static chunked schedule"); 3733 } 3734 llvm::Value *Args[] = { 3735 UpdateLocation, 3736 ThreadId, 3737 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3738 M2)), // Schedule type 3739 Values.IL.getPointer(), // &isLastIter 3740 Values.LB.getPointer(), // &LB 3741 Values.UB.getPointer(), // &UB 3742 Values.ST.getPointer(), // &Stride 3743 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3744 Chunk // Chunk 3745 }; 3746 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3747 } 3748 3749 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3750 SourceLocation Loc, 3751 OpenMPDirectiveKind DKind, 3752 const OpenMPScheduleTy &ScheduleKind, 3753 const StaticRTInput &Values) { 3754 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3755 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3756 assert(isOpenMPWorksharingDirective(DKind) && 3757 "Expected loop-based or sections-based directive."); 3758 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3759 isOpenMPLoopDirective(DKind) 3760 ? OMP_IDENT_WORK_LOOP 3761 : OMP_IDENT_WORK_SECTIONS); 3762 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3763 llvm::FunctionCallee StaticInitFunction = 3764 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3765 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3766 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3767 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3768 } 3769 3770 void CGOpenMPRuntime::emitDistributeStaticInit( 3771 CodeGenFunction &CGF, SourceLocation Loc, 3772 OpenMPDistScheduleClauseKind SchedKind, 3773 const CGOpenMPRuntime::StaticRTInput &Values) { 3774 OpenMPSchedType ScheduleNum = 3775 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3776 llvm::Value *UpdatedLocation = 3777 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3778 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3779 llvm::FunctionCallee StaticInitFunction = 3780 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3781 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3782 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3783 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3784 } 3785 3786 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3787 SourceLocation Loc, 3788 OpenMPDirectiveKind DKind) { 3789 if (!CGF.HaveInsertPoint()) 3790 return; 3791 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3792 llvm::Value *Args[] = { 3793 emitUpdateLocation(CGF, Loc, 3794 isOpenMPDistributeDirective(DKind) 3795 ? OMP_IDENT_WORK_DISTRIBUTE 3796 : isOpenMPLoopDirective(DKind) 3797 ? OMP_IDENT_WORK_LOOP 3798 : OMP_IDENT_WORK_SECTIONS), 3799 getThreadID(CGF, Loc)}; 3800 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3801 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3802 Args); 3803 } 3804 3805 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3806 SourceLocation Loc, 3807 unsigned IVSize, 3808 bool IVSigned) { 3809 if (!CGF.HaveInsertPoint()) 3810 return; 3811 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3812 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3813 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3814 } 3815 3816 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3817 SourceLocation Loc, unsigned IVSize, 3818 bool IVSigned, Address IL, 3819 Address LB, Address UB, 3820 Address ST) { 3821 // Call __kmpc_dispatch_next( 3822 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3823 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3824 // kmp_int[32|64] *p_stride); 3825 llvm::Value *Args[] = { 3826 emitUpdateLocation(CGF, Loc), 3827 getThreadID(CGF, Loc), 3828 IL.getPointer(), // &isLastIter 3829 LB.getPointer(), // &Lower 3830 UB.getPointer(), // &Upper 3831 ST.getPointer() // &Stride 3832 }; 3833 llvm::Value *Call = 3834 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3835 return CGF.EmitScalarConversion( 3836 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3837 CGF.getContext().BoolTy, Loc); 3838 } 3839 3840 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3841 llvm::Value *NumThreads, 3842 SourceLocation Loc) { 3843 if (!CGF.HaveInsertPoint()) 3844 return; 3845 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3846 llvm::Value *Args[] = { 3847 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3848 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3849 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3850 Args); 3851 } 3852 3853 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3854 ProcBindKind ProcBind, 3855 SourceLocation Loc) { 3856 if (!CGF.HaveInsertPoint()) 3857 return; 3858 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 3859 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3860 llvm::Value *Args[] = { 3861 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3862 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 3863 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3864 } 3865 3866 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3867 SourceLocation Loc, llvm::AtomicOrdering AO) { 3868 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3869 if (OMPBuilder) { 3870 OMPBuilder->CreateFlush(CGF.Builder); 3871 } else { 3872 if (!CGF.HaveInsertPoint()) 3873 return; 3874 // Build call void __kmpc_flush(ident_t *loc) 3875 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3876 emitUpdateLocation(CGF, Loc)); 3877 } 3878 } 3879 3880 namespace { 3881 /// Indexes of fields for type kmp_task_t. 3882 enum KmpTaskTFields { 3883 /// List of shared variables. 3884 KmpTaskTShareds, 3885 /// Task routine. 3886 KmpTaskTRoutine, 3887 /// Partition id for the untied tasks. 3888 KmpTaskTPartId, 3889 /// Function with call of destructors for private variables. 3890 Data1, 3891 /// Task priority. 3892 Data2, 3893 /// (Taskloops only) Lower bound. 3894 KmpTaskTLowerBound, 3895 /// (Taskloops only) Upper bound. 3896 KmpTaskTUpperBound, 3897 /// (Taskloops only) Stride. 3898 KmpTaskTStride, 3899 /// (Taskloops only) Is last iteration flag. 3900 KmpTaskTLastIter, 3901 /// (Taskloops only) Reduction data. 3902 KmpTaskTReductions, 3903 }; 3904 } // anonymous namespace 3905 3906 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3907 return OffloadEntriesTargetRegion.empty() && 3908 OffloadEntriesDeviceGlobalVar.empty(); 3909 } 3910 3911 /// Initialize target region entry. 3912 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3913 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3914 StringRef ParentName, unsigned LineNum, 3915 unsigned Order) { 3916 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3917 "only required for the device " 3918 "code generation."); 3919 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3920 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3921 OMPTargetRegionEntryTargetRegion); 3922 ++OffloadingEntriesNum; 3923 } 3924 3925 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3926 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3927 StringRef ParentName, unsigned LineNum, 3928 llvm::Constant *Addr, llvm::Constant *ID, 3929 OMPTargetRegionEntryKind Flags) { 3930 // If we are emitting code for a target, the entry is already initialized, 3931 // only has to be registered. 3932 if (CGM.getLangOpts().OpenMPIsDevice) { 3933 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3934 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3935 DiagnosticsEngine::Error, 3936 "Unable to find target region on line '%0' in the device code."); 3937 CGM.getDiags().Report(DiagID) << LineNum; 3938 return; 3939 } 3940 auto &Entry = 3941 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3942 assert(Entry.isValid() && "Entry not initialized!"); 3943 Entry.setAddress(Addr); 3944 Entry.setID(ID); 3945 Entry.setFlags(Flags); 3946 } else { 3947 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3948 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3949 ++OffloadingEntriesNum; 3950 } 3951 } 3952 3953 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3954 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3955 unsigned LineNum) const { 3956 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3957 if (PerDevice == OffloadEntriesTargetRegion.end()) 3958 return false; 3959 auto PerFile = PerDevice->second.find(FileID); 3960 if (PerFile == PerDevice->second.end()) 3961 return false; 3962 auto PerParentName = PerFile->second.find(ParentName); 3963 if (PerParentName == PerFile->second.end()) 3964 return false; 3965 auto PerLine = PerParentName->second.find(LineNum); 3966 if (PerLine == PerParentName->second.end()) 3967 return false; 3968 // Fail if this entry is already registered. 3969 if (PerLine->second.getAddress() || PerLine->second.getID()) 3970 return false; 3971 return true; 3972 } 3973 3974 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3975 const OffloadTargetRegionEntryInfoActTy &Action) { 3976 // Scan all target region entries and perform the provided action. 3977 for (const auto &D : OffloadEntriesTargetRegion) 3978 for (const auto &F : D.second) 3979 for (const auto &P : F.second) 3980 for (const auto &L : P.second) 3981 Action(D.first, F.first, P.first(), L.first, L.second); 3982 } 3983 3984 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3985 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3986 OMPTargetGlobalVarEntryKind Flags, 3987 unsigned Order) { 3988 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3989 "only required for the device " 3990 "code generation."); 3991 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3992 ++OffloadingEntriesNum; 3993 } 3994 3995 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3996 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3997 CharUnits VarSize, 3998 OMPTargetGlobalVarEntryKind Flags, 3999 llvm::GlobalValue::LinkageTypes Linkage) { 4000 if (CGM.getLangOpts().OpenMPIsDevice) { 4001 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4002 assert(Entry.isValid() && Entry.getFlags() == Flags && 4003 "Entry not initialized!"); 4004 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4005 "Resetting with the new address."); 4006 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 4007 if (Entry.getVarSize().isZero()) { 4008 Entry.setVarSize(VarSize); 4009 Entry.setLinkage(Linkage); 4010 } 4011 return; 4012 } 4013 Entry.setVarSize(VarSize); 4014 Entry.setLinkage(Linkage); 4015 Entry.setAddress(Addr); 4016 } else { 4017 if (hasDeviceGlobalVarEntryInfo(VarName)) { 4018 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4019 assert(Entry.isValid() && Entry.getFlags() == Flags && 4020 "Entry not initialized!"); 4021 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4022 "Resetting with the new address."); 4023 if (Entry.getVarSize().isZero()) { 4024 Entry.setVarSize(VarSize); 4025 Entry.setLinkage(Linkage); 4026 } 4027 return; 4028 } 4029 OffloadEntriesDeviceGlobalVar.try_emplace( 4030 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 4031 ++OffloadingEntriesNum; 4032 } 4033 } 4034 4035 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4036 actOnDeviceGlobalVarEntriesInfo( 4037 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4038 // Scan all target region entries and perform the provided action. 4039 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4040 Action(E.getKey(), E.getValue()); 4041 } 4042 4043 void CGOpenMPRuntime::createOffloadEntry( 4044 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4045 llvm::GlobalValue::LinkageTypes Linkage) { 4046 StringRef Name = Addr->getName(); 4047 llvm::Module &M = CGM.getModule(); 4048 llvm::LLVMContext &C = M.getContext(); 4049 4050 // Create constant string with the name. 4051 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4052 4053 std::string StringName = getName({"omp_offloading", "entry_name"}); 4054 auto *Str = new llvm::GlobalVariable( 4055 M, StrPtrInit->getType(), /*isConstant=*/true, 4056 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4057 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4058 4059 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4060 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4061 llvm::ConstantInt::get(CGM.SizeTy, Size), 4062 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4063 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4064 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4065 llvm::GlobalVariable *Entry = createGlobalStruct( 4066 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4067 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4068 4069 // The entry has to be created in the section the linker expects it to be. 4070 Entry->setSection("omp_offloading_entries"); 4071 } 4072 4073 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4074 // Emit the offloading entries and metadata so that the device codegen side 4075 // can easily figure out what to emit. The produced metadata looks like 4076 // this: 4077 // 4078 // !omp_offload.info = !{!1, ...} 4079 // 4080 // Right now we only generate metadata for function that contain target 4081 // regions. 4082 4083 // If we are in simd mode or there are no entries, we don't need to do 4084 // anything. 4085 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 4086 return; 4087 4088 llvm::Module &M = CGM.getModule(); 4089 llvm::LLVMContext &C = M.getContext(); 4090 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4091 SourceLocation, StringRef>, 4092 16> 4093 OrderedEntries(OffloadEntriesInfoManager.size()); 4094 llvm::SmallVector<StringRef, 16> ParentFunctions( 4095 OffloadEntriesInfoManager.size()); 4096 4097 // Auxiliary methods to create metadata values and strings. 4098 auto &&GetMDInt = [this](unsigned V) { 4099 return llvm::ConstantAsMetadata::get( 4100 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4101 }; 4102 4103 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4104 4105 // Create the offloading info metadata node. 4106 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4107 4108 // Create function that emits metadata for each target region entry; 4109 auto &&TargetRegionMetadataEmitter = 4110 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4111 &GetMDString]( 4112 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4113 unsigned Line, 4114 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4115 // Generate metadata for target regions. Each entry of this metadata 4116 // contains: 4117 // - Entry 0 -> Kind of this type of metadata (0). 4118 // - Entry 1 -> Device ID of the file where the entry was identified. 4119 // - Entry 2 -> File ID of the file where the entry was identified. 4120 // - Entry 3 -> Mangled name of the function where the entry was 4121 // identified. 4122 // - Entry 4 -> Line in the file where the entry was identified. 4123 // - Entry 5 -> Order the entry was created. 4124 // The first element of the metadata node is the kind. 4125 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4126 GetMDInt(FileID), GetMDString(ParentName), 4127 GetMDInt(Line), GetMDInt(E.getOrder())}; 4128 4129 SourceLocation Loc; 4130 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4131 E = CGM.getContext().getSourceManager().fileinfo_end(); 4132 I != E; ++I) { 4133 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4134 I->getFirst()->getUniqueID().getFile() == FileID) { 4135 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4136 I->getFirst(), Line, 1); 4137 break; 4138 } 4139 } 4140 // Save this entry in the right position of the ordered entries array. 4141 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4142 ParentFunctions[E.getOrder()] = ParentName; 4143 4144 // Add metadata to the named metadata node. 4145 MD->addOperand(llvm::MDNode::get(C, Ops)); 4146 }; 4147 4148 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4149 TargetRegionMetadataEmitter); 4150 4151 // Create function that emits metadata for each device global variable entry; 4152 auto &&DeviceGlobalVarMetadataEmitter = 4153 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4154 MD](StringRef MangledName, 4155 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4156 &E) { 4157 // Generate metadata for global variables. Each entry of this metadata 4158 // contains: 4159 // - Entry 0 -> Kind of this type of metadata (1). 4160 // - Entry 1 -> Mangled name of the variable. 4161 // - Entry 2 -> Declare target kind. 4162 // - Entry 3 -> Order the entry was created. 4163 // The first element of the metadata node is the kind. 4164 llvm::Metadata *Ops[] = { 4165 GetMDInt(E.getKind()), GetMDString(MangledName), 4166 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4167 4168 // Save this entry in the right position of the ordered entries array. 4169 OrderedEntries[E.getOrder()] = 4170 std::make_tuple(&E, SourceLocation(), MangledName); 4171 4172 // Add metadata to the named metadata node. 4173 MD->addOperand(llvm::MDNode::get(C, Ops)); 4174 }; 4175 4176 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4177 DeviceGlobalVarMetadataEmitter); 4178 4179 for (const auto &E : OrderedEntries) { 4180 assert(std::get<0>(E) && "All ordered entries must exist!"); 4181 if (const auto *CE = 4182 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4183 std::get<0>(E))) { 4184 if (!CE->getID() || !CE->getAddress()) { 4185 // Do not blame the entry if the parent funtion is not emitted. 4186 StringRef FnName = ParentFunctions[CE->getOrder()]; 4187 if (!CGM.GetGlobalValue(FnName)) 4188 continue; 4189 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4190 DiagnosticsEngine::Error, 4191 "Offloading entry for target region in %0 is incorrect: either the " 4192 "address or the ID is invalid."); 4193 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4194 continue; 4195 } 4196 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4197 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4198 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4199 OffloadEntryInfoDeviceGlobalVar>( 4200 std::get<0>(E))) { 4201 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4202 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4203 CE->getFlags()); 4204 switch (Flags) { 4205 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4206 if (CGM.getLangOpts().OpenMPIsDevice && 4207 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4208 continue; 4209 if (!CE->getAddress()) { 4210 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4211 DiagnosticsEngine::Error, "Offloading entry for declare target " 4212 "variable %0 is incorrect: the " 4213 "address is invalid."); 4214 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4215 continue; 4216 } 4217 // The vaiable has no definition - no need to add the entry. 4218 if (CE->getVarSize().isZero()) 4219 continue; 4220 break; 4221 } 4222 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4223 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4224 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4225 "Declaret target link address is set."); 4226 if (CGM.getLangOpts().OpenMPIsDevice) 4227 continue; 4228 if (!CE->getAddress()) { 4229 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4230 DiagnosticsEngine::Error, 4231 "Offloading entry for declare target variable is incorrect: the " 4232 "address is invalid."); 4233 CGM.getDiags().Report(DiagID); 4234 continue; 4235 } 4236 break; 4237 } 4238 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4239 CE->getVarSize().getQuantity(), Flags, 4240 CE->getLinkage()); 4241 } else { 4242 llvm_unreachable("Unsupported entry kind."); 4243 } 4244 } 4245 } 4246 4247 /// Loads all the offload entries information from the host IR 4248 /// metadata. 4249 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4250 // If we are in target mode, load the metadata from the host IR. This code has 4251 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4252 4253 if (!CGM.getLangOpts().OpenMPIsDevice) 4254 return; 4255 4256 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4257 return; 4258 4259 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4260 if (auto EC = Buf.getError()) { 4261 CGM.getDiags().Report(diag::err_cannot_open_file) 4262 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4263 return; 4264 } 4265 4266 llvm::LLVMContext C; 4267 auto ME = expectedToErrorOrAndEmitErrors( 4268 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4269 4270 if (auto EC = ME.getError()) { 4271 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4272 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4273 CGM.getDiags().Report(DiagID) 4274 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4275 return; 4276 } 4277 4278 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4279 if (!MD) 4280 return; 4281 4282 for (llvm::MDNode *MN : MD->operands()) { 4283 auto &&GetMDInt = [MN](unsigned Idx) { 4284 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4285 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4286 }; 4287 4288 auto &&GetMDString = [MN](unsigned Idx) { 4289 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4290 return V->getString(); 4291 }; 4292 4293 switch (GetMDInt(0)) { 4294 default: 4295 llvm_unreachable("Unexpected metadata!"); 4296 break; 4297 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4298 OffloadingEntryInfoTargetRegion: 4299 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4300 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4301 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4302 /*Order=*/GetMDInt(5)); 4303 break; 4304 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4305 OffloadingEntryInfoDeviceGlobalVar: 4306 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4307 /*MangledName=*/GetMDString(1), 4308 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4309 /*Flags=*/GetMDInt(2)), 4310 /*Order=*/GetMDInt(3)); 4311 break; 4312 } 4313 } 4314 } 4315 4316 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4317 if (!KmpRoutineEntryPtrTy) { 4318 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4319 ASTContext &C = CGM.getContext(); 4320 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4321 FunctionProtoType::ExtProtoInfo EPI; 4322 KmpRoutineEntryPtrQTy = C.getPointerType( 4323 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4324 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4325 } 4326 } 4327 4328 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4329 // Make sure the type of the entry is already created. This is the type we 4330 // have to create: 4331 // struct __tgt_offload_entry{ 4332 // void *addr; // Pointer to the offload entry info. 4333 // // (function or global) 4334 // char *name; // Name of the function or global. 4335 // size_t size; // Size of the entry info (0 if it a function). 4336 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4337 // int32_t reserved; // Reserved, to use by the runtime library. 4338 // }; 4339 if (TgtOffloadEntryQTy.isNull()) { 4340 ASTContext &C = CGM.getContext(); 4341 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4342 RD->startDefinition(); 4343 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4344 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4345 addFieldToRecordDecl(C, RD, C.getSizeType()); 4346 addFieldToRecordDecl( 4347 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4348 addFieldToRecordDecl( 4349 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4350 RD->completeDefinition(); 4351 RD->addAttr(PackedAttr::CreateImplicit(C)); 4352 TgtOffloadEntryQTy = C.getRecordType(RD); 4353 } 4354 return TgtOffloadEntryQTy; 4355 } 4356 4357 namespace { 4358 struct PrivateHelpersTy { 4359 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original, 4360 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit) 4361 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy), 4362 PrivateElemInit(PrivateElemInit) {} 4363 const Expr *OriginalRef = nullptr; 4364 const VarDecl *Original = nullptr; 4365 const VarDecl *PrivateCopy = nullptr; 4366 const VarDecl *PrivateElemInit = nullptr; 4367 }; 4368 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4369 } // anonymous namespace 4370 4371 static RecordDecl * 4372 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4373 if (!Privates.empty()) { 4374 ASTContext &C = CGM.getContext(); 4375 // Build struct .kmp_privates_t. { 4376 // /* private vars */ 4377 // }; 4378 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4379 RD->startDefinition(); 4380 for (const auto &Pair : Privates) { 4381 const VarDecl *VD = Pair.second.Original; 4382 QualType Type = VD->getType().getNonReferenceType(); 4383 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4384 if (VD->hasAttrs()) { 4385 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4386 E(VD->getAttrs().end()); 4387 I != E; ++I) 4388 FD->addAttr(*I); 4389 } 4390 } 4391 RD->completeDefinition(); 4392 return RD; 4393 } 4394 return nullptr; 4395 } 4396 4397 static RecordDecl * 4398 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4399 QualType KmpInt32Ty, 4400 QualType KmpRoutineEntryPointerQTy) { 4401 ASTContext &C = CGM.getContext(); 4402 // Build struct kmp_task_t { 4403 // void * shareds; 4404 // kmp_routine_entry_t routine; 4405 // kmp_int32 part_id; 4406 // kmp_cmplrdata_t data1; 4407 // kmp_cmplrdata_t data2; 4408 // For taskloops additional fields: 4409 // kmp_uint64 lb; 4410 // kmp_uint64 ub; 4411 // kmp_int64 st; 4412 // kmp_int32 liter; 4413 // void * reductions; 4414 // }; 4415 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4416 UD->startDefinition(); 4417 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4418 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4419 UD->completeDefinition(); 4420 QualType KmpCmplrdataTy = C.getRecordType(UD); 4421 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4422 RD->startDefinition(); 4423 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4424 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4425 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4426 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4427 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4428 if (isOpenMPTaskLoopDirective(Kind)) { 4429 QualType KmpUInt64Ty = 4430 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4431 QualType KmpInt64Ty = 4432 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4433 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4434 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4435 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4436 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4437 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4438 } 4439 RD->completeDefinition(); 4440 return RD; 4441 } 4442 4443 static RecordDecl * 4444 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4445 ArrayRef<PrivateDataTy> Privates) { 4446 ASTContext &C = CGM.getContext(); 4447 // Build struct kmp_task_t_with_privates { 4448 // kmp_task_t task_data; 4449 // .kmp_privates_t. privates; 4450 // }; 4451 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4452 RD->startDefinition(); 4453 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4454 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4455 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4456 RD->completeDefinition(); 4457 return RD; 4458 } 4459 4460 /// Emit a proxy function which accepts kmp_task_t as the second 4461 /// argument. 4462 /// \code 4463 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4464 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4465 /// For taskloops: 4466 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4467 /// tt->reductions, tt->shareds); 4468 /// return 0; 4469 /// } 4470 /// \endcode 4471 static llvm::Function * 4472 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4473 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4474 QualType KmpTaskTWithPrivatesPtrQTy, 4475 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4476 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4477 llvm::Value *TaskPrivatesMap) { 4478 ASTContext &C = CGM.getContext(); 4479 FunctionArgList Args; 4480 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4481 ImplicitParamDecl::Other); 4482 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4483 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4484 ImplicitParamDecl::Other); 4485 Args.push_back(&GtidArg); 4486 Args.push_back(&TaskTypeArg); 4487 const auto &TaskEntryFnInfo = 4488 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4489 llvm::FunctionType *TaskEntryTy = 4490 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4491 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4492 auto *TaskEntry = llvm::Function::Create( 4493 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4494 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4495 TaskEntry->setDoesNotRecurse(); 4496 CodeGenFunction CGF(CGM); 4497 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4498 Loc, Loc); 4499 4500 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4501 // tt, 4502 // For taskloops: 4503 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4504 // tt->task_data.shareds); 4505 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4506 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4507 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4508 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4509 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4510 const auto *KmpTaskTWithPrivatesQTyRD = 4511 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4512 LValue Base = 4513 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4514 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4515 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4516 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4517 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 4518 4519 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4520 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4521 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4522 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4523 CGF.ConvertTypeForMem(SharedsPtrTy)); 4524 4525 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4526 llvm::Value *PrivatesParam; 4527 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4528 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4529 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4530 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 4531 } else { 4532 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4533 } 4534 4535 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4536 TaskPrivatesMap, 4537 CGF.Builder 4538 .CreatePointerBitCastOrAddrSpaceCast( 4539 TDBase.getAddress(CGF), CGF.VoidPtrTy) 4540 .getPointer()}; 4541 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4542 std::end(CommonArgs)); 4543 if (isOpenMPTaskLoopDirective(Kind)) { 4544 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4545 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4546 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4547 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4548 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4549 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4550 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4551 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4552 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4553 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4554 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4555 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4556 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4557 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4558 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4559 CallArgs.push_back(LBParam); 4560 CallArgs.push_back(UBParam); 4561 CallArgs.push_back(StParam); 4562 CallArgs.push_back(LIParam); 4563 CallArgs.push_back(RParam); 4564 } 4565 CallArgs.push_back(SharedsParam); 4566 4567 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4568 CallArgs); 4569 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4570 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4571 CGF.FinishFunction(); 4572 return TaskEntry; 4573 } 4574 4575 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4576 SourceLocation Loc, 4577 QualType KmpInt32Ty, 4578 QualType KmpTaskTWithPrivatesPtrQTy, 4579 QualType KmpTaskTWithPrivatesQTy) { 4580 ASTContext &C = CGM.getContext(); 4581 FunctionArgList Args; 4582 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4583 ImplicitParamDecl::Other); 4584 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4585 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4586 ImplicitParamDecl::Other); 4587 Args.push_back(&GtidArg); 4588 Args.push_back(&TaskTypeArg); 4589 const auto &DestructorFnInfo = 4590 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4591 llvm::FunctionType *DestructorFnTy = 4592 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4593 std::string Name = 4594 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4595 auto *DestructorFn = 4596 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4597 Name, &CGM.getModule()); 4598 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4599 DestructorFnInfo); 4600 DestructorFn->setDoesNotRecurse(); 4601 CodeGenFunction CGF(CGM); 4602 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4603 Args, Loc, Loc); 4604 4605 LValue Base = CGF.EmitLoadOfPointerLValue( 4606 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4607 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4608 const auto *KmpTaskTWithPrivatesQTyRD = 4609 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4610 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4611 Base = CGF.EmitLValueForField(Base, *FI); 4612 for (const auto *Field : 4613 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4614 if (QualType::DestructionKind DtorKind = 4615 Field->getType().isDestructedType()) { 4616 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4617 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 4618 } 4619 } 4620 CGF.FinishFunction(); 4621 return DestructorFn; 4622 } 4623 4624 /// Emit a privates mapping function for correct handling of private and 4625 /// firstprivate variables. 4626 /// \code 4627 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4628 /// **noalias priv1,..., <tyn> **noalias privn) { 4629 /// *priv1 = &.privates.priv1; 4630 /// ...; 4631 /// *privn = &.privates.privn; 4632 /// } 4633 /// \endcode 4634 static llvm::Value * 4635 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4636 ArrayRef<const Expr *> PrivateVars, 4637 ArrayRef<const Expr *> FirstprivateVars, 4638 ArrayRef<const Expr *> LastprivateVars, 4639 QualType PrivatesQTy, 4640 ArrayRef<PrivateDataTy> Privates) { 4641 ASTContext &C = CGM.getContext(); 4642 FunctionArgList Args; 4643 ImplicitParamDecl TaskPrivatesArg( 4644 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4645 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4646 ImplicitParamDecl::Other); 4647 Args.push_back(&TaskPrivatesArg); 4648 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4649 unsigned Counter = 1; 4650 for (const Expr *E : PrivateVars) { 4651 Args.push_back(ImplicitParamDecl::Create( 4652 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4653 C.getPointerType(C.getPointerType(E->getType())) 4654 .withConst() 4655 .withRestrict(), 4656 ImplicitParamDecl::Other)); 4657 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4658 PrivateVarsPos[VD] = Counter; 4659 ++Counter; 4660 } 4661 for (const Expr *E : FirstprivateVars) { 4662 Args.push_back(ImplicitParamDecl::Create( 4663 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4664 C.getPointerType(C.getPointerType(E->getType())) 4665 .withConst() 4666 .withRestrict(), 4667 ImplicitParamDecl::Other)); 4668 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4669 PrivateVarsPos[VD] = Counter; 4670 ++Counter; 4671 } 4672 for (const Expr *E : LastprivateVars) { 4673 Args.push_back(ImplicitParamDecl::Create( 4674 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4675 C.getPointerType(C.getPointerType(E->getType())) 4676 .withConst() 4677 .withRestrict(), 4678 ImplicitParamDecl::Other)); 4679 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4680 PrivateVarsPos[VD] = Counter; 4681 ++Counter; 4682 } 4683 const auto &TaskPrivatesMapFnInfo = 4684 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4685 llvm::FunctionType *TaskPrivatesMapTy = 4686 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4687 std::string Name = 4688 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4689 auto *TaskPrivatesMap = llvm::Function::Create( 4690 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4691 &CGM.getModule()); 4692 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4693 TaskPrivatesMapFnInfo); 4694 if (CGM.getLangOpts().Optimize) { 4695 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4696 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4697 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4698 } 4699 CodeGenFunction CGF(CGM); 4700 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4701 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4702 4703 // *privi = &.privates.privi; 4704 LValue Base = CGF.EmitLoadOfPointerLValue( 4705 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4706 TaskPrivatesArg.getType()->castAs<PointerType>()); 4707 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4708 Counter = 0; 4709 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4710 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4711 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4712 LValue RefLVal = 4713 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4714 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4715 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 4716 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 4717 ++Counter; 4718 } 4719 CGF.FinishFunction(); 4720 return TaskPrivatesMap; 4721 } 4722 4723 /// Emit initialization for private variables in task-based directives. 4724 static void emitPrivatesInit(CodeGenFunction &CGF, 4725 const OMPExecutableDirective &D, 4726 Address KmpTaskSharedsPtr, LValue TDBase, 4727 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4728 QualType SharedsTy, QualType SharedsPtrTy, 4729 const OMPTaskDataTy &Data, 4730 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4731 ASTContext &C = CGF.getContext(); 4732 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4733 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4734 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4735 ? OMPD_taskloop 4736 : OMPD_task; 4737 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4738 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4739 LValue SrcBase; 4740 bool IsTargetTask = 4741 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4742 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4743 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4744 // PointersArray and SizesArray. The original variables for these arrays are 4745 // not captured and we get their addresses explicitly. 4746 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) || 4747 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4748 SrcBase = CGF.MakeAddrLValue( 4749 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4750 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4751 SharedsTy); 4752 } 4753 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4754 for (const PrivateDataTy &Pair : Privates) { 4755 const VarDecl *VD = Pair.second.PrivateCopy; 4756 const Expr *Init = VD->getAnyInitializer(); 4757 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4758 !CGF.isTrivialInitializer(Init)))) { 4759 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4760 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4761 const VarDecl *OriginalVD = Pair.second.Original; 4762 // Check if the variable is the target-based BasePointersArray, 4763 // PointersArray or SizesArray. 4764 LValue SharedRefLValue; 4765 QualType Type = PrivateLValue.getType(); 4766 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4767 if (IsTargetTask && !SharedField) { 4768 assert(isa<ImplicitParamDecl>(OriginalVD) && 4769 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4770 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4771 ->getNumParams() == 0 && 4772 isa<TranslationUnitDecl>( 4773 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4774 ->getDeclContext()) && 4775 "Expected artificial target data variable."); 4776 SharedRefLValue = 4777 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4778 } else if (ForDup) { 4779 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4780 SharedRefLValue = CGF.MakeAddrLValue( 4781 Address(SharedRefLValue.getPointer(CGF), 4782 C.getDeclAlign(OriginalVD)), 4783 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4784 SharedRefLValue.getTBAAInfo()); 4785 } else { 4786 InlinedOpenMPRegionRAII Region( 4787 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown, 4788 /*HasCancel=*/false); 4789 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 4790 } 4791 if (Type->isArrayType()) { 4792 // Initialize firstprivate array. 4793 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4794 // Perform simple memcpy. 4795 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4796 } else { 4797 // Initialize firstprivate array using element-by-element 4798 // initialization. 4799 CGF.EmitOMPAggregateAssign( 4800 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 4801 Type, 4802 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4803 Address SrcElement) { 4804 // Clean up any temporaries needed by the initialization. 4805 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4806 InitScope.addPrivate( 4807 Elem, [SrcElement]() -> Address { return SrcElement; }); 4808 (void)InitScope.Privatize(); 4809 // Emit initialization for single element. 4810 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4811 CGF, &CapturesInfo); 4812 CGF.EmitAnyExprToMem(Init, DestElement, 4813 Init->getType().getQualifiers(), 4814 /*IsInitializer=*/false); 4815 }); 4816 } 4817 } else { 4818 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4819 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 4820 return SharedRefLValue.getAddress(CGF); 4821 }); 4822 (void)InitScope.Privatize(); 4823 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4824 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4825 /*capturedByInit=*/false); 4826 } 4827 } else { 4828 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4829 } 4830 } 4831 ++FI; 4832 } 4833 } 4834 4835 /// Check if duplication function is required for taskloops. 4836 static bool checkInitIsRequired(CodeGenFunction &CGF, 4837 ArrayRef<PrivateDataTy> Privates) { 4838 bool InitRequired = false; 4839 for (const PrivateDataTy &Pair : Privates) { 4840 const VarDecl *VD = Pair.second.PrivateCopy; 4841 const Expr *Init = VD->getAnyInitializer(); 4842 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4843 !CGF.isTrivialInitializer(Init)); 4844 if (InitRequired) 4845 break; 4846 } 4847 return InitRequired; 4848 } 4849 4850 4851 /// Emit task_dup function (for initialization of 4852 /// private/firstprivate/lastprivate vars and last_iter flag) 4853 /// \code 4854 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4855 /// lastpriv) { 4856 /// // setup lastprivate flag 4857 /// task_dst->last = lastpriv; 4858 /// // could be constructor calls here... 4859 /// } 4860 /// \endcode 4861 static llvm::Value * 4862 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4863 const OMPExecutableDirective &D, 4864 QualType KmpTaskTWithPrivatesPtrQTy, 4865 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4866 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4867 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4868 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4869 ASTContext &C = CGM.getContext(); 4870 FunctionArgList Args; 4871 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4872 KmpTaskTWithPrivatesPtrQTy, 4873 ImplicitParamDecl::Other); 4874 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4875 KmpTaskTWithPrivatesPtrQTy, 4876 ImplicitParamDecl::Other); 4877 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4878 ImplicitParamDecl::Other); 4879 Args.push_back(&DstArg); 4880 Args.push_back(&SrcArg); 4881 Args.push_back(&LastprivArg); 4882 const auto &TaskDupFnInfo = 4883 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4884 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4885 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4886 auto *TaskDup = llvm::Function::Create( 4887 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4888 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4889 TaskDup->setDoesNotRecurse(); 4890 CodeGenFunction CGF(CGM); 4891 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4892 Loc); 4893 4894 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4895 CGF.GetAddrOfLocalVar(&DstArg), 4896 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4897 // task_dst->liter = lastpriv; 4898 if (WithLastIter) { 4899 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4900 LValue Base = CGF.EmitLValueForField( 4901 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4902 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4903 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4904 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4905 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4906 } 4907 4908 // Emit initial values for private copies (if any). 4909 assert(!Privates.empty()); 4910 Address KmpTaskSharedsPtr = Address::invalid(); 4911 if (!Data.FirstprivateVars.empty()) { 4912 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4913 CGF.GetAddrOfLocalVar(&SrcArg), 4914 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4915 LValue Base = CGF.EmitLValueForField( 4916 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4917 KmpTaskSharedsPtr = Address( 4918 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4919 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4920 KmpTaskTShareds)), 4921 Loc), 4922 CGF.getNaturalTypeAlignment(SharedsTy)); 4923 } 4924 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4925 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4926 CGF.FinishFunction(); 4927 return TaskDup; 4928 } 4929 4930 /// Checks if destructor function is required to be generated. 4931 /// \return true if cleanups are required, false otherwise. 4932 static bool 4933 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4934 bool NeedsCleanup = false; 4935 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4936 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4937 for (const FieldDecl *FD : PrivateRD->fields()) { 4938 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4939 if (NeedsCleanup) 4940 break; 4941 } 4942 return NeedsCleanup; 4943 } 4944 4945 CGOpenMPRuntime::TaskResultTy 4946 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4947 const OMPExecutableDirective &D, 4948 llvm::Function *TaskFunction, QualType SharedsTy, 4949 Address Shareds, const OMPTaskDataTy &Data) { 4950 ASTContext &C = CGM.getContext(); 4951 llvm::SmallVector<PrivateDataTy, 4> Privates; 4952 // Aggregate privates and sort them by the alignment. 4953 const auto *I = Data.PrivateCopies.begin(); 4954 for (const Expr *E : Data.PrivateVars) { 4955 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4956 Privates.emplace_back( 4957 C.getDeclAlign(VD), 4958 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4959 /*PrivateElemInit=*/nullptr)); 4960 ++I; 4961 } 4962 I = Data.FirstprivateCopies.begin(); 4963 const auto *IElemInitRef = Data.FirstprivateInits.begin(); 4964 for (const Expr *E : Data.FirstprivateVars) { 4965 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4966 Privates.emplace_back( 4967 C.getDeclAlign(VD), 4968 PrivateHelpersTy( 4969 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4970 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4971 ++I; 4972 ++IElemInitRef; 4973 } 4974 I = Data.LastprivateCopies.begin(); 4975 for (const Expr *E : Data.LastprivateVars) { 4976 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4977 Privates.emplace_back( 4978 C.getDeclAlign(VD), 4979 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4980 /*PrivateElemInit=*/nullptr)); 4981 ++I; 4982 } 4983 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 4984 return L.first > R.first; 4985 }); 4986 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 4987 // Build type kmp_routine_entry_t (if not built yet). 4988 emitKmpRoutineEntryT(KmpInt32Ty); 4989 // Build type kmp_task_t (if not built yet). 4990 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 4991 if (SavedKmpTaskloopTQTy.isNull()) { 4992 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4993 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4994 } 4995 KmpTaskTQTy = SavedKmpTaskloopTQTy; 4996 } else { 4997 assert((D.getDirectiveKind() == OMPD_task || 4998 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 4999 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5000 "Expected taskloop, task or target directive"); 5001 if (SavedKmpTaskTQTy.isNull()) { 5002 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5003 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5004 } 5005 KmpTaskTQTy = SavedKmpTaskTQTy; 5006 } 5007 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5008 // Build particular struct kmp_task_t for the given task. 5009 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5010 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5011 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5012 QualType KmpTaskTWithPrivatesPtrQTy = 5013 C.getPointerType(KmpTaskTWithPrivatesQTy); 5014 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5015 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5016 KmpTaskTWithPrivatesTy->getPointerTo(); 5017 llvm::Value *KmpTaskTWithPrivatesTySize = 5018 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5019 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5020 5021 // Emit initial values for private copies (if any). 5022 llvm::Value *TaskPrivatesMap = nullptr; 5023 llvm::Type *TaskPrivatesMapTy = 5024 std::next(TaskFunction->arg_begin(), 3)->getType(); 5025 if (!Privates.empty()) { 5026 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5027 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5028 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5029 FI->getType(), Privates); 5030 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5031 TaskPrivatesMap, TaskPrivatesMapTy); 5032 } else { 5033 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5034 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5035 } 5036 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5037 // kmp_task_t *tt); 5038 llvm::Function *TaskEntry = emitProxyTaskFunction( 5039 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5040 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5041 TaskPrivatesMap); 5042 5043 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5044 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5045 // kmp_routine_entry_t *task_entry); 5046 // Task flags. Format is taken from 5047 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5048 // description of kmp_tasking_flags struct. 5049 enum { 5050 TiedFlag = 0x1, 5051 FinalFlag = 0x2, 5052 DestructorsFlag = 0x8, 5053 PriorityFlag = 0x20, 5054 DetachableFlag = 0x40, 5055 }; 5056 unsigned Flags = Data.Tied ? TiedFlag : 0; 5057 bool NeedsCleanup = false; 5058 if (!Privates.empty()) { 5059 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5060 if (NeedsCleanup) 5061 Flags = Flags | DestructorsFlag; 5062 } 5063 if (Data.Priority.getInt()) 5064 Flags = Flags | PriorityFlag; 5065 if (D.hasClausesOfKind<OMPDetachClause>()) 5066 Flags = Flags | DetachableFlag; 5067 llvm::Value *TaskFlags = 5068 Data.Final.getPointer() 5069 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5070 CGF.Builder.getInt32(FinalFlag), 5071 CGF.Builder.getInt32(/*C=*/0)) 5072 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5073 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5074 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5075 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5076 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5077 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5078 TaskEntry, KmpRoutineEntryPtrTy)}; 5079 llvm::Value *NewTask; 5080 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5081 // Check if we have any device clause associated with the directive. 5082 const Expr *Device = nullptr; 5083 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5084 Device = C->getDevice(); 5085 // Emit device ID if any otherwise use default value. 5086 llvm::Value *DeviceID; 5087 if (Device) 5088 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5089 CGF.Int64Ty, /*isSigned=*/true); 5090 else 5091 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5092 AllocArgs.push_back(DeviceID); 5093 NewTask = CGF.EmitRuntimeCall( 5094 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5095 } else { 5096 NewTask = CGF.EmitRuntimeCall( 5097 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5098 } 5099 // Emit detach clause initialization. 5100 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid, 5101 // task_descriptor); 5102 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) { 5103 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts(); 5104 LValue EvtLVal = CGF.EmitLValue(Evt); 5105 5106 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 5107 // int gtid, kmp_task_t *task); 5108 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc()); 5109 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc()); 5110 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false); 5111 llvm::Value *EvtVal = CGF.EmitRuntimeCall( 5112 createRuntimeFunction(OMPRTL__kmpc_task_allow_completion_event), 5113 {Loc, Tid, NewTask}); 5114 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(), 5115 Evt->getExprLoc()); 5116 CGF.EmitStoreOfScalar(EvtVal, EvtLVal); 5117 } 5118 llvm::Value *NewTaskNewTaskTTy = 5119 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5120 NewTask, KmpTaskTWithPrivatesPtrTy); 5121 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5122 KmpTaskTWithPrivatesQTy); 5123 LValue TDBase = 5124 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5125 // Fill the data in the resulting kmp_task_t record. 5126 // Copy shareds if there are any. 5127 Address KmpTaskSharedsPtr = Address::invalid(); 5128 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5129 KmpTaskSharedsPtr = 5130 Address(CGF.EmitLoadOfScalar( 5131 CGF.EmitLValueForField( 5132 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5133 KmpTaskTShareds)), 5134 Loc), 5135 CGF.getNaturalTypeAlignment(SharedsTy)); 5136 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5137 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5138 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5139 } 5140 // Emit initial values for private copies (if any). 5141 TaskResultTy Result; 5142 if (!Privates.empty()) { 5143 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5144 SharedsTy, SharedsPtrTy, Data, Privates, 5145 /*ForDup=*/false); 5146 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5147 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5148 Result.TaskDupFn = emitTaskDupFunction( 5149 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5150 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5151 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5152 } 5153 } 5154 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5155 enum { Priority = 0, Destructors = 1 }; 5156 // Provide pointer to function with destructors for privates. 5157 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5158 const RecordDecl *KmpCmplrdataUD = 5159 (*FI)->getType()->getAsUnionType()->getDecl(); 5160 if (NeedsCleanup) { 5161 llvm::Value *DestructorFn = emitDestructorsFunction( 5162 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5163 KmpTaskTWithPrivatesQTy); 5164 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5165 LValue DestructorsLV = CGF.EmitLValueForField( 5166 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5167 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5168 DestructorFn, KmpRoutineEntryPtrTy), 5169 DestructorsLV); 5170 } 5171 // Set priority. 5172 if (Data.Priority.getInt()) { 5173 LValue Data2LV = CGF.EmitLValueForField( 5174 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5175 LValue PriorityLV = CGF.EmitLValueForField( 5176 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5177 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5178 } 5179 Result.NewTask = NewTask; 5180 Result.TaskEntry = TaskEntry; 5181 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5182 Result.TDBase = TDBase; 5183 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5184 return Result; 5185 } 5186 5187 namespace { 5188 /// Dependence kind for RTL. 5189 enum RTLDependenceKindTy { 5190 DepIn = 0x01, 5191 DepInOut = 0x3, 5192 DepMutexInOutSet = 0x4 5193 }; 5194 /// Fields ids in kmp_depend_info record. 5195 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5196 } // namespace 5197 5198 /// Translates internal dependency kind into the runtime kind. 5199 static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) { 5200 RTLDependenceKindTy DepKind; 5201 switch (K) { 5202 case OMPC_DEPEND_in: 5203 DepKind = DepIn; 5204 break; 5205 // Out and InOut dependencies must use the same code. 5206 case OMPC_DEPEND_out: 5207 case OMPC_DEPEND_inout: 5208 DepKind = DepInOut; 5209 break; 5210 case OMPC_DEPEND_mutexinoutset: 5211 DepKind = DepMutexInOutSet; 5212 break; 5213 case OMPC_DEPEND_source: 5214 case OMPC_DEPEND_sink: 5215 case OMPC_DEPEND_depobj: 5216 case OMPC_DEPEND_unknown: 5217 llvm_unreachable("Unknown task dependence type"); 5218 } 5219 return DepKind; 5220 } 5221 5222 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 5223 static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, 5224 QualType &FlagsTy) { 5225 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5226 if (KmpDependInfoTy.isNull()) { 5227 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5228 KmpDependInfoRD->startDefinition(); 5229 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5230 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5231 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5232 KmpDependInfoRD->completeDefinition(); 5233 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5234 } 5235 } 5236 5237 std::pair<llvm::Value *, LValue> 5238 CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, 5239 SourceLocation Loc) { 5240 ASTContext &C = CGM.getContext(); 5241 QualType FlagsTy; 5242 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5243 RecordDecl *KmpDependInfoRD = 5244 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5245 LValue Base = CGF.EmitLoadOfPointerLValue( 5246 DepobjLVal.getAddress(CGF), 5247 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5248 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5249 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5250 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 5251 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 5252 Base.getTBAAInfo()); 5253 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5254 Addr.getPointer(), 5255 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5256 LValue NumDepsBase = CGF.MakeAddrLValue( 5257 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 5258 Base.getBaseInfo(), Base.getTBAAInfo()); 5259 // NumDeps = deps[i].base_addr; 5260 LValue BaseAddrLVal = CGF.EmitLValueForField( 5261 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5262 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc); 5263 return std::make_pair(NumDeps, Base); 5264 } 5265 5266 namespace { 5267 /// Loop generator for OpenMP iterator expression. 5268 class OMPIteratorGeneratorScope final 5269 : public CodeGenFunction::OMPPrivateScope { 5270 CodeGenFunction &CGF; 5271 const OMPIteratorExpr *E = nullptr; 5272 SmallVector<CodeGenFunction::JumpDest, 4> ContDests; 5273 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests; 5274 OMPIteratorGeneratorScope() = delete; 5275 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete; 5276 5277 public: 5278 OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E) 5279 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) { 5280 if (!E) 5281 return; 5282 SmallVector<llvm::Value *, 4> Uppers; 5283 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 5284 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper)); 5285 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I)); 5286 addPrivate(VD, [&CGF, VD]() { 5287 return CGF.CreateMemTemp(VD->getType(), VD->getName()); 5288 }); 5289 const OMPIteratorHelperData &HelperData = E->getHelper(I); 5290 addPrivate(HelperData.CounterVD, [&CGF, &HelperData]() { 5291 return CGF.CreateMemTemp(HelperData.CounterVD->getType(), 5292 "counter.addr"); 5293 }); 5294 } 5295 Privatize(); 5296 5297 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 5298 const OMPIteratorHelperData &HelperData = E->getHelper(I); 5299 LValue CLVal = 5300 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD), 5301 HelperData.CounterVD->getType()); 5302 // Counter = 0; 5303 CGF.EmitStoreOfScalar( 5304 llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0), 5305 CLVal); 5306 CodeGenFunction::JumpDest &ContDest = 5307 ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont")); 5308 CodeGenFunction::JumpDest &ExitDest = 5309 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit")); 5310 // N = <number-of_iterations>; 5311 llvm::Value *N = Uppers[I]; 5312 // cont: 5313 // if (Counter < N) goto body; else goto exit; 5314 CGF.EmitBlock(ContDest.getBlock()); 5315 auto *CVal = 5316 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation()); 5317 llvm::Value *Cmp = 5318 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType() 5319 ? CGF.Builder.CreateICmpSLT(CVal, N) 5320 : CGF.Builder.CreateICmpULT(CVal, N); 5321 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body"); 5322 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock()); 5323 // body: 5324 CGF.EmitBlock(BodyBB); 5325 // Iteri = Begini + Counter * Stepi; 5326 CGF.EmitIgnoredExpr(HelperData.Update); 5327 } 5328 } 5329 ~OMPIteratorGeneratorScope() { 5330 if (!E) 5331 return; 5332 for (unsigned I = E->numOfIterators(); I > 0; --I) { 5333 // Counter = Counter + 1; 5334 const OMPIteratorHelperData &HelperData = E->getHelper(I - 1); 5335 CGF.EmitIgnoredExpr(HelperData.CounterUpdate); 5336 // goto cont; 5337 CGF.EmitBranchThroughCleanup(ContDests[I - 1]); 5338 // exit: 5339 CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1); 5340 } 5341 } 5342 }; 5343 } // namespace 5344 5345 static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 5346 llvm::PointerUnion<unsigned *, LValue *> Pos, 5347 const OMPTaskDataTy::DependData &Data, 5348 Address DependenciesArray) { 5349 CodeGenModule &CGM = CGF.CGM; 5350 ASTContext &C = CGM.getContext(); 5351 QualType FlagsTy; 5352 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5353 RecordDecl *KmpDependInfoRD = 5354 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5355 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5356 5357 OMPIteratorGeneratorScope IteratorScope( 5358 CGF, cast_or_null<OMPIteratorExpr>( 5359 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 5360 : nullptr)); 5361 for (const Expr *E : Data.DepExprs) { 5362 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E); 5363 llvm::Value *Addr; 5364 if (OASE) { 5365 const Expr *Base = OASE->getBase(); 5366 Addr = CGF.EmitScalarExpr(Base); 5367 } else { 5368 Addr = CGF.EmitLValue(E).getPointer(CGF); 5369 } 5370 llvm::Value *Size; 5371 QualType Ty = E->getType(); 5372 if (OASE) { 5373 Size = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType()); 5374 for (const Expr *SE : OASE->getDimensions()) { 5375 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 5376 Sz = CGF.EmitScalarConversion(Sz, SE->getType(), 5377 CGF.getContext().getSizeType(), 5378 SE->getExprLoc()); 5379 Size = CGF.Builder.CreateNUWMul(Size, Sz); 5380 } 5381 } else if (const auto *ASE = 5382 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5383 LValue UpAddrLVal = 5384 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5385 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 5386 UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 5387 llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGM.SizeTy); 5388 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5389 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5390 } else { 5391 Size = CGF.getTypeSize(Ty); 5392 } 5393 LValue Base; 5394 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 5395 Base = CGF.MakeAddrLValue( 5396 CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy); 5397 } else { 5398 LValue &PosLVal = *Pos.get<LValue *>(); 5399 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 5400 Base = CGF.MakeAddrLValue( 5401 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Idx), 5402 DependenciesArray.getAlignment()), 5403 KmpDependInfoTy); 5404 } 5405 // deps[i].base_addr = &<Dependencies[i].second>; 5406 LValue BaseAddrLVal = CGF.EmitLValueForField( 5407 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5408 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 5409 BaseAddrLVal); 5410 // deps[i].len = sizeof(<Dependencies[i].second>); 5411 LValue LenLVal = CGF.EmitLValueForField( 5412 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5413 CGF.EmitStoreOfScalar(Size, LenLVal); 5414 // deps[i].flags = <Dependencies[i].first>; 5415 RTLDependenceKindTy DepKind = translateDependencyKind(Data.DepKind); 5416 LValue FlagsLVal = CGF.EmitLValueForField( 5417 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5418 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5419 FlagsLVal); 5420 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 5421 ++(*P); 5422 } else { 5423 LValue &PosLVal = *Pos.get<LValue *>(); 5424 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 5425 Idx = CGF.Builder.CreateNUWAdd(Idx, 5426 llvm::ConstantInt::get(Idx->getType(), 1)); 5427 CGF.EmitStoreOfScalar(Idx, PosLVal); 5428 } 5429 } 5430 } 5431 5432 static SmallVector<llvm::Value *, 4> 5433 emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 5434 const OMPTaskDataTy::DependData &Data) { 5435 assert(Data.DepKind == OMPC_DEPEND_depobj && 5436 "Expected depobj dependecy kind."); 5437 SmallVector<llvm::Value *, 4> Sizes; 5438 SmallVector<LValue, 4> SizeLVals; 5439 ASTContext &C = CGF.getContext(); 5440 QualType FlagsTy; 5441 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5442 RecordDecl *KmpDependInfoRD = 5443 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5444 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5445 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 5446 { 5447 OMPIteratorGeneratorScope IteratorScope( 5448 CGF, cast_or_null<OMPIteratorExpr>( 5449 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 5450 : nullptr)); 5451 for (const Expr *E : Data.DepExprs) { 5452 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 5453 LValue Base = CGF.EmitLoadOfPointerLValue( 5454 DepobjLVal.getAddress(CGF), 5455 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5456 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5457 Base.getAddress(CGF), KmpDependInfoPtrT); 5458 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 5459 Base.getTBAAInfo()); 5460 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5461 Addr.getPointer(), 5462 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5463 LValue NumDepsBase = CGF.MakeAddrLValue( 5464 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 5465 Base.getBaseInfo(), Base.getTBAAInfo()); 5466 // NumDeps = deps[i].base_addr; 5467 LValue BaseAddrLVal = CGF.EmitLValueForField( 5468 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5469 llvm::Value *NumDeps = 5470 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 5471 LValue NumLVal = CGF.MakeAddrLValue( 5472 CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"), 5473 C.getUIntPtrType()); 5474 CGF.InitTempAlloca(NumLVal.getAddress(CGF), 5475 llvm::ConstantInt::get(CGF.IntPtrTy, 0)); 5476 llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc()); 5477 llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps); 5478 CGF.EmitStoreOfScalar(Add, NumLVal); 5479 SizeLVals.push_back(NumLVal); 5480 } 5481 } 5482 for (unsigned I = 0, E = SizeLVals.size(); I < E; ++I) { 5483 llvm::Value *Size = 5484 CGF.EmitLoadOfScalar(SizeLVals[I], Data.DepExprs[I]->getExprLoc()); 5485 Sizes.push_back(Size); 5486 } 5487 return Sizes; 5488 } 5489 5490 static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 5491 LValue PosLVal, 5492 const OMPTaskDataTy::DependData &Data, 5493 Address DependenciesArray) { 5494 assert(Data.DepKind == OMPC_DEPEND_depobj && 5495 "Expected depobj dependecy kind."); 5496 ASTContext &C = CGF.getContext(); 5497 QualType FlagsTy; 5498 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5499 RecordDecl *KmpDependInfoRD = 5500 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5501 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5502 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 5503 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy); 5504 { 5505 OMPIteratorGeneratorScope IteratorScope( 5506 CGF, cast_or_null<OMPIteratorExpr>( 5507 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 5508 : nullptr)); 5509 for (unsigned I = 0, End = Data.DepExprs.size(); I < End; ++I) { 5510 const Expr *E = Data.DepExprs[I]; 5511 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 5512 LValue Base = CGF.EmitLoadOfPointerLValue( 5513 DepobjLVal.getAddress(CGF), 5514 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5515 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5516 Base.getAddress(CGF), KmpDependInfoPtrT); 5517 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 5518 Base.getTBAAInfo()); 5519 5520 // Get number of elements in a single depobj. 5521 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5522 Addr.getPointer(), 5523 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5524 LValue NumDepsBase = CGF.MakeAddrLValue( 5525 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 5526 Base.getBaseInfo(), Base.getTBAAInfo()); 5527 // NumDeps = deps[i].base_addr; 5528 LValue BaseAddrLVal = CGF.EmitLValueForField( 5529 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5530 llvm::Value *NumDeps = 5531 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 5532 5533 // memcopy dependency data. 5534 llvm::Value *Size = CGF.Builder.CreateNUWMul( 5535 ElSize, 5536 CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); 5537 llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 5538 Address DepAddr = 5539 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Pos), 5540 DependenciesArray.getAlignment()); 5541 CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); 5542 5543 // Increase pos. 5544 // pos += size; 5545 llvm::Value *Add = CGF.Builder.CreateNUWAdd(Pos, NumDeps); 5546 CGF.EmitStoreOfScalar(Add, PosLVal); 5547 } 5548 } 5549 } 5550 5551 std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause( 5552 CodeGenFunction &CGF, ArrayRef<OMPTaskDataTy::DependData> Dependencies, 5553 SourceLocation Loc) { 5554 if (llvm::all_of(Dependencies, [](const OMPTaskDataTy::DependData &D) { 5555 return D.DepExprs.empty(); 5556 })) 5557 return std::make_pair(nullptr, Address::invalid()); 5558 // Process list of dependencies. 5559 ASTContext &C = CGM.getContext(); 5560 Address DependenciesArray = Address::invalid(); 5561 llvm::Value *NumOfElements = nullptr; 5562 unsigned NumDependencies = std::accumulate( 5563 Dependencies.begin(), Dependencies.end(), 0, 5564 [](unsigned V, const OMPTaskDataTy::DependData &D) { 5565 return D.DepKind == OMPC_DEPEND_depobj 5566 ? V 5567 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size())); 5568 }); 5569 QualType FlagsTy; 5570 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5571 bool HasDepobjDeps = false; 5572 bool HasRegularWithIterators = false; 5573 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0); 5574 llvm::Value *NumOfRegularWithIterators = 5575 llvm::ConstantInt::get(CGF.IntPtrTy, 1); 5576 // Calculate number of depobj dependecies and regular deps with the iterators. 5577 for (const OMPTaskDataTy::DependData &D : Dependencies) { 5578 if (D.DepKind == OMPC_DEPEND_depobj) { 5579 SmallVector<llvm::Value *, 4> Sizes = 5580 emitDepobjElementsSizes(CGF, KmpDependInfoTy, D); 5581 for (llvm::Value *Size : Sizes) { 5582 NumOfDepobjElements = 5583 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, Size); 5584 } 5585 HasDepobjDeps = true; 5586 continue; 5587 } 5588 // Include number of iterations, if any. 5589 if (const auto *IE = cast_or_null<OMPIteratorExpr>(D.IteratorExpr)) { 5590 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 5591 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 5592 Sz = CGF.Builder.CreateIntCast(Sz, CGF.IntPtrTy, /*isSigned=*/false); 5593 NumOfRegularWithIterators = 5594 CGF.Builder.CreateNUWMul(NumOfRegularWithIterators, Sz); 5595 } 5596 HasRegularWithIterators = true; 5597 continue; 5598 } 5599 } 5600 5601 QualType KmpDependInfoArrayTy; 5602 if (HasDepobjDeps || HasRegularWithIterators) { 5603 NumOfElements = llvm::ConstantInt::get(CGM.IntPtrTy, NumDependencies, 5604 /*isSigned=*/false); 5605 if (HasDepobjDeps) { 5606 NumOfElements = 5607 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements); 5608 } 5609 if (HasRegularWithIterators) { 5610 NumOfElements = 5611 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements); 5612 } 5613 OpaqueValueExpr OVE(Loc, 5614 C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0), 5615 VK_RValue); 5616 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 5617 RValue::get(NumOfElements)); 5618 KmpDependInfoArrayTy = 5619 C.getVariableArrayType(KmpDependInfoTy, &OVE, ArrayType::Normal, 5620 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 5621 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy); 5622 // Properly emit variable-sized array. 5623 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy, 5624 ImplicitParamDecl::Other); 5625 CGF.EmitVarDecl(*PD); 5626 DependenciesArray = CGF.GetAddrOfLocalVar(PD); 5627 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 5628 /*isSigned=*/false); 5629 } else { 5630 KmpDependInfoArrayTy = C.getConstantArrayType( 5631 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), nullptr, 5632 ArrayType::Normal, /*IndexTypeQuals=*/0); 5633 DependenciesArray = 5634 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5635 DependenciesArray = CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0); 5636 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 5637 /*isSigned=*/false); 5638 } 5639 unsigned Pos = 0; 5640 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 5641 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 5642 Dependencies[I].IteratorExpr) 5643 continue; 5644 emitDependData(CGF, KmpDependInfoTy, &Pos, Dependencies[I], 5645 DependenciesArray); 5646 } 5647 // Copy regular dependecies with iterators. 5648 LValue PosLVal = CGF.MakeAddrLValue( 5649 CGF.CreateMemTemp(C.getSizeType(), "dep.counter.addr"), C.getSizeType()); 5650 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 5651 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 5652 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 5653 !Dependencies[I].IteratorExpr) 5654 continue; 5655 emitDependData(CGF, KmpDependInfoTy, &PosLVal, Dependencies[I], 5656 DependenciesArray); 5657 } 5658 // Copy final depobj arrays without iterators. 5659 if (HasDepobjDeps) { 5660 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 5661 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj) 5662 continue; 5663 emitDepobjElements(CGF, KmpDependInfoTy, PosLVal, Dependencies[I], 5664 DependenciesArray); 5665 } 5666 } 5667 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5668 DependenciesArray, CGF.VoidPtrTy); 5669 return std::make_pair(NumOfElements, DependenciesArray); 5670 } 5671 5672 Address CGOpenMPRuntime::emitDepobjDependClause( 5673 CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, 5674 SourceLocation Loc) { 5675 if (Dependencies.DepExprs.empty()) 5676 return Address::invalid(); 5677 // Process list of dependencies. 5678 ASTContext &C = CGM.getContext(); 5679 Address DependenciesArray = Address::invalid(); 5680 unsigned NumDependencies = Dependencies.DepExprs.size(); 5681 QualType FlagsTy; 5682 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5683 RecordDecl *KmpDependInfoRD = 5684 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5685 5686 llvm::Value *Size; 5687 // Define type kmp_depend_info[<Dependencies.size()>]; 5688 // For depobj reserve one extra element to store the number of elements. 5689 // It is required to handle depobj(x) update(in) construct. 5690 // kmp_depend_info[<Dependencies.size()>] deps; 5691 llvm::Value *NumDepsVal; 5692 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoTy); 5693 if (const auto *IE = 5694 cast_or_null<OMPIteratorExpr>(Dependencies.IteratorExpr)) { 5695 NumDepsVal = llvm::ConstantInt::get(CGF.SizeTy, 1); 5696 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 5697 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 5698 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 5699 NumDepsVal = CGF.Builder.CreateNUWMul(NumDepsVal, Sz); 5700 } 5701 Size = CGF.Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.SizeTy, 1), 5702 NumDepsVal); 5703 CharUnits SizeInBytes = 5704 C.getTypeSizeInChars(KmpDependInfoTy).alignTo(Align); 5705 llvm::Value *RecSize = CGM.getSize(SizeInBytes); 5706 Size = CGF.Builder.CreateNUWMul(Size, RecSize); 5707 NumDepsVal = 5708 CGF.Builder.CreateIntCast(NumDepsVal, CGF.IntPtrTy, /*isSigned=*/false); 5709 } else { 5710 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5711 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1), 5712 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5713 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy); 5714 Size = CGM.getSize(Sz.alignTo(Align)); 5715 NumDepsVal = llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies); 5716 } 5717 // Need to allocate on the dynamic memory. 5718 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5719 // Use default allocator. 5720 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5721 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 5722 5723 llvm::Value *Addr = CGF.EmitRuntimeCall( 5724 createRuntimeFunction(OMPRTL__kmpc_alloc), Args, ".dep.arr.addr"); 5725 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5726 Addr, CGF.ConvertTypeForMem(KmpDependInfoTy)->getPointerTo()); 5727 DependenciesArray = Address(Addr, Align); 5728 // Write number of elements in the first element of array for depobj. 5729 LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy); 5730 // deps[i].base_addr = NumDependencies; 5731 LValue BaseAddrLVal = CGF.EmitLValueForField( 5732 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5733 CGF.EmitStoreOfScalar(NumDepsVal, BaseAddrLVal); 5734 llvm::PointerUnion<unsigned *, LValue *> Pos; 5735 unsigned Idx = 1; 5736 LValue PosLVal; 5737 if (Dependencies.IteratorExpr) { 5738 PosLVal = CGF.MakeAddrLValue( 5739 CGF.CreateMemTemp(C.getSizeType(), "iterator.counter.addr"), 5740 C.getSizeType()); 5741 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Idx), PosLVal, 5742 /*IsInit=*/true); 5743 Pos = &PosLVal; 5744 } else { 5745 Pos = &Idx; 5746 } 5747 emitDependData(CGF, KmpDependInfoTy, Pos, Dependencies, DependenciesArray); 5748 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5749 CGF.Builder.CreateConstGEP(DependenciesArray, 1), CGF.VoidPtrTy); 5750 return DependenciesArray; 5751 } 5752 5753 void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, 5754 SourceLocation Loc) { 5755 ASTContext &C = CGM.getContext(); 5756 QualType FlagsTy; 5757 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5758 LValue Base = CGF.EmitLoadOfPointerLValue( 5759 DepobjLVal.getAddress(CGF), 5760 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5761 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5762 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5763 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 5764 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5765 Addr.getPointer(), 5766 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5767 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, 5768 CGF.VoidPtrTy); 5769 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5770 // Use default allocator. 5771 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5772 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator}; 5773 5774 // _kmpc_free(gtid, addr, nullptr); 5775 (void)CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_free), Args); 5776 } 5777 5778 void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, 5779 OpenMPDependClauseKind NewDepKind, 5780 SourceLocation Loc) { 5781 ASTContext &C = CGM.getContext(); 5782 QualType FlagsTy; 5783 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5784 RecordDecl *KmpDependInfoRD = 5785 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5786 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5787 llvm::Value *NumDeps; 5788 LValue Base; 5789 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 5790 5791 Address Begin = Base.getAddress(CGF); 5792 // Cast from pointer to array type to pointer to single element. 5793 llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps); 5794 // The basic structure here is a while-do loop. 5795 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); 5796 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); 5797 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5798 CGF.EmitBlock(BodyBB); 5799 llvm::PHINode *ElementPHI = 5800 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); 5801 ElementPHI->addIncoming(Begin.getPointer(), EntryBB); 5802 Begin = Address(ElementPHI, Begin.getAlignment()); 5803 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), 5804 Base.getTBAAInfo()); 5805 // deps[i].flags = NewDepKind; 5806 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind); 5807 LValue FlagsLVal = CGF.EmitLValueForField( 5808 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5809 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5810 FlagsLVal); 5811 5812 // Shift the address forward by one element. 5813 Address ElementNext = 5814 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); 5815 ElementPHI->addIncoming(ElementNext.getPointer(), 5816 CGF.Builder.GetInsertBlock()); 5817 llvm::Value *IsEmpty = 5818 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); 5819 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5820 // Done. 5821 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5822 } 5823 5824 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5825 const OMPExecutableDirective &D, 5826 llvm::Function *TaskFunction, 5827 QualType SharedsTy, Address Shareds, 5828 const Expr *IfCond, 5829 const OMPTaskDataTy &Data) { 5830 if (!CGF.HaveInsertPoint()) 5831 return; 5832 5833 TaskResultTy Result = 5834 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5835 llvm::Value *NewTask = Result.NewTask; 5836 llvm::Function *TaskEntry = Result.TaskEntry; 5837 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5838 LValue TDBase = Result.TDBase; 5839 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5840 // Process list of dependences. 5841 Address DependenciesArray = Address::invalid(); 5842 llvm::Value *NumOfElements; 5843 std::tie(NumOfElements, DependenciesArray) = 5844 emitDependClause(CGF, Data.Dependences, Loc); 5845 5846 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5847 // libcall. 5848 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5849 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5850 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5851 // list is not empty 5852 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5853 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5854 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5855 llvm::Value *DepTaskArgs[7]; 5856 if (!Data.Dependences.empty()) { 5857 DepTaskArgs[0] = UpLoc; 5858 DepTaskArgs[1] = ThreadID; 5859 DepTaskArgs[2] = NewTask; 5860 DepTaskArgs[3] = NumOfElements; 5861 DepTaskArgs[4] = DependenciesArray.getPointer(); 5862 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5863 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5864 } 5865 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs, 5866 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5867 if (!Data.Tied) { 5868 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5869 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5870 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5871 } 5872 if (!Data.Dependences.empty()) { 5873 CGF.EmitRuntimeCall( 5874 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5875 } else { 5876 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5877 TaskArgs); 5878 } 5879 // Check if parent region is untied and build return for untied task; 5880 if (auto *Region = 5881 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5882 Region->emitUntiedSwitch(CGF); 5883 }; 5884 5885 llvm::Value *DepWaitTaskArgs[6]; 5886 if (!Data.Dependences.empty()) { 5887 DepWaitTaskArgs[0] = UpLoc; 5888 DepWaitTaskArgs[1] = ThreadID; 5889 DepWaitTaskArgs[2] = NumOfElements; 5890 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5891 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5892 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5893 } 5894 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5895 &Data, &DepWaitTaskArgs, 5896 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5897 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5898 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5899 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5900 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5901 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5902 // is specified. 5903 if (!Data.Dependences.empty()) 5904 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5905 DepWaitTaskArgs); 5906 // Call proxy_task_entry(gtid, new_task); 5907 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5908 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5909 Action.Enter(CGF); 5910 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5911 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5912 OutlinedFnArgs); 5913 }; 5914 5915 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5916 // kmp_task_t *new_task); 5917 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5918 // kmp_task_t *new_task); 5919 RegionCodeGenTy RCG(CodeGen); 5920 CommonActionTy Action( 5921 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5922 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5923 RCG.setAction(Action); 5924 RCG(CGF); 5925 }; 5926 5927 if (IfCond) { 5928 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5929 } else { 5930 RegionCodeGenTy ThenRCG(ThenCodeGen); 5931 ThenRCG(CGF); 5932 } 5933 } 5934 5935 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5936 const OMPLoopDirective &D, 5937 llvm::Function *TaskFunction, 5938 QualType SharedsTy, Address Shareds, 5939 const Expr *IfCond, 5940 const OMPTaskDataTy &Data) { 5941 if (!CGF.HaveInsertPoint()) 5942 return; 5943 TaskResultTy Result = 5944 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5945 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5946 // libcall. 5947 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5948 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5949 // sched, kmp_uint64 grainsize, void *task_dup); 5950 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5951 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5952 llvm::Value *IfVal; 5953 if (IfCond) { 5954 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5955 /*isSigned=*/true); 5956 } else { 5957 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5958 } 5959 5960 LValue LBLVal = CGF.EmitLValueForField( 5961 Result.TDBase, 5962 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5963 const auto *LBVar = 5964 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5965 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5966 LBLVal.getQuals(), 5967 /*IsInitializer=*/true); 5968 LValue UBLVal = CGF.EmitLValueForField( 5969 Result.TDBase, 5970 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5971 const auto *UBVar = 5972 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5973 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5974 UBLVal.getQuals(), 5975 /*IsInitializer=*/true); 5976 LValue StLVal = CGF.EmitLValueForField( 5977 Result.TDBase, 5978 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5979 const auto *StVar = 5980 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5981 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5982 StLVal.getQuals(), 5983 /*IsInitializer=*/true); 5984 // Store reductions address. 5985 LValue RedLVal = CGF.EmitLValueForField( 5986 Result.TDBase, 5987 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5988 if (Data.Reductions) { 5989 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5990 } else { 5991 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5992 CGF.getContext().VoidPtrTy); 5993 } 5994 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5995 llvm::Value *TaskArgs[] = { 5996 UpLoc, 5997 ThreadID, 5998 Result.NewTask, 5999 IfVal, 6000 LBLVal.getPointer(CGF), 6001 UBLVal.getPointer(CGF), 6002 CGF.EmitLoadOfScalar(StLVal, Loc), 6003 llvm::ConstantInt::getSigned( 6004 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 6005 llvm::ConstantInt::getSigned( 6006 CGF.IntTy, Data.Schedule.getPointer() 6007 ? Data.Schedule.getInt() ? NumTasks : Grainsize 6008 : NoSchedule), 6009 Data.Schedule.getPointer() 6010 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 6011 /*isSigned=*/false) 6012 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 6013 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6014 Result.TaskDupFn, CGF.VoidPtrTy) 6015 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 6016 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 6017 } 6018 6019 /// Emit reduction operation for each element of array (required for 6020 /// array sections) LHS op = RHS. 6021 /// \param Type Type of array. 6022 /// \param LHSVar Variable on the left side of the reduction operation 6023 /// (references element of array in original variable). 6024 /// \param RHSVar Variable on the right side of the reduction operation 6025 /// (references element of array in original variable). 6026 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 6027 /// RHSVar. 6028 static void EmitOMPAggregateReduction( 6029 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 6030 const VarDecl *RHSVar, 6031 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 6032 const Expr *, const Expr *)> &RedOpGen, 6033 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 6034 const Expr *UpExpr = nullptr) { 6035 // Perform element-by-element initialization. 6036 QualType ElementTy; 6037 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 6038 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 6039 6040 // Drill down to the base element type on both arrays. 6041 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 6042 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 6043 6044 llvm::Value *RHSBegin = RHSAddr.getPointer(); 6045 llvm::Value *LHSBegin = LHSAddr.getPointer(); 6046 // Cast from pointer to array type to pointer to single element. 6047 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 6048 // The basic structure here is a while-do loop. 6049 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 6050 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 6051 llvm::Value *IsEmpty = 6052 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 6053 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 6054 6055 // Enter the loop body, making that address the current address. 6056 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 6057 CGF.EmitBlock(BodyBB); 6058 6059 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 6060 6061 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 6062 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 6063 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 6064 Address RHSElementCurrent = 6065 Address(RHSElementPHI, 6066 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 6067 6068 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 6069 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 6070 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 6071 Address LHSElementCurrent = 6072 Address(LHSElementPHI, 6073 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 6074 6075 // Emit copy. 6076 CodeGenFunction::OMPPrivateScope Scope(CGF); 6077 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 6078 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 6079 Scope.Privatize(); 6080 RedOpGen(CGF, XExpr, EExpr, UpExpr); 6081 Scope.ForceCleanup(); 6082 6083 // Shift the address forward by one element. 6084 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 6085 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 6086 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 6087 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 6088 // Check whether we've reached the end. 6089 llvm::Value *Done = 6090 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 6091 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 6092 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 6093 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 6094 6095 // Done. 6096 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 6097 } 6098 6099 /// Emit reduction combiner. If the combiner is a simple expression emit it as 6100 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 6101 /// UDR combiner function. 6102 static void emitReductionCombiner(CodeGenFunction &CGF, 6103 const Expr *ReductionOp) { 6104 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 6105 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 6106 if (const auto *DRE = 6107 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 6108 if (const auto *DRD = 6109 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 6110 std::pair<llvm::Function *, llvm::Function *> Reduction = 6111 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 6112 RValue Func = RValue::get(Reduction.first); 6113 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 6114 CGF.EmitIgnoredExpr(ReductionOp); 6115 return; 6116 } 6117 CGF.EmitIgnoredExpr(ReductionOp); 6118 } 6119 6120 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 6121 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 6122 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 6123 ArrayRef<const Expr *> ReductionOps) { 6124 ASTContext &C = CGM.getContext(); 6125 6126 // void reduction_func(void *LHSArg, void *RHSArg); 6127 FunctionArgList Args; 6128 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6129 ImplicitParamDecl::Other); 6130 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6131 ImplicitParamDecl::Other); 6132 Args.push_back(&LHSArg); 6133 Args.push_back(&RHSArg); 6134 const auto &CGFI = 6135 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6136 std::string Name = getName({"omp", "reduction", "reduction_func"}); 6137 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 6138 llvm::GlobalValue::InternalLinkage, Name, 6139 &CGM.getModule()); 6140 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 6141 Fn->setDoesNotRecurse(); 6142 CodeGenFunction CGF(CGM); 6143 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 6144 6145 // Dst = (void*[n])(LHSArg); 6146 // Src = (void*[n])(RHSArg); 6147 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6148 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 6149 ArgsType), CGF.getPointerAlign()); 6150 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6151 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 6152 ArgsType), CGF.getPointerAlign()); 6153 6154 // ... 6155 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 6156 // ... 6157 CodeGenFunction::OMPPrivateScope Scope(CGF); 6158 auto IPriv = Privates.begin(); 6159 unsigned Idx = 0; 6160 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 6161 const auto *RHSVar = 6162 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 6163 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 6164 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 6165 }); 6166 const auto *LHSVar = 6167 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 6168 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 6169 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 6170 }); 6171 QualType PrivTy = (*IPriv)->getType(); 6172 if (PrivTy->isVariablyModifiedType()) { 6173 // Get array size and emit VLA type. 6174 ++Idx; 6175 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 6176 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 6177 const VariableArrayType *VLA = 6178 CGF.getContext().getAsVariableArrayType(PrivTy); 6179 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 6180 CodeGenFunction::OpaqueValueMapping OpaqueMap( 6181 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 6182 CGF.EmitVariablyModifiedType(PrivTy); 6183 } 6184 } 6185 Scope.Privatize(); 6186 IPriv = Privates.begin(); 6187 auto ILHS = LHSExprs.begin(); 6188 auto IRHS = RHSExprs.begin(); 6189 for (const Expr *E : ReductionOps) { 6190 if ((*IPriv)->getType()->isArrayType()) { 6191 // Emit reduction for array section. 6192 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 6193 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 6194 EmitOMPAggregateReduction( 6195 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 6196 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 6197 emitReductionCombiner(CGF, E); 6198 }); 6199 } else { 6200 // Emit reduction for array subscript or single variable. 6201 emitReductionCombiner(CGF, E); 6202 } 6203 ++IPriv; 6204 ++ILHS; 6205 ++IRHS; 6206 } 6207 Scope.ForceCleanup(); 6208 CGF.FinishFunction(); 6209 return Fn; 6210 } 6211 6212 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 6213 const Expr *ReductionOp, 6214 const Expr *PrivateRef, 6215 const DeclRefExpr *LHS, 6216 const DeclRefExpr *RHS) { 6217 if (PrivateRef->getType()->isArrayType()) { 6218 // Emit reduction for array section. 6219 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 6220 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 6221 EmitOMPAggregateReduction( 6222 CGF, PrivateRef->getType(), LHSVar, RHSVar, 6223 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 6224 emitReductionCombiner(CGF, ReductionOp); 6225 }); 6226 } else { 6227 // Emit reduction for array subscript or single variable. 6228 emitReductionCombiner(CGF, ReductionOp); 6229 } 6230 } 6231 6232 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 6233 ArrayRef<const Expr *> Privates, 6234 ArrayRef<const Expr *> LHSExprs, 6235 ArrayRef<const Expr *> RHSExprs, 6236 ArrayRef<const Expr *> ReductionOps, 6237 ReductionOptionsTy Options) { 6238 if (!CGF.HaveInsertPoint()) 6239 return; 6240 6241 bool WithNowait = Options.WithNowait; 6242 bool SimpleReduction = Options.SimpleReduction; 6243 6244 // Next code should be emitted for reduction: 6245 // 6246 // static kmp_critical_name lock = { 0 }; 6247 // 6248 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 6249 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 6250 // ... 6251 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 6252 // *(Type<n>-1*)rhs[<n>-1]); 6253 // } 6254 // 6255 // ... 6256 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 6257 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 6258 // RedList, reduce_func, &<lock>)) { 6259 // case 1: 6260 // ... 6261 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 6262 // ... 6263 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 6264 // break; 6265 // case 2: 6266 // ... 6267 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 6268 // ... 6269 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 6270 // break; 6271 // default:; 6272 // } 6273 // 6274 // if SimpleReduction is true, only the next code is generated: 6275 // ... 6276 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 6277 // ... 6278 6279 ASTContext &C = CGM.getContext(); 6280 6281 if (SimpleReduction) { 6282 CodeGenFunction::RunCleanupsScope Scope(CGF); 6283 auto IPriv = Privates.begin(); 6284 auto ILHS = LHSExprs.begin(); 6285 auto IRHS = RHSExprs.begin(); 6286 for (const Expr *E : ReductionOps) { 6287 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 6288 cast<DeclRefExpr>(*IRHS)); 6289 ++IPriv; 6290 ++ILHS; 6291 ++IRHS; 6292 } 6293 return; 6294 } 6295 6296 // 1. Build a list of reduction variables. 6297 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 6298 auto Size = RHSExprs.size(); 6299 for (const Expr *E : Privates) { 6300 if (E->getType()->isVariablyModifiedType()) 6301 // Reserve place for array size. 6302 ++Size; 6303 } 6304 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 6305 QualType ReductionArrayTy = 6306 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 6307 /*IndexTypeQuals=*/0); 6308 Address ReductionList = 6309 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 6310 auto IPriv = Privates.begin(); 6311 unsigned Idx = 0; 6312 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 6313 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 6314 CGF.Builder.CreateStore( 6315 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6316 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 6317 Elem); 6318 if ((*IPriv)->getType()->isVariablyModifiedType()) { 6319 // Store array size. 6320 ++Idx; 6321 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 6322 llvm::Value *Size = CGF.Builder.CreateIntCast( 6323 CGF.getVLASize( 6324 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 6325 .NumElts, 6326 CGF.SizeTy, /*isSigned=*/false); 6327 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 6328 Elem); 6329 } 6330 } 6331 6332 // 2. Emit reduce_func(). 6333 llvm::Function *ReductionFn = emitReductionFunction( 6334 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 6335 LHSExprs, RHSExprs, ReductionOps); 6336 6337 // 3. Create static kmp_critical_name lock = { 0 }; 6338 std::string Name = getName({"reduction"}); 6339 llvm::Value *Lock = getCriticalRegionLock(Name); 6340 6341 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 6342 // RedList, reduce_func, &<lock>); 6343 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 6344 llvm::Value *ThreadId = getThreadID(CGF, Loc); 6345 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 6346 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6347 ReductionList.getPointer(), CGF.VoidPtrTy); 6348 llvm::Value *Args[] = { 6349 IdentTLoc, // ident_t *<loc> 6350 ThreadId, // i32 <gtid> 6351 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 6352 ReductionArrayTySize, // size_type sizeof(RedList) 6353 RL, // void *RedList 6354 ReductionFn, // void (*) (void *, void *) <reduce_func> 6355 Lock // kmp_critical_name *&<lock> 6356 }; 6357 llvm::Value *Res = CGF.EmitRuntimeCall( 6358 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 6359 : OMPRTL__kmpc_reduce), 6360 Args); 6361 6362 // 5. Build switch(res) 6363 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 6364 llvm::SwitchInst *SwInst = 6365 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 6366 6367 // 6. Build case 1: 6368 // ... 6369 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 6370 // ... 6371 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 6372 // break; 6373 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 6374 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 6375 CGF.EmitBlock(Case1BB); 6376 6377 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 6378 llvm::Value *EndArgs[] = { 6379 IdentTLoc, // ident_t *<loc> 6380 ThreadId, // i32 <gtid> 6381 Lock // kmp_critical_name *&<lock> 6382 }; 6383 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 6384 CodeGenFunction &CGF, PrePostActionTy &Action) { 6385 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6386 auto IPriv = Privates.begin(); 6387 auto ILHS = LHSExprs.begin(); 6388 auto IRHS = RHSExprs.begin(); 6389 for (const Expr *E : ReductionOps) { 6390 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 6391 cast<DeclRefExpr>(*IRHS)); 6392 ++IPriv; 6393 ++ILHS; 6394 ++IRHS; 6395 } 6396 }; 6397 RegionCodeGenTy RCG(CodeGen); 6398 CommonActionTy Action( 6399 nullptr, llvm::None, 6400 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 6401 : OMPRTL__kmpc_end_reduce), 6402 EndArgs); 6403 RCG.setAction(Action); 6404 RCG(CGF); 6405 6406 CGF.EmitBranch(DefaultBB); 6407 6408 // 7. Build case 2: 6409 // ... 6410 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 6411 // ... 6412 // break; 6413 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 6414 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 6415 CGF.EmitBlock(Case2BB); 6416 6417 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 6418 CodeGenFunction &CGF, PrePostActionTy &Action) { 6419 auto ILHS = LHSExprs.begin(); 6420 auto IRHS = RHSExprs.begin(); 6421 auto IPriv = Privates.begin(); 6422 for (const Expr *E : ReductionOps) { 6423 const Expr *XExpr = nullptr; 6424 const Expr *EExpr = nullptr; 6425 const Expr *UpExpr = nullptr; 6426 BinaryOperatorKind BO = BO_Comma; 6427 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 6428 if (BO->getOpcode() == BO_Assign) { 6429 XExpr = BO->getLHS(); 6430 UpExpr = BO->getRHS(); 6431 } 6432 } 6433 // Try to emit update expression as a simple atomic. 6434 const Expr *RHSExpr = UpExpr; 6435 if (RHSExpr) { 6436 // Analyze RHS part of the whole expression. 6437 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 6438 RHSExpr->IgnoreParenImpCasts())) { 6439 // If this is a conditional operator, analyze its condition for 6440 // min/max reduction operator. 6441 RHSExpr = ACO->getCond(); 6442 } 6443 if (const auto *BORHS = 6444 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 6445 EExpr = BORHS->getRHS(); 6446 BO = BORHS->getOpcode(); 6447 } 6448 } 6449 if (XExpr) { 6450 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 6451 auto &&AtomicRedGen = [BO, VD, 6452 Loc](CodeGenFunction &CGF, const Expr *XExpr, 6453 const Expr *EExpr, const Expr *UpExpr) { 6454 LValue X = CGF.EmitLValue(XExpr); 6455 RValue E; 6456 if (EExpr) 6457 E = CGF.EmitAnyExpr(EExpr); 6458 CGF.EmitOMPAtomicSimpleUpdateExpr( 6459 X, E, BO, /*IsXLHSInRHSPart=*/true, 6460 llvm::AtomicOrdering::Monotonic, Loc, 6461 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 6462 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6463 PrivateScope.addPrivate( 6464 VD, [&CGF, VD, XRValue, Loc]() { 6465 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 6466 CGF.emitOMPSimpleStore( 6467 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 6468 VD->getType().getNonReferenceType(), Loc); 6469 return LHSTemp; 6470 }); 6471 (void)PrivateScope.Privatize(); 6472 return CGF.EmitAnyExpr(UpExpr); 6473 }); 6474 }; 6475 if ((*IPriv)->getType()->isArrayType()) { 6476 // Emit atomic reduction for array section. 6477 const auto *RHSVar = 6478 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 6479 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 6480 AtomicRedGen, XExpr, EExpr, UpExpr); 6481 } else { 6482 // Emit atomic reduction for array subscript or single variable. 6483 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 6484 } 6485 } else { 6486 // Emit as a critical region. 6487 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 6488 const Expr *, const Expr *) { 6489 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6490 std::string Name = RT.getName({"atomic_reduction"}); 6491 RT.emitCriticalRegion( 6492 CGF, Name, 6493 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 6494 Action.Enter(CGF); 6495 emitReductionCombiner(CGF, E); 6496 }, 6497 Loc); 6498 }; 6499 if ((*IPriv)->getType()->isArrayType()) { 6500 const auto *LHSVar = 6501 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 6502 const auto *RHSVar = 6503 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 6504 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 6505 CritRedGen); 6506 } else { 6507 CritRedGen(CGF, nullptr, nullptr, nullptr); 6508 } 6509 } 6510 ++ILHS; 6511 ++IRHS; 6512 ++IPriv; 6513 } 6514 }; 6515 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 6516 if (!WithNowait) { 6517 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 6518 llvm::Value *EndArgs[] = { 6519 IdentTLoc, // ident_t *<loc> 6520 ThreadId, // i32 <gtid> 6521 Lock // kmp_critical_name *&<lock> 6522 }; 6523 CommonActionTy Action(nullptr, llvm::None, 6524 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 6525 EndArgs); 6526 AtomicRCG.setAction(Action); 6527 AtomicRCG(CGF); 6528 } else { 6529 AtomicRCG(CGF); 6530 } 6531 6532 CGF.EmitBranch(DefaultBB); 6533 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 6534 } 6535 6536 /// Generates unique name for artificial threadprivate variables. 6537 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 6538 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 6539 const Expr *Ref) { 6540 SmallString<256> Buffer; 6541 llvm::raw_svector_ostream Out(Buffer); 6542 const clang::DeclRefExpr *DE; 6543 const VarDecl *D = ::getBaseDecl(Ref, DE); 6544 if (!D) 6545 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 6546 D = D->getCanonicalDecl(); 6547 std::string Name = CGM.getOpenMPRuntime().getName( 6548 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 6549 Out << Prefix << Name << "_" 6550 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 6551 return std::string(Out.str()); 6552 } 6553 6554 /// Emits reduction initializer function: 6555 /// \code 6556 /// void @.red_init(void* %arg, void* %orig) { 6557 /// %0 = bitcast void* %arg to <type>* 6558 /// store <type> <init>, <type>* %0 6559 /// ret void 6560 /// } 6561 /// \endcode 6562 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 6563 SourceLocation Loc, 6564 ReductionCodeGen &RCG, unsigned N) { 6565 ASTContext &C = CGM.getContext(); 6566 QualType VoidPtrTy = C.VoidPtrTy; 6567 VoidPtrTy.addRestrict(); 6568 FunctionArgList Args; 6569 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 6570 ImplicitParamDecl::Other); 6571 ImplicitParamDecl ParamOrig(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 6572 ImplicitParamDecl::Other); 6573 Args.emplace_back(&Param); 6574 Args.emplace_back(&ParamOrig); 6575 const auto &FnInfo = 6576 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6577 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6578 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6579 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6580 Name, &CGM.getModule()); 6581 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6582 Fn->setDoesNotRecurse(); 6583 CodeGenFunction CGF(CGM); 6584 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6585 Address PrivateAddr = CGF.EmitLoadOfPointer( 6586 CGF.GetAddrOfLocalVar(&Param), 6587 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6588 llvm::Value *Size = nullptr; 6589 // If the size of the reduction item is non-constant, load it from global 6590 // threadprivate variable. 6591 if (RCG.getSizes(N).second) { 6592 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6593 CGF, CGM.getContext().getSizeType(), 6594 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6595 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6596 CGM.getContext().getSizeType(), Loc); 6597 } 6598 RCG.emitAggregateType(CGF, N, Size); 6599 LValue OrigLVal; 6600 // If initializer uses initializer from declare reduction construct, emit a 6601 // pointer to the address of the original reduction item (reuired by reduction 6602 // initializer) 6603 if (RCG.usesReductionInitializer(N)) { 6604 Address SharedAddr = CGF.GetAddrOfLocalVar(&ParamOrig); 6605 SharedAddr = CGF.EmitLoadOfPointer( 6606 SharedAddr, 6607 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6608 OrigLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6609 } else { 6610 OrigLVal = CGF.MakeNaturalAlignAddrLValue( 6611 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6612 CGM.getContext().VoidPtrTy); 6613 } 6614 // Emit the initializer: 6615 // %0 = bitcast void* %arg to <type>* 6616 // store <type> <init>, <type>* %0 6617 RCG.emitInitialization(CGF, N, PrivateAddr, OrigLVal, 6618 [](CodeGenFunction &) { return false; }); 6619 CGF.FinishFunction(); 6620 return Fn; 6621 } 6622 6623 /// Emits reduction combiner function: 6624 /// \code 6625 /// void @.red_comb(void* %arg0, void* %arg1) { 6626 /// %lhs = bitcast void* %arg0 to <type>* 6627 /// %rhs = bitcast void* %arg1 to <type>* 6628 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6629 /// store <type> %2, <type>* %lhs 6630 /// ret void 6631 /// } 6632 /// \endcode 6633 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6634 SourceLocation Loc, 6635 ReductionCodeGen &RCG, unsigned N, 6636 const Expr *ReductionOp, 6637 const Expr *LHS, const Expr *RHS, 6638 const Expr *PrivateRef) { 6639 ASTContext &C = CGM.getContext(); 6640 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6641 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6642 FunctionArgList Args; 6643 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6644 C.VoidPtrTy, ImplicitParamDecl::Other); 6645 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6646 ImplicitParamDecl::Other); 6647 Args.emplace_back(&ParamInOut); 6648 Args.emplace_back(&ParamIn); 6649 const auto &FnInfo = 6650 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6651 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6652 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6653 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6654 Name, &CGM.getModule()); 6655 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6656 Fn->setDoesNotRecurse(); 6657 CodeGenFunction CGF(CGM); 6658 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6659 llvm::Value *Size = nullptr; 6660 // If the size of the reduction item is non-constant, load it from global 6661 // threadprivate variable. 6662 if (RCG.getSizes(N).second) { 6663 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6664 CGF, CGM.getContext().getSizeType(), 6665 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6666 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6667 CGM.getContext().getSizeType(), Loc); 6668 } 6669 RCG.emitAggregateType(CGF, N, Size); 6670 // Remap lhs and rhs variables to the addresses of the function arguments. 6671 // %lhs = bitcast void* %arg0 to <type>* 6672 // %rhs = bitcast void* %arg1 to <type>* 6673 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6674 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6675 // Pull out the pointer to the variable. 6676 Address PtrAddr = CGF.EmitLoadOfPointer( 6677 CGF.GetAddrOfLocalVar(&ParamInOut), 6678 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6679 return CGF.Builder.CreateElementBitCast( 6680 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6681 }); 6682 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6683 // Pull out the pointer to the variable. 6684 Address PtrAddr = CGF.EmitLoadOfPointer( 6685 CGF.GetAddrOfLocalVar(&ParamIn), 6686 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6687 return CGF.Builder.CreateElementBitCast( 6688 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6689 }); 6690 PrivateScope.Privatize(); 6691 // Emit the combiner body: 6692 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6693 // store <type> %2, <type>* %lhs 6694 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6695 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6696 cast<DeclRefExpr>(RHS)); 6697 CGF.FinishFunction(); 6698 return Fn; 6699 } 6700 6701 /// Emits reduction finalizer function: 6702 /// \code 6703 /// void @.red_fini(void* %arg) { 6704 /// %0 = bitcast void* %arg to <type>* 6705 /// <destroy>(<type>* %0) 6706 /// ret void 6707 /// } 6708 /// \endcode 6709 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6710 SourceLocation Loc, 6711 ReductionCodeGen &RCG, unsigned N) { 6712 if (!RCG.needCleanups(N)) 6713 return nullptr; 6714 ASTContext &C = CGM.getContext(); 6715 FunctionArgList Args; 6716 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6717 ImplicitParamDecl::Other); 6718 Args.emplace_back(&Param); 6719 const auto &FnInfo = 6720 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6721 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6722 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6723 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6724 Name, &CGM.getModule()); 6725 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6726 Fn->setDoesNotRecurse(); 6727 CodeGenFunction CGF(CGM); 6728 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6729 Address PrivateAddr = CGF.EmitLoadOfPointer( 6730 CGF.GetAddrOfLocalVar(&Param), 6731 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6732 llvm::Value *Size = nullptr; 6733 // If the size of the reduction item is non-constant, load it from global 6734 // threadprivate variable. 6735 if (RCG.getSizes(N).second) { 6736 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6737 CGF, CGM.getContext().getSizeType(), 6738 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6739 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6740 CGM.getContext().getSizeType(), Loc); 6741 } 6742 RCG.emitAggregateType(CGF, N, Size); 6743 // Emit the finalizer body: 6744 // <destroy>(<type>* %0) 6745 RCG.emitCleanups(CGF, N, PrivateAddr); 6746 CGF.FinishFunction(Loc); 6747 return Fn; 6748 } 6749 6750 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6751 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6752 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6753 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6754 return nullptr; 6755 6756 // Build typedef struct: 6757 // kmp_taskred_input { 6758 // void *reduce_shar; // shared reduction item 6759 // void *reduce_orig; // original reduction item used for initialization 6760 // size_t reduce_size; // size of data item 6761 // void *reduce_init; // data initialization routine 6762 // void *reduce_fini; // data finalization routine 6763 // void *reduce_comb; // data combiner routine 6764 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6765 // } kmp_taskred_input_t; 6766 ASTContext &C = CGM.getContext(); 6767 RecordDecl *RD = C.buildImplicitRecord("kmp_taskred_input_t"); 6768 RD->startDefinition(); 6769 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6770 const FieldDecl *OrigFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6771 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6772 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6773 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6774 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6775 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6776 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6777 RD->completeDefinition(); 6778 QualType RDType = C.getRecordType(RD); 6779 unsigned Size = Data.ReductionVars.size(); 6780 llvm::APInt ArraySize(/*numBits=*/64, Size); 6781 QualType ArrayRDType = C.getConstantArrayType( 6782 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6783 // kmp_task_red_input_t .rd_input.[Size]; 6784 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6785 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionVars, 6786 Data.ReductionCopies, Data.ReductionOps); 6787 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6788 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6789 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6790 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6791 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6792 TaskRedInput.getPointer(), Idxs, 6793 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6794 ".rd_input.gep."); 6795 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6796 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6797 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6798 RCG.emitSharedOrigLValue(CGF, Cnt); 6799 llvm::Value *CastedShared = 6800 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6801 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6802 // ElemLVal.reduce_orig = &Origs[Cnt]; 6803 LValue OrigLVal = CGF.EmitLValueForField(ElemLVal, OrigFD); 6804 llvm::Value *CastedOrig = 6805 CGF.EmitCastToVoidPtr(RCG.getOrigLValue(Cnt).getPointer(CGF)); 6806 CGF.EmitStoreOfScalar(CastedOrig, OrigLVal); 6807 RCG.emitAggregateType(CGF, Cnt); 6808 llvm::Value *SizeValInChars; 6809 llvm::Value *SizeVal; 6810 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6811 // We use delayed creation/initialization for VLAs and array sections. It is 6812 // required because runtime does not provide the way to pass the sizes of 6813 // VLAs/array sections to initializer/combiner/finalizer functions. Instead 6814 // threadprivate global variables are used to store these values and use 6815 // them in the functions. 6816 bool DelayedCreation = !!SizeVal; 6817 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6818 /*isSigned=*/false); 6819 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6820 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6821 // ElemLVal.reduce_init = init; 6822 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6823 llvm::Value *InitAddr = 6824 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6825 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6826 // ElemLVal.reduce_fini = fini; 6827 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6828 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6829 llvm::Value *FiniAddr = Fini 6830 ? CGF.EmitCastToVoidPtr(Fini) 6831 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6832 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6833 // ElemLVal.reduce_comb = comb; 6834 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6835 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6836 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6837 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6838 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6839 // ElemLVal.flags = 0; 6840 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6841 if (DelayedCreation) { 6842 CGF.EmitStoreOfScalar( 6843 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6844 FlagsLVal); 6845 } else 6846 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6847 FlagsLVal.getType()); 6848 } 6849 // Build call void *__kmpc_taskred_init(int gtid, int num_data, void *data); 6850 llvm::Value *Args[] = { 6851 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6852 /*isSigned=*/true), 6853 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6854 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6855 CGM.VoidPtrTy)}; 6856 return CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskred_init), 6857 Args); 6858 } 6859 6860 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6861 SourceLocation Loc, 6862 ReductionCodeGen &RCG, 6863 unsigned N) { 6864 auto Sizes = RCG.getSizes(N); 6865 // Emit threadprivate global variable if the type is non-constant 6866 // (Sizes.second = nullptr). 6867 if (Sizes.second) { 6868 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6869 /*isSigned=*/false); 6870 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6871 CGF, CGM.getContext().getSizeType(), 6872 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6873 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6874 } 6875 } 6876 6877 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6878 SourceLocation Loc, 6879 llvm::Value *ReductionsPtr, 6880 LValue SharedLVal) { 6881 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6882 // *d); 6883 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6884 CGM.IntTy, 6885 /*isSigned=*/true), 6886 ReductionsPtr, 6887 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6888 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6889 return Address( 6890 CGF.EmitRuntimeCall( 6891 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6892 SharedLVal.getAlignment()); 6893 } 6894 6895 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6896 SourceLocation Loc) { 6897 if (!CGF.HaveInsertPoint()) 6898 return; 6899 6900 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 6901 if (OMPBuilder) { 6902 OMPBuilder->CreateTaskwait(CGF.Builder); 6903 } else { 6904 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6905 // global_tid); 6906 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6907 // Ignore return result until untied tasks are supported. 6908 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6909 } 6910 6911 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6912 Region->emitUntiedSwitch(CGF); 6913 } 6914 6915 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6916 OpenMPDirectiveKind InnerKind, 6917 const RegionCodeGenTy &CodeGen, 6918 bool HasCancel) { 6919 if (!CGF.HaveInsertPoint()) 6920 return; 6921 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6922 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6923 } 6924 6925 namespace { 6926 enum RTCancelKind { 6927 CancelNoreq = 0, 6928 CancelParallel = 1, 6929 CancelLoop = 2, 6930 CancelSections = 3, 6931 CancelTaskgroup = 4 6932 }; 6933 } // anonymous namespace 6934 6935 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6936 RTCancelKind CancelKind = CancelNoreq; 6937 if (CancelRegion == OMPD_parallel) 6938 CancelKind = CancelParallel; 6939 else if (CancelRegion == OMPD_for) 6940 CancelKind = CancelLoop; 6941 else if (CancelRegion == OMPD_sections) 6942 CancelKind = CancelSections; 6943 else { 6944 assert(CancelRegion == OMPD_taskgroup); 6945 CancelKind = CancelTaskgroup; 6946 } 6947 return CancelKind; 6948 } 6949 6950 void CGOpenMPRuntime::emitCancellationPointCall( 6951 CodeGenFunction &CGF, SourceLocation Loc, 6952 OpenMPDirectiveKind CancelRegion) { 6953 if (!CGF.HaveInsertPoint()) 6954 return; 6955 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6956 // global_tid, kmp_int32 cncl_kind); 6957 if (auto *OMPRegionInfo = 6958 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6959 // For 'cancellation point taskgroup', the task region info may not have a 6960 // cancel. This may instead happen in another adjacent task. 6961 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6962 llvm::Value *Args[] = { 6963 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6964 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6965 // Ignore return result until untied tasks are supported. 6966 llvm::Value *Result = CGF.EmitRuntimeCall( 6967 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6968 // if (__kmpc_cancellationpoint()) { 6969 // exit from construct; 6970 // } 6971 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6972 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6973 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6974 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6975 CGF.EmitBlock(ExitBB); 6976 // exit from construct; 6977 CodeGenFunction::JumpDest CancelDest = 6978 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6979 CGF.EmitBranchThroughCleanup(CancelDest); 6980 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6981 } 6982 } 6983 } 6984 6985 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6986 const Expr *IfCond, 6987 OpenMPDirectiveKind CancelRegion) { 6988 if (!CGF.HaveInsertPoint()) 6989 return; 6990 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6991 // kmp_int32 cncl_kind); 6992 if (auto *OMPRegionInfo = 6993 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6994 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6995 PrePostActionTy &) { 6996 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6997 llvm::Value *Args[] = { 6998 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6999 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 7000 // Ignore return result until untied tasks are supported. 7001 llvm::Value *Result = CGF.EmitRuntimeCall( 7002 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 7003 // if (__kmpc_cancel()) { 7004 // exit from construct; 7005 // } 7006 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 7007 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 7008 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 7009 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 7010 CGF.EmitBlock(ExitBB); 7011 // exit from construct; 7012 CodeGenFunction::JumpDest CancelDest = 7013 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 7014 CGF.EmitBranchThroughCleanup(CancelDest); 7015 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 7016 }; 7017 if (IfCond) { 7018 emitIfClause(CGF, IfCond, ThenGen, 7019 [](CodeGenFunction &, PrePostActionTy &) {}); 7020 } else { 7021 RegionCodeGenTy ThenRCG(ThenGen); 7022 ThenRCG(CGF); 7023 } 7024 } 7025 } 7026 7027 void CGOpenMPRuntime::emitTargetOutlinedFunction( 7028 const OMPExecutableDirective &D, StringRef ParentName, 7029 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 7030 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 7031 assert(!ParentName.empty() && "Invalid target region parent name!"); 7032 HasEmittedTargetRegion = true; 7033 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 7034 IsOffloadEntry, CodeGen); 7035 } 7036 7037 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 7038 const OMPExecutableDirective &D, StringRef ParentName, 7039 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 7040 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 7041 // Create a unique name for the entry function using the source location 7042 // information of the current target region. The name will be something like: 7043 // 7044 // __omp_offloading_DD_FFFF_PP_lBB 7045 // 7046 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 7047 // mangled name of the function that encloses the target region and BB is the 7048 // line number of the target region. 7049 7050 unsigned DeviceID; 7051 unsigned FileID; 7052 unsigned Line; 7053 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 7054 Line); 7055 SmallString<64> EntryFnName; 7056 { 7057 llvm::raw_svector_ostream OS(EntryFnName); 7058 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 7059 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 7060 } 7061 7062 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 7063 7064 CodeGenFunction CGF(CGM, true); 7065 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 7066 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7067 7068 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 7069 7070 // If this target outline function is not an offload entry, we don't need to 7071 // register it. 7072 if (!IsOffloadEntry) 7073 return; 7074 7075 // The target region ID is used by the runtime library to identify the current 7076 // target region, so it only has to be unique and not necessarily point to 7077 // anything. It could be the pointer to the outlined function that implements 7078 // the target region, but we aren't using that so that the compiler doesn't 7079 // need to keep that, and could therefore inline the host function if proven 7080 // worthwhile during optimization. In the other hand, if emitting code for the 7081 // device, the ID has to be the function address so that it can retrieved from 7082 // the offloading entry and launched by the runtime library. We also mark the 7083 // outlined function to have external linkage in case we are emitting code for 7084 // the device, because these functions will be entry points to the device. 7085 7086 if (CGM.getLangOpts().OpenMPIsDevice) { 7087 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 7088 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 7089 OutlinedFn->setDSOLocal(false); 7090 } else { 7091 std::string Name = getName({EntryFnName, "region_id"}); 7092 OutlinedFnID = new llvm::GlobalVariable( 7093 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 7094 llvm::GlobalValue::WeakAnyLinkage, 7095 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 7096 } 7097 7098 // Register the information for the entry associated with this target region. 7099 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 7100 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 7101 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 7102 } 7103 7104 /// Checks if the expression is constant or does not have non-trivial function 7105 /// calls. 7106 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 7107 // We can skip constant expressions. 7108 // We can skip expressions with trivial calls or simple expressions. 7109 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 7110 !E->hasNonTrivialCall(Ctx)) && 7111 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 7112 } 7113 7114 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 7115 const Stmt *Body) { 7116 const Stmt *Child = Body->IgnoreContainers(); 7117 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 7118 Child = nullptr; 7119 for (const Stmt *S : C->body()) { 7120 if (const auto *E = dyn_cast<Expr>(S)) { 7121 if (isTrivial(Ctx, E)) 7122 continue; 7123 } 7124 // Some of the statements can be ignored. 7125 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 7126 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 7127 continue; 7128 // Analyze declarations. 7129 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 7130 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 7131 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 7132 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 7133 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 7134 isa<UsingDirectiveDecl>(D) || 7135 isa<OMPDeclareReductionDecl>(D) || 7136 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 7137 return true; 7138 const auto *VD = dyn_cast<VarDecl>(D); 7139 if (!VD) 7140 return false; 7141 return VD->isConstexpr() || 7142 ((VD->getType().isTrivialType(Ctx) || 7143 VD->getType()->isReferenceType()) && 7144 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 7145 })) 7146 continue; 7147 } 7148 // Found multiple children - cannot get the one child only. 7149 if (Child) 7150 return nullptr; 7151 Child = S; 7152 } 7153 if (Child) 7154 Child = Child->IgnoreContainers(); 7155 } 7156 return Child; 7157 } 7158 7159 /// Emit the number of teams for a target directive. Inspect the num_teams 7160 /// clause associated with a teams construct combined or closely nested 7161 /// with the target directive. 7162 /// 7163 /// Emit a team of size one for directives such as 'target parallel' that 7164 /// have no associated teams construct. 7165 /// 7166 /// Otherwise, return nullptr. 7167 static llvm::Value * 7168 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 7169 const OMPExecutableDirective &D) { 7170 assert(!CGF.getLangOpts().OpenMPIsDevice && 7171 "Clauses associated with the teams directive expected to be emitted " 7172 "only for the host!"); 7173 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 7174 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 7175 "Expected target-based executable directive."); 7176 CGBuilderTy &Bld = CGF.Builder; 7177 switch (DirectiveKind) { 7178 case OMPD_target: { 7179 const auto *CS = D.getInnermostCapturedStmt(); 7180 const auto *Body = 7181 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 7182 const Stmt *ChildStmt = 7183 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 7184 if (const auto *NestedDir = 7185 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 7186 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 7187 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 7188 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7189 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7190 const Expr *NumTeams = 7191 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 7192 llvm::Value *NumTeamsVal = 7193 CGF.EmitScalarExpr(NumTeams, 7194 /*IgnoreResultAssign*/ true); 7195 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 7196 /*isSigned=*/true); 7197 } 7198 return Bld.getInt32(0); 7199 } 7200 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 7201 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 7202 return Bld.getInt32(1); 7203 return Bld.getInt32(0); 7204 } 7205 return nullptr; 7206 } 7207 case OMPD_target_teams: 7208 case OMPD_target_teams_distribute: 7209 case OMPD_target_teams_distribute_simd: 7210 case OMPD_target_teams_distribute_parallel_for: 7211 case OMPD_target_teams_distribute_parallel_for_simd: { 7212 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 7213 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 7214 const Expr *NumTeams = 7215 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 7216 llvm::Value *NumTeamsVal = 7217 CGF.EmitScalarExpr(NumTeams, 7218 /*IgnoreResultAssign*/ true); 7219 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 7220 /*isSigned=*/true); 7221 } 7222 return Bld.getInt32(0); 7223 } 7224 case OMPD_target_parallel: 7225 case OMPD_target_parallel_for: 7226 case OMPD_target_parallel_for_simd: 7227 case OMPD_target_simd: 7228 return Bld.getInt32(1); 7229 case OMPD_parallel: 7230 case OMPD_for: 7231 case OMPD_parallel_for: 7232 case OMPD_parallel_master: 7233 case OMPD_parallel_sections: 7234 case OMPD_for_simd: 7235 case OMPD_parallel_for_simd: 7236 case OMPD_cancel: 7237 case OMPD_cancellation_point: 7238 case OMPD_ordered: 7239 case OMPD_threadprivate: 7240 case OMPD_allocate: 7241 case OMPD_task: 7242 case OMPD_simd: 7243 case OMPD_sections: 7244 case OMPD_section: 7245 case OMPD_single: 7246 case OMPD_master: 7247 case OMPD_critical: 7248 case OMPD_taskyield: 7249 case OMPD_barrier: 7250 case OMPD_taskwait: 7251 case OMPD_taskgroup: 7252 case OMPD_atomic: 7253 case OMPD_flush: 7254 case OMPD_depobj: 7255 case OMPD_scan: 7256 case OMPD_teams: 7257 case OMPD_target_data: 7258 case OMPD_target_exit_data: 7259 case OMPD_target_enter_data: 7260 case OMPD_distribute: 7261 case OMPD_distribute_simd: 7262 case OMPD_distribute_parallel_for: 7263 case OMPD_distribute_parallel_for_simd: 7264 case OMPD_teams_distribute: 7265 case OMPD_teams_distribute_simd: 7266 case OMPD_teams_distribute_parallel_for: 7267 case OMPD_teams_distribute_parallel_for_simd: 7268 case OMPD_target_update: 7269 case OMPD_declare_simd: 7270 case OMPD_declare_variant: 7271 case OMPD_begin_declare_variant: 7272 case OMPD_end_declare_variant: 7273 case OMPD_declare_target: 7274 case OMPD_end_declare_target: 7275 case OMPD_declare_reduction: 7276 case OMPD_declare_mapper: 7277 case OMPD_taskloop: 7278 case OMPD_taskloop_simd: 7279 case OMPD_master_taskloop: 7280 case OMPD_master_taskloop_simd: 7281 case OMPD_parallel_master_taskloop: 7282 case OMPD_parallel_master_taskloop_simd: 7283 case OMPD_requires: 7284 case OMPD_unknown: 7285 break; 7286 } 7287 llvm_unreachable("Unexpected directive kind."); 7288 } 7289 7290 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 7291 llvm::Value *DefaultThreadLimitVal) { 7292 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7293 CGF.getContext(), CS->getCapturedStmt()); 7294 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7295 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 7296 llvm::Value *NumThreads = nullptr; 7297 llvm::Value *CondVal = nullptr; 7298 // Handle if clause. If if clause present, the number of threads is 7299 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 7300 if (Dir->hasClausesOfKind<OMPIfClause>()) { 7301 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7302 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7303 const OMPIfClause *IfClause = nullptr; 7304 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 7305 if (C->getNameModifier() == OMPD_unknown || 7306 C->getNameModifier() == OMPD_parallel) { 7307 IfClause = C; 7308 break; 7309 } 7310 } 7311 if (IfClause) { 7312 const Expr *Cond = IfClause->getCondition(); 7313 bool Result; 7314 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 7315 if (!Result) 7316 return CGF.Builder.getInt32(1); 7317 } else { 7318 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 7319 if (const auto *PreInit = 7320 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 7321 for (const auto *I : PreInit->decls()) { 7322 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7323 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7324 } else { 7325 CodeGenFunction::AutoVarEmission Emission = 7326 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7327 CGF.EmitAutoVarCleanups(Emission); 7328 } 7329 } 7330 } 7331 CondVal = CGF.EvaluateExprAsBool(Cond); 7332 } 7333 } 7334 } 7335 // Check the value of num_threads clause iff if clause was not specified 7336 // or is not evaluated to false. 7337 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 7338 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7339 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7340 const auto *NumThreadsClause = 7341 Dir->getSingleClause<OMPNumThreadsClause>(); 7342 CodeGenFunction::LexicalScope Scope( 7343 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 7344 if (const auto *PreInit = 7345 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 7346 for (const auto *I : PreInit->decls()) { 7347 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7348 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7349 } else { 7350 CodeGenFunction::AutoVarEmission Emission = 7351 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7352 CGF.EmitAutoVarCleanups(Emission); 7353 } 7354 } 7355 } 7356 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 7357 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 7358 /*isSigned=*/false); 7359 if (DefaultThreadLimitVal) 7360 NumThreads = CGF.Builder.CreateSelect( 7361 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 7362 DefaultThreadLimitVal, NumThreads); 7363 } else { 7364 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 7365 : CGF.Builder.getInt32(0); 7366 } 7367 // Process condition of the if clause. 7368 if (CondVal) { 7369 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 7370 CGF.Builder.getInt32(1)); 7371 } 7372 return NumThreads; 7373 } 7374 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 7375 return CGF.Builder.getInt32(1); 7376 return DefaultThreadLimitVal; 7377 } 7378 return DefaultThreadLimitVal ? DefaultThreadLimitVal 7379 : CGF.Builder.getInt32(0); 7380 } 7381 7382 /// Emit the number of threads for a target directive. Inspect the 7383 /// thread_limit clause associated with a teams construct combined or closely 7384 /// nested with the target directive. 7385 /// 7386 /// Emit the num_threads clause for directives such as 'target parallel' that 7387 /// have no associated teams construct. 7388 /// 7389 /// Otherwise, return nullptr. 7390 static llvm::Value * 7391 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 7392 const OMPExecutableDirective &D) { 7393 assert(!CGF.getLangOpts().OpenMPIsDevice && 7394 "Clauses associated with the teams directive expected to be emitted " 7395 "only for the host!"); 7396 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 7397 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 7398 "Expected target-based executable directive."); 7399 CGBuilderTy &Bld = CGF.Builder; 7400 llvm::Value *ThreadLimitVal = nullptr; 7401 llvm::Value *NumThreadsVal = nullptr; 7402 switch (DirectiveKind) { 7403 case OMPD_target: { 7404 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7405 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7406 return NumThreads; 7407 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7408 CGF.getContext(), CS->getCapturedStmt()); 7409 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7410 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 7411 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7412 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7413 const auto *ThreadLimitClause = 7414 Dir->getSingleClause<OMPThreadLimitClause>(); 7415 CodeGenFunction::LexicalScope Scope( 7416 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 7417 if (const auto *PreInit = 7418 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 7419 for (const auto *I : PreInit->decls()) { 7420 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7421 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7422 } else { 7423 CodeGenFunction::AutoVarEmission Emission = 7424 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7425 CGF.EmitAutoVarCleanups(Emission); 7426 } 7427 } 7428 } 7429 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7430 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7431 ThreadLimitVal = 7432 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7433 } 7434 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 7435 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 7436 CS = Dir->getInnermostCapturedStmt(); 7437 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7438 CGF.getContext(), CS->getCapturedStmt()); 7439 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 7440 } 7441 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 7442 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 7443 CS = Dir->getInnermostCapturedStmt(); 7444 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7445 return NumThreads; 7446 } 7447 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 7448 return Bld.getInt32(1); 7449 } 7450 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7451 } 7452 case OMPD_target_teams: { 7453 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7454 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7455 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7456 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7457 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7458 ThreadLimitVal = 7459 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7460 } 7461 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7462 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7463 return NumThreads; 7464 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7465 CGF.getContext(), CS->getCapturedStmt()); 7466 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7467 if (Dir->getDirectiveKind() == OMPD_distribute) { 7468 CS = Dir->getInnermostCapturedStmt(); 7469 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7470 return NumThreads; 7471 } 7472 } 7473 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7474 } 7475 case OMPD_target_teams_distribute: 7476 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7477 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7478 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7479 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7480 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7481 ThreadLimitVal = 7482 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7483 } 7484 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 7485 case OMPD_target_parallel: 7486 case OMPD_target_parallel_for: 7487 case OMPD_target_parallel_for_simd: 7488 case OMPD_target_teams_distribute_parallel_for: 7489 case OMPD_target_teams_distribute_parallel_for_simd: { 7490 llvm::Value *CondVal = nullptr; 7491 // Handle if clause. If if clause present, the number of threads is 7492 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 7493 if (D.hasClausesOfKind<OMPIfClause>()) { 7494 const OMPIfClause *IfClause = nullptr; 7495 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 7496 if (C->getNameModifier() == OMPD_unknown || 7497 C->getNameModifier() == OMPD_parallel) { 7498 IfClause = C; 7499 break; 7500 } 7501 } 7502 if (IfClause) { 7503 const Expr *Cond = IfClause->getCondition(); 7504 bool Result; 7505 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 7506 if (!Result) 7507 return Bld.getInt32(1); 7508 } else { 7509 CodeGenFunction::RunCleanupsScope Scope(CGF); 7510 CondVal = CGF.EvaluateExprAsBool(Cond); 7511 } 7512 } 7513 } 7514 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7515 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7516 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7517 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7518 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7519 ThreadLimitVal = 7520 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7521 } 7522 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 7523 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 7524 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 7525 llvm::Value *NumThreads = CGF.EmitScalarExpr( 7526 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 7527 NumThreadsVal = 7528 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 7529 ThreadLimitVal = ThreadLimitVal 7530 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 7531 ThreadLimitVal), 7532 NumThreadsVal, ThreadLimitVal) 7533 : NumThreadsVal; 7534 } 7535 if (!ThreadLimitVal) 7536 ThreadLimitVal = Bld.getInt32(0); 7537 if (CondVal) 7538 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 7539 return ThreadLimitVal; 7540 } 7541 case OMPD_target_teams_distribute_simd: 7542 case OMPD_target_simd: 7543 return Bld.getInt32(1); 7544 case OMPD_parallel: 7545 case OMPD_for: 7546 case OMPD_parallel_for: 7547 case OMPD_parallel_master: 7548 case OMPD_parallel_sections: 7549 case OMPD_for_simd: 7550 case OMPD_parallel_for_simd: 7551 case OMPD_cancel: 7552 case OMPD_cancellation_point: 7553 case OMPD_ordered: 7554 case OMPD_threadprivate: 7555 case OMPD_allocate: 7556 case OMPD_task: 7557 case OMPD_simd: 7558 case OMPD_sections: 7559 case OMPD_section: 7560 case OMPD_single: 7561 case OMPD_master: 7562 case OMPD_critical: 7563 case OMPD_taskyield: 7564 case OMPD_barrier: 7565 case OMPD_taskwait: 7566 case OMPD_taskgroup: 7567 case OMPD_atomic: 7568 case OMPD_flush: 7569 case OMPD_depobj: 7570 case OMPD_scan: 7571 case OMPD_teams: 7572 case OMPD_target_data: 7573 case OMPD_target_exit_data: 7574 case OMPD_target_enter_data: 7575 case OMPD_distribute: 7576 case OMPD_distribute_simd: 7577 case OMPD_distribute_parallel_for: 7578 case OMPD_distribute_parallel_for_simd: 7579 case OMPD_teams_distribute: 7580 case OMPD_teams_distribute_simd: 7581 case OMPD_teams_distribute_parallel_for: 7582 case OMPD_teams_distribute_parallel_for_simd: 7583 case OMPD_target_update: 7584 case OMPD_declare_simd: 7585 case OMPD_declare_variant: 7586 case OMPD_begin_declare_variant: 7587 case OMPD_end_declare_variant: 7588 case OMPD_declare_target: 7589 case OMPD_end_declare_target: 7590 case OMPD_declare_reduction: 7591 case OMPD_declare_mapper: 7592 case OMPD_taskloop: 7593 case OMPD_taskloop_simd: 7594 case OMPD_master_taskloop: 7595 case OMPD_master_taskloop_simd: 7596 case OMPD_parallel_master_taskloop: 7597 case OMPD_parallel_master_taskloop_simd: 7598 case OMPD_requires: 7599 case OMPD_unknown: 7600 break; 7601 } 7602 llvm_unreachable("Unsupported directive kind."); 7603 } 7604 7605 namespace { 7606 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7607 7608 // Utility to handle information from clauses associated with a given 7609 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7610 // It provides a convenient interface to obtain the information and generate 7611 // code for that information. 7612 class MappableExprsHandler { 7613 public: 7614 /// Values for bit flags used to specify the mapping type for 7615 /// offloading. 7616 enum OpenMPOffloadMappingFlags : uint64_t { 7617 /// No flags 7618 OMP_MAP_NONE = 0x0, 7619 /// Allocate memory on the device and move data from host to device. 7620 OMP_MAP_TO = 0x01, 7621 /// Allocate memory on the device and move data from device to host. 7622 OMP_MAP_FROM = 0x02, 7623 /// Always perform the requested mapping action on the element, even 7624 /// if it was already mapped before. 7625 OMP_MAP_ALWAYS = 0x04, 7626 /// Delete the element from the device environment, ignoring the 7627 /// current reference count associated with the element. 7628 OMP_MAP_DELETE = 0x08, 7629 /// The element being mapped is a pointer-pointee pair; both the 7630 /// pointer and the pointee should be mapped. 7631 OMP_MAP_PTR_AND_OBJ = 0x10, 7632 /// This flags signals that the base address of an entry should be 7633 /// passed to the target kernel as an argument. 7634 OMP_MAP_TARGET_PARAM = 0x20, 7635 /// Signal that the runtime library has to return the device pointer 7636 /// in the current position for the data being mapped. Used when we have the 7637 /// use_device_ptr clause. 7638 OMP_MAP_RETURN_PARAM = 0x40, 7639 /// This flag signals that the reference being passed is a pointer to 7640 /// private data. 7641 OMP_MAP_PRIVATE = 0x80, 7642 /// Pass the element to the device by value. 7643 OMP_MAP_LITERAL = 0x100, 7644 /// Implicit map 7645 OMP_MAP_IMPLICIT = 0x200, 7646 /// Close is a hint to the runtime to allocate memory close to 7647 /// the target device. 7648 OMP_MAP_CLOSE = 0x400, 7649 /// The 16 MSBs of the flags indicate whether the entry is member of some 7650 /// struct/class. 7651 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7652 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7653 }; 7654 7655 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7656 static unsigned getFlagMemberOffset() { 7657 unsigned Offset = 0; 7658 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7659 Remain = Remain >> 1) 7660 Offset++; 7661 return Offset; 7662 } 7663 7664 /// Class that associates information with a base pointer to be passed to the 7665 /// runtime library. 7666 class BasePointerInfo { 7667 /// The base pointer. 7668 llvm::Value *Ptr = nullptr; 7669 /// The base declaration that refers to this device pointer, or null if 7670 /// there is none. 7671 const ValueDecl *DevPtrDecl = nullptr; 7672 7673 public: 7674 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7675 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7676 llvm::Value *operator*() const { return Ptr; } 7677 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7678 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7679 }; 7680 7681 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7682 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7683 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7684 7685 /// Map between a struct and the its lowest & highest elements which have been 7686 /// mapped. 7687 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7688 /// HE(FieldIndex, Pointer)} 7689 struct StructRangeInfoTy { 7690 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7691 0, Address::invalid()}; 7692 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7693 0, Address::invalid()}; 7694 Address Base = Address::invalid(); 7695 }; 7696 7697 private: 7698 /// Kind that defines how a device pointer has to be returned. 7699 struct MapInfo { 7700 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7701 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7702 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7703 bool ReturnDevicePointer = false; 7704 bool IsImplicit = false; 7705 7706 MapInfo() = default; 7707 MapInfo( 7708 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7709 OpenMPMapClauseKind MapType, 7710 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7711 bool ReturnDevicePointer, bool IsImplicit) 7712 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7713 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7714 }; 7715 7716 /// If use_device_ptr is used on a pointer which is a struct member and there 7717 /// is no map information about it, then emission of that entry is deferred 7718 /// until the whole struct has been processed. 7719 struct DeferredDevicePtrEntryTy { 7720 const Expr *IE = nullptr; 7721 const ValueDecl *VD = nullptr; 7722 7723 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7724 : IE(IE), VD(VD) {} 7725 }; 7726 7727 /// The target directive from where the mappable clauses were extracted. It 7728 /// is either a executable directive or a user-defined mapper directive. 7729 llvm::PointerUnion<const OMPExecutableDirective *, 7730 const OMPDeclareMapperDecl *> 7731 CurDir; 7732 7733 /// Function the directive is being generated for. 7734 CodeGenFunction &CGF; 7735 7736 /// Set of all first private variables in the current directive. 7737 /// bool data is set to true if the variable is implicitly marked as 7738 /// firstprivate, false otherwise. 7739 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7740 7741 /// Map between device pointer declarations and their expression components. 7742 /// The key value for declarations in 'this' is null. 7743 llvm::DenseMap< 7744 const ValueDecl *, 7745 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7746 DevPointersMap; 7747 7748 llvm::Value *getExprTypeSize(const Expr *E) const { 7749 QualType ExprTy = E->getType().getCanonicalType(); 7750 7751 // Calculate the size for array shaping expression. 7752 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) { 7753 llvm::Value *Size = 7754 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType()); 7755 for (const Expr *SE : OAE->getDimensions()) { 7756 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 7757 Sz = CGF.EmitScalarConversion(Sz, SE->getType(), 7758 CGF.getContext().getSizeType(), 7759 SE->getExprLoc()); 7760 Size = CGF.Builder.CreateNUWMul(Size, Sz); 7761 } 7762 return Size; 7763 } 7764 7765 // Reference types are ignored for mapping purposes. 7766 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7767 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7768 7769 // Given that an array section is considered a built-in type, we need to 7770 // do the calculation based on the length of the section instead of relying 7771 // on CGF.getTypeSize(E->getType()). 7772 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7773 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7774 OAE->getBase()->IgnoreParenImpCasts()) 7775 .getCanonicalType(); 7776 7777 // If there is no length associated with the expression and lower bound is 7778 // not specified too, that means we are using the whole length of the 7779 // base. 7780 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7781 !OAE->getLowerBound()) 7782 return CGF.getTypeSize(BaseTy); 7783 7784 llvm::Value *ElemSize; 7785 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7786 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7787 } else { 7788 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7789 assert(ATy && "Expecting array type if not a pointer type."); 7790 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7791 } 7792 7793 // If we don't have a length at this point, that is because we have an 7794 // array section with a single element. 7795 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7796 return ElemSize; 7797 7798 if (const Expr *LenExpr = OAE->getLength()) { 7799 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7800 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7801 CGF.getContext().getSizeType(), 7802 LenExpr->getExprLoc()); 7803 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7804 } 7805 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7806 OAE->getLowerBound() && "expected array_section[lb:]."); 7807 // Size = sizetype - lb * elemtype; 7808 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7809 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7810 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7811 CGF.getContext().getSizeType(), 7812 OAE->getLowerBound()->getExprLoc()); 7813 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7814 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7815 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7816 LengthVal = CGF.Builder.CreateSelect( 7817 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7818 return LengthVal; 7819 } 7820 return CGF.getTypeSize(ExprTy); 7821 } 7822 7823 /// Return the corresponding bits for a given map clause modifier. Add 7824 /// a flag marking the map as a pointer if requested. Add a flag marking the 7825 /// map as the first one of a series of maps that relate to the same map 7826 /// expression. 7827 OpenMPOffloadMappingFlags getMapTypeBits( 7828 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7829 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7830 OpenMPOffloadMappingFlags Bits = 7831 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7832 switch (MapType) { 7833 case OMPC_MAP_alloc: 7834 case OMPC_MAP_release: 7835 // alloc and release is the default behavior in the runtime library, i.e. 7836 // if we don't pass any bits alloc/release that is what the runtime is 7837 // going to do. Therefore, we don't need to signal anything for these two 7838 // type modifiers. 7839 break; 7840 case OMPC_MAP_to: 7841 Bits |= OMP_MAP_TO; 7842 break; 7843 case OMPC_MAP_from: 7844 Bits |= OMP_MAP_FROM; 7845 break; 7846 case OMPC_MAP_tofrom: 7847 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7848 break; 7849 case OMPC_MAP_delete: 7850 Bits |= OMP_MAP_DELETE; 7851 break; 7852 case OMPC_MAP_unknown: 7853 llvm_unreachable("Unexpected map type!"); 7854 } 7855 if (AddPtrFlag) 7856 Bits |= OMP_MAP_PTR_AND_OBJ; 7857 if (AddIsTargetParamFlag) 7858 Bits |= OMP_MAP_TARGET_PARAM; 7859 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7860 != MapModifiers.end()) 7861 Bits |= OMP_MAP_ALWAYS; 7862 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7863 != MapModifiers.end()) 7864 Bits |= OMP_MAP_CLOSE; 7865 return Bits; 7866 } 7867 7868 /// Return true if the provided expression is a final array section. A 7869 /// final array section, is one whose length can't be proved to be one. 7870 bool isFinalArraySectionExpression(const Expr *E) const { 7871 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7872 7873 // It is not an array section and therefore not a unity-size one. 7874 if (!OASE) 7875 return false; 7876 7877 // An array section with no colon always refer to a single element. 7878 if (OASE->getColonLoc().isInvalid()) 7879 return false; 7880 7881 const Expr *Length = OASE->getLength(); 7882 7883 // If we don't have a length we have to check if the array has size 1 7884 // for this dimension. Also, we should always expect a length if the 7885 // base type is pointer. 7886 if (!Length) { 7887 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7888 OASE->getBase()->IgnoreParenImpCasts()) 7889 .getCanonicalType(); 7890 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7891 return ATy->getSize().getSExtValue() != 1; 7892 // If we don't have a constant dimension length, we have to consider 7893 // the current section as having any size, so it is not necessarily 7894 // unitary. If it happen to be unity size, that's user fault. 7895 return true; 7896 } 7897 7898 // Check if the length evaluates to 1. 7899 Expr::EvalResult Result; 7900 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7901 return true; // Can have more that size 1. 7902 7903 llvm::APSInt ConstLength = Result.Val.getInt(); 7904 return ConstLength.getSExtValue() != 1; 7905 } 7906 7907 /// Generate the base pointers, section pointers, sizes and map type 7908 /// bits for the provided map type, map modifier, and expression components. 7909 /// \a IsFirstComponent should be set to true if the provided set of 7910 /// components is the first associated with a capture. 7911 void generateInfoForComponentList( 7912 OpenMPMapClauseKind MapType, 7913 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7914 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7915 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7916 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7917 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7918 bool IsImplicit, 7919 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7920 OverlappedElements = llvm::None) const { 7921 // The following summarizes what has to be generated for each map and the 7922 // types below. The generated information is expressed in this order: 7923 // base pointer, section pointer, size, flags 7924 // (to add to the ones that come from the map type and modifier). 7925 // 7926 // double d; 7927 // int i[100]; 7928 // float *p; 7929 // 7930 // struct S1 { 7931 // int i; 7932 // float f[50]; 7933 // } 7934 // struct S2 { 7935 // int i; 7936 // float f[50]; 7937 // S1 s; 7938 // double *p; 7939 // struct S2 *ps; 7940 // } 7941 // S2 s; 7942 // S2 *ps; 7943 // 7944 // map(d) 7945 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7946 // 7947 // map(i) 7948 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7949 // 7950 // map(i[1:23]) 7951 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7952 // 7953 // map(p) 7954 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7955 // 7956 // map(p[1:24]) 7957 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7958 // 7959 // map(s) 7960 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7961 // 7962 // map(s.i) 7963 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7964 // 7965 // map(s.s.f) 7966 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7967 // 7968 // map(s.p) 7969 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7970 // 7971 // map(to: s.p[:22]) 7972 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7973 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7974 // &(s.p), &(s.p[0]), 22*sizeof(double), 7975 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7976 // (*) alloc space for struct members, only this is a target parameter 7977 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7978 // optimizes this entry out, same in the examples below) 7979 // (***) map the pointee (map: to) 7980 // 7981 // map(s.ps) 7982 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7983 // 7984 // map(from: s.ps->s.i) 7985 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7986 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7987 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7988 // 7989 // map(to: s.ps->ps) 7990 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7991 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7992 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7993 // 7994 // map(s.ps->ps->ps) 7995 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7996 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7997 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7998 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7999 // 8000 // map(to: s.ps->ps->s.f[:22]) 8001 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 8002 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 8003 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 8004 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 8005 // 8006 // map(ps) 8007 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 8008 // 8009 // map(ps->i) 8010 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 8011 // 8012 // map(ps->s.f) 8013 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 8014 // 8015 // map(from: ps->p) 8016 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 8017 // 8018 // map(to: ps->p[:22]) 8019 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 8020 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 8021 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 8022 // 8023 // map(ps->ps) 8024 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 8025 // 8026 // map(from: ps->ps->s.i) 8027 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 8028 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 8029 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 8030 // 8031 // map(from: ps->ps->ps) 8032 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 8033 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 8034 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 8035 // 8036 // map(ps->ps->ps->ps) 8037 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 8038 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 8039 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 8040 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 8041 // 8042 // map(to: ps->ps->ps->s.f[:22]) 8043 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 8044 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 8045 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 8046 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 8047 // 8048 // map(to: s.f[:22]) map(from: s.p[:33]) 8049 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 8050 // sizeof(double*) (**), TARGET_PARAM 8051 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 8052 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 8053 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 8054 // (*) allocate contiguous space needed to fit all mapped members even if 8055 // we allocate space for members not mapped (in this example, 8056 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 8057 // them as well because they fall between &s.f[0] and &s.p) 8058 // 8059 // map(from: s.f[:22]) map(to: ps->p[:33]) 8060 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 8061 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 8062 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 8063 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 8064 // (*) the struct this entry pertains to is the 2nd element in the list of 8065 // arguments, hence MEMBER_OF(2) 8066 // 8067 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 8068 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 8069 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 8070 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 8071 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 8072 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 8073 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 8074 // (*) the struct this entry pertains to is the 4th element in the list 8075 // of arguments, hence MEMBER_OF(4) 8076 8077 // Track if the map information being generated is the first for a capture. 8078 bool IsCaptureFirstInfo = IsFirstComponentList; 8079 // When the variable is on a declare target link or in a to clause with 8080 // unified memory, a reference is needed to hold the host/device address 8081 // of the variable. 8082 bool RequiresReference = false; 8083 8084 // Scan the components from the base to the complete expression. 8085 auto CI = Components.rbegin(); 8086 auto CE = Components.rend(); 8087 auto I = CI; 8088 8089 // Track if the map information being generated is the first for a list of 8090 // components. 8091 bool IsExpressionFirstInfo = true; 8092 Address BP = Address::invalid(); 8093 const Expr *AssocExpr = I->getAssociatedExpression(); 8094 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 8095 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8096 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr); 8097 8098 if (isa<MemberExpr>(AssocExpr)) { 8099 // The base is the 'this' pointer. The content of the pointer is going 8100 // to be the base of the field being mapped. 8101 BP = CGF.LoadCXXThisAddress(); 8102 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 8103 (OASE && 8104 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 8105 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 8106 } else if (OAShE && 8107 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) { 8108 BP = Address( 8109 CGF.EmitScalarExpr(OAShE->getBase()), 8110 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType())); 8111 } else { 8112 // The base is the reference to the variable. 8113 // BP = &Var. 8114 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 8115 if (const auto *VD = 8116 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 8117 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8118 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 8119 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 8120 (*Res == OMPDeclareTargetDeclAttr::MT_To && 8121 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 8122 RequiresReference = true; 8123 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 8124 } 8125 } 8126 } 8127 8128 // If the variable is a pointer and is being dereferenced (i.e. is not 8129 // the last component), the base has to be the pointer itself, not its 8130 // reference. References are ignored for mapping purposes. 8131 QualType Ty = 8132 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 8133 if (Ty->isAnyPointerType() && std::next(I) != CE) { 8134 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 8135 8136 // We do not need to generate individual map information for the 8137 // pointer, it can be associated with the combined storage. 8138 ++I; 8139 } 8140 } 8141 8142 // Track whether a component of the list should be marked as MEMBER_OF some 8143 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 8144 // in a component list should be marked as MEMBER_OF, all subsequent entries 8145 // do not belong to the base struct. E.g. 8146 // struct S2 s; 8147 // s.ps->ps->ps->f[:] 8148 // (1) (2) (3) (4) 8149 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 8150 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 8151 // is the pointee of ps(2) which is not member of struct s, so it should not 8152 // be marked as such (it is still PTR_AND_OBJ). 8153 // The variable is initialized to false so that PTR_AND_OBJ entries which 8154 // are not struct members are not considered (e.g. array of pointers to 8155 // data). 8156 bool ShouldBeMemberOf = false; 8157 8158 // Variable keeping track of whether or not we have encountered a component 8159 // in the component list which is a member expression. Useful when we have a 8160 // pointer or a final array section, in which case it is the previous 8161 // component in the list which tells us whether we have a member expression. 8162 // E.g. X.f[:] 8163 // While processing the final array section "[:]" it is "f" which tells us 8164 // whether we are dealing with a member of a declared struct. 8165 const MemberExpr *EncounteredME = nullptr; 8166 8167 for (; I != CE; ++I) { 8168 // If the current component is member of a struct (parent struct) mark it. 8169 if (!EncounteredME) { 8170 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 8171 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 8172 // as MEMBER_OF the parent struct. 8173 if (EncounteredME) 8174 ShouldBeMemberOf = true; 8175 } 8176 8177 auto Next = std::next(I); 8178 8179 // We need to generate the addresses and sizes if this is the last 8180 // component, if the component is a pointer or if it is an array section 8181 // whose length can't be proved to be one. If this is a pointer, it 8182 // becomes the base address for the following components. 8183 8184 // A final array section, is one whose length can't be proved to be one. 8185 bool IsFinalArraySection = 8186 isFinalArraySectionExpression(I->getAssociatedExpression()); 8187 8188 // Get information on whether the element is a pointer. Have to do a 8189 // special treatment for array sections given that they are built-in 8190 // types. 8191 const auto *OASE = 8192 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 8193 const auto *OAShE = 8194 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression()); 8195 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression()); 8196 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression()); 8197 bool IsPointer = 8198 OAShE || 8199 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 8200 .getCanonicalType() 8201 ->isAnyPointerType()) || 8202 I->getAssociatedExpression()->getType()->isAnyPointerType(); 8203 bool IsNonDerefPointer = IsPointer && !UO && !BO; 8204 8205 if (Next == CE || IsNonDerefPointer || IsFinalArraySection) { 8206 // If this is not the last component, we expect the pointer to be 8207 // associated with an array expression or member expression. 8208 assert((Next == CE || 8209 isa<MemberExpr>(Next->getAssociatedExpression()) || 8210 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 8211 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || 8212 isa<UnaryOperator>(Next->getAssociatedExpression()) || 8213 isa<BinaryOperator>(Next->getAssociatedExpression())) && 8214 "Unexpected expression"); 8215 8216 Address LB = Address::invalid(); 8217 if (OAShE) { 8218 LB = Address(CGF.EmitScalarExpr(OAShE->getBase()), 8219 CGF.getContext().getTypeAlignInChars( 8220 OAShE->getBase()->getType())); 8221 } else { 8222 LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 8223 .getAddress(CGF); 8224 } 8225 8226 // If this component is a pointer inside the base struct then we don't 8227 // need to create any entry for it - it will be combined with the object 8228 // it is pointing to into a single PTR_AND_OBJ entry. 8229 bool IsMemberPointer = 8230 IsPointer && EncounteredME && 8231 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 8232 EncounteredME); 8233 if (!OverlappedElements.empty()) { 8234 // Handle base element with the info for overlapped elements. 8235 assert(!PartialStruct.Base.isValid() && "The base element is set."); 8236 assert(Next == CE && 8237 "Expected last element for the overlapped elements."); 8238 assert(!IsPointer && 8239 "Unexpected base element with the pointer type."); 8240 // Mark the whole struct as the struct that requires allocation on the 8241 // device. 8242 PartialStruct.LowestElem = {0, LB}; 8243 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 8244 I->getAssociatedExpression()->getType()); 8245 Address HB = CGF.Builder.CreateConstGEP( 8246 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 8247 CGF.VoidPtrTy), 8248 TypeSize.getQuantity() - 1); 8249 PartialStruct.HighestElem = { 8250 std::numeric_limits<decltype( 8251 PartialStruct.HighestElem.first)>::max(), 8252 HB}; 8253 PartialStruct.Base = BP; 8254 // Emit data for non-overlapped data. 8255 OpenMPOffloadMappingFlags Flags = 8256 OMP_MAP_MEMBER_OF | 8257 getMapTypeBits(MapType, MapModifiers, IsImplicit, 8258 /*AddPtrFlag=*/false, 8259 /*AddIsTargetParamFlag=*/false); 8260 LB = BP; 8261 llvm::Value *Size = nullptr; 8262 // Do bitcopy of all non-overlapped structure elements. 8263 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 8264 Component : OverlappedElements) { 8265 Address ComponentLB = Address::invalid(); 8266 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 8267 Component) { 8268 if (MC.getAssociatedDeclaration()) { 8269 ComponentLB = 8270 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 8271 .getAddress(CGF); 8272 Size = CGF.Builder.CreatePtrDiff( 8273 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 8274 CGF.EmitCastToVoidPtr(LB.getPointer())); 8275 break; 8276 } 8277 } 8278 BasePointers.push_back(BP.getPointer()); 8279 Pointers.push_back(LB.getPointer()); 8280 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 8281 /*isSigned=*/true)); 8282 Types.push_back(Flags); 8283 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 8284 } 8285 BasePointers.push_back(BP.getPointer()); 8286 Pointers.push_back(LB.getPointer()); 8287 Size = CGF.Builder.CreatePtrDiff( 8288 CGF.EmitCastToVoidPtr( 8289 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 8290 CGF.EmitCastToVoidPtr(LB.getPointer())); 8291 Sizes.push_back( 8292 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 8293 Types.push_back(Flags); 8294 break; 8295 } 8296 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 8297 if (!IsMemberPointer) { 8298 BasePointers.push_back(BP.getPointer()); 8299 Pointers.push_back(LB.getPointer()); 8300 Sizes.push_back( 8301 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 8302 8303 // We need to add a pointer flag for each map that comes from the 8304 // same expression except for the first one. We also need to signal 8305 // this map is the first one that relates with the current capture 8306 // (there is a set of entries for each capture). 8307 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 8308 MapType, MapModifiers, IsImplicit, 8309 !IsExpressionFirstInfo || RequiresReference, 8310 IsCaptureFirstInfo && !RequiresReference); 8311 8312 if (!IsExpressionFirstInfo) { 8313 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 8314 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 8315 if (IsPointer) 8316 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 8317 OMP_MAP_DELETE | OMP_MAP_CLOSE); 8318 8319 if (ShouldBeMemberOf) { 8320 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 8321 // should be later updated with the correct value of MEMBER_OF. 8322 Flags |= OMP_MAP_MEMBER_OF; 8323 // From now on, all subsequent PTR_AND_OBJ entries should not be 8324 // marked as MEMBER_OF. 8325 ShouldBeMemberOf = false; 8326 } 8327 } 8328 8329 Types.push_back(Flags); 8330 } 8331 8332 // If we have encountered a member expression so far, keep track of the 8333 // mapped member. If the parent is "*this", then the value declaration 8334 // is nullptr. 8335 if (EncounteredME) { 8336 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl()); 8337 unsigned FieldIndex = FD->getFieldIndex(); 8338 8339 // Update info about the lowest and highest elements for this struct 8340 if (!PartialStruct.Base.isValid()) { 8341 PartialStruct.LowestElem = {FieldIndex, LB}; 8342 PartialStruct.HighestElem = {FieldIndex, LB}; 8343 PartialStruct.Base = BP; 8344 } else if (FieldIndex < PartialStruct.LowestElem.first) { 8345 PartialStruct.LowestElem = {FieldIndex, LB}; 8346 } else if (FieldIndex > PartialStruct.HighestElem.first) { 8347 PartialStruct.HighestElem = {FieldIndex, LB}; 8348 } 8349 } 8350 8351 // If we have a final array section, we are done with this expression. 8352 if (IsFinalArraySection) 8353 break; 8354 8355 // The pointer becomes the base for the next element. 8356 if (Next != CE) 8357 BP = LB; 8358 8359 IsExpressionFirstInfo = false; 8360 IsCaptureFirstInfo = false; 8361 } 8362 } 8363 } 8364 8365 /// Return the adjusted map modifiers if the declaration a capture refers to 8366 /// appears in a first-private clause. This is expected to be used only with 8367 /// directives that start with 'target'. 8368 MappableExprsHandler::OpenMPOffloadMappingFlags 8369 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 8370 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 8371 8372 // A first private variable captured by reference will use only the 8373 // 'private ptr' and 'map to' flag. Return the right flags if the captured 8374 // declaration is known as first-private in this handler. 8375 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 8376 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 8377 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 8378 return MappableExprsHandler::OMP_MAP_ALWAYS | 8379 MappableExprsHandler::OMP_MAP_TO; 8380 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 8381 return MappableExprsHandler::OMP_MAP_TO | 8382 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 8383 return MappableExprsHandler::OMP_MAP_PRIVATE | 8384 MappableExprsHandler::OMP_MAP_TO; 8385 } 8386 return MappableExprsHandler::OMP_MAP_TO | 8387 MappableExprsHandler::OMP_MAP_FROM; 8388 } 8389 8390 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 8391 // Rotate by getFlagMemberOffset() bits. 8392 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 8393 << getFlagMemberOffset()); 8394 } 8395 8396 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 8397 OpenMPOffloadMappingFlags MemberOfFlag) { 8398 // If the entry is PTR_AND_OBJ but has not been marked with the special 8399 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 8400 // marked as MEMBER_OF. 8401 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 8402 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 8403 return; 8404 8405 // Reset the placeholder value to prepare the flag for the assignment of the 8406 // proper MEMBER_OF value. 8407 Flags &= ~OMP_MAP_MEMBER_OF; 8408 Flags |= MemberOfFlag; 8409 } 8410 8411 void getPlainLayout(const CXXRecordDecl *RD, 8412 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 8413 bool AsBase) const { 8414 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 8415 8416 llvm::StructType *St = 8417 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 8418 8419 unsigned NumElements = St->getNumElements(); 8420 llvm::SmallVector< 8421 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 8422 RecordLayout(NumElements); 8423 8424 // Fill bases. 8425 for (const auto &I : RD->bases()) { 8426 if (I.isVirtual()) 8427 continue; 8428 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8429 // Ignore empty bases. 8430 if (Base->isEmpty() || CGF.getContext() 8431 .getASTRecordLayout(Base) 8432 .getNonVirtualSize() 8433 .isZero()) 8434 continue; 8435 8436 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 8437 RecordLayout[FieldIndex] = Base; 8438 } 8439 // Fill in virtual bases. 8440 for (const auto &I : RD->vbases()) { 8441 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8442 // Ignore empty bases. 8443 if (Base->isEmpty()) 8444 continue; 8445 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 8446 if (RecordLayout[FieldIndex]) 8447 continue; 8448 RecordLayout[FieldIndex] = Base; 8449 } 8450 // Fill in all the fields. 8451 assert(!RD->isUnion() && "Unexpected union."); 8452 for (const auto *Field : RD->fields()) { 8453 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 8454 // will fill in later.) 8455 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 8456 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 8457 RecordLayout[FieldIndex] = Field; 8458 } 8459 } 8460 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 8461 &Data : RecordLayout) { 8462 if (Data.isNull()) 8463 continue; 8464 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 8465 getPlainLayout(Base, Layout, /*AsBase=*/true); 8466 else 8467 Layout.push_back(Data.get<const FieldDecl *>()); 8468 } 8469 } 8470 8471 public: 8472 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 8473 : CurDir(&Dir), CGF(CGF) { 8474 // Extract firstprivate clause information. 8475 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 8476 for (const auto *D : C->varlists()) 8477 FirstPrivateDecls.try_emplace( 8478 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 8479 // Extract device pointer clause information. 8480 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 8481 for (auto L : C->component_lists()) 8482 DevPointersMap[L.first].push_back(L.second); 8483 } 8484 8485 /// Constructor for the declare mapper directive. 8486 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 8487 : CurDir(&Dir), CGF(CGF) {} 8488 8489 /// Generate code for the combined entry if we have a partially mapped struct 8490 /// and take care of the mapping flags of the arguments corresponding to 8491 /// individual struct members. 8492 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 8493 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8494 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 8495 const StructRangeInfoTy &PartialStruct) const { 8496 // Base is the base of the struct 8497 BasePointers.push_back(PartialStruct.Base.getPointer()); 8498 // Pointer is the address of the lowest element 8499 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 8500 Pointers.push_back(LB); 8501 // Size is (addr of {highest+1} element) - (addr of lowest element) 8502 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 8503 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 8504 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 8505 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 8506 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 8507 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 8508 /*isSigned=*/false); 8509 Sizes.push_back(Size); 8510 // Map type is always TARGET_PARAM 8511 Types.push_back(OMP_MAP_TARGET_PARAM); 8512 // Remove TARGET_PARAM flag from the first element 8513 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 8514 8515 // All other current entries will be MEMBER_OF the combined entry 8516 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8517 // 0xFFFF in the MEMBER_OF field). 8518 OpenMPOffloadMappingFlags MemberOfFlag = 8519 getMemberOfFlag(BasePointers.size() - 1); 8520 for (auto &M : CurTypes) 8521 setCorrectMemberOfFlag(M, MemberOfFlag); 8522 } 8523 8524 /// Generate all the base pointers, section pointers, sizes and map 8525 /// types for the extracted mappable expressions. Also, for each item that 8526 /// relates with a device pointer, a pair of the relevant declaration and 8527 /// index where it occurs is appended to the device pointers info array. 8528 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 8529 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8530 MapFlagsArrayTy &Types) const { 8531 // We have to process the component lists that relate with the same 8532 // declaration in a single chunk so that we can generate the map flags 8533 // correctly. Therefore, we organize all lists in a map. 8534 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8535 8536 // Helper function to fill the information map for the different supported 8537 // clauses. 8538 auto &&InfoGen = [&Info]( 8539 const ValueDecl *D, 8540 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8541 OpenMPMapClauseKind MapType, 8542 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8543 bool ReturnDevicePointer, bool IsImplicit) { 8544 const ValueDecl *VD = 8545 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8546 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8547 IsImplicit); 8548 }; 8549 8550 assert(CurDir.is<const OMPExecutableDirective *>() && 8551 "Expect a executable directive"); 8552 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8553 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 8554 for (const auto L : C->component_lists()) { 8555 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 8556 /*ReturnDevicePointer=*/false, C->isImplicit()); 8557 } 8558 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 8559 for (const auto L : C->component_lists()) { 8560 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 8561 /*ReturnDevicePointer=*/false, C->isImplicit()); 8562 } 8563 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 8564 for (const auto L : C->component_lists()) { 8565 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 8566 /*ReturnDevicePointer=*/false, C->isImplicit()); 8567 } 8568 8569 // Look at the use_device_ptr clause information and mark the existing map 8570 // entries as such. If there is no map information for an entry in the 8571 // use_device_ptr list, we create one with map type 'alloc' and zero size 8572 // section. It is the user fault if that was not mapped before. If there is 8573 // no map information and the pointer is a struct member, then we defer the 8574 // emission of that entry until the whole struct has been processed. 8575 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 8576 DeferredInfo; 8577 8578 for (const auto *C : 8579 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 8580 for (const auto L : C->component_lists()) { 8581 assert(!L.second.empty() && "Not expecting empty list of components!"); 8582 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 8583 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8584 const Expr *IE = L.second.back().getAssociatedExpression(); 8585 // If the first component is a member expression, we have to look into 8586 // 'this', which maps to null in the map of map information. Otherwise 8587 // look directly for the information. 8588 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8589 8590 // We potentially have map information for this declaration already. 8591 // Look for the first set of components that refer to it. 8592 if (It != Info.end()) { 8593 auto CI = std::find_if( 8594 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 8595 return MI.Components.back().getAssociatedDeclaration() == VD; 8596 }); 8597 // If we found a map entry, signal that the pointer has to be returned 8598 // and move on to the next declaration. 8599 if (CI != It->second.end()) { 8600 CI->ReturnDevicePointer = true; 8601 continue; 8602 } 8603 } 8604 8605 // We didn't find any match in our map information - generate a zero 8606 // size array section - if the pointer is a struct member we defer this 8607 // action until the whole struct has been processed. 8608 if (isa<MemberExpr>(IE)) { 8609 // Insert the pointer into Info to be processed by 8610 // generateInfoForComponentList. Because it is a member pointer 8611 // without a pointee, no entry will be generated for it, therefore 8612 // we need to generate one after the whole struct has been processed. 8613 // Nonetheless, generateInfoForComponentList must be called to take 8614 // the pointer into account for the calculation of the range of the 8615 // partial struct. 8616 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 8617 /*ReturnDevicePointer=*/false, C->isImplicit()); 8618 DeferredInfo[nullptr].emplace_back(IE, VD); 8619 } else { 8620 llvm::Value *Ptr = 8621 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8622 BasePointers.emplace_back(Ptr, VD); 8623 Pointers.push_back(Ptr); 8624 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8625 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8626 } 8627 } 8628 } 8629 8630 for (const auto &M : Info) { 8631 // We need to know when we generate information for the first component 8632 // associated with a capture, because the mapping flags depend on it. 8633 bool IsFirstComponentList = true; 8634 8635 // Temporary versions of arrays 8636 MapBaseValuesArrayTy CurBasePointers; 8637 MapValuesArrayTy CurPointers; 8638 MapValuesArrayTy CurSizes; 8639 MapFlagsArrayTy CurTypes; 8640 StructRangeInfoTy PartialStruct; 8641 8642 for (const MapInfo &L : M.second) { 8643 assert(!L.Components.empty() && 8644 "Not expecting declaration with no component lists."); 8645 8646 // Remember the current base pointer index. 8647 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8648 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8649 CurBasePointers, CurPointers, CurSizes, 8650 CurTypes, PartialStruct, 8651 IsFirstComponentList, L.IsImplicit); 8652 8653 // If this entry relates with a device pointer, set the relevant 8654 // declaration and add the 'return pointer' flag. 8655 if (L.ReturnDevicePointer) { 8656 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8657 "Unexpected number of mapped base pointers."); 8658 8659 const ValueDecl *RelevantVD = 8660 L.Components.back().getAssociatedDeclaration(); 8661 assert(RelevantVD && 8662 "No relevant declaration related with device pointer??"); 8663 8664 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8665 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8666 } 8667 IsFirstComponentList = false; 8668 } 8669 8670 // Append any pending zero-length pointers which are struct members and 8671 // used with use_device_ptr. 8672 auto CI = DeferredInfo.find(M.first); 8673 if (CI != DeferredInfo.end()) { 8674 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8675 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8676 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8677 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8678 CurBasePointers.emplace_back(BasePtr, L.VD); 8679 CurPointers.push_back(Ptr); 8680 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8681 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8682 // value MEMBER_OF=FFFF so that the entry is later updated with the 8683 // correct value of MEMBER_OF. 8684 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8685 OMP_MAP_MEMBER_OF); 8686 } 8687 } 8688 8689 // If there is an entry in PartialStruct it means we have a struct with 8690 // individual members mapped. Emit an extra combined entry. 8691 if (PartialStruct.Base.isValid()) 8692 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8693 PartialStruct); 8694 8695 // We need to append the results of this capture to what we already have. 8696 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8697 Pointers.append(CurPointers.begin(), CurPointers.end()); 8698 Sizes.append(CurSizes.begin(), CurSizes.end()); 8699 Types.append(CurTypes.begin(), CurTypes.end()); 8700 } 8701 } 8702 8703 /// Generate all the base pointers, section pointers, sizes and map types for 8704 /// the extracted map clauses of user-defined mapper. 8705 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8706 MapValuesArrayTy &Pointers, 8707 MapValuesArrayTy &Sizes, 8708 MapFlagsArrayTy &Types) const { 8709 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8710 "Expect a declare mapper directive"); 8711 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8712 // We have to process the component lists that relate with the same 8713 // declaration in a single chunk so that we can generate the map flags 8714 // correctly. Therefore, we organize all lists in a map. 8715 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8716 8717 // Helper function to fill the information map for the different supported 8718 // clauses. 8719 auto &&InfoGen = [&Info]( 8720 const ValueDecl *D, 8721 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8722 OpenMPMapClauseKind MapType, 8723 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8724 bool ReturnDevicePointer, bool IsImplicit) { 8725 const ValueDecl *VD = 8726 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8727 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8728 IsImplicit); 8729 }; 8730 8731 for (const auto *C : CurMapperDir->clauselists()) { 8732 const auto *MC = cast<OMPMapClause>(C); 8733 for (const auto L : MC->component_lists()) { 8734 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8735 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8736 } 8737 } 8738 8739 for (const auto &M : Info) { 8740 // We need to know when we generate information for the first component 8741 // associated with a capture, because the mapping flags depend on it. 8742 bool IsFirstComponentList = true; 8743 8744 // Temporary versions of arrays 8745 MapBaseValuesArrayTy CurBasePointers; 8746 MapValuesArrayTy CurPointers; 8747 MapValuesArrayTy CurSizes; 8748 MapFlagsArrayTy CurTypes; 8749 StructRangeInfoTy PartialStruct; 8750 8751 for (const MapInfo &L : M.second) { 8752 assert(!L.Components.empty() && 8753 "Not expecting declaration with no component lists."); 8754 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8755 CurBasePointers, CurPointers, CurSizes, 8756 CurTypes, PartialStruct, 8757 IsFirstComponentList, L.IsImplicit); 8758 IsFirstComponentList = false; 8759 } 8760 8761 // If there is an entry in PartialStruct it means we have a struct with 8762 // individual members mapped. Emit an extra combined entry. 8763 if (PartialStruct.Base.isValid()) 8764 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8765 PartialStruct); 8766 8767 // We need to append the results of this capture to what we already have. 8768 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8769 Pointers.append(CurPointers.begin(), CurPointers.end()); 8770 Sizes.append(CurSizes.begin(), CurSizes.end()); 8771 Types.append(CurTypes.begin(), CurTypes.end()); 8772 } 8773 } 8774 8775 /// Emit capture info for lambdas for variables captured by reference. 8776 void generateInfoForLambdaCaptures( 8777 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8778 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8779 MapFlagsArrayTy &Types, 8780 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8781 const auto *RD = VD->getType() 8782 .getCanonicalType() 8783 .getNonReferenceType() 8784 ->getAsCXXRecordDecl(); 8785 if (!RD || !RD->isLambda()) 8786 return; 8787 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8788 LValue VDLVal = CGF.MakeAddrLValue( 8789 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8790 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8791 FieldDecl *ThisCapture = nullptr; 8792 RD->getCaptureFields(Captures, ThisCapture); 8793 if (ThisCapture) { 8794 LValue ThisLVal = 8795 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8796 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8797 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8798 VDLVal.getPointer(CGF)); 8799 BasePointers.push_back(ThisLVal.getPointer(CGF)); 8800 Pointers.push_back(ThisLValVal.getPointer(CGF)); 8801 Sizes.push_back( 8802 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8803 CGF.Int64Ty, /*isSigned=*/true)); 8804 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8805 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8806 } 8807 for (const LambdaCapture &LC : RD->captures()) { 8808 if (!LC.capturesVariable()) 8809 continue; 8810 const VarDecl *VD = LC.getCapturedVar(); 8811 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8812 continue; 8813 auto It = Captures.find(VD); 8814 assert(It != Captures.end() && "Found lambda capture without field."); 8815 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8816 if (LC.getCaptureKind() == LCK_ByRef) { 8817 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8818 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8819 VDLVal.getPointer(CGF)); 8820 BasePointers.push_back(VarLVal.getPointer(CGF)); 8821 Pointers.push_back(VarLValVal.getPointer(CGF)); 8822 Sizes.push_back(CGF.Builder.CreateIntCast( 8823 CGF.getTypeSize( 8824 VD->getType().getCanonicalType().getNonReferenceType()), 8825 CGF.Int64Ty, /*isSigned=*/true)); 8826 } else { 8827 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8828 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8829 VDLVal.getPointer(CGF)); 8830 BasePointers.push_back(VarLVal.getPointer(CGF)); 8831 Pointers.push_back(VarRVal.getScalarVal()); 8832 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8833 } 8834 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8835 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8836 } 8837 } 8838 8839 /// Set correct indices for lambdas captures. 8840 void adjustMemberOfForLambdaCaptures( 8841 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8842 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8843 MapFlagsArrayTy &Types) const { 8844 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8845 // Set correct member_of idx for all implicit lambda captures. 8846 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8847 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8848 continue; 8849 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8850 assert(BasePtr && "Unable to find base lambda address."); 8851 int TgtIdx = -1; 8852 for (unsigned J = I; J > 0; --J) { 8853 unsigned Idx = J - 1; 8854 if (Pointers[Idx] != BasePtr) 8855 continue; 8856 TgtIdx = Idx; 8857 break; 8858 } 8859 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8860 // All other current entries will be MEMBER_OF the combined entry 8861 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8862 // 0xFFFF in the MEMBER_OF field). 8863 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8864 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8865 } 8866 } 8867 8868 /// Generate the base pointers, section pointers, sizes and map types 8869 /// associated to a given capture. 8870 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8871 llvm::Value *Arg, 8872 MapBaseValuesArrayTy &BasePointers, 8873 MapValuesArrayTy &Pointers, 8874 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8875 StructRangeInfoTy &PartialStruct) const { 8876 assert(!Cap->capturesVariableArrayType() && 8877 "Not expecting to generate map info for a variable array type!"); 8878 8879 // We need to know when we generating information for the first component 8880 const ValueDecl *VD = Cap->capturesThis() 8881 ? nullptr 8882 : Cap->getCapturedVar()->getCanonicalDecl(); 8883 8884 // If this declaration appears in a is_device_ptr clause we just have to 8885 // pass the pointer by value. If it is a reference to a declaration, we just 8886 // pass its value. 8887 if (DevPointersMap.count(VD)) { 8888 BasePointers.emplace_back(Arg, VD); 8889 Pointers.push_back(Arg); 8890 Sizes.push_back( 8891 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8892 CGF.Int64Ty, /*isSigned=*/true)); 8893 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8894 return; 8895 } 8896 8897 using MapData = 8898 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8899 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8900 SmallVector<MapData, 4> DeclComponentLists; 8901 assert(CurDir.is<const OMPExecutableDirective *>() && 8902 "Expect a executable directive"); 8903 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8904 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8905 for (const auto L : C->decl_component_lists(VD)) { 8906 assert(L.first == VD && 8907 "We got information for the wrong declaration??"); 8908 assert(!L.second.empty() && 8909 "Not expecting declaration with no component lists."); 8910 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8911 C->getMapTypeModifiers(), 8912 C->isImplicit()); 8913 } 8914 } 8915 8916 // Find overlapping elements (including the offset from the base element). 8917 llvm::SmallDenseMap< 8918 const MapData *, 8919 llvm::SmallVector< 8920 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8921 4> 8922 OverlappedData; 8923 size_t Count = 0; 8924 for (const MapData &L : DeclComponentLists) { 8925 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8926 OpenMPMapClauseKind MapType; 8927 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8928 bool IsImplicit; 8929 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8930 ++Count; 8931 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8932 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8933 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8934 auto CI = Components.rbegin(); 8935 auto CE = Components.rend(); 8936 auto SI = Components1.rbegin(); 8937 auto SE = Components1.rend(); 8938 for (; CI != CE && SI != SE; ++CI, ++SI) { 8939 if (CI->getAssociatedExpression()->getStmtClass() != 8940 SI->getAssociatedExpression()->getStmtClass()) 8941 break; 8942 // Are we dealing with different variables/fields? 8943 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8944 break; 8945 } 8946 // Found overlapping if, at least for one component, reached the head of 8947 // the components list. 8948 if (CI == CE || SI == SE) { 8949 assert((CI != CE || SI != SE) && 8950 "Unexpected full match of the mapping components."); 8951 const MapData &BaseData = CI == CE ? L : L1; 8952 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8953 SI == SE ? Components : Components1; 8954 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8955 OverlappedElements.getSecond().push_back(SubData); 8956 } 8957 } 8958 } 8959 // Sort the overlapped elements for each item. 8960 llvm::SmallVector<const FieldDecl *, 4> Layout; 8961 if (!OverlappedData.empty()) { 8962 if (const auto *CRD = 8963 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8964 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8965 else { 8966 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8967 Layout.append(RD->field_begin(), RD->field_end()); 8968 } 8969 } 8970 for (auto &Pair : OverlappedData) { 8971 llvm::sort( 8972 Pair.getSecond(), 8973 [&Layout]( 8974 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8975 OMPClauseMappableExprCommon::MappableExprComponentListRef 8976 Second) { 8977 auto CI = First.rbegin(); 8978 auto CE = First.rend(); 8979 auto SI = Second.rbegin(); 8980 auto SE = Second.rend(); 8981 for (; CI != CE && SI != SE; ++CI, ++SI) { 8982 if (CI->getAssociatedExpression()->getStmtClass() != 8983 SI->getAssociatedExpression()->getStmtClass()) 8984 break; 8985 // Are we dealing with different variables/fields? 8986 if (CI->getAssociatedDeclaration() != 8987 SI->getAssociatedDeclaration()) 8988 break; 8989 } 8990 8991 // Lists contain the same elements. 8992 if (CI == CE && SI == SE) 8993 return false; 8994 8995 // List with less elements is less than list with more elements. 8996 if (CI == CE || SI == SE) 8997 return CI == CE; 8998 8999 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 9000 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 9001 if (FD1->getParent() == FD2->getParent()) 9002 return FD1->getFieldIndex() < FD2->getFieldIndex(); 9003 const auto It = 9004 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 9005 return FD == FD1 || FD == FD2; 9006 }); 9007 return *It == FD1; 9008 }); 9009 } 9010 9011 // Associated with a capture, because the mapping flags depend on it. 9012 // Go through all of the elements with the overlapped elements. 9013 for (const auto &Pair : OverlappedData) { 9014 const MapData &L = *Pair.getFirst(); 9015 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9016 OpenMPMapClauseKind MapType; 9017 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9018 bool IsImplicit; 9019 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 9020 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 9021 OverlappedComponents = Pair.getSecond(); 9022 bool IsFirstComponentList = true; 9023 generateInfoForComponentList(MapType, MapModifiers, Components, 9024 BasePointers, Pointers, Sizes, Types, 9025 PartialStruct, IsFirstComponentList, 9026 IsImplicit, OverlappedComponents); 9027 } 9028 // Go through other elements without overlapped elements. 9029 bool IsFirstComponentList = OverlappedData.empty(); 9030 for (const MapData &L : DeclComponentLists) { 9031 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9032 OpenMPMapClauseKind MapType; 9033 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9034 bool IsImplicit; 9035 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 9036 auto It = OverlappedData.find(&L); 9037 if (It == OverlappedData.end()) 9038 generateInfoForComponentList(MapType, MapModifiers, Components, 9039 BasePointers, Pointers, Sizes, Types, 9040 PartialStruct, IsFirstComponentList, 9041 IsImplicit); 9042 IsFirstComponentList = false; 9043 } 9044 } 9045 9046 /// Generate the base pointers, section pointers, sizes and map types 9047 /// associated with the declare target link variables. 9048 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 9049 MapValuesArrayTy &Pointers, 9050 MapValuesArrayTy &Sizes, 9051 MapFlagsArrayTy &Types) const { 9052 assert(CurDir.is<const OMPExecutableDirective *>() && 9053 "Expect a executable directive"); 9054 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 9055 // Map other list items in the map clause which are not captured variables 9056 // but "declare target link" global variables. 9057 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 9058 for (const auto L : C->component_lists()) { 9059 if (!L.first) 9060 continue; 9061 const auto *VD = dyn_cast<VarDecl>(L.first); 9062 if (!VD) 9063 continue; 9064 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9065 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9066 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 9067 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 9068 continue; 9069 StructRangeInfoTy PartialStruct; 9070 generateInfoForComponentList( 9071 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 9072 Pointers, Sizes, Types, PartialStruct, 9073 /*IsFirstComponentList=*/true, C->isImplicit()); 9074 assert(!PartialStruct.Base.isValid() && 9075 "No partial structs for declare target link expected."); 9076 } 9077 } 9078 } 9079 9080 /// Generate the default map information for a given capture \a CI, 9081 /// record field declaration \a RI and captured value \a CV. 9082 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 9083 const FieldDecl &RI, llvm::Value *CV, 9084 MapBaseValuesArrayTy &CurBasePointers, 9085 MapValuesArrayTy &CurPointers, 9086 MapValuesArrayTy &CurSizes, 9087 MapFlagsArrayTy &CurMapTypes) const { 9088 bool IsImplicit = true; 9089 // Do the default mapping. 9090 if (CI.capturesThis()) { 9091 CurBasePointers.push_back(CV); 9092 CurPointers.push_back(CV); 9093 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 9094 CurSizes.push_back( 9095 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 9096 CGF.Int64Ty, /*isSigned=*/true)); 9097 // Default map type. 9098 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 9099 } else if (CI.capturesVariableByCopy()) { 9100 CurBasePointers.push_back(CV); 9101 CurPointers.push_back(CV); 9102 if (!RI.getType()->isAnyPointerType()) { 9103 // We have to signal to the runtime captures passed by value that are 9104 // not pointers. 9105 CurMapTypes.push_back(OMP_MAP_LITERAL); 9106 CurSizes.push_back(CGF.Builder.CreateIntCast( 9107 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 9108 } else { 9109 // Pointers are implicitly mapped with a zero size and no flags 9110 // (other than first map that is added for all implicit maps). 9111 CurMapTypes.push_back(OMP_MAP_NONE); 9112 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 9113 } 9114 const VarDecl *VD = CI.getCapturedVar(); 9115 auto I = FirstPrivateDecls.find(VD); 9116 if (I != FirstPrivateDecls.end()) 9117 IsImplicit = I->getSecond(); 9118 } else { 9119 assert(CI.capturesVariable() && "Expected captured reference."); 9120 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 9121 QualType ElementType = PtrTy->getPointeeType(); 9122 CurSizes.push_back(CGF.Builder.CreateIntCast( 9123 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 9124 // The default map type for a scalar/complex type is 'to' because by 9125 // default the value doesn't have to be retrieved. For an aggregate 9126 // type, the default is 'tofrom'. 9127 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 9128 const VarDecl *VD = CI.getCapturedVar(); 9129 auto I = FirstPrivateDecls.find(VD); 9130 if (I != FirstPrivateDecls.end() && 9131 VD->getType().isConstant(CGF.getContext())) { 9132 llvm::Constant *Addr = 9133 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 9134 // Copy the value of the original variable to the new global copy. 9135 CGF.Builder.CreateMemCpy( 9136 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 9137 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 9138 CurSizes.back(), /*IsVolatile=*/false); 9139 // Use new global variable as the base pointers. 9140 CurBasePointers.push_back(Addr); 9141 CurPointers.push_back(Addr); 9142 } else { 9143 CurBasePointers.push_back(CV); 9144 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 9145 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 9146 CV, ElementType, CGF.getContext().getDeclAlign(VD), 9147 AlignmentSource::Decl)); 9148 CurPointers.push_back(PtrAddr.getPointer()); 9149 } else { 9150 CurPointers.push_back(CV); 9151 } 9152 } 9153 if (I != FirstPrivateDecls.end()) 9154 IsImplicit = I->getSecond(); 9155 } 9156 // Every default map produces a single argument which is a target parameter. 9157 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 9158 9159 // Add flag stating this is an implicit map. 9160 if (IsImplicit) 9161 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 9162 } 9163 }; 9164 } // anonymous namespace 9165 9166 /// Emit the arrays used to pass the captures and map information to the 9167 /// offloading runtime library. If there is no map or capture information, 9168 /// return nullptr by reference. 9169 static void 9170 emitOffloadingArrays(CodeGenFunction &CGF, 9171 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 9172 MappableExprsHandler::MapValuesArrayTy &Pointers, 9173 MappableExprsHandler::MapValuesArrayTy &Sizes, 9174 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 9175 CGOpenMPRuntime::TargetDataInfo &Info) { 9176 CodeGenModule &CGM = CGF.CGM; 9177 ASTContext &Ctx = CGF.getContext(); 9178 9179 // Reset the array information. 9180 Info.clearArrayInfo(); 9181 Info.NumberOfPtrs = BasePointers.size(); 9182 9183 if (Info.NumberOfPtrs) { 9184 // Detect if we have any capture size requiring runtime evaluation of the 9185 // size so that a constant array could be eventually used. 9186 bool hasRuntimeEvaluationCaptureSize = false; 9187 for (llvm::Value *S : Sizes) 9188 if (!isa<llvm::Constant>(S)) { 9189 hasRuntimeEvaluationCaptureSize = true; 9190 break; 9191 } 9192 9193 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 9194 QualType PointerArrayType = Ctx.getConstantArrayType( 9195 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 9196 /*IndexTypeQuals=*/0); 9197 9198 Info.BasePointersArray = 9199 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 9200 Info.PointersArray = 9201 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 9202 9203 // If we don't have any VLA types or other types that require runtime 9204 // evaluation, we can use a constant array for the map sizes, otherwise we 9205 // need to fill up the arrays as we do for the pointers. 9206 QualType Int64Ty = 9207 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 9208 if (hasRuntimeEvaluationCaptureSize) { 9209 QualType SizeArrayType = Ctx.getConstantArrayType( 9210 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 9211 /*IndexTypeQuals=*/0); 9212 Info.SizesArray = 9213 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 9214 } else { 9215 // We expect all the sizes to be constant, so we collect them to create 9216 // a constant array. 9217 SmallVector<llvm::Constant *, 16> ConstSizes; 9218 for (llvm::Value *S : Sizes) 9219 ConstSizes.push_back(cast<llvm::Constant>(S)); 9220 9221 auto *SizesArrayInit = llvm::ConstantArray::get( 9222 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 9223 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 9224 auto *SizesArrayGbl = new llvm::GlobalVariable( 9225 CGM.getModule(), SizesArrayInit->getType(), 9226 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 9227 SizesArrayInit, Name); 9228 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 9229 Info.SizesArray = SizesArrayGbl; 9230 } 9231 9232 // The map types are always constant so we don't need to generate code to 9233 // fill arrays. Instead, we create an array constant. 9234 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 9235 llvm::copy(MapTypes, Mapping.begin()); 9236 llvm::Constant *MapTypesArrayInit = 9237 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 9238 std::string MaptypesName = 9239 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 9240 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 9241 CGM.getModule(), MapTypesArrayInit->getType(), 9242 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 9243 MapTypesArrayInit, MaptypesName); 9244 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 9245 Info.MapTypesArray = MapTypesArrayGbl; 9246 9247 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 9248 llvm::Value *BPVal = *BasePointers[I]; 9249 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 9250 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9251 Info.BasePointersArray, 0, I); 9252 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9253 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9254 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9255 CGF.Builder.CreateStore(BPVal, BPAddr); 9256 9257 if (Info.requiresDevicePointerInfo()) 9258 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 9259 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 9260 9261 llvm::Value *PVal = Pointers[I]; 9262 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9263 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9264 Info.PointersArray, 0, I); 9265 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9266 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9267 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9268 CGF.Builder.CreateStore(PVal, PAddr); 9269 9270 if (hasRuntimeEvaluationCaptureSize) { 9271 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 9272 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9273 Info.SizesArray, 9274 /*Idx0=*/0, 9275 /*Idx1=*/I); 9276 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 9277 CGF.Builder.CreateStore( 9278 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 9279 SAddr); 9280 } 9281 } 9282 } 9283 } 9284 9285 /// Emit the arguments to be passed to the runtime library based on the 9286 /// arrays of pointers, sizes and map types. 9287 static void emitOffloadingArraysArgument( 9288 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 9289 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 9290 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 9291 CodeGenModule &CGM = CGF.CGM; 9292 if (Info.NumberOfPtrs) { 9293 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9294 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9295 Info.BasePointersArray, 9296 /*Idx0=*/0, /*Idx1=*/0); 9297 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9298 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9299 Info.PointersArray, 9300 /*Idx0=*/0, 9301 /*Idx1=*/0); 9302 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9303 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 9304 /*Idx0=*/0, /*Idx1=*/0); 9305 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9306 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9307 Info.MapTypesArray, 9308 /*Idx0=*/0, 9309 /*Idx1=*/0); 9310 } else { 9311 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9312 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9313 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9314 MapTypesArrayArg = 9315 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9316 } 9317 } 9318 9319 /// Check for inner distribute directive. 9320 static const OMPExecutableDirective * 9321 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 9322 const auto *CS = D.getInnermostCapturedStmt(); 9323 const auto *Body = 9324 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 9325 const Stmt *ChildStmt = 9326 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9327 9328 if (const auto *NestedDir = 9329 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9330 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 9331 switch (D.getDirectiveKind()) { 9332 case OMPD_target: 9333 if (isOpenMPDistributeDirective(DKind)) 9334 return NestedDir; 9335 if (DKind == OMPD_teams) { 9336 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 9337 /*IgnoreCaptured=*/true); 9338 if (!Body) 9339 return nullptr; 9340 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9341 if (const auto *NND = 9342 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9343 DKind = NND->getDirectiveKind(); 9344 if (isOpenMPDistributeDirective(DKind)) 9345 return NND; 9346 } 9347 } 9348 return nullptr; 9349 case OMPD_target_teams: 9350 if (isOpenMPDistributeDirective(DKind)) 9351 return NestedDir; 9352 return nullptr; 9353 case OMPD_target_parallel: 9354 case OMPD_target_simd: 9355 case OMPD_target_parallel_for: 9356 case OMPD_target_parallel_for_simd: 9357 return nullptr; 9358 case OMPD_target_teams_distribute: 9359 case OMPD_target_teams_distribute_simd: 9360 case OMPD_target_teams_distribute_parallel_for: 9361 case OMPD_target_teams_distribute_parallel_for_simd: 9362 case OMPD_parallel: 9363 case OMPD_for: 9364 case OMPD_parallel_for: 9365 case OMPD_parallel_master: 9366 case OMPD_parallel_sections: 9367 case OMPD_for_simd: 9368 case OMPD_parallel_for_simd: 9369 case OMPD_cancel: 9370 case OMPD_cancellation_point: 9371 case OMPD_ordered: 9372 case OMPD_threadprivate: 9373 case OMPD_allocate: 9374 case OMPD_task: 9375 case OMPD_simd: 9376 case OMPD_sections: 9377 case OMPD_section: 9378 case OMPD_single: 9379 case OMPD_master: 9380 case OMPD_critical: 9381 case OMPD_taskyield: 9382 case OMPD_barrier: 9383 case OMPD_taskwait: 9384 case OMPD_taskgroup: 9385 case OMPD_atomic: 9386 case OMPD_flush: 9387 case OMPD_depobj: 9388 case OMPD_scan: 9389 case OMPD_teams: 9390 case OMPD_target_data: 9391 case OMPD_target_exit_data: 9392 case OMPD_target_enter_data: 9393 case OMPD_distribute: 9394 case OMPD_distribute_simd: 9395 case OMPD_distribute_parallel_for: 9396 case OMPD_distribute_parallel_for_simd: 9397 case OMPD_teams_distribute: 9398 case OMPD_teams_distribute_simd: 9399 case OMPD_teams_distribute_parallel_for: 9400 case OMPD_teams_distribute_parallel_for_simd: 9401 case OMPD_target_update: 9402 case OMPD_declare_simd: 9403 case OMPD_declare_variant: 9404 case OMPD_begin_declare_variant: 9405 case OMPD_end_declare_variant: 9406 case OMPD_declare_target: 9407 case OMPD_end_declare_target: 9408 case OMPD_declare_reduction: 9409 case OMPD_declare_mapper: 9410 case OMPD_taskloop: 9411 case OMPD_taskloop_simd: 9412 case OMPD_master_taskloop: 9413 case OMPD_master_taskloop_simd: 9414 case OMPD_parallel_master_taskloop: 9415 case OMPD_parallel_master_taskloop_simd: 9416 case OMPD_requires: 9417 case OMPD_unknown: 9418 llvm_unreachable("Unexpected directive."); 9419 } 9420 } 9421 9422 return nullptr; 9423 } 9424 9425 /// Emit the user-defined mapper function. The code generation follows the 9426 /// pattern in the example below. 9427 /// \code 9428 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 9429 /// void *base, void *begin, 9430 /// int64_t size, int64_t type) { 9431 /// // Allocate space for an array section first. 9432 /// if (size > 1 && !maptype.IsDelete) 9433 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9434 /// size*sizeof(Ty), clearToFrom(type)); 9435 /// // Map members. 9436 /// for (unsigned i = 0; i < size; i++) { 9437 /// // For each component specified by this mapper: 9438 /// for (auto c : all_components) { 9439 /// if (c.hasMapper()) 9440 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 9441 /// c.arg_type); 9442 /// else 9443 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 9444 /// c.arg_begin, c.arg_size, c.arg_type); 9445 /// } 9446 /// } 9447 /// // Delete the array section. 9448 /// if (size > 1 && maptype.IsDelete) 9449 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9450 /// size*sizeof(Ty), clearToFrom(type)); 9451 /// } 9452 /// \endcode 9453 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 9454 CodeGenFunction *CGF) { 9455 if (UDMMap.count(D) > 0) 9456 return; 9457 ASTContext &C = CGM.getContext(); 9458 QualType Ty = D->getType(); 9459 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 9460 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 9461 auto *MapperVarDecl = 9462 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 9463 SourceLocation Loc = D->getLocation(); 9464 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 9465 9466 // Prepare mapper function arguments and attributes. 9467 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9468 C.VoidPtrTy, ImplicitParamDecl::Other); 9469 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9470 ImplicitParamDecl::Other); 9471 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9472 C.VoidPtrTy, ImplicitParamDecl::Other); 9473 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9474 ImplicitParamDecl::Other); 9475 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9476 ImplicitParamDecl::Other); 9477 FunctionArgList Args; 9478 Args.push_back(&HandleArg); 9479 Args.push_back(&BaseArg); 9480 Args.push_back(&BeginArg); 9481 Args.push_back(&SizeArg); 9482 Args.push_back(&TypeArg); 9483 const CGFunctionInfo &FnInfo = 9484 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 9485 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 9486 SmallString<64> TyStr; 9487 llvm::raw_svector_ostream Out(TyStr); 9488 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 9489 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 9490 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 9491 Name, &CGM.getModule()); 9492 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 9493 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 9494 // Start the mapper function code generation. 9495 CodeGenFunction MapperCGF(CGM); 9496 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 9497 // Compute the starting and end addreses of array elements. 9498 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 9499 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 9500 C.getPointerType(Int64Ty), Loc); 9501 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 9502 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 9503 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 9504 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 9505 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 9506 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 9507 C.getPointerType(Int64Ty), Loc); 9508 // Prepare common arguments for array initiation and deletion. 9509 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 9510 MapperCGF.GetAddrOfLocalVar(&HandleArg), 9511 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9512 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 9513 MapperCGF.GetAddrOfLocalVar(&BaseArg), 9514 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9515 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 9516 MapperCGF.GetAddrOfLocalVar(&BeginArg), 9517 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9518 9519 // Emit array initiation if this is an array section and \p MapType indicates 9520 // that memory allocation is required. 9521 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 9522 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9523 ElementSize, HeadBB, /*IsInit=*/true); 9524 9525 // Emit a for loop to iterate through SizeArg of elements and map all of them. 9526 9527 // Emit the loop header block. 9528 MapperCGF.EmitBlock(HeadBB); 9529 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 9530 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 9531 // Evaluate whether the initial condition is satisfied. 9532 llvm::Value *IsEmpty = 9533 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 9534 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 9535 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 9536 9537 // Emit the loop body block. 9538 MapperCGF.EmitBlock(BodyBB); 9539 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 9540 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 9541 PtrPHI->addIncoming(PtrBegin, EntryBB); 9542 Address PtrCurrent = 9543 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 9544 .getAlignment() 9545 .alignmentOfArrayElement(ElementSize)); 9546 // Privatize the declared variable of mapper to be the current array element. 9547 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 9548 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 9549 return MapperCGF 9550 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 9551 .getAddress(MapperCGF); 9552 }); 9553 (void)Scope.Privatize(); 9554 9555 // Get map clause information. Fill up the arrays with all mapped variables. 9556 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9557 MappableExprsHandler::MapValuesArrayTy Pointers; 9558 MappableExprsHandler::MapValuesArrayTy Sizes; 9559 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9560 MappableExprsHandler MEHandler(*D, MapperCGF); 9561 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 9562 9563 // Call the runtime API __tgt_mapper_num_components to get the number of 9564 // pre-existing components. 9565 llvm::Value *OffloadingArgs[] = {Handle}; 9566 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 9567 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 9568 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 9569 PreviousSize, 9570 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 9571 9572 // Fill up the runtime mapper handle for all components. 9573 for (unsigned I = 0; I < BasePointers.size(); ++I) { 9574 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 9575 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9576 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 9577 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9578 llvm::Value *CurSizeArg = Sizes[I]; 9579 9580 // Extract the MEMBER_OF field from the map type. 9581 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 9582 MapperCGF.EmitBlock(MemberBB); 9583 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 9584 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 9585 OriMapType, 9586 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 9587 llvm::BasicBlock *MemberCombineBB = 9588 MapperCGF.createBasicBlock("omp.member.combine"); 9589 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 9590 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 9591 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 9592 // Add the number of pre-existing components to the MEMBER_OF field if it 9593 // is valid. 9594 MapperCGF.EmitBlock(MemberCombineBB); 9595 llvm::Value *CombinedMember = 9596 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 9597 // Do nothing if it is not a member of previous components. 9598 MapperCGF.EmitBlock(TypeBB); 9599 llvm::PHINode *MemberMapType = 9600 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 9601 MemberMapType->addIncoming(OriMapType, MemberBB); 9602 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 9603 9604 // Combine the map type inherited from user-defined mapper with that 9605 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9606 // bits of the \a MapType, which is the input argument of the mapper 9607 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9608 // bits of MemberMapType. 9609 // [OpenMP 5.0], 1.2.6. map-type decay. 9610 // | alloc | to | from | tofrom | release | delete 9611 // ---------------------------------------------------------- 9612 // alloc | alloc | alloc | alloc | alloc | release | delete 9613 // to | alloc | to | alloc | to | release | delete 9614 // from | alloc | alloc | from | from | release | delete 9615 // tofrom | alloc | to | from | tofrom | release | delete 9616 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9617 MapType, 9618 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9619 MappableExprsHandler::OMP_MAP_FROM)); 9620 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9621 llvm::BasicBlock *AllocElseBB = 9622 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9623 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9624 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9625 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9626 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9627 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9628 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9629 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9630 MapperCGF.EmitBlock(AllocBB); 9631 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9632 MemberMapType, 9633 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9634 MappableExprsHandler::OMP_MAP_FROM))); 9635 MapperCGF.Builder.CreateBr(EndBB); 9636 MapperCGF.EmitBlock(AllocElseBB); 9637 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9638 LeftToFrom, 9639 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9640 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9641 // In case of to, clear OMP_MAP_FROM. 9642 MapperCGF.EmitBlock(ToBB); 9643 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9644 MemberMapType, 9645 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9646 MapperCGF.Builder.CreateBr(EndBB); 9647 MapperCGF.EmitBlock(ToElseBB); 9648 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9649 LeftToFrom, 9650 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9651 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9652 // In case of from, clear OMP_MAP_TO. 9653 MapperCGF.EmitBlock(FromBB); 9654 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9655 MemberMapType, 9656 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9657 // In case of tofrom, do nothing. 9658 MapperCGF.EmitBlock(EndBB); 9659 llvm::PHINode *CurMapType = 9660 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9661 CurMapType->addIncoming(AllocMapType, AllocBB); 9662 CurMapType->addIncoming(ToMapType, ToBB); 9663 CurMapType->addIncoming(FromMapType, FromBB); 9664 CurMapType->addIncoming(MemberMapType, ToElseBB); 9665 9666 // TODO: call the corresponding mapper function if a user-defined mapper is 9667 // associated with this map clause. 9668 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9669 // data structure. 9670 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9671 CurSizeArg, CurMapType}; 9672 MapperCGF.EmitRuntimeCall( 9673 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9674 OffloadingArgs); 9675 } 9676 9677 // Update the pointer to point to the next element that needs to be mapped, 9678 // and check whether we have mapped all elements. 9679 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9680 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9681 PtrPHI->addIncoming(PtrNext, BodyBB); 9682 llvm::Value *IsDone = 9683 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9684 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9685 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9686 9687 MapperCGF.EmitBlock(ExitBB); 9688 // Emit array deletion if this is an array section and \p MapType indicates 9689 // that deletion is required. 9690 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9691 ElementSize, DoneBB, /*IsInit=*/false); 9692 9693 // Emit the function exit block. 9694 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9695 MapperCGF.FinishFunction(); 9696 UDMMap.try_emplace(D, Fn); 9697 if (CGF) { 9698 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9699 Decls.second.push_back(D); 9700 } 9701 } 9702 9703 /// Emit the array initialization or deletion portion for user-defined mapper 9704 /// code generation. First, it evaluates whether an array section is mapped and 9705 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9706 /// true, and \a MapType indicates to not delete this array, array 9707 /// initialization code is generated. If \a IsInit is false, and \a MapType 9708 /// indicates to not this array, array deletion code is generated. 9709 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9710 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9711 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9712 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9713 StringRef Prefix = IsInit ? ".init" : ".del"; 9714 9715 // Evaluate if this is an array section. 9716 llvm::BasicBlock *IsDeleteBB = 9717 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"})); 9718 llvm::BasicBlock *BodyBB = 9719 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 9720 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9721 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9722 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9723 9724 // Evaluate if we are going to delete this section. 9725 MapperCGF.EmitBlock(IsDeleteBB); 9726 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9727 MapType, 9728 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9729 llvm::Value *DeleteCond; 9730 if (IsInit) { 9731 DeleteCond = MapperCGF.Builder.CreateIsNull( 9732 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9733 } else { 9734 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9735 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9736 } 9737 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9738 9739 MapperCGF.EmitBlock(BodyBB); 9740 // Get the array size by multiplying element size and element number (i.e., \p 9741 // Size). 9742 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9743 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9744 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9745 // memory allocation/deletion purpose only. 9746 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9747 MapType, 9748 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9749 MappableExprsHandler::OMP_MAP_FROM))); 9750 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9751 // data structure. 9752 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9753 MapperCGF.EmitRuntimeCall( 9754 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9755 } 9756 9757 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9758 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9759 llvm::Value *DeviceID, 9760 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9761 const OMPLoopDirective &D)> 9762 SizeEmitter) { 9763 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9764 const OMPExecutableDirective *TD = &D; 9765 // Get nested teams distribute kind directive, if any. 9766 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9767 TD = getNestedDistributeDirective(CGM.getContext(), D); 9768 if (!TD) 9769 return; 9770 const auto *LD = cast<OMPLoopDirective>(TD); 9771 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9772 PrePostActionTy &) { 9773 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9774 llvm::Value *Args[] = {DeviceID, NumIterations}; 9775 CGF.EmitRuntimeCall( 9776 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9777 } 9778 }; 9779 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9780 } 9781 9782 void CGOpenMPRuntime::emitTargetCall( 9783 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9784 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9785 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 9786 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9787 const OMPLoopDirective &D)> 9788 SizeEmitter) { 9789 if (!CGF.HaveInsertPoint()) 9790 return; 9791 9792 assert(OutlinedFn && "Invalid outlined function!"); 9793 9794 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9795 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9796 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9797 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9798 PrePostActionTy &) { 9799 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9800 }; 9801 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9802 9803 CodeGenFunction::OMPTargetDataInfo InputInfo; 9804 llvm::Value *MapTypesArray = nullptr; 9805 // Fill up the pointer arrays and transfer execution to the device. 9806 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9807 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9808 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9809 if (Device.getInt() == OMPC_DEVICE_ancestor) { 9810 // Reverse offloading is not supported, so just execute on the host. 9811 if (RequiresOuterTask) { 9812 CapturedVars.clear(); 9813 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9814 } 9815 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9816 return; 9817 } 9818 9819 // On top of the arrays that were filled up, the target offloading call 9820 // takes as arguments the device id as well as the host pointer. The host 9821 // pointer is used by the runtime library to identify the current target 9822 // region, so it only has to be unique and not necessarily point to 9823 // anything. It could be the pointer to the outlined function that 9824 // implements the target region, but we aren't using that so that the 9825 // compiler doesn't need to keep that, and could therefore inline the host 9826 // function if proven worthwhile during optimization. 9827 9828 // From this point on, we need to have an ID of the target region defined. 9829 assert(OutlinedFnID && "Invalid outlined function ID!"); 9830 9831 // Emit device ID if any. 9832 llvm::Value *DeviceID; 9833 if (Device.getPointer()) { 9834 assert((Device.getInt() == OMPC_DEVICE_unknown || 9835 Device.getInt() == OMPC_DEVICE_device_num) && 9836 "Expected device_num modifier."); 9837 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer()); 9838 DeviceID = 9839 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true); 9840 } else { 9841 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9842 } 9843 9844 // Emit the number of elements in the offloading arrays. 9845 llvm::Value *PointerNum = 9846 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9847 9848 // Return value of the runtime offloading call. 9849 llvm::Value *Return; 9850 9851 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9852 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9853 9854 // Emit tripcount for the target loop-based directive. 9855 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9856 9857 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9858 // The target region is an outlined function launched by the runtime 9859 // via calls __tgt_target() or __tgt_target_teams(). 9860 // 9861 // __tgt_target() launches a target region with one team and one thread, 9862 // executing a serial region. This master thread may in turn launch 9863 // more threads within its team upon encountering a parallel region, 9864 // however, no additional teams can be launched on the device. 9865 // 9866 // __tgt_target_teams() launches a target region with one or more teams, 9867 // each with one or more threads. This call is required for target 9868 // constructs such as: 9869 // 'target teams' 9870 // 'target' / 'teams' 9871 // 'target teams distribute parallel for' 9872 // 'target parallel' 9873 // and so on. 9874 // 9875 // Note that on the host and CPU targets, the runtime implementation of 9876 // these calls simply call the outlined function without forking threads. 9877 // The outlined functions themselves have runtime calls to 9878 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9879 // the compiler in emitTeamsCall() and emitParallelCall(). 9880 // 9881 // In contrast, on the NVPTX target, the implementation of 9882 // __tgt_target_teams() launches a GPU kernel with the requested number 9883 // of teams and threads so no additional calls to the runtime are required. 9884 if (NumTeams) { 9885 // If we have NumTeams defined this means that we have an enclosed teams 9886 // region. Therefore we also expect to have NumThreads defined. These two 9887 // values should be defined in the presence of a teams directive, 9888 // regardless of having any clauses associated. If the user is using teams 9889 // but no clauses, these two values will be the default that should be 9890 // passed to the runtime library - a 32-bit integer with the value zero. 9891 assert(NumThreads && "Thread limit expression should be available along " 9892 "with number of teams."); 9893 llvm::Value *OffloadingArgs[] = {DeviceID, 9894 OutlinedFnID, 9895 PointerNum, 9896 InputInfo.BasePointersArray.getPointer(), 9897 InputInfo.PointersArray.getPointer(), 9898 InputInfo.SizesArray.getPointer(), 9899 MapTypesArray, 9900 NumTeams, 9901 NumThreads}; 9902 Return = CGF.EmitRuntimeCall( 9903 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9904 : OMPRTL__tgt_target_teams), 9905 OffloadingArgs); 9906 } else { 9907 llvm::Value *OffloadingArgs[] = {DeviceID, 9908 OutlinedFnID, 9909 PointerNum, 9910 InputInfo.BasePointersArray.getPointer(), 9911 InputInfo.PointersArray.getPointer(), 9912 InputInfo.SizesArray.getPointer(), 9913 MapTypesArray}; 9914 Return = CGF.EmitRuntimeCall( 9915 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9916 : OMPRTL__tgt_target), 9917 OffloadingArgs); 9918 } 9919 9920 // Check the error code and execute the host version if required. 9921 llvm::BasicBlock *OffloadFailedBlock = 9922 CGF.createBasicBlock("omp_offload.failed"); 9923 llvm::BasicBlock *OffloadContBlock = 9924 CGF.createBasicBlock("omp_offload.cont"); 9925 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9926 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9927 9928 CGF.EmitBlock(OffloadFailedBlock); 9929 if (RequiresOuterTask) { 9930 CapturedVars.clear(); 9931 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9932 } 9933 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9934 CGF.EmitBranch(OffloadContBlock); 9935 9936 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9937 }; 9938 9939 // Notify that the host version must be executed. 9940 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9941 RequiresOuterTask](CodeGenFunction &CGF, 9942 PrePostActionTy &) { 9943 if (RequiresOuterTask) { 9944 CapturedVars.clear(); 9945 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9946 } 9947 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9948 }; 9949 9950 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9951 &CapturedVars, RequiresOuterTask, 9952 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9953 // Fill up the arrays with all the captured variables. 9954 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9955 MappableExprsHandler::MapValuesArrayTy Pointers; 9956 MappableExprsHandler::MapValuesArrayTy Sizes; 9957 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9958 9959 // Get mappable expression information. 9960 MappableExprsHandler MEHandler(D, CGF); 9961 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9962 9963 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9964 auto CV = CapturedVars.begin(); 9965 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9966 CE = CS.capture_end(); 9967 CI != CE; ++CI, ++RI, ++CV) { 9968 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9969 MappableExprsHandler::MapValuesArrayTy CurPointers; 9970 MappableExprsHandler::MapValuesArrayTy CurSizes; 9971 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9972 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9973 9974 // VLA sizes are passed to the outlined region by copy and do not have map 9975 // information associated. 9976 if (CI->capturesVariableArrayType()) { 9977 CurBasePointers.push_back(*CV); 9978 CurPointers.push_back(*CV); 9979 CurSizes.push_back(CGF.Builder.CreateIntCast( 9980 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9981 // Copy to the device as an argument. No need to retrieve it. 9982 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9983 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9984 MappableExprsHandler::OMP_MAP_IMPLICIT); 9985 } else { 9986 // If we have any information in the map clause, we use it, otherwise we 9987 // just do a default mapping. 9988 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9989 CurSizes, CurMapTypes, PartialStruct); 9990 if (CurBasePointers.empty()) 9991 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9992 CurPointers, CurSizes, CurMapTypes); 9993 // Generate correct mapping for variables captured by reference in 9994 // lambdas. 9995 if (CI->capturesVariable()) 9996 MEHandler.generateInfoForLambdaCaptures( 9997 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9998 CurMapTypes, LambdaPointers); 9999 } 10000 // We expect to have at least an element of information for this capture. 10001 assert(!CurBasePointers.empty() && 10002 "Non-existing map pointer for capture!"); 10003 assert(CurBasePointers.size() == CurPointers.size() && 10004 CurBasePointers.size() == CurSizes.size() && 10005 CurBasePointers.size() == CurMapTypes.size() && 10006 "Inconsistent map information sizes!"); 10007 10008 // If there is an entry in PartialStruct it means we have a struct with 10009 // individual members mapped. Emit an extra combined entry. 10010 if (PartialStruct.Base.isValid()) 10011 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 10012 CurMapTypes, PartialStruct); 10013 10014 // We need to append the results of this capture to what we already have. 10015 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 10016 Pointers.append(CurPointers.begin(), CurPointers.end()); 10017 Sizes.append(CurSizes.begin(), CurSizes.end()); 10018 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 10019 } 10020 // Adjust MEMBER_OF flags for the lambdas captures. 10021 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 10022 Pointers, MapTypes); 10023 // Map other list items in the map clause which are not captured variables 10024 // but "declare target link" global variables. 10025 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 10026 MapTypes); 10027 10028 TargetDataInfo Info; 10029 // Fill up the arrays and create the arguments. 10030 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10031 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10032 Info.PointersArray, Info.SizesArray, 10033 Info.MapTypesArray, Info); 10034 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10035 InputInfo.BasePointersArray = 10036 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10037 InputInfo.PointersArray = 10038 Address(Info.PointersArray, CGM.getPointerAlign()); 10039 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 10040 MapTypesArray = Info.MapTypesArray; 10041 if (RequiresOuterTask) 10042 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10043 else 10044 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10045 }; 10046 10047 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 10048 CodeGenFunction &CGF, PrePostActionTy &) { 10049 if (RequiresOuterTask) { 10050 CodeGenFunction::OMPTargetDataInfo InputInfo; 10051 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 10052 } else { 10053 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 10054 } 10055 }; 10056 10057 // If we have a target function ID it means that we need to support 10058 // offloading, otherwise, just execute on the host. We need to execute on host 10059 // regardless of the conditional in the if clause if, e.g., the user do not 10060 // specify target triples. 10061 if (OutlinedFnID) { 10062 if (IfCond) { 10063 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 10064 } else { 10065 RegionCodeGenTy ThenRCG(TargetThenGen); 10066 ThenRCG(CGF); 10067 } 10068 } else { 10069 RegionCodeGenTy ElseRCG(TargetElseGen); 10070 ElseRCG(CGF); 10071 } 10072 } 10073 10074 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 10075 StringRef ParentName) { 10076 if (!S) 10077 return; 10078 10079 // Codegen OMP target directives that offload compute to the device. 10080 bool RequiresDeviceCodegen = 10081 isa<OMPExecutableDirective>(S) && 10082 isOpenMPTargetExecutionDirective( 10083 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 10084 10085 if (RequiresDeviceCodegen) { 10086 const auto &E = *cast<OMPExecutableDirective>(S); 10087 unsigned DeviceID; 10088 unsigned FileID; 10089 unsigned Line; 10090 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 10091 FileID, Line); 10092 10093 // Is this a target region that should not be emitted as an entry point? If 10094 // so just signal we are done with this target region. 10095 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 10096 ParentName, Line)) 10097 return; 10098 10099 switch (E.getDirectiveKind()) { 10100 case OMPD_target: 10101 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 10102 cast<OMPTargetDirective>(E)); 10103 break; 10104 case OMPD_target_parallel: 10105 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 10106 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 10107 break; 10108 case OMPD_target_teams: 10109 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 10110 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 10111 break; 10112 case OMPD_target_teams_distribute: 10113 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 10114 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 10115 break; 10116 case OMPD_target_teams_distribute_simd: 10117 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 10118 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 10119 break; 10120 case OMPD_target_parallel_for: 10121 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 10122 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 10123 break; 10124 case OMPD_target_parallel_for_simd: 10125 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 10126 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 10127 break; 10128 case OMPD_target_simd: 10129 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 10130 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 10131 break; 10132 case OMPD_target_teams_distribute_parallel_for: 10133 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 10134 CGM, ParentName, 10135 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 10136 break; 10137 case OMPD_target_teams_distribute_parallel_for_simd: 10138 CodeGenFunction:: 10139 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 10140 CGM, ParentName, 10141 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 10142 break; 10143 case OMPD_parallel: 10144 case OMPD_for: 10145 case OMPD_parallel_for: 10146 case OMPD_parallel_master: 10147 case OMPD_parallel_sections: 10148 case OMPD_for_simd: 10149 case OMPD_parallel_for_simd: 10150 case OMPD_cancel: 10151 case OMPD_cancellation_point: 10152 case OMPD_ordered: 10153 case OMPD_threadprivate: 10154 case OMPD_allocate: 10155 case OMPD_task: 10156 case OMPD_simd: 10157 case OMPD_sections: 10158 case OMPD_section: 10159 case OMPD_single: 10160 case OMPD_master: 10161 case OMPD_critical: 10162 case OMPD_taskyield: 10163 case OMPD_barrier: 10164 case OMPD_taskwait: 10165 case OMPD_taskgroup: 10166 case OMPD_atomic: 10167 case OMPD_flush: 10168 case OMPD_depobj: 10169 case OMPD_scan: 10170 case OMPD_teams: 10171 case OMPD_target_data: 10172 case OMPD_target_exit_data: 10173 case OMPD_target_enter_data: 10174 case OMPD_distribute: 10175 case OMPD_distribute_simd: 10176 case OMPD_distribute_parallel_for: 10177 case OMPD_distribute_parallel_for_simd: 10178 case OMPD_teams_distribute: 10179 case OMPD_teams_distribute_simd: 10180 case OMPD_teams_distribute_parallel_for: 10181 case OMPD_teams_distribute_parallel_for_simd: 10182 case OMPD_target_update: 10183 case OMPD_declare_simd: 10184 case OMPD_declare_variant: 10185 case OMPD_begin_declare_variant: 10186 case OMPD_end_declare_variant: 10187 case OMPD_declare_target: 10188 case OMPD_end_declare_target: 10189 case OMPD_declare_reduction: 10190 case OMPD_declare_mapper: 10191 case OMPD_taskloop: 10192 case OMPD_taskloop_simd: 10193 case OMPD_master_taskloop: 10194 case OMPD_master_taskloop_simd: 10195 case OMPD_parallel_master_taskloop: 10196 case OMPD_parallel_master_taskloop_simd: 10197 case OMPD_requires: 10198 case OMPD_unknown: 10199 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 10200 } 10201 return; 10202 } 10203 10204 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 10205 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 10206 return; 10207 10208 scanForTargetRegionsFunctions( 10209 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 10210 return; 10211 } 10212 10213 // If this is a lambda function, look into its body. 10214 if (const auto *L = dyn_cast<LambdaExpr>(S)) 10215 S = L->getBody(); 10216 10217 // Keep looking for target regions recursively. 10218 for (const Stmt *II : S->children()) 10219 scanForTargetRegionsFunctions(II, ParentName); 10220 } 10221 10222 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 10223 // If emitting code for the host, we do not process FD here. Instead we do 10224 // the normal code generation. 10225 if (!CGM.getLangOpts().OpenMPIsDevice) { 10226 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 10227 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10228 OMPDeclareTargetDeclAttr::getDeviceType(FD); 10229 // Do not emit device_type(nohost) functions for the host. 10230 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 10231 return true; 10232 } 10233 return false; 10234 } 10235 10236 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 10237 // Try to detect target regions in the function. 10238 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 10239 StringRef Name = CGM.getMangledName(GD); 10240 scanForTargetRegionsFunctions(FD->getBody(), Name); 10241 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10242 OMPDeclareTargetDeclAttr::getDeviceType(FD); 10243 // Do not emit device_type(nohost) functions for the host. 10244 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 10245 return true; 10246 } 10247 10248 // Do not to emit function if it is not marked as declare target. 10249 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 10250 AlreadyEmittedTargetDecls.count(VD) == 0; 10251 } 10252 10253 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 10254 if (!CGM.getLangOpts().OpenMPIsDevice) 10255 return false; 10256 10257 // Check if there are Ctors/Dtors in this declaration and look for target 10258 // regions in it. We use the complete variant to produce the kernel name 10259 // mangling. 10260 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 10261 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 10262 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 10263 StringRef ParentName = 10264 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 10265 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 10266 } 10267 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 10268 StringRef ParentName = 10269 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 10270 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 10271 } 10272 } 10273 10274 // Do not to emit variable if it is not marked as declare target. 10275 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10276 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 10277 cast<VarDecl>(GD.getDecl())); 10278 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 10279 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10280 HasRequiresUnifiedSharedMemory)) { 10281 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 10282 return true; 10283 } 10284 return false; 10285 } 10286 10287 llvm::Constant * 10288 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 10289 const VarDecl *VD) { 10290 assert(VD->getType().isConstant(CGM.getContext()) && 10291 "Expected constant variable."); 10292 StringRef VarName; 10293 llvm::Constant *Addr; 10294 llvm::GlobalValue::LinkageTypes Linkage; 10295 QualType Ty = VD->getType(); 10296 SmallString<128> Buffer; 10297 { 10298 unsigned DeviceID; 10299 unsigned FileID; 10300 unsigned Line; 10301 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 10302 FileID, Line); 10303 llvm::raw_svector_ostream OS(Buffer); 10304 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 10305 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 10306 VarName = OS.str(); 10307 } 10308 Linkage = llvm::GlobalValue::InternalLinkage; 10309 Addr = 10310 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 10311 getDefaultFirstprivateAddressSpace()); 10312 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 10313 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 10314 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 10315 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10316 VarName, Addr, VarSize, 10317 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 10318 return Addr; 10319 } 10320 10321 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 10322 llvm::Constant *Addr) { 10323 if (CGM.getLangOpts().OMPTargetTriples.empty() && 10324 !CGM.getLangOpts().OpenMPIsDevice) 10325 return; 10326 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10327 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10328 if (!Res) { 10329 if (CGM.getLangOpts().OpenMPIsDevice) { 10330 // Register non-target variables being emitted in device code (debug info 10331 // may cause this). 10332 StringRef VarName = CGM.getMangledName(VD); 10333 EmittedNonTargetVariables.try_emplace(VarName, Addr); 10334 } 10335 return; 10336 } 10337 // Register declare target variables. 10338 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 10339 StringRef VarName; 10340 CharUnits VarSize; 10341 llvm::GlobalValue::LinkageTypes Linkage; 10342 10343 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10344 !HasRequiresUnifiedSharedMemory) { 10345 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10346 VarName = CGM.getMangledName(VD); 10347 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 10348 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 10349 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 10350 } else { 10351 VarSize = CharUnits::Zero(); 10352 } 10353 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 10354 // Temp solution to prevent optimizations of the internal variables. 10355 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 10356 std::string RefName = getName({VarName, "ref"}); 10357 if (!CGM.GetGlobalValue(RefName)) { 10358 llvm::Constant *AddrRef = 10359 getOrCreateInternalVariable(Addr->getType(), RefName); 10360 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 10361 GVAddrRef->setConstant(/*Val=*/true); 10362 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 10363 GVAddrRef->setInitializer(Addr); 10364 CGM.addCompilerUsedGlobal(GVAddrRef); 10365 } 10366 } 10367 } else { 10368 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 10369 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10370 HasRequiresUnifiedSharedMemory)) && 10371 "Declare target attribute must link or to with unified memory."); 10372 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 10373 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 10374 else 10375 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10376 10377 if (CGM.getLangOpts().OpenMPIsDevice) { 10378 VarName = Addr->getName(); 10379 Addr = nullptr; 10380 } else { 10381 VarName = getAddrOfDeclareTargetVar(VD).getName(); 10382 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 10383 } 10384 VarSize = CGM.getPointerSize(); 10385 Linkage = llvm::GlobalValue::WeakAnyLinkage; 10386 } 10387 10388 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10389 VarName, Addr, VarSize, Flags, Linkage); 10390 } 10391 10392 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 10393 if (isa<FunctionDecl>(GD.getDecl()) || 10394 isa<OMPDeclareReductionDecl>(GD.getDecl())) 10395 return emitTargetFunctions(GD); 10396 10397 return emitTargetGlobalVariable(GD); 10398 } 10399 10400 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 10401 for (const VarDecl *VD : DeferredGlobalVariables) { 10402 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10403 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10404 if (!Res) 10405 continue; 10406 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10407 !HasRequiresUnifiedSharedMemory) { 10408 CGM.EmitGlobal(VD); 10409 } else { 10410 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 10411 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10412 HasRequiresUnifiedSharedMemory)) && 10413 "Expected link clause or to clause with unified memory."); 10414 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 10415 } 10416 } 10417 } 10418 10419 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 10420 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 10421 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 10422 " Expected target-based directive."); 10423 } 10424 10425 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 10426 for (const OMPClause *Clause : D->clauselists()) { 10427 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 10428 HasRequiresUnifiedSharedMemory = true; 10429 } else if (const auto *AC = 10430 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 10431 switch (AC->getAtomicDefaultMemOrderKind()) { 10432 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 10433 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 10434 break; 10435 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 10436 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 10437 break; 10438 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 10439 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 10440 break; 10441 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 10442 break; 10443 } 10444 } 10445 } 10446 } 10447 10448 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 10449 return RequiresAtomicOrdering; 10450 } 10451 10452 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 10453 LangAS &AS) { 10454 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 10455 return false; 10456 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 10457 switch(A->getAllocatorType()) { 10458 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 10459 // Not supported, fallback to the default mem space. 10460 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 10461 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 10462 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 10463 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 10464 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 10465 case OMPAllocateDeclAttr::OMPConstMemAlloc: 10466 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 10467 AS = LangAS::Default; 10468 return true; 10469 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 10470 llvm_unreachable("Expected predefined allocator for the variables with the " 10471 "static storage."); 10472 } 10473 return false; 10474 } 10475 10476 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 10477 return HasRequiresUnifiedSharedMemory; 10478 } 10479 10480 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 10481 CodeGenModule &CGM) 10482 : CGM(CGM) { 10483 if (CGM.getLangOpts().OpenMPIsDevice) { 10484 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 10485 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 10486 } 10487 } 10488 10489 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 10490 if (CGM.getLangOpts().OpenMPIsDevice) 10491 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 10492 } 10493 10494 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 10495 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 10496 return true; 10497 10498 const auto *D = cast<FunctionDecl>(GD.getDecl()); 10499 // Do not to emit function if it is marked as declare target as it was already 10500 // emitted. 10501 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 10502 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 10503 if (auto *F = dyn_cast_or_null<llvm::Function>( 10504 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 10505 return !F->isDeclaration(); 10506 return false; 10507 } 10508 return true; 10509 } 10510 10511 return !AlreadyEmittedTargetDecls.insert(D).second; 10512 } 10513 10514 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 10515 // If we don't have entries or if we are emitting code for the device, we 10516 // don't need to do anything. 10517 if (CGM.getLangOpts().OMPTargetTriples.empty() || 10518 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 10519 (OffloadEntriesInfoManager.empty() && 10520 !HasEmittedDeclareTargetRegion && 10521 !HasEmittedTargetRegion)) 10522 return nullptr; 10523 10524 // Create and register the function that handles the requires directives. 10525 ASTContext &C = CGM.getContext(); 10526 10527 llvm::Function *RequiresRegFn; 10528 { 10529 CodeGenFunction CGF(CGM); 10530 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 10531 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 10532 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 10533 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 10534 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 10535 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 10536 // TODO: check for other requires clauses. 10537 // The requires directive takes effect only when a target region is 10538 // present in the compilation unit. Otherwise it is ignored and not 10539 // passed to the runtime. This avoids the runtime from throwing an error 10540 // for mismatching requires clauses across compilation units that don't 10541 // contain at least 1 target region. 10542 assert((HasEmittedTargetRegion || 10543 HasEmittedDeclareTargetRegion || 10544 !OffloadEntriesInfoManager.empty()) && 10545 "Target or declare target region expected."); 10546 if (HasRequiresUnifiedSharedMemory) 10547 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 10548 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 10549 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 10550 CGF.FinishFunction(); 10551 } 10552 return RequiresRegFn; 10553 } 10554 10555 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 10556 const OMPExecutableDirective &D, 10557 SourceLocation Loc, 10558 llvm::Function *OutlinedFn, 10559 ArrayRef<llvm::Value *> CapturedVars) { 10560 if (!CGF.HaveInsertPoint()) 10561 return; 10562 10563 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10564 CodeGenFunction::RunCleanupsScope Scope(CGF); 10565 10566 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 10567 llvm::Value *Args[] = { 10568 RTLoc, 10569 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 10570 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 10571 llvm::SmallVector<llvm::Value *, 16> RealArgs; 10572 RealArgs.append(std::begin(Args), std::end(Args)); 10573 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 10574 10575 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 10576 CGF.EmitRuntimeCall(RTLFn, RealArgs); 10577 } 10578 10579 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 10580 const Expr *NumTeams, 10581 const Expr *ThreadLimit, 10582 SourceLocation Loc) { 10583 if (!CGF.HaveInsertPoint()) 10584 return; 10585 10586 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10587 10588 llvm::Value *NumTeamsVal = 10589 NumTeams 10590 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 10591 CGF.CGM.Int32Ty, /* isSigned = */ true) 10592 : CGF.Builder.getInt32(0); 10593 10594 llvm::Value *ThreadLimitVal = 10595 ThreadLimit 10596 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 10597 CGF.CGM.Int32Ty, /* isSigned = */ true) 10598 : CGF.Builder.getInt32(0); 10599 10600 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 10601 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 10602 ThreadLimitVal}; 10603 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 10604 PushNumTeamsArgs); 10605 } 10606 10607 void CGOpenMPRuntime::emitTargetDataCalls( 10608 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10609 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 10610 if (!CGF.HaveInsertPoint()) 10611 return; 10612 10613 // Action used to replace the default codegen action and turn privatization 10614 // off. 10615 PrePostActionTy NoPrivAction; 10616 10617 // Generate the code for the opening of the data environment. Capture all the 10618 // arguments of the runtime call by reference because they are used in the 10619 // closing of the region. 10620 auto &&BeginThenGen = [this, &D, Device, &Info, 10621 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 10622 // Fill up the arrays with all the mapped variables. 10623 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10624 MappableExprsHandler::MapValuesArrayTy Pointers; 10625 MappableExprsHandler::MapValuesArrayTy Sizes; 10626 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10627 10628 // Get map clause information. 10629 MappableExprsHandler MCHandler(D, CGF); 10630 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10631 10632 // Fill up the arrays and create the arguments. 10633 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10634 10635 llvm::Value *BasePointersArrayArg = nullptr; 10636 llvm::Value *PointersArrayArg = nullptr; 10637 llvm::Value *SizesArrayArg = nullptr; 10638 llvm::Value *MapTypesArrayArg = nullptr; 10639 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10640 SizesArrayArg, MapTypesArrayArg, Info); 10641 10642 // Emit device ID if any. 10643 llvm::Value *DeviceID = nullptr; 10644 if (Device) { 10645 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10646 CGF.Int64Ty, /*isSigned=*/true); 10647 } else { 10648 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10649 } 10650 10651 // Emit the number of elements in the offloading arrays. 10652 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10653 10654 llvm::Value *OffloadingArgs[] = { 10655 DeviceID, PointerNum, BasePointersArrayArg, 10656 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10657 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 10658 OffloadingArgs); 10659 10660 // If device pointer privatization is required, emit the body of the region 10661 // here. It will have to be duplicated: with and without privatization. 10662 if (!Info.CaptureDeviceAddrMap.empty()) 10663 CodeGen(CGF); 10664 }; 10665 10666 // Generate code for the closing of the data region. 10667 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10668 PrePostActionTy &) { 10669 assert(Info.isValid() && "Invalid data environment closing arguments."); 10670 10671 llvm::Value *BasePointersArrayArg = nullptr; 10672 llvm::Value *PointersArrayArg = nullptr; 10673 llvm::Value *SizesArrayArg = nullptr; 10674 llvm::Value *MapTypesArrayArg = nullptr; 10675 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10676 SizesArrayArg, MapTypesArrayArg, Info); 10677 10678 // Emit device ID if any. 10679 llvm::Value *DeviceID = nullptr; 10680 if (Device) { 10681 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10682 CGF.Int64Ty, /*isSigned=*/true); 10683 } else { 10684 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10685 } 10686 10687 // Emit the number of elements in the offloading arrays. 10688 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10689 10690 llvm::Value *OffloadingArgs[] = { 10691 DeviceID, PointerNum, BasePointersArrayArg, 10692 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10693 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10694 OffloadingArgs); 10695 }; 10696 10697 // If we need device pointer privatization, we need to emit the body of the 10698 // region with no privatization in the 'else' branch of the conditional. 10699 // Otherwise, we don't have to do anything. 10700 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10701 PrePostActionTy &) { 10702 if (!Info.CaptureDeviceAddrMap.empty()) { 10703 CodeGen.setAction(NoPrivAction); 10704 CodeGen(CGF); 10705 } 10706 }; 10707 10708 // We don't have to do anything to close the region if the if clause evaluates 10709 // to false. 10710 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10711 10712 if (IfCond) { 10713 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10714 } else { 10715 RegionCodeGenTy RCG(BeginThenGen); 10716 RCG(CGF); 10717 } 10718 10719 // If we don't require privatization of device pointers, we emit the body in 10720 // between the runtime calls. This avoids duplicating the body code. 10721 if (Info.CaptureDeviceAddrMap.empty()) { 10722 CodeGen.setAction(NoPrivAction); 10723 CodeGen(CGF); 10724 } 10725 10726 if (IfCond) { 10727 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10728 } else { 10729 RegionCodeGenTy RCG(EndThenGen); 10730 RCG(CGF); 10731 } 10732 } 10733 10734 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10735 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10736 const Expr *Device) { 10737 if (!CGF.HaveInsertPoint()) 10738 return; 10739 10740 assert((isa<OMPTargetEnterDataDirective>(D) || 10741 isa<OMPTargetExitDataDirective>(D) || 10742 isa<OMPTargetUpdateDirective>(D)) && 10743 "Expecting either target enter, exit data, or update directives."); 10744 10745 CodeGenFunction::OMPTargetDataInfo InputInfo; 10746 llvm::Value *MapTypesArray = nullptr; 10747 // Generate the code for the opening of the data environment. 10748 auto &&ThenGen = [this, &D, Device, &InputInfo, 10749 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10750 // Emit device ID if any. 10751 llvm::Value *DeviceID = nullptr; 10752 if (Device) { 10753 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10754 CGF.Int64Ty, /*isSigned=*/true); 10755 } else { 10756 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10757 } 10758 10759 // Emit the number of elements in the offloading arrays. 10760 llvm::Constant *PointerNum = 10761 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10762 10763 llvm::Value *OffloadingArgs[] = {DeviceID, 10764 PointerNum, 10765 InputInfo.BasePointersArray.getPointer(), 10766 InputInfo.PointersArray.getPointer(), 10767 InputInfo.SizesArray.getPointer(), 10768 MapTypesArray}; 10769 10770 // Select the right runtime function call for each expected standalone 10771 // directive. 10772 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10773 OpenMPRTLFunction RTLFn; 10774 switch (D.getDirectiveKind()) { 10775 case OMPD_target_enter_data: 10776 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10777 : OMPRTL__tgt_target_data_begin; 10778 break; 10779 case OMPD_target_exit_data: 10780 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10781 : OMPRTL__tgt_target_data_end; 10782 break; 10783 case OMPD_target_update: 10784 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10785 : OMPRTL__tgt_target_data_update; 10786 break; 10787 case OMPD_parallel: 10788 case OMPD_for: 10789 case OMPD_parallel_for: 10790 case OMPD_parallel_master: 10791 case OMPD_parallel_sections: 10792 case OMPD_for_simd: 10793 case OMPD_parallel_for_simd: 10794 case OMPD_cancel: 10795 case OMPD_cancellation_point: 10796 case OMPD_ordered: 10797 case OMPD_threadprivate: 10798 case OMPD_allocate: 10799 case OMPD_task: 10800 case OMPD_simd: 10801 case OMPD_sections: 10802 case OMPD_section: 10803 case OMPD_single: 10804 case OMPD_master: 10805 case OMPD_critical: 10806 case OMPD_taskyield: 10807 case OMPD_barrier: 10808 case OMPD_taskwait: 10809 case OMPD_taskgroup: 10810 case OMPD_atomic: 10811 case OMPD_flush: 10812 case OMPD_depobj: 10813 case OMPD_scan: 10814 case OMPD_teams: 10815 case OMPD_target_data: 10816 case OMPD_distribute: 10817 case OMPD_distribute_simd: 10818 case OMPD_distribute_parallel_for: 10819 case OMPD_distribute_parallel_for_simd: 10820 case OMPD_teams_distribute: 10821 case OMPD_teams_distribute_simd: 10822 case OMPD_teams_distribute_parallel_for: 10823 case OMPD_teams_distribute_parallel_for_simd: 10824 case OMPD_declare_simd: 10825 case OMPD_declare_variant: 10826 case OMPD_begin_declare_variant: 10827 case OMPD_end_declare_variant: 10828 case OMPD_declare_target: 10829 case OMPD_end_declare_target: 10830 case OMPD_declare_reduction: 10831 case OMPD_declare_mapper: 10832 case OMPD_taskloop: 10833 case OMPD_taskloop_simd: 10834 case OMPD_master_taskloop: 10835 case OMPD_master_taskloop_simd: 10836 case OMPD_parallel_master_taskloop: 10837 case OMPD_parallel_master_taskloop_simd: 10838 case OMPD_target: 10839 case OMPD_target_simd: 10840 case OMPD_target_teams_distribute: 10841 case OMPD_target_teams_distribute_simd: 10842 case OMPD_target_teams_distribute_parallel_for: 10843 case OMPD_target_teams_distribute_parallel_for_simd: 10844 case OMPD_target_teams: 10845 case OMPD_target_parallel: 10846 case OMPD_target_parallel_for: 10847 case OMPD_target_parallel_for_simd: 10848 case OMPD_requires: 10849 case OMPD_unknown: 10850 llvm_unreachable("Unexpected standalone target data directive."); 10851 break; 10852 } 10853 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10854 }; 10855 10856 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10857 CodeGenFunction &CGF, PrePostActionTy &) { 10858 // Fill up the arrays with all the mapped variables. 10859 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10860 MappableExprsHandler::MapValuesArrayTy Pointers; 10861 MappableExprsHandler::MapValuesArrayTy Sizes; 10862 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10863 10864 // Get map clause information. 10865 MappableExprsHandler MEHandler(D, CGF); 10866 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10867 10868 TargetDataInfo Info; 10869 // Fill up the arrays and create the arguments. 10870 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10871 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10872 Info.PointersArray, Info.SizesArray, 10873 Info.MapTypesArray, Info); 10874 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10875 InputInfo.BasePointersArray = 10876 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10877 InputInfo.PointersArray = 10878 Address(Info.PointersArray, CGM.getPointerAlign()); 10879 InputInfo.SizesArray = 10880 Address(Info.SizesArray, CGM.getPointerAlign()); 10881 MapTypesArray = Info.MapTypesArray; 10882 if (D.hasClausesOfKind<OMPDependClause>()) 10883 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10884 else 10885 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10886 }; 10887 10888 if (IfCond) { 10889 emitIfClause(CGF, IfCond, TargetThenGen, 10890 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10891 } else { 10892 RegionCodeGenTy ThenRCG(TargetThenGen); 10893 ThenRCG(CGF); 10894 } 10895 } 10896 10897 namespace { 10898 /// Kind of parameter in a function with 'declare simd' directive. 10899 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10900 /// Attribute set of the parameter. 10901 struct ParamAttrTy { 10902 ParamKindTy Kind = Vector; 10903 llvm::APSInt StrideOrArg; 10904 llvm::APSInt Alignment; 10905 }; 10906 } // namespace 10907 10908 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10909 ArrayRef<ParamAttrTy> ParamAttrs) { 10910 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10911 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10912 // of that clause. The VLEN value must be power of 2. 10913 // In other case the notion of the function`s "characteristic data type" (CDT) 10914 // is used to compute the vector length. 10915 // CDT is defined in the following order: 10916 // a) For non-void function, the CDT is the return type. 10917 // b) If the function has any non-uniform, non-linear parameters, then the 10918 // CDT is the type of the first such parameter. 10919 // c) If the CDT determined by a) or b) above is struct, union, or class 10920 // type which is pass-by-value (except for the type that maps to the 10921 // built-in complex data type), the characteristic data type is int. 10922 // d) If none of the above three cases is applicable, the CDT is int. 10923 // The VLEN is then determined based on the CDT and the size of vector 10924 // register of that ISA for which current vector version is generated. The 10925 // VLEN is computed using the formula below: 10926 // VLEN = sizeof(vector_register) / sizeof(CDT), 10927 // where vector register size specified in section 3.2.1 Registers and the 10928 // Stack Frame of original AMD64 ABI document. 10929 QualType RetType = FD->getReturnType(); 10930 if (RetType.isNull()) 10931 return 0; 10932 ASTContext &C = FD->getASTContext(); 10933 QualType CDT; 10934 if (!RetType.isNull() && !RetType->isVoidType()) { 10935 CDT = RetType; 10936 } else { 10937 unsigned Offset = 0; 10938 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10939 if (ParamAttrs[Offset].Kind == Vector) 10940 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10941 ++Offset; 10942 } 10943 if (CDT.isNull()) { 10944 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10945 if (ParamAttrs[I + Offset].Kind == Vector) { 10946 CDT = FD->getParamDecl(I)->getType(); 10947 break; 10948 } 10949 } 10950 } 10951 } 10952 if (CDT.isNull()) 10953 CDT = C.IntTy; 10954 CDT = CDT->getCanonicalTypeUnqualified(); 10955 if (CDT->isRecordType() || CDT->isUnionType()) 10956 CDT = C.IntTy; 10957 return C.getTypeSize(CDT); 10958 } 10959 10960 static void 10961 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10962 const llvm::APSInt &VLENVal, 10963 ArrayRef<ParamAttrTy> ParamAttrs, 10964 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10965 struct ISADataTy { 10966 char ISA; 10967 unsigned VecRegSize; 10968 }; 10969 ISADataTy ISAData[] = { 10970 { 10971 'b', 128 10972 }, // SSE 10973 { 10974 'c', 256 10975 }, // AVX 10976 { 10977 'd', 256 10978 }, // AVX2 10979 { 10980 'e', 512 10981 }, // AVX512 10982 }; 10983 llvm::SmallVector<char, 2> Masked; 10984 switch (State) { 10985 case OMPDeclareSimdDeclAttr::BS_Undefined: 10986 Masked.push_back('N'); 10987 Masked.push_back('M'); 10988 break; 10989 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10990 Masked.push_back('N'); 10991 break; 10992 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10993 Masked.push_back('M'); 10994 break; 10995 } 10996 for (char Mask : Masked) { 10997 for (const ISADataTy &Data : ISAData) { 10998 SmallString<256> Buffer; 10999 llvm::raw_svector_ostream Out(Buffer); 11000 Out << "_ZGV" << Data.ISA << Mask; 11001 if (!VLENVal) { 11002 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 11003 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 11004 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 11005 } else { 11006 Out << VLENVal; 11007 } 11008 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 11009 switch (ParamAttr.Kind){ 11010 case LinearWithVarStride: 11011 Out << 's' << ParamAttr.StrideOrArg; 11012 break; 11013 case Linear: 11014 Out << 'l'; 11015 if (!!ParamAttr.StrideOrArg) 11016 Out << ParamAttr.StrideOrArg; 11017 break; 11018 case Uniform: 11019 Out << 'u'; 11020 break; 11021 case Vector: 11022 Out << 'v'; 11023 break; 11024 } 11025 if (!!ParamAttr.Alignment) 11026 Out << 'a' << ParamAttr.Alignment; 11027 } 11028 Out << '_' << Fn->getName(); 11029 Fn->addFnAttr(Out.str()); 11030 } 11031 } 11032 } 11033 11034 // This are the Functions that are needed to mangle the name of the 11035 // vector functions generated by the compiler, according to the rules 11036 // defined in the "Vector Function ABI specifications for AArch64", 11037 // available at 11038 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 11039 11040 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 11041 /// 11042 /// TODO: Need to implement the behavior for reference marked with a 11043 /// var or no linear modifiers (1.b in the section). For this, we 11044 /// need to extend ParamKindTy to support the linear modifiers. 11045 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 11046 QT = QT.getCanonicalType(); 11047 11048 if (QT->isVoidType()) 11049 return false; 11050 11051 if (Kind == ParamKindTy::Uniform) 11052 return false; 11053 11054 if (Kind == ParamKindTy::Linear) 11055 return false; 11056 11057 // TODO: Handle linear references with modifiers 11058 11059 if (Kind == ParamKindTy::LinearWithVarStride) 11060 return false; 11061 11062 return true; 11063 } 11064 11065 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 11066 static bool getAArch64PBV(QualType QT, ASTContext &C) { 11067 QT = QT.getCanonicalType(); 11068 unsigned Size = C.getTypeSize(QT); 11069 11070 // Only scalars and complex within 16 bytes wide set PVB to true. 11071 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 11072 return false; 11073 11074 if (QT->isFloatingType()) 11075 return true; 11076 11077 if (QT->isIntegerType()) 11078 return true; 11079 11080 if (QT->isPointerType()) 11081 return true; 11082 11083 // TODO: Add support for complex types (section 3.1.2, item 2). 11084 11085 return false; 11086 } 11087 11088 /// Computes the lane size (LS) of a return type or of an input parameter, 11089 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 11090 /// TODO: Add support for references, section 3.2.1, item 1. 11091 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 11092 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 11093 QualType PTy = QT.getCanonicalType()->getPointeeType(); 11094 if (getAArch64PBV(PTy, C)) 11095 return C.getTypeSize(PTy); 11096 } 11097 if (getAArch64PBV(QT, C)) 11098 return C.getTypeSize(QT); 11099 11100 return C.getTypeSize(C.getUIntPtrType()); 11101 } 11102 11103 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 11104 // signature of the scalar function, as defined in 3.2.2 of the 11105 // AAVFABI. 11106 static std::tuple<unsigned, unsigned, bool> 11107 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 11108 QualType RetType = FD->getReturnType().getCanonicalType(); 11109 11110 ASTContext &C = FD->getASTContext(); 11111 11112 bool OutputBecomesInput = false; 11113 11114 llvm::SmallVector<unsigned, 8> Sizes; 11115 if (!RetType->isVoidType()) { 11116 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 11117 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 11118 OutputBecomesInput = true; 11119 } 11120 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11121 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 11122 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 11123 } 11124 11125 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 11126 // The LS of a function parameter / return value can only be a power 11127 // of 2, starting from 8 bits, up to 128. 11128 assert(std::all_of(Sizes.begin(), Sizes.end(), 11129 [](unsigned Size) { 11130 return Size == 8 || Size == 16 || Size == 32 || 11131 Size == 64 || Size == 128; 11132 }) && 11133 "Invalid size"); 11134 11135 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 11136 *std::max_element(std::begin(Sizes), std::end(Sizes)), 11137 OutputBecomesInput); 11138 } 11139 11140 /// Mangle the parameter part of the vector function name according to 11141 /// their OpenMP classification. The mangling function is defined in 11142 /// section 3.5 of the AAVFABI. 11143 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 11144 SmallString<256> Buffer; 11145 llvm::raw_svector_ostream Out(Buffer); 11146 for (const auto &ParamAttr : ParamAttrs) { 11147 switch (ParamAttr.Kind) { 11148 case LinearWithVarStride: 11149 Out << "ls" << ParamAttr.StrideOrArg; 11150 break; 11151 case Linear: 11152 Out << 'l'; 11153 // Don't print the step value if it is not present or if it is 11154 // equal to 1. 11155 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 11156 Out << ParamAttr.StrideOrArg; 11157 break; 11158 case Uniform: 11159 Out << 'u'; 11160 break; 11161 case Vector: 11162 Out << 'v'; 11163 break; 11164 } 11165 11166 if (!!ParamAttr.Alignment) 11167 Out << 'a' << ParamAttr.Alignment; 11168 } 11169 11170 return std::string(Out.str()); 11171 } 11172 11173 // Function used to add the attribute. The parameter `VLEN` is 11174 // templated to allow the use of "x" when targeting scalable functions 11175 // for SVE. 11176 template <typename T> 11177 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 11178 char ISA, StringRef ParSeq, 11179 StringRef MangledName, bool OutputBecomesInput, 11180 llvm::Function *Fn) { 11181 SmallString<256> Buffer; 11182 llvm::raw_svector_ostream Out(Buffer); 11183 Out << Prefix << ISA << LMask << VLEN; 11184 if (OutputBecomesInput) 11185 Out << "v"; 11186 Out << ParSeq << "_" << MangledName; 11187 Fn->addFnAttr(Out.str()); 11188 } 11189 11190 // Helper function to generate the Advanced SIMD names depending on 11191 // the value of the NDS when simdlen is not present. 11192 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 11193 StringRef Prefix, char ISA, 11194 StringRef ParSeq, StringRef MangledName, 11195 bool OutputBecomesInput, 11196 llvm::Function *Fn) { 11197 switch (NDS) { 11198 case 8: 11199 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11200 OutputBecomesInput, Fn); 11201 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 11202 OutputBecomesInput, Fn); 11203 break; 11204 case 16: 11205 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11206 OutputBecomesInput, Fn); 11207 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11208 OutputBecomesInput, Fn); 11209 break; 11210 case 32: 11211 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11212 OutputBecomesInput, Fn); 11213 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11214 OutputBecomesInput, Fn); 11215 break; 11216 case 64: 11217 case 128: 11218 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11219 OutputBecomesInput, Fn); 11220 break; 11221 default: 11222 llvm_unreachable("Scalar type is too wide."); 11223 } 11224 } 11225 11226 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 11227 static void emitAArch64DeclareSimdFunction( 11228 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 11229 ArrayRef<ParamAttrTy> ParamAttrs, 11230 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 11231 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 11232 11233 // Get basic data for building the vector signature. 11234 const auto Data = getNDSWDS(FD, ParamAttrs); 11235 const unsigned NDS = std::get<0>(Data); 11236 const unsigned WDS = std::get<1>(Data); 11237 const bool OutputBecomesInput = std::get<2>(Data); 11238 11239 // Check the values provided via `simdlen` by the user. 11240 // 1. A `simdlen(1)` doesn't produce vector signatures, 11241 if (UserVLEN == 1) { 11242 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11243 DiagnosticsEngine::Warning, 11244 "The clause simdlen(1) has no effect when targeting aarch64."); 11245 CGM.getDiags().Report(SLoc, DiagID); 11246 return; 11247 } 11248 11249 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 11250 // Advanced SIMD output. 11251 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 11252 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11253 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 11254 "power of 2 when targeting Advanced SIMD."); 11255 CGM.getDiags().Report(SLoc, DiagID); 11256 return; 11257 } 11258 11259 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 11260 // limits. 11261 if (ISA == 's' && UserVLEN != 0) { 11262 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 11263 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11264 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 11265 "lanes in the architectural constraints " 11266 "for SVE (min is 128-bit, max is " 11267 "2048-bit, by steps of 128-bit)"); 11268 CGM.getDiags().Report(SLoc, DiagID) << WDS; 11269 return; 11270 } 11271 } 11272 11273 // Sort out parameter sequence. 11274 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 11275 StringRef Prefix = "_ZGV"; 11276 // Generate simdlen from user input (if any). 11277 if (UserVLEN) { 11278 if (ISA == 's') { 11279 // SVE generates only a masked function. 11280 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11281 OutputBecomesInput, Fn); 11282 } else { 11283 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11284 // Advanced SIMD generates one or two functions, depending on 11285 // the `[not]inbranch` clause. 11286 switch (State) { 11287 case OMPDeclareSimdDeclAttr::BS_Undefined: 11288 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11289 OutputBecomesInput, Fn); 11290 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11291 OutputBecomesInput, Fn); 11292 break; 11293 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11294 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11295 OutputBecomesInput, Fn); 11296 break; 11297 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11298 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11299 OutputBecomesInput, Fn); 11300 break; 11301 } 11302 } 11303 } else { 11304 // If no user simdlen is provided, follow the AAVFABI rules for 11305 // generating the vector length. 11306 if (ISA == 's') { 11307 // SVE, section 3.4.1, item 1. 11308 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 11309 OutputBecomesInput, Fn); 11310 } else { 11311 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11312 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 11313 // two vector names depending on the use of the clause 11314 // `[not]inbranch`. 11315 switch (State) { 11316 case OMPDeclareSimdDeclAttr::BS_Undefined: 11317 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11318 OutputBecomesInput, Fn); 11319 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11320 OutputBecomesInput, Fn); 11321 break; 11322 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11323 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11324 OutputBecomesInput, Fn); 11325 break; 11326 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11327 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11328 OutputBecomesInput, Fn); 11329 break; 11330 } 11331 } 11332 } 11333 } 11334 11335 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 11336 llvm::Function *Fn) { 11337 ASTContext &C = CGM.getContext(); 11338 FD = FD->getMostRecentDecl(); 11339 // Map params to their positions in function decl. 11340 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 11341 if (isa<CXXMethodDecl>(FD)) 11342 ParamPositions.try_emplace(FD, 0); 11343 unsigned ParamPos = ParamPositions.size(); 11344 for (const ParmVarDecl *P : FD->parameters()) { 11345 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 11346 ++ParamPos; 11347 } 11348 while (FD) { 11349 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 11350 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 11351 // Mark uniform parameters. 11352 for (const Expr *E : Attr->uniforms()) { 11353 E = E->IgnoreParenImpCasts(); 11354 unsigned Pos; 11355 if (isa<CXXThisExpr>(E)) { 11356 Pos = ParamPositions[FD]; 11357 } else { 11358 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11359 ->getCanonicalDecl(); 11360 Pos = ParamPositions[PVD]; 11361 } 11362 ParamAttrs[Pos].Kind = Uniform; 11363 } 11364 // Get alignment info. 11365 auto NI = Attr->alignments_begin(); 11366 for (const Expr *E : Attr->aligneds()) { 11367 E = E->IgnoreParenImpCasts(); 11368 unsigned Pos; 11369 QualType ParmTy; 11370 if (isa<CXXThisExpr>(E)) { 11371 Pos = ParamPositions[FD]; 11372 ParmTy = E->getType(); 11373 } else { 11374 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11375 ->getCanonicalDecl(); 11376 Pos = ParamPositions[PVD]; 11377 ParmTy = PVD->getType(); 11378 } 11379 ParamAttrs[Pos].Alignment = 11380 (*NI) 11381 ? (*NI)->EvaluateKnownConstInt(C) 11382 : llvm::APSInt::getUnsigned( 11383 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 11384 .getQuantity()); 11385 ++NI; 11386 } 11387 // Mark linear parameters. 11388 auto SI = Attr->steps_begin(); 11389 auto MI = Attr->modifiers_begin(); 11390 for (const Expr *E : Attr->linears()) { 11391 E = E->IgnoreParenImpCasts(); 11392 unsigned Pos; 11393 if (isa<CXXThisExpr>(E)) { 11394 Pos = ParamPositions[FD]; 11395 } else { 11396 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11397 ->getCanonicalDecl(); 11398 Pos = ParamPositions[PVD]; 11399 } 11400 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 11401 ParamAttr.Kind = Linear; 11402 if (*SI) { 11403 Expr::EvalResult Result; 11404 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 11405 if (const auto *DRE = 11406 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 11407 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 11408 ParamAttr.Kind = LinearWithVarStride; 11409 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 11410 ParamPositions[StridePVD->getCanonicalDecl()]); 11411 } 11412 } 11413 } else { 11414 ParamAttr.StrideOrArg = Result.Val.getInt(); 11415 } 11416 } 11417 ++SI; 11418 ++MI; 11419 } 11420 llvm::APSInt VLENVal; 11421 SourceLocation ExprLoc; 11422 const Expr *VLENExpr = Attr->getSimdlen(); 11423 if (VLENExpr) { 11424 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 11425 ExprLoc = VLENExpr->getExprLoc(); 11426 } 11427 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 11428 if (CGM.getTriple().isX86()) { 11429 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 11430 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 11431 unsigned VLEN = VLENVal.getExtValue(); 11432 StringRef MangledName = Fn->getName(); 11433 if (CGM.getTarget().hasFeature("sve")) 11434 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11435 MangledName, 's', 128, Fn, ExprLoc); 11436 if (CGM.getTarget().hasFeature("neon")) 11437 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11438 MangledName, 'n', 128, Fn, ExprLoc); 11439 } 11440 } 11441 FD = FD->getPreviousDecl(); 11442 } 11443 } 11444 11445 namespace { 11446 /// Cleanup action for doacross support. 11447 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 11448 public: 11449 static const int DoacrossFinArgs = 2; 11450 11451 private: 11452 llvm::FunctionCallee RTLFn; 11453 llvm::Value *Args[DoacrossFinArgs]; 11454 11455 public: 11456 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 11457 ArrayRef<llvm::Value *> CallArgs) 11458 : RTLFn(RTLFn) { 11459 assert(CallArgs.size() == DoacrossFinArgs); 11460 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11461 } 11462 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11463 if (!CGF.HaveInsertPoint()) 11464 return; 11465 CGF.EmitRuntimeCall(RTLFn, Args); 11466 } 11467 }; 11468 } // namespace 11469 11470 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11471 const OMPLoopDirective &D, 11472 ArrayRef<Expr *> NumIterations) { 11473 if (!CGF.HaveInsertPoint()) 11474 return; 11475 11476 ASTContext &C = CGM.getContext(); 11477 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 11478 RecordDecl *RD; 11479 if (KmpDimTy.isNull()) { 11480 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 11481 // kmp_int64 lo; // lower 11482 // kmp_int64 up; // upper 11483 // kmp_int64 st; // stride 11484 // }; 11485 RD = C.buildImplicitRecord("kmp_dim"); 11486 RD->startDefinition(); 11487 addFieldToRecordDecl(C, RD, Int64Ty); 11488 addFieldToRecordDecl(C, RD, Int64Ty); 11489 addFieldToRecordDecl(C, RD, Int64Ty); 11490 RD->completeDefinition(); 11491 KmpDimTy = C.getRecordType(RD); 11492 } else { 11493 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 11494 } 11495 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 11496 QualType ArrayTy = 11497 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 11498 11499 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 11500 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 11501 enum { LowerFD = 0, UpperFD, StrideFD }; 11502 // Fill dims with data. 11503 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 11504 LValue DimsLVal = CGF.MakeAddrLValue( 11505 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 11506 // dims.upper = num_iterations; 11507 LValue UpperLVal = CGF.EmitLValueForField( 11508 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 11509 llvm::Value *NumIterVal = CGF.EmitScalarConversion( 11510 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(), 11511 Int64Ty, NumIterations[I]->getExprLoc()); 11512 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 11513 // dims.stride = 1; 11514 LValue StrideLVal = CGF.EmitLValueForField( 11515 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 11516 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 11517 StrideLVal); 11518 } 11519 11520 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 11521 // kmp_int32 num_dims, struct kmp_dim * dims); 11522 llvm::Value *Args[] = { 11523 emitUpdateLocation(CGF, D.getBeginLoc()), 11524 getThreadID(CGF, D.getBeginLoc()), 11525 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 11526 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11527 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 11528 CGM.VoidPtrTy)}; 11529 11530 llvm::FunctionCallee RTLFn = 11531 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 11532 CGF.EmitRuntimeCall(RTLFn, Args); 11533 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 11534 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 11535 llvm::FunctionCallee FiniRTLFn = 11536 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 11537 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11538 llvm::makeArrayRef(FiniArgs)); 11539 } 11540 11541 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11542 const OMPDependClause *C) { 11543 QualType Int64Ty = 11544 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 11545 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 11546 QualType ArrayTy = CGM.getContext().getConstantArrayType( 11547 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 11548 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 11549 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 11550 const Expr *CounterVal = C->getLoopData(I); 11551 assert(CounterVal); 11552 llvm::Value *CntVal = CGF.EmitScalarConversion( 11553 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 11554 CounterVal->getExprLoc()); 11555 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 11556 /*Volatile=*/false, Int64Ty); 11557 } 11558 llvm::Value *Args[] = { 11559 emitUpdateLocation(CGF, C->getBeginLoc()), 11560 getThreadID(CGF, C->getBeginLoc()), 11561 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 11562 llvm::FunctionCallee RTLFn; 11563 if (C->getDependencyKind() == OMPC_DEPEND_source) { 11564 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 11565 } else { 11566 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 11567 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 11568 } 11569 CGF.EmitRuntimeCall(RTLFn, Args); 11570 } 11571 11572 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 11573 llvm::FunctionCallee Callee, 11574 ArrayRef<llvm::Value *> Args) const { 11575 assert(Loc.isValid() && "Outlined function call location must be valid."); 11576 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 11577 11578 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 11579 if (Fn->doesNotThrow()) { 11580 CGF.EmitNounwindRuntimeCall(Fn, Args); 11581 return; 11582 } 11583 } 11584 CGF.EmitRuntimeCall(Callee, Args); 11585 } 11586 11587 void CGOpenMPRuntime::emitOutlinedFunctionCall( 11588 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 11589 ArrayRef<llvm::Value *> Args) const { 11590 emitCall(CGF, Loc, OutlinedFn, Args); 11591 } 11592 11593 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 11594 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 11595 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 11596 HasEmittedDeclareTargetRegion = true; 11597 } 11598 11599 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 11600 const VarDecl *NativeParam, 11601 const VarDecl *TargetParam) const { 11602 return CGF.GetAddrOfLocalVar(NativeParam); 11603 } 11604 11605 namespace { 11606 /// Cleanup action for allocate support. 11607 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 11608 public: 11609 static const int CleanupArgs = 3; 11610 11611 private: 11612 llvm::FunctionCallee RTLFn; 11613 llvm::Value *Args[CleanupArgs]; 11614 11615 public: 11616 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 11617 ArrayRef<llvm::Value *> CallArgs) 11618 : RTLFn(RTLFn) { 11619 assert(CallArgs.size() == CleanupArgs && 11620 "Size of arguments does not match."); 11621 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11622 } 11623 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11624 if (!CGF.HaveInsertPoint()) 11625 return; 11626 CGF.EmitRuntimeCall(RTLFn, Args); 11627 } 11628 }; 11629 } // namespace 11630 11631 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 11632 const VarDecl *VD) { 11633 if (!VD) 11634 return Address::invalid(); 11635 const VarDecl *CVD = VD->getCanonicalDecl(); 11636 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 11637 return Address::invalid(); 11638 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 11639 // Use the default allocation. 11640 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 11641 !AA->getAllocator()) 11642 return Address::invalid(); 11643 llvm::Value *Size; 11644 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11645 if (CVD->getType()->isVariablyModifiedType()) { 11646 Size = CGF.getTypeSize(CVD->getType()); 11647 // Align the size: ((size + align - 1) / align) * align 11648 Size = CGF.Builder.CreateNUWAdd( 11649 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11650 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11651 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11652 } else { 11653 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 11654 Size = CGM.getSize(Sz.alignTo(Align)); 11655 } 11656 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11657 assert(AA->getAllocator() && 11658 "Expected allocator expression for non-default allocator."); 11659 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11660 // According to the standard, the original allocator type is a enum (integer). 11661 // Convert to pointer type, if required. 11662 if (Allocator->getType()->isIntegerTy()) 11663 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11664 else if (Allocator->getType()->isPointerTy()) 11665 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11666 CGM.VoidPtrTy); 11667 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11668 11669 llvm::Value *Addr = 11670 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11671 getName({CVD->getName(), ".void.addr"})); 11672 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11673 Allocator}; 11674 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11675 11676 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11677 llvm::makeArrayRef(FiniArgs)); 11678 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11679 Addr, 11680 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11681 getName({CVD->getName(), ".addr"})); 11682 return Address(Addr, Align); 11683 } 11684 11685 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 11686 CodeGenModule &CGM, const OMPLoopDirective &S) 11687 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 11688 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11689 if (!NeedToPush) 11690 return; 11691 NontemporalDeclsSet &DS = 11692 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 11693 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 11694 for (const Stmt *Ref : C->private_refs()) { 11695 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 11696 const ValueDecl *VD; 11697 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 11698 VD = DRE->getDecl(); 11699 } else { 11700 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 11701 assert((ME->isImplicitCXXThis() || 11702 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 11703 "Expected member of current class."); 11704 VD = ME->getMemberDecl(); 11705 } 11706 DS.insert(VD); 11707 } 11708 } 11709 } 11710 11711 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 11712 if (!NeedToPush) 11713 return; 11714 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 11715 } 11716 11717 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 11718 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11719 11720 return llvm::any_of( 11721 CGM.getOpenMPRuntime().NontemporalDeclsStack, 11722 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 11723 } 11724 11725 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 11726 const OMPExecutableDirective &S, 11727 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 11728 const { 11729 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 11730 // Vars in target/task regions must be excluded completely. 11731 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 11732 isOpenMPTaskingDirective(S.getDirectiveKind())) { 11733 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11734 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 11735 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 11736 for (const CapturedStmt::Capture &Cap : CS->captures()) { 11737 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 11738 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 11739 } 11740 } 11741 // Exclude vars in private clauses. 11742 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 11743 for (const Expr *Ref : C->varlists()) { 11744 if (!Ref->getType()->isScalarType()) 11745 continue; 11746 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11747 if (!DRE) 11748 continue; 11749 NeedToCheckForLPCs.insert(DRE->getDecl()); 11750 } 11751 } 11752 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 11753 for (const Expr *Ref : C->varlists()) { 11754 if (!Ref->getType()->isScalarType()) 11755 continue; 11756 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11757 if (!DRE) 11758 continue; 11759 NeedToCheckForLPCs.insert(DRE->getDecl()); 11760 } 11761 } 11762 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11763 for (const Expr *Ref : C->varlists()) { 11764 if (!Ref->getType()->isScalarType()) 11765 continue; 11766 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11767 if (!DRE) 11768 continue; 11769 NeedToCheckForLPCs.insert(DRE->getDecl()); 11770 } 11771 } 11772 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 11773 for (const Expr *Ref : C->varlists()) { 11774 if (!Ref->getType()->isScalarType()) 11775 continue; 11776 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11777 if (!DRE) 11778 continue; 11779 NeedToCheckForLPCs.insert(DRE->getDecl()); 11780 } 11781 } 11782 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 11783 for (const Expr *Ref : C->varlists()) { 11784 if (!Ref->getType()->isScalarType()) 11785 continue; 11786 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11787 if (!DRE) 11788 continue; 11789 NeedToCheckForLPCs.insert(DRE->getDecl()); 11790 } 11791 } 11792 for (const Decl *VD : NeedToCheckForLPCs) { 11793 for (const LastprivateConditionalData &Data : 11794 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 11795 if (Data.DeclToUniqueName.count(VD) > 0) { 11796 if (!Data.Disabled) 11797 NeedToAddForLPCsAsDisabled.insert(VD); 11798 break; 11799 } 11800 } 11801 } 11802 } 11803 11804 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11805 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 11806 : CGM(CGF.CGM), 11807 Action((CGM.getLangOpts().OpenMP >= 50 && 11808 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 11809 [](const OMPLastprivateClause *C) { 11810 return C->getKind() == 11811 OMPC_LASTPRIVATE_conditional; 11812 })) 11813 ? ActionToDo::PushAsLastprivateConditional 11814 : ActionToDo::DoNotPush) { 11815 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11816 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 11817 return; 11818 assert(Action == ActionToDo::PushAsLastprivateConditional && 11819 "Expected a push action."); 11820 LastprivateConditionalData &Data = 11821 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11822 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11823 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 11824 continue; 11825 11826 for (const Expr *Ref : C->varlists()) { 11827 Data.DeclToUniqueName.insert(std::make_pair( 11828 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 11829 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 11830 } 11831 } 11832 Data.IVLVal = IVLVal; 11833 Data.Fn = CGF.CurFn; 11834 } 11835 11836 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11837 CodeGenFunction &CGF, const OMPExecutableDirective &S) 11838 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 11839 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11840 if (CGM.getLangOpts().OpenMP < 50) 11841 return; 11842 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 11843 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 11844 if (!NeedToAddForLPCsAsDisabled.empty()) { 11845 Action = ActionToDo::DisableLastprivateConditional; 11846 LastprivateConditionalData &Data = 11847 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11848 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 11849 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 11850 Data.Fn = CGF.CurFn; 11851 Data.Disabled = true; 11852 } 11853 } 11854 11855 CGOpenMPRuntime::LastprivateConditionalRAII 11856 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 11857 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 11858 return LastprivateConditionalRAII(CGF, S); 11859 } 11860 11861 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 11862 if (CGM.getLangOpts().OpenMP < 50) 11863 return; 11864 if (Action == ActionToDo::DisableLastprivateConditional) { 11865 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11866 "Expected list of disabled private vars."); 11867 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11868 } 11869 if (Action == ActionToDo::PushAsLastprivateConditional) { 11870 assert( 11871 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11872 "Expected list of lastprivate conditional vars."); 11873 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11874 } 11875 } 11876 11877 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 11878 const VarDecl *VD) { 11879 ASTContext &C = CGM.getContext(); 11880 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 11881 if (I == LastprivateConditionalToTypes.end()) 11882 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 11883 QualType NewType; 11884 const FieldDecl *VDField; 11885 const FieldDecl *FiredField; 11886 LValue BaseLVal; 11887 auto VI = I->getSecond().find(VD); 11888 if (VI == I->getSecond().end()) { 11889 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 11890 RD->startDefinition(); 11891 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 11892 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 11893 RD->completeDefinition(); 11894 NewType = C.getRecordType(RD); 11895 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 11896 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 11897 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 11898 } else { 11899 NewType = std::get<0>(VI->getSecond()); 11900 VDField = std::get<1>(VI->getSecond()); 11901 FiredField = std::get<2>(VI->getSecond()); 11902 BaseLVal = std::get<3>(VI->getSecond()); 11903 } 11904 LValue FiredLVal = 11905 CGF.EmitLValueForField(BaseLVal, FiredField); 11906 CGF.EmitStoreOfScalar( 11907 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 11908 FiredLVal); 11909 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 11910 } 11911 11912 namespace { 11913 /// Checks if the lastprivate conditional variable is referenced in LHS. 11914 class LastprivateConditionalRefChecker final 11915 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 11916 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 11917 const Expr *FoundE = nullptr; 11918 const Decl *FoundD = nullptr; 11919 StringRef UniqueDeclName; 11920 LValue IVLVal; 11921 llvm::Function *FoundFn = nullptr; 11922 SourceLocation Loc; 11923 11924 public: 11925 bool VisitDeclRefExpr(const DeclRefExpr *E) { 11926 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11927 llvm::reverse(LPM)) { 11928 auto It = D.DeclToUniqueName.find(E->getDecl()); 11929 if (It == D.DeclToUniqueName.end()) 11930 continue; 11931 if (D.Disabled) 11932 return false; 11933 FoundE = E; 11934 FoundD = E->getDecl()->getCanonicalDecl(); 11935 UniqueDeclName = It->second; 11936 IVLVal = D.IVLVal; 11937 FoundFn = D.Fn; 11938 break; 11939 } 11940 return FoundE == E; 11941 } 11942 bool VisitMemberExpr(const MemberExpr *E) { 11943 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 11944 return false; 11945 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11946 llvm::reverse(LPM)) { 11947 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 11948 if (It == D.DeclToUniqueName.end()) 11949 continue; 11950 if (D.Disabled) 11951 return false; 11952 FoundE = E; 11953 FoundD = E->getMemberDecl()->getCanonicalDecl(); 11954 UniqueDeclName = It->second; 11955 IVLVal = D.IVLVal; 11956 FoundFn = D.Fn; 11957 break; 11958 } 11959 return FoundE == E; 11960 } 11961 bool VisitStmt(const Stmt *S) { 11962 for (const Stmt *Child : S->children()) { 11963 if (!Child) 11964 continue; 11965 if (const auto *E = dyn_cast<Expr>(Child)) 11966 if (!E->isGLValue()) 11967 continue; 11968 if (Visit(Child)) 11969 return true; 11970 } 11971 return false; 11972 } 11973 explicit LastprivateConditionalRefChecker( 11974 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 11975 : LPM(LPM) {} 11976 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 11977 getFoundData() const { 11978 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 11979 } 11980 }; 11981 } // namespace 11982 11983 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 11984 LValue IVLVal, 11985 StringRef UniqueDeclName, 11986 LValue LVal, 11987 SourceLocation Loc) { 11988 // Last updated loop counter for the lastprivate conditional var. 11989 // int<xx> last_iv = 0; 11990 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 11991 llvm::Constant *LastIV = 11992 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 11993 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 11994 IVLVal.getAlignment().getAsAlign()); 11995 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 11996 11997 // Last value of the lastprivate conditional. 11998 // decltype(priv_a) last_a; 11999 llvm::Constant *Last = getOrCreateInternalVariable( 12000 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 12001 cast<llvm::GlobalVariable>(Last)->setAlignment( 12002 LVal.getAlignment().getAsAlign()); 12003 LValue LastLVal = 12004 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 12005 12006 // Global loop counter. Required to handle inner parallel-for regions. 12007 // iv 12008 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 12009 12010 // #pragma omp critical(a) 12011 // if (last_iv <= iv) { 12012 // last_iv = iv; 12013 // last_a = priv_a; 12014 // } 12015 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 12016 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 12017 Action.Enter(CGF); 12018 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 12019 // (last_iv <= iv) ? Check if the variable is updated and store new 12020 // value in global var. 12021 llvm::Value *CmpRes; 12022 if (IVLVal.getType()->isSignedIntegerType()) { 12023 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 12024 } else { 12025 assert(IVLVal.getType()->isUnsignedIntegerType() && 12026 "Loop iteration variable must be integer."); 12027 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 12028 } 12029 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 12030 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 12031 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 12032 // { 12033 CGF.EmitBlock(ThenBB); 12034 12035 // last_iv = iv; 12036 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 12037 12038 // last_a = priv_a; 12039 switch (CGF.getEvaluationKind(LVal.getType())) { 12040 case TEK_Scalar: { 12041 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 12042 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 12043 break; 12044 } 12045 case TEK_Complex: { 12046 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 12047 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 12048 break; 12049 } 12050 case TEK_Aggregate: 12051 llvm_unreachable( 12052 "Aggregates are not supported in lastprivate conditional."); 12053 } 12054 // } 12055 CGF.EmitBranch(ExitBB); 12056 // There is no need to emit line number for unconditional branch. 12057 (void)ApplyDebugLocation::CreateEmpty(CGF); 12058 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 12059 }; 12060 12061 if (CGM.getLangOpts().OpenMPSimd) { 12062 // Do not emit as a critical region as no parallel region could be emitted. 12063 RegionCodeGenTy ThenRCG(CodeGen); 12064 ThenRCG(CGF); 12065 } else { 12066 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 12067 } 12068 } 12069 12070 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 12071 const Expr *LHS) { 12072 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12073 return; 12074 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 12075 if (!Checker.Visit(LHS)) 12076 return; 12077 const Expr *FoundE; 12078 const Decl *FoundD; 12079 StringRef UniqueDeclName; 12080 LValue IVLVal; 12081 llvm::Function *FoundFn; 12082 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 12083 Checker.getFoundData(); 12084 if (FoundFn != CGF.CurFn) { 12085 // Special codegen for inner parallel regions. 12086 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 12087 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 12088 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 12089 "Lastprivate conditional is not found in outer region."); 12090 QualType StructTy = std::get<0>(It->getSecond()); 12091 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 12092 LValue PrivLVal = CGF.EmitLValue(FoundE); 12093 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12094 PrivLVal.getAddress(CGF), 12095 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 12096 LValue BaseLVal = 12097 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 12098 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 12099 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 12100 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 12101 FiredLVal, llvm::AtomicOrdering::Unordered, 12102 /*IsVolatile=*/true, /*isInit=*/false); 12103 return; 12104 } 12105 12106 // Private address of the lastprivate conditional in the current context. 12107 // priv_a 12108 LValue LVal = CGF.EmitLValue(FoundE); 12109 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 12110 FoundE->getExprLoc()); 12111 } 12112 12113 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 12114 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12115 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 12116 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12117 return; 12118 auto Range = llvm::reverse(LastprivateConditionalStack); 12119 auto It = llvm::find_if( 12120 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 12121 if (It == Range.end() || It->Fn != CGF.CurFn) 12122 return; 12123 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 12124 assert(LPCI != LastprivateConditionalToTypes.end() && 12125 "Lastprivates must be registered already."); 12126 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12127 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 12128 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 12129 for (const auto &Pair : It->DeclToUniqueName) { 12130 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 12131 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 12132 continue; 12133 auto I = LPCI->getSecond().find(Pair.first); 12134 assert(I != LPCI->getSecond().end() && 12135 "Lastprivate must be rehistered already."); 12136 // bool Cmp = priv_a.Fired != 0; 12137 LValue BaseLVal = std::get<3>(I->getSecond()); 12138 LValue FiredLVal = 12139 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 12140 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 12141 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 12142 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 12143 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 12144 // if (Cmp) { 12145 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 12146 CGF.EmitBlock(ThenBB); 12147 Address Addr = CGF.GetAddrOfLocalVar(VD); 12148 LValue LVal; 12149 if (VD->getType()->isReferenceType()) 12150 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 12151 AlignmentSource::Decl); 12152 else 12153 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 12154 AlignmentSource::Decl); 12155 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 12156 D.getBeginLoc()); 12157 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 12158 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 12159 // } 12160 } 12161 } 12162 12163 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 12164 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 12165 SourceLocation Loc) { 12166 if (CGF.getLangOpts().OpenMP < 50) 12167 return; 12168 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 12169 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 12170 "Unknown lastprivate conditional variable."); 12171 StringRef UniqueName = It->second; 12172 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 12173 // The variable was not updated in the region - exit. 12174 if (!GV) 12175 return; 12176 LValue LPLVal = CGF.MakeAddrLValue( 12177 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 12178 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 12179 CGF.EmitStoreOfScalar(Res, PrivLVal); 12180 } 12181 12182 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 12183 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12184 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12185 llvm_unreachable("Not supported in SIMD-only mode"); 12186 } 12187 12188 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 12189 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12190 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12191 llvm_unreachable("Not supported in SIMD-only mode"); 12192 } 12193 12194 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 12195 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12196 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 12197 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 12198 bool Tied, unsigned &NumberOfParts) { 12199 llvm_unreachable("Not supported in SIMD-only mode"); 12200 } 12201 12202 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 12203 SourceLocation Loc, 12204 llvm::Function *OutlinedFn, 12205 ArrayRef<llvm::Value *> CapturedVars, 12206 const Expr *IfCond) { 12207 llvm_unreachable("Not supported in SIMD-only mode"); 12208 } 12209 12210 void CGOpenMPSIMDRuntime::emitCriticalRegion( 12211 CodeGenFunction &CGF, StringRef CriticalName, 12212 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 12213 const Expr *Hint) { 12214 llvm_unreachable("Not supported in SIMD-only mode"); 12215 } 12216 12217 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 12218 const RegionCodeGenTy &MasterOpGen, 12219 SourceLocation Loc) { 12220 llvm_unreachable("Not supported in SIMD-only mode"); 12221 } 12222 12223 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 12224 SourceLocation Loc) { 12225 llvm_unreachable("Not supported in SIMD-only mode"); 12226 } 12227 12228 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 12229 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 12230 SourceLocation Loc) { 12231 llvm_unreachable("Not supported in SIMD-only mode"); 12232 } 12233 12234 void CGOpenMPSIMDRuntime::emitSingleRegion( 12235 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 12236 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 12237 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 12238 ArrayRef<const Expr *> AssignmentOps) { 12239 llvm_unreachable("Not supported in SIMD-only mode"); 12240 } 12241 12242 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 12243 const RegionCodeGenTy &OrderedOpGen, 12244 SourceLocation Loc, 12245 bool IsThreads) { 12246 llvm_unreachable("Not supported in SIMD-only mode"); 12247 } 12248 12249 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 12250 SourceLocation Loc, 12251 OpenMPDirectiveKind Kind, 12252 bool EmitChecks, 12253 bool ForceSimpleCall) { 12254 llvm_unreachable("Not supported in SIMD-only mode"); 12255 } 12256 12257 void CGOpenMPSIMDRuntime::emitForDispatchInit( 12258 CodeGenFunction &CGF, SourceLocation Loc, 12259 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 12260 bool Ordered, const DispatchRTInput &DispatchValues) { 12261 llvm_unreachable("Not supported in SIMD-only mode"); 12262 } 12263 12264 void CGOpenMPSIMDRuntime::emitForStaticInit( 12265 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 12266 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 12267 llvm_unreachable("Not supported in SIMD-only mode"); 12268 } 12269 12270 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 12271 CodeGenFunction &CGF, SourceLocation Loc, 12272 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 12273 llvm_unreachable("Not supported in SIMD-only mode"); 12274 } 12275 12276 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 12277 SourceLocation Loc, 12278 unsigned IVSize, 12279 bool IVSigned) { 12280 llvm_unreachable("Not supported in SIMD-only mode"); 12281 } 12282 12283 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 12284 SourceLocation Loc, 12285 OpenMPDirectiveKind DKind) { 12286 llvm_unreachable("Not supported in SIMD-only mode"); 12287 } 12288 12289 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 12290 SourceLocation Loc, 12291 unsigned IVSize, bool IVSigned, 12292 Address IL, Address LB, 12293 Address UB, Address ST) { 12294 llvm_unreachable("Not supported in SIMD-only mode"); 12295 } 12296 12297 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 12298 llvm::Value *NumThreads, 12299 SourceLocation Loc) { 12300 llvm_unreachable("Not supported in SIMD-only mode"); 12301 } 12302 12303 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 12304 ProcBindKind ProcBind, 12305 SourceLocation Loc) { 12306 llvm_unreachable("Not supported in SIMD-only mode"); 12307 } 12308 12309 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 12310 const VarDecl *VD, 12311 Address VDAddr, 12312 SourceLocation Loc) { 12313 llvm_unreachable("Not supported in SIMD-only mode"); 12314 } 12315 12316 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 12317 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 12318 CodeGenFunction *CGF) { 12319 llvm_unreachable("Not supported in SIMD-only mode"); 12320 } 12321 12322 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 12323 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 12324 llvm_unreachable("Not supported in SIMD-only mode"); 12325 } 12326 12327 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 12328 ArrayRef<const Expr *> Vars, 12329 SourceLocation Loc, 12330 llvm::AtomicOrdering AO) { 12331 llvm_unreachable("Not supported in SIMD-only mode"); 12332 } 12333 12334 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 12335 const OMPExecutableDirective &D, 12336 llvm::Function *TaskFunction, 12337 QualType SharedsTy, Address Shareds, 12338 const Expr *IfCond, 12339 const OMPTaskDataTy &Data) { 12340 llvm_unreachable("Not supported in SIMD-only mode"); 12341 } 12342 12343 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 12344 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 12345 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 12346 const Expr *IfCond, const OMPTaskDataTy &Data) { 12347 llvm_unreachable("Not supported in SIMD-only mode"); 12348 } 12349 12350 void CGOpenMPSIMDRuntime::emitReduction( 12351 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 12352 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 12353 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 12354 assert(Options.SimpleReduction && "Only simple reduction is expected."); 12355 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 12356 ReductionOps, Options); 12357 } 12358 12359 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 12360 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 12361 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 12362 llvm_unreachable("Not supported in SIMD-only mode"); 12363 } 12364 12365 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 12366 SourceLocation Loc, 12367 ReductionCodeGen &RCG, 12368 unsigned N) { 12369 llvm_unreachable("Not supported in SIMD-only mode"); 12370 } 12371 12372 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 12373 SourceLocation Loc, 12374 llvm::Value *ReductionsPtr, 12375 LValue SharedLVal) { 12376 llvm_unreachable("Not supported in SIMD-only mode"); 12377 } 12378 12379 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 12380 SourceLocation Loc) { 12381 llvm_unreachable("Not supported in SIMD-only mode"); 12382 } 12383 12384 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 12385 CodeGenFunction &CGF, SourceLocation Loc, 12386 OpenMPDirectiveKind CancelRegion) { 12387 llvm_unreachable("Not supported in SIMD-only mode"); 12388 } 12389 12390 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 12391 SourceLocation Loc, const Expr *IfCond, 12392 OpenMPDirectiveKind CancelRegion) { 12393 llvm_unreachable("Not supported in SIMD-only mode"); 12394 } 12395 12396 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 12397 const OMPExecutableDirective &D, StringRef ParentName, 12398 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 12399 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 12400 llvm_unreachable("Not supported in SIMD-only mode"); 12401 } 12402 12403 void CGOpenMPSIMDRuntime::emitTargetCall( 12404 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12405 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 12406 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 12407 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 12408 const OMPLoopDirective &D)> 12409 SizeEmitter) { 12410 llvm_unreachable("Not supported in SIMD-only mode"); 12411 } 12412 12413 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 12414 llvm_unreachable("Not supported in SIMD-only mode"); 12415 } 12416 12417 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 12418 llvm_unreachable("Not supported in SIMD-only mode"); 12419 } 12420 12421 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 12422 return false; 12423 } 12424 12425 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 12426 const OMPExecutableDirective &D, 12427 SourceLocation Loc, 12428 llvm::Function *OutlinedFn, 12429 ArrayRef<llvm::Value *> CapturedVars) { 12430 llvm_unreachable("Not supported in SIMD-only mode"); 12431 } 12432 12433 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 12434 const Expr *NumTeams, 12435 const Expr *ThreadLimit, 12436 SourceLocation Loc) { 12437 llvm_unreachable("Not supported in SIMD-only mode"); 12438 } 12439 12440 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 12441 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12442 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 12443 llvm_unreachable("Not supported in SIMD-only mode"); 12444 } 12445 12446 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 12447 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12448 const Expr *Device) { 12449 llvm_unreachable("Not supported in SIMD-only mode"); 12450 } 12451 12452 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 12453 const OMPLoopDirective &D, 12454 ArrayRef<Expr *> NumIterations) { 12455 llvm_unreachable("Not supported in SIMD-only mode"); 12456 } 12457 12458 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12459 const OMPDependClause *C) { 12460 llvm_unreachable("Not supported in SIMD-only mode"); 12461 } 12462 12463 const VarDecl * 12464 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 12465 const VarDecl *NativeParam) const { 12466 llvm_unreachable("Not supported in SIMD-only mode"); 12467 } 12468 12469 Address 12470 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 12471 const VarDecl *NativeParam, 12472 const VarDecl *TargetParam) const { 12473 llvm_unreachable("Not supported in SIMD-only mode"); 12474 } 12475