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 "TargetInfo.h" 19 #include "clang/AST/APValue.h" 20 #include "clang/AST/Attr.h" 21 #include "clang/AST/Decl.h" 22 #include "clang/AST/OpenMPClause.h" 23 #include "clang/AST/StmtOpenMP.h" 24 #include "clang/AST/StmtVisitor.h" 25 #include "clang/Basic/BitmaskEnum.h" 26 #include "clang/Basic/FileManager.h" 27 #include "clang/Basic/OpenMPKinds.h" 28 #include "clang/Basic/SourceManager.h" 29 #include "clang/CodeGen/ConstantInitBuilder.h" 30 #include "llvm/ADT/ArrayRef.h" 31 #include "llvm/ADT/SetOperations.h" 32 #include "llvm/ADT/SmallBitVector.h" 33 #include "llvm/ADT/StringExtras.h" 34 #include "llvm/Bitcode/BitcodeReader.h" 35 #include "llvm/IR/Constants.h" 36 #include "llvm/IR/DerivedTypes.h" 37 #include "llvm/IR/GlobalValue.h" 38 #include "llvm/IR/InstrTypes.h" 39 #include "llvm/IR/Value.h" 40 #include "llvm/Support/AtomicOrdering.h" 41 #include "llvm/Support/Format.h" 42 #include "llvm/Support/raw_ostream.h" 43 #include <cassert> 44 #include <numeric> 45 46 using namespace clang; 47 using namespace CodeGen; 48 using namespace llvm::omp; 49 50 namespace { 51 /// Base class for handling code generation inside OpenMP regions. 52 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 53 public: 54 /// Kinds of OpenMP regions used in codegen. 55 enum CGOpenMPRegionKind { 56 /// Region with outlined function for standalone 'parallel' 57 /// directive. 58 ParallelOutlinedRegion, 59 /// Region with outlined function for standalone 'task' directive. 60 TaskOutlinedRegion, 61 /// Region for constructs that do not require function outlining, 62 /// like 'for', 'sections', 'atomic' etc. directives. 63 InlinedRegion, 64 /// Region with outlined function for standalone 'target' directive. 65 TargetRegion, 66 }; 67 68 CGOpenMPRegionInfo(const CapturedStmt &CS, 69 const CGOpenMPRegionKind RegionKind, 70 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 71 bool HasCancel) 72 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 73 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 74 75 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 76 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 77 bool HasCancel) 78 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 79 Kind(Kind), HasCancel(HasCancel) {} 80 81 /// Get a variable or parameter for storing global thread id 82 /// inside OpenMP construct. 83 virtual const VarDecl *getThreadIDVariable() const = 0; 84 85 /// Emit the captured statement body. 86 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 87 88 /// Get an LValue for the current ThreadID variable. 89 /// \return LValue for thread id variable. This LValue always has type int32*. 90 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 91 92 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 93 94 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 95 96 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 97 98 bool hasCancel() const { return HasCancel; } 99 100 static bool classof(const CGCapturedStmtInfo *Info) { 101 return Info->getKind() == CR_OpenMP; 102 } 103 104 ~CGOpenMPRegionInfo() override = default; 105 106 protected: 107 CGOpenMPRegionKind RegionKind; 108 RegionCodeGenTy CodeGen; 109 OpenMPDirectiveKind Kind; 110 bool HasCancel; 111 }; 112 113 /// API for captured statement code generation in OpenMP constructs. 114 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 115 public: 116 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 117 const RegionCodeGenTy &CodeGen, 118 OpenMPDirectiveKind Kind, bool HasCancel, 119 StringRef HelperName) 120 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 121 HasCancel), 122 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 123 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 124 } 125 126 /// Get a variable or parameter for storing global thread id 127 /// inside OpenMP construct. 128 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 129 130 /// Get the name of the capture helper. 131 StringRef getHelperName() const override { return HelperName; } 132 133 static bool classof(const CGCapturedStmtInfo *Info) { 134 return CGOpenMPRegionInfo::classof(Info) && 135 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 136 ParallelOutlinedRegion; 137 } 138 139 private: 140 /// A variable or parameter storing global thread id for OpenMP 141 /// constructs. 142 const VarDecl *ThreadIDVar; 143 StringRef HelperName; 144 }; 145 146 /// API for captured statement code generation in OpenMP constructs. 147 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 148 public: 149 class UntiedTaskActionTy final : public PrePostActionTy { 150 bool Untied; 151 const VarDecl *PartIDVar; 152 const RegionCodeGenTy UntiedCodeGen; 153 llvm::SwitchInst *UntiedSwitch = nullptr; 154 155 public: 156 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 157 const RegionCodeGenTy &UntiedCodeGen) 158 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 159 void Enter(CodeGenFunction &CGF) override { 160 if (Untied) { 161 // Emit task switching point. 162 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 163 CGF.GetAddrOfLocalVar(PartIDVar), 164 PartIDVar->getType()->castAs<PointerType>()); 165 llvm::Value *Res = 166 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 167 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 168 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 169 CGF.EmitBlock(DoneBB); 170 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 171 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 172 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 173 CGF.Builder.GetInsertBlock()); 174 emitUntiedSwitch(CGF); 175 } 176 } 177 void emitUntiedSwitch(CodeGenFunction &CGF) const { 178 if (Untied) { 179 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 180 CGF.GetAddrOfLocalVar(PartIDVar), 181 PartIDVar->getType()->castAs<PointerType>()); 182 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 183 PartIdLVal); 184 UntiedCodeGen(CGF); 185 CodeGenFunction::JumpDest CurPoint = 186 CGF.getJumpDestInCurrentScope(".untied.next."); 187 CGF.EmitBranch(CGF.ReturnBlock.getBlock()); 188 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 189 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 190 CGF.Builder.GetInsertBlock()); 191 CGF.EmitBranchThroughCleanup(CurPoint); 192 CGF.EmitBlock(CurPoint.getBlock()); 193 } 194 } 195 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 196 }; 197 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 198 const VarDecl *ThreadIDVar, 199 const RegionCodeGenTy &CodeGen, 200 OpenMPDirectiveKind Kind, bool HasCancel, 201 const UntiedTaskActionTy &Action) 202 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 203 ThreadIDVar(ThreadIDVar), Action(Action) { 204 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 205 } 206 207 /// Get a variable or parameter for storing global thread id 208 /// inside OpenMP construct. 209 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 210 211 /// Get an LValue for the current ThreadID variable. 212 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 213 214 /// Get the name of the capture helper. 215 StringRef getHelperName() const override { return ".omp_outlined."; } 216 217 void emitUntiedSwitch(CodeGenFunction &CGF) override { 218 Action.emitUntiedSwitch(CGF); 219 } 220 221 static bool classof(const CGCapturedStmtInfo *Info) { 222 return CGOpenMPRegionInfo::classof(Info) && 223 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 224 TaskOutlinedRegion; 225 } 226 227 private: 228 /// A variable or parameter storing global thread id for OpenMP 229 /// constructs. 230 const VarDecl *ThreadIDVar; 231 /// Action for emitting code for untied tasks. 232 const UntiedTaskActionTy &Action; 233 }; 234 235 /// API for inlined captured statement code generation in OpenMP 236 /// constructs. 237 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 238 public: 239 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 240 const RegionCodeGenTy &CodeGen, 241 OpenMPDirectiveKind Kind, bool HasCancel) 242 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 243 OldCSI(OldCSI), 244 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 245 246 // Retrieve the value of the context parameter. 247 llvm::Value *getContextValue() const override { 248 if (OuterRegionInfo) 249 return OuterRegionInfo->getContextValue(); 250 llvm_unreachable("No context value for inlined OpenMP region"); 251 } 252 253 void setContextValue(llvm::Value *V) override { 254 if (OuterRegionInfo) { 255 OuterRegionInfo->setContextValue(V); 256 return; 257 } 258 llvm_unreachable("No context value for inlined OpenMP region"); 259 } 260 261 /// Lookup the captured field decl for a variable. 262 const FieldDecl *lookup(const VarDecl *VD) const override { 263 if (OuterRegionInfo) 264 return OuterRegionInfo->lookup(VD); 265 // If there is no outer outlined region,no need to lookup in a list of 266 // captured variables, we can use the original one. 267 return nullptr; 268 } 269 270 FieldDecl *getThisFieldDecl() const override { 271 if (OuterRegionInfo) 272 return OuterRegionInfo->getThisFieldDecl(); 273 return nullptr; 274 } 275 276 /// Get a variable or parameter for storing global thread id 277 /// inside OpenMP construct. 278 const VarDecl *getThreadIDVariable() const override { 279 if (OuterRegionInfo) 280 return OuterRegionInfo->getThreadIDVariable(); 281 return nullptr; 282 } 283 284 /// Get an LValue for the current ThreadID variable. 285 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 286 if (OuterRegionInfo) 287 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 288 llvm_unreachable("No LValue for inlined OpenMP construct"); 289 } 290 291 /// Get the name of the capture helper. 292 StringRef getHelperName() const override { 293 if (auto *OuterRegionInfo = getOldCSI()) 294 return OuterRegionInfo->getHelperName(); 295 llvm_unreachable("No helper name for inlined OpenMP construct"); 296 } 297 298 void emitUntiedSwitch(CodeGenFunction &CGF) override { 299 if (OuterRegionInfo) 300 OuterRegionInfo->emitUntiedSwitch(CGF); 301 } 302 303 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 304 305 static bool classof(const CGCapturedStmtInfo *Info) { 306 return CGOpenMPRegionInfo::classof(Info) && 307 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 308 } 309 310 ~CGOpenMPInlinedRegionInfo() override = default; 311 312 private: 313 /// CodeGen info about outer OpenMP region. 314 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 315 CGOpenMPRegionInfo *OuterRegionInfo; 316 }; 317 318 /// API for captured statement code generation in OpenMP target 319 /// constructs. For this captures, implicit parameters are used instead of the 320 /// captured fields. The name of the target region has to be unique in a given 321 /// application so it is provided by the client, because only the client has 322 /// the information to generate that. 323 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 324 public: 325 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 326 const RegionCodeGenTy &CodeGen, StringRef HelperName) 327 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 328 /*HasCancel=*/false), 329 HelperName(HelperName) {} 330 331 /// This is unused for target regions because each starts executing 332 /// with a single thread. 333 const VarDecl *getThreadIDVariable() const override { return nullptr; } 334 335 /// Get the name of the capture helper. 336 StringRef getHelperName() const override { return HelperName; } 337 338 static bool classof(const CGCapturedStmtInfo *Info) { 339 return CGOpenMPRegionInfo::classof(Info) && 340 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 341 } 342 343 private: 344 StringRef HelperName; 345 }; 346 347 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 348 llvm_unreachable("No codegen for expressions"); 349 } 350 /// API for generation of expressions captured in a innermost OpenMP 351 /// region. 352 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 353 public: 354 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 355 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 356 OMPD_unknown, 357 /*HasCancel=*/false), 358 PrivScope(CGF) { 359 // Make sure the globals captured in the provided statement are local by 360 // using the privatization logic. We assume the same variable is not 361 // captured more than once. 362 for (const auto &C : CS.captures()) { 363 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 364 continue; 365 366 const VarDecl *VD = C.getCapturedVar(); 367 if (VD->isLocalVarDeclOrParm()) 368 continue; 369 370 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 371 /*RefersToEnclosingVariableOrCapture=*/false, 372 VD->getType().getNonReferenceType(), VK_LValue, 373 C.getLocation()); 374 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress(CGF)); 375 } 376 (void)PrivScope.Privatize(); 377 } 378 379 /// Lookup the captured field decl for a variable. 380 const FieldDecl *lookup(const VarDecl *VD) const override { 381 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 382 return FD; 383 return nullptr; 384 } 385 386 /// Emit the captured statement body. 387 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 388 llvm_unreachable("No body for expressions"); 389 } 390 391 /// Get a variable or parameter for storing global thread id 392 /// inside OpenMP construct. 393 const VarDecl *getThreadIDVariable() const override { 394 llvm_unreachable("No thread id for expressions"); 395 } 396 397 /// Get the name of the capture helper. 398 StringRef getHelperName() const override { 399 llvm_unreachable("No helper name for expressions"); 400 } 401 402 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 403 404 private: 405 /// Private scope to capture global variables. 406 CodeGenFunction::OMPPrivateScope PrivScope; 407 }; 408 409 /// RAII for emitting code of OpenMP constructs. 410 class InlinedOpenMPRegionRAII { 411 CodeGenFunction &CGF; 412 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 413 FieldDecl *LambdaThisCaptureField = nullptr; 414 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 415 bool NoInheritance = false; 416 417 public: 418 /// Constructs region for combined constructs. 419 /// \param CodeGen Code generation sequence for combined directives. Includes 420 /// a list of functions used for code generation of implicitly inlined 421 /// regions. 422 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 423 OpenMPDirectiveKind Kind, bool HasCancel, 424 bool NoInheritance = true) 425 : CGF(CGF), NoInheritance(NoInheritance) { 426 // Start emission for the construct. 427 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 428 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 429 if (NoInheritance) { 430 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 431 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 432 CGF.LambdaThisCaptureField = nullptr; 433 BlockInfo = CGF.BlockInfo; 434 CGF.BlockInfo = nullptr; 435 } 436 } 437 438 ~InlinedOpenMPRegionRAII() { 439 // Restore original CapturedStmtInfo only if we're done with code emission. 440 auto *OldCSI = 441 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 442 delete CGF.CapturedStmtInfo; 443 CGF.CapturedStmtInfo = OldCSI; 444 if (NoInheritance) { 445 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 446 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 447 CGF.BlockInfo = BlockInfo; 448 } 449 } 450 }; 451 452 /// Values for bit flags used in the ident_t to describe the fields. 453 /// All enumeric elements are named and described in accordance with the code 454 /// from https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h 455 enum OpenMPLocationFlags : unsigned { 456 /// Use trampoline for internal microtask. 457 OMP_IDENT_IMD = 0x01, 458 /// Use c-style ident structure. 459 OMP_IDENT_KMPC = 0x02, 460 /// Atomic reduction option for kmpc_reduce. 461 OMP_ATOMIC_REDUCE = 0x10, 462 /// Explicit 'barrier' directive. 463 OMP_IDENT_BARRIER_EXPL = 0x20, 464 /// Implicit barrier in code. 465 OMP_IDENT_BARRIER_IMPL = 0x40, 466 /// Implicit barrier in 'for' directive. 467 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 468 /// Implicit barrier in 'sections' directive. 469 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 470 /// Implicit barrier in 'single' directive. 471 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 472 /// Call of __kmp_for_static_init for static loop. 473 OMP_IDENT_WORK_LOOP = 0x200, 474 /// Call of __kmp_for_static_init for sections. 475 OMP_IDENT_WORK_SECTIONS = 0x400, 476 /// Call of __kmp_for_static_init for distribute. 477 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 478 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 479 }; 480 481 namespace { 482 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 483 /// Values for bit flags for marking which requires clauses have been used. 484 enum OpenMPOffloadingRequiresDirFlags : int64_t { 485 /// flag undefined. 486 OMP_REQ_UNDEFINED = 0x000, 487 /// no requires clause present. 488 OMP_REQ_NONE = 0x001, 489 /// reverse_offload clause. 490 OMP_REQ_REVERSE_OFFLOAD = 0x002, 491 /// unified_address clause. 492 OMP_REQ_UNIFIED_ADDRESS = 0x004, 493 /// unified_shared_memory clause. 494 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 495 /// dynamic_allocators clause. 496 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 497 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 498 }; 499 500 enum OpenMPOffloadingReservedDeviceIDs { 501 /// Device ID if the device was not defined, runtime should get it 502 /// from environment variables in the spec. 503 OMP_DEVICEID_UNDEF = -1, 504 }; 505 } // anonymous namespace 506 507 /// Describes ident structure that describes a source location. 508 /// All descriptions are taken from 509 /// https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h 510 /// Original structure: 511 /// typedef struct ident { 512 /// kmp_int32 reserved_1; /**< might be used in Fortran; 513 /// see above */ 514 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 515 /// KMP_IDENT_KMPC identifies this union 516 /// member */ 517 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 518 /// see above */ 519 ///#if USE_ITT_BUILD 520 /// /* but currently used for storing 521 /// region-specific ITT */ 522 /// /* contextual information. */ 523 ///#endif /* USE_ITT_BUILD */ 524 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 525 /// C++ */ 526 /// char const *psource; /**< String describing the source location. 527 /// The string is composed of semi-colon separated 528 // fields which describe the source file, 529 /// the function and a pair of line numbers that 530 /// delimit the construct. 531 /// */ 532 /// } ident_t; 533 enum IdentFieldIndex { 534 /// might be used in Fortran 535 IdentField_Reserved_1, 536 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 537 IdentField_Flags, 538 /// Not really used in Fortran any more 539 IdentField_Reserved_2, 540 /// Source[4] in Fortran, do not use for C++ 541 IdentField_Reserved_3, 542 /// String describing the source location. The string is composed of 543 /// semi-colon separated fields which describe the source file, the function 544 /// and a pair of line numbers that delimit the construct. 545 IdentField_PSource 546 }; 547 548 /// Schedule types for 'omp for' loops (these enumerators are taken from 549 /// the enum sched_type in kmp.h). 550 enum OpenMPSchedType { 551 /// Lower bound for default (unordered) versions. 552 OMP_sch_lower = 32, 553 OMP_sch_static_chunked = 33, 554 OMP_sch_static = 34, 555 OMP_sch_dynamic_chunked = 35, 556 OMP_sch_guided_chunked = 36, 557 OMP_sch_runtime = 37, 558 OMP_sch_auto = 38, 559 /// static with chunk adjustment (e.g., simd) 560 OMP_sch_static_balanced_chunked = 45, 561 /// Lower bound for 'ordered' versions. 562 OMP_ord_lower = 64, 563 OMP_ord_static_chunked = 65, 564 OMP_ord_static = 66, 565 OMP_ord_dynamic_chunked = 67, 566 OMP_ord_guided_chunked = 68, 567 OMP_ord_runtime = 69, 568 OMP_ord_auto = 70, 569 OMP_sch_default = OMP_sch_static, 570 /// dist_schedule types 571 OMP_dist_sch_static_chunked = 91, 572 OMP_dist_sch_static = 92, 573 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 574 /// Set if the monotonic schedule modifier was present. 575 OMP_sch_modifier_monotonic = (1 << 29), 576 /// Set if the nonmonotonic schedule modifier was present. 577 OMP_sch_modifier_nonmonotonic = (1 << 30), 578 }; 579 580 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 581 /// region. 582 class CleanupTy final : public EHScopeStack::Cleanup { 583 PrePostActionTy *Action; 584 585 public: 586 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 587 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 588 if (!CGF.HaveInsertPoint()) 589 return; 590 Action->Exit(CGF); 591 } 592 }; 593 594 } // anonymous namespace 595 596 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 597 CodeGenFunction::RunCleanupsScope Scope(CGF); 598 if (PrePostAction) { 599 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 600 Callback(CodeGen, CGF, *PrePostAction); 601 } else { 602 PrePostActionTy Action; 603 Callback(CodeGen, CGF, Action); 604 } 605 } 606 607 /// Check if the combiner is a call to UDR combiner and if it is so return the 608 /// UDR decl used for reduction. 609 static const OMPDeclareReductionDecl * 610 getReductionInit(const Expr *ReductionOp) { 611 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 612 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 613 if (const auto *DRE = 614 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 615 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 616 return DRD; 617 return nullptr; 618 } 619 620 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 621 const OMPDeclareReductionDecl *DRD, 622 const Expr *InitOp, 623 Address Private, Address Original, 624 QualType Ty) { 625 if (DRD->getInitializer()) { 626 std::pair<llvm::Function *, llvm::Function *> Reduction = 627 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 628 const auto *CE = cast<CallExpr>(InitOp); 629 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 630 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 631 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 632 const auto *LHSDRE = 633 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 634 const auto *RHSDRE = 635 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 636 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 637 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), Private); 638 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), Original); 639 (void)PrivateScope.Privatize(); 640 RValue Func = RValue::get(Reduction.second); 641 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 642 CGF.EmitIgnoredExpr(InitOp); 643 } else { 644 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 645 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 646 auto *GV = new llvm::GlobalVariable( 647 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 648 llvm::GlobalValue::PrivateLinkage, Init, Name); 649 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 650 RValue InitRVal; 651 switch (CGF.getEvaluationKind(Ty)) { 652 case TEK_Scalar: 653 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 654 break; 655 case TEK_Complex: 656 InitRVal = 657 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 658 break; 659 case TEK_Aggregate: { 660 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_LValue); 661 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, LV); 662 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 663 /*IsInitializer=*/false); 664 return; 665 } 666 } 667 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_PRValue); 668 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 669 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 670 /*IsInitializer=*/false); 671 } 672 } 673 674 /// Emit initialization of arrays of complex types. 675 /// \param DestAddr Address of the array. 676 /// \param Type Type of array. 677 /// \param Init Initial expression of array. 678 /// \param SrcAddr Address of the original array. 679 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 680 QualType Type, bool EmitDeclareReductionInit, 681 const Expr *Init, 682 const OMPDeclareReductionDecl *DRD, 683 Address SrcAddr = Address::invalid()) { 684 // Perform element-by-element initialization. 685 QualType ElementTy; 686 687 // Drill down to the base element type on both arrays. 688 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 689 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 690 if (DRD) 691 SrcAddr = 692 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 693 694 llvm::Value *SrcBegin = nullptr; 695 if (DRD) 696 SrcBegin = SrcAddr.getPointer(); 697 llvm::Value *DestBegin = DestAddr.getPointer(); 698 // Cast from pointer to array type to pointer to single element. 699 llvm::Value *DestEnd = 700 CGF.Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements); 701 // The basic structure here is a while-do loop. 702 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 703 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 704 llvm::Value *IsEmpty = 705 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 706 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 707 708 // Enter the loop body, making that address the current address. 709 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 710 CGF.EmitBlock(BodyBB); 711 712 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 713 714 llvm::PHINode *SrcElementPHI = nullptr; 715 Address SrcElementCurrent = Address::invalid(); 716 if (DRD) { 717 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 718 "omp.arraycpy.srcElementPast"); 719 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 720 SrcElementCurrent = 721 Address(SrcElementPHI, SrcAddr.getElementType(), 722 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 723 } 724 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 725 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 726 DestElementPHI->addIncoming(DestBegin, EntryBB); 727 Address DestElementCurrent = 728 Address(DestElementPHI, DestAddr.getElementType(), 729 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 730 731 // Emit copy. 732 { 733 CodeGenFunction::RunCleanupsScope InitScope(CGF); 734 if (EmitDeclareReductionInit) { 735 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 736 SrcElementCurrent, ElementTy); 737 } else 738 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 739 /*IsInitializer=*/false); 740 } 741 742 if (DRD) { 743 // Shift the address forward by one element. 744 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 745 SrcAddr.getElementType(), SrcElementPHI, /*Idx0=*/1, 746 "omp.arraycpy.dest.element"); 747 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 748 } 749 750 // Shift the address forward by one element. 751 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 752 DestAddr.getElementType(), DestElementPHI, /*Idx0=*/1, 753 "omp.arraycpy.dest.element"); 754 // Check whether we've reached the end. 755 llvm::Value *Done = 756 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 757 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 758 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 759 760 // Done. 761 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 762 } 763 764 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 765 return CGF.EmitOMPSharedLValue(E); 766 } 767 768 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 769 const Expr *E) { 770 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 771 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 772 return LValue(); 773 } 774 775 void ReductionCodeGen::emitAggregateInitialization( 776 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, 777 const OMPDeclareReductionDecl *DRD) { 778 // Emit VarDecl with copy init for arrays. 779 // Get the address of the original variable captured in current 780 // captured region. 781 const auto *PrivateVD = 782 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 783 bool EmitDeclareReductionInit = 784 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 785 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 786 EmitDeclareReductionInit, 787 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 788 : PrivateVD->getInit(), 789 DRD, SharedAddr); 790 } 791 792 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 793 ArrayRef<const Expr *> Origs, 794 ArrayRef<const Expr *> Privates, 795 ArrayRef<const Expr *> ReductionOps) { 796 ClausesData.reserve(Shareds.size()); 797 SharedAddresses.reserve(Shareds.size()); 798 Sizes.reserve(Shareds.size()); 799 BaseDecls.reserve(Shareds.size()); 800 const auto *IOrig = Origs.begin(); 801 const auto *IPriv = Privates.begin(); 802 const auto *IRed = ReductionOps.begin(); 803 for (const Expr *Ref : Shareds) { 804 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed); 805 std::advance(IOrig, 1); 806 std::advance(IPriv, 1); 807 std::advance(IRed, 1); 808 } 809 } 810 811 void ReductionCodeGen::emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N) { 812 assert(SharedAddresses.size() == N && OrigAddresses.size() == N && 813 "Number of generated lvalues must be exactly N."); 814 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared); 815 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared); 816 SharedAddresses.emplace_back(First, Second); 817 if (ClausesData[N].Shared == ClausesData[N].Ref) { 818 OrigAddresses.emplace_back(First, Second); 819 } else { 820 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 821 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 822 OrigAddresses.emplace_back(First, Second); 823 } 824 } 825 826 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 827 QualType PrivateType = getPrivateType(N); 828 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 829 if (!PrivateType->isVariablyModifiedType()) { 830 Sizes.emplace_back( 831 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()), 832 nullptr); 833 return; 834 } 835 llvm::Value *Size; 836 llvm::Value *SizeInChars; 837 auto *ElemType = OrigAddresses[N].first.getAddress(CGF).getElementType(); 838 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 839 if (AsArraySection) { 840 Size = CGF.Builder.CreatePtrDiff(ElemType, 841 OrigAddresses[N].second.getPointer(CGF), 842 OrigAddresses[N].first.getPointer(CGF)); 843 Size = CGF.Builder.CreateNUWAdd( 844 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 845 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 846 } else { 847 SizeInChars = 848 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()); 849 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 850 } 851 Sizes.emplace_back(SizeInChars, Size); 852 CodeGenFunction::OpaqueValueMapping OpaqueMap( 853 CGF, 854 cast<OpaqueValueExpr>( 855 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 856 RValue::get(Size)); 857 CGF.EmitVariablyModifiedType(PrivateType); 858 } 859 860 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 861 llvm::Value *Size) { 862 QualType PrivateType = getPrivateType(N); 863 if (!PrivateType->isVariablyModifiedType()) { 864 assert(!Size && !Sizes[N].second && 865 "Size should be nullptr for non-variably modified reduction " 866 "items."); 867 return; 868 } 869 CodeGenFunction::OpaqueValueMapping OpaqueMap( 870 CGF, 871 cast<OpaqueValueExpr>( 872 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 873 RValue::get(Size)); 874 CGF.EmitVariablyModifiedType(PrivateType); 875 } 876 877 void ReductionCodeGen::emitInitialization( 878 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, 879 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 880 assert(SharedAddresses.size() > N && "No variable was generated"); 881 const auto *PrivateVD = 882 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 883 const OMPDeclareReductionDecl *DRD = 884 getReductionInit(ClausesData[N].ReductionOp); 885 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 886 if (DRD && DRD->getInitializer()) 887 (void)DefaultInit(CGF); 888 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD); 889 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 890 (void)DefaultInit(CGF); 891 QualType SharedType = SharedAddresses[N].first.getType(); 892 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 893 PrivateAddr, SharedAddr, SharedType); 894 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 895 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 896 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 897 PrivateVD->getType().getQualifiers(), 898 /*IsInitializer=*/false); 899 } 900 } 901 902 bool ReductionCodeGen::needCleanups(unsigned N) { 903 QualType PrivateType = getPrivateType(N); 904 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 905 return DTorKind != QualType::DK_none; 906 } 907 908 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 909 Address PrivateAddr) { 910 QualType PrivateType = getPrivateType(N); 911 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 912 if (needCleanups(N)) { 913 PrivateAddr = CGF.Builder.CreateElementBitCast( 914 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 915 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 916 } 917 } 918 919 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 920 LValue BaseLV) { 921 BaseTy = BaseTy.getNonReferenceType(); 922 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 923 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 924 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 925 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 926 } else { 927 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 928 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 929 } 930 BaseTy = BaseTy->getPointeeType(); 931 } 932 return CGF.MakeAddrLValue( 933 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 934 CGF.ConvertTypeForMem(ElTy)), 935 BaseLV.getType(), BaseLV.getBaseInfo(), 936 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 937 } 938 939 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 940 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 941 llvm::Value *Addr) { 942 Address Tmp = Address::invalid(); 943 Address TopTmp = Address::invalid(); 944 Address MostTopTmp = Address::invalid(); 945 BaseTy = BaseTy.getNonReferenceType(); 946 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 947 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 948 Tmp = CGF.CreateMemTemp(BaseTy); 949 if (TopTmp.isValid()) 950 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 951 else 952 MostTopTmp = Tmp; 953 TopTmp = Tmp; 954 BaseTy = BaseTy->getPointeeType(); 955 } 956 llvm::Type *Ty = BaseLVType; 957 if (Tmp.isValid()) 958 Ty = Tmp.getElementType(); 959 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 960 if (Tmp.isValid()) { 961 CGF.Builder.CreateStore(Addr, Tmp); 962 return MostTopTmp; 963 } 964 return Address::deprecated(Addr, BaseLVAlignment); 965 } 966 967 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 968 const VarDecl *OrigVD = nullptr; 969 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 970 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 971 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 972 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 973 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 974 Base = TempASE->getBase()->IgnoreParenImpCasts(); 975 DE = cast<DeclRefExpr>(Base); 976 OrigVD = cast<VarDecl>(DE->getDecl()); 977 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 978 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 979 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 980 Base = TempASE->getBase()->IgnoreParenImpCasts(); 981 DE = cast<DeclRefExpr>(Base); 982 OrigVD = cast<VarDecl>(DE->getDecl()); 983 } 984 return OrigVD; 985 } 986 987 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 988 Address PrivateAddr) { 989 const DeclRefExpr *DE; 990 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 991 BaseDecls.emplace_back(OrigVD); 992 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 993 LValue BaseLValue = 994 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 995 OriginalBaseLValue); 996 Address SharedAddr = SharedAddresses[N].first.getAddress(CGF); 997 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 998 SharedAddr.getElementType(), BaseLValue.getPointer(CGF), 999 SharedAddr.getPointer()); 1000 llvm::Value *PrivatePointer = 1001 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1002 PrivateAddr.getPointer(), SharedAddr.getType()); 1003 llvm::Value *Ptr = CGF.Builder.CreateGEP( 1004 SharedAddr.getElementType(), PrivatePointer, Adjustment); 1005 return castToBase(CGF, OrigVD->getType(), 1006 SharedAddresses[N].first.getType(), 1007 OriginalBaseLValue.getAddress(CGF).getType(), 1008 OriginalBaseLValue.getAlignment(), Ptr); 1009 } 1010 BaseDecls.emplace_back( 1011 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1012 return PrivateAddr; 1013 } 1014 1015 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1016 const OMPDeclareReductionDecl *DRD = 1017 getReductionInit(ClausesData[N].ReductionOp); 1018 return DRD && DRD->getInitializer(); 1019 } 1020 1021 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1022 return CGF.EmitLoadOfPointerLValue( 1023 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1024 getThreadIDVariable()->getType()->castAs<PointerType>()); 1025 } 1026 1027 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt *S) { 1028 if (!CGF.HaveInsertPoint()) 1029 return; 1030 // 1.2.2 OpenMP Language Terminology 1031 // Structured block - An executable statement with a single entry at the 1032 // top and a single exit at the bottom. 1033 // The point of exit cannot be a branch out of the structured block. 1034 // longjmp() and throw() must not violate the entry/exit criteria. 1035 CGF.EHStack.pushTerminate(); 1036 if (S) 1037 CGF.incrementProfileCounter(S); 1038 CodeGen(CGF); 1039 CGF.EHStack.popTerminate(); 1040 } 1041 1042 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1043 CodeGenFunction &CGF) { 1044 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1045 getThreadIDVariable()->getType(), 1046 AlignmentSource::Decl); 1047 } 1048 1049 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1050 QualType FieldTy) { 1051 auto *Field = FieldDecl::Create( 1052 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1053 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1054 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1055 Field->setAccess(AS_public); 1056 DC->addDecl(Field); 1057 return Field; 1058 } 1059 1060 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1061 StringRef Separator) 1062 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1063 OMPBuilder(CGM.getModule()), OffloadEntriesInfoManager(CGM) { 1064 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1065 1066 // Initialize Types used in OpenMPIRBuilder from OMPKinds.def 1067 OMPBuilder.initialize(); 1068 loadOffloadInfoMetadata(); 1069 } 1070 1071 void CGOpenMPRuntime::clear() { 1072 InternalVars.clear(); 1073 // Clean non-target variable declarations possibly used only in debug info. 1074 for (const auto &Data : EmittedNonTargetVariables) { 1075 if (!Data.getValue().pointsToAliveValue()) 1076 continue; 1077 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1078 if (!GV) 1079 continue; 1080 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1081 continue; 1082 GV->eraseFromParent(); 1083 } 1084 } 1085 1086 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1087 SmallString<128> Buffer; 1088 llvm::raw_svector_ostream OS(Buffer); 1089 StringRef Sep = FirstSeparator; 1090 for (StringRef Part : Parts) { 1091 OS << Sep << Part; 1092 Sep = Separator; 1093 } 1094 return std::string(OS.str()); 1095 } 1096 1097 static llvm::Function * 1098 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1099 const Expr *CombinerInitializer, const VarDecl *In, 1100 const VarDecl *Out, bool IsCombiner) { 1101 // void .omp_combiner.(Ty *in, Ty *out); 1102 ASTContext &C = CGM.getContext(); 1103 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1104 FunctionArgList Args; 1105 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1106 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1107 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1108 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1109 Args.push_back(&OmpOutParm); 1110 Args.push_back(&OmpInParm); 1111 const CGFunctionInfo &FnInfo = 1112 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1113 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1114 std::string Name = CGM.getOpenMPRuntime().getName( 1115 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1116 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1117 Name, &CGM.getModule()); 1118 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1119 if (CGM.getLangOpts().Optimize) { 1120 Fn->removeFnAttr(llvm::Attribute::NoInline); 1121 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1122 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1123 } 1124 CodeGenFunction CGF(CGM); 1125 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1126 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1127 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1128 Out->getLocation()); 1129 CodeGenFunction::OMPPrivateScope Scope(CGF); 1130 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1131 Scope.addPrivate( 1132 In, CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1133 .getAddress(CGF)); 1134 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1135 Scope.addPrivate( 1136 Out, CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1137 .getAddress(CGF)); 1138 (void)Scope.Privatize(); 1139 if (!IsCombiner && Out->hasInit() && 1140 !CGF.isTrivialInitializer(Out->getInit())) { 1141 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1142 Out->getType().getQualifiers(), 1143 /*IsInitializer=*/true); 1144 } 1145 if (CombinerInitializer) 1146 CGF.EmitIgnoredExpr(CombinerInitializer); 1147 Scope.ForceCleanup(); 1148 CGF.FinishFunction(); 1149 return Fn; 1150 } 1151 1152 void CGOpenMPRuntime::emitUserDefinedReduction( 1153 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1154 if (UDRMap.count(D) > 0) 1155 return; 1156 llvm::Function *Combiner = emitCombinerOrInitializer( 1157 CGM, D->getType(), D->getCombiner(), 1158 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1159 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1160 /*IsCombiner=*/true); 1161 llvm::Function *Initializer = nullptr; 1162 if (const Expr *Init = D->getInitializer()) { 1163 Initializer = emitCombinerOrInitializer( 1164 CGM, D->getType(), 1165 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1166 : nullptr, 1167 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1168 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1169 /*IsCombiner=*/false); 1170 } 1171 UDRMap.try_emplace(D, Combiner, Initializer); 1172 if (CGF) { 1173 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1174 Decls.second.push_back(D); 1175 } 1176 } 1177 1178 std::pair<llvm::Function *, llvm::Function *> 1179 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1180 auto I = UDRMap.find(D); 1181 if (I != UDRMap.end()) 1182 return I->second; 1183 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1184 return UDRMap.lookup(D); 1185 } 1186 1187 namespace { 1188 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1189 // Builder if one is present. 1190 struct PushAndPopStackRAII { 1191 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1192 bool HasCancel, llvm::omp::Directive Kind) 1193 : OMPBuilder(OMPBuilder) { 1194 if (!OMPBuilder) 1195 return; 1196 1197 // The following callback is the crucial part of clangs cleanup process. 1198 // 1199 // NOTE: 1200 // Once the OpenMPIRBuilder is used to create parallel regions (and 1201 // similar), the cancellation destination (Dest below) is determined via 1202 // IP. That means if we have variables to finalize we split the block at IP, 1203 // use the new block (=BB) as destination to build a JumpDest (via 1204 // getJumpDestInCurrentScope(BB)) which then is fed to 1205 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1206 // to push & pop an FinalizationInfo object. 1207 // The FiniCB will still be needed but at the point where the 1208 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1209 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1210 assert(IP.getBlock()->end() == IP.getPoint() && 1211 "Clang CG should cause non-terminated block!"); 1212 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1213 CGF.Builder.restoreIP(IP); 1214 CodeGenFunction::JumpDest Dest = 1215 CGF.getOMPCancelDestination(OMPD_parallel); 1216 CGF.EmitBranchThroughCleanup(Dest); 1217 }; 1218 1219 // TODO: Remove this once we emit parallel regions through the 1220 // OpenMPIRBuilder as it can do this setup internally. 1221 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel}); 1222 OMPBuilder->pushFinalizationCB(std::move(FI)); 1223 } 1224 ~PushAndPopStackRAII() { 1225 if (OMPBuilder) 1226 OMPBuilder->popFinalizationCB(); 1227 } 1228 llvm::OpenMPIRBuilder *OMPBuilder; 1229 }; 1230 } // namespace 1231 1232 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1233 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1234 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1235 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1236 assert(ThreadIDVar->getType()->isPointerType() && 1237 "thread id variable must be of type kmp_int32 *"); 1238 CodeGenFunction CGF(CGM, true); 1239 bool HasCancel = false; 1240 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1241 HasCancel = OPD->hasCancel(); 1242 else if (const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D)) 1243 HasCancel = OPD->hasCancel(); 1244 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1245 HasCancel = OPSD->hasCancel(); 1246 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1247 HasCancel = OPFD->hasCancel(); 1248 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1249 HasCancel = OPFD->hasCancel(); 1250 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1251 HasCancel = OPFD->hasCancel(); 1252 else if (const auto *OPFD = 1253 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1254 HasCancel = OPFD->hasCancel(); 1255 else if (const auto *OPFD = 1256 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1257 HasCancel = OPFD->hasCancel(); 1258 1259 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1260 // parallel region to make cancellation barriers work properly. 1261 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); 1262 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind); 1263 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1264 HasCancel, OutlinedHelperName); 1265 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1266 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1267 } 1268 1269 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1270 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1271 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1272 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1273 return emitParallelOrTeamsOutlinedFunction( 1274 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1275 } 1276 1277 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1278 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1279 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1280 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1281 return emitParallelOrTeamsOutlinedFunction( 1282 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1283 } 1284 1285 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1286 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1287 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1288 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1289 bool Tied, unsigned &NumberOfParts) { 1290 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1291 PrePostActionTy &) { 1292 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1293 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1294 llvm::Value *TaskArgs[] = { 1295 UpLoc, ThreadID, 1296 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1297 TaskTVar->getType()->castAs<PointerType>()) 1298 .getPointer(CGF)}; 1299 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1300 CGM.getModule(), OMPRTL___kmpc_omp_task), 1301 TaskArgs); 1302 }; 1303 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1304 UntiedCodeGen); 1305 CodeGen.setAction(Action); 1306 assert(!ThreadIDVar->getType()->isPointerType() && 1307 "thread id variable must be of type kmp_int32 for tasks"); 1308 const OpenMPDirectiveKind Region = 1309 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1310 : OMPD_task; 1311 const CapturedStmt *CS = D.getCapturedStmt(Region); 1312 bool HasCancel = false; 1313 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D)) 1314 HasCancel = TD->hasCancel(); 1315 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D)) 1316 HasCancel = TD->hasCancel(); 1317 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D)) 1318 HasCancel = TD->hasCancel(); 1319 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D)) 1320 HasCancel = TD->hasCancel(); 1321 1322 CodeGenFunction CGF(CGM, true); 1323 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1324 InnermostKind, HasCancel, Action); 1325 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1326 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1327 if (!Tied) 1328 NumberOfParts = Action.getNumberOfParts(); 1329 return Res; 1330 } 1331 1332 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1333 const RecordDecl *RD, const CGRecordLayout &RL, 1334 ArrayRef<llvm::Constant *> Data) { 1335 llvm::StructType *StructTy = RL.getLLVMType(); 1336 unsigned PrevIdx = 0; 1337 ConstantInitBuilder CIBuilder(CGM); 1338 const auto *DI = Data.begin(); 1339 for (const FieldDecl *FD : RD->fields()) { 1340 unsigned Idx = RL.getLLVMFieldNo(FD); 1341 // Fill the alignment. 1342 for (unsigned I = PrevIdx; I < Idx; ++I) 1343 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1344 PrevIdx = Idx + 1; 1345 Fields.add(*DI); 1346 ++DI; 1347 } 1348 } 1349 1350 template <class... As> 1351 static llvm::GlobalVariable * 1352 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1353 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1354 As &&... Args) { 1355 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1356 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1357 ConstantInitBuilder CIBuilder(CGM); 1358 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1359 buildStructValue(Fields, CGM, RD, RL, Data); 1360 return Fields.finishAndCreateGlobal( 1361 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1362 std::forward<As>(Args)...); 1363 } 1364 1365 template <typename T> 1366 static void 1367 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1368 ArrayRef<llvm::Constant *> Data, 1369 T &Parent) { 1370 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1371 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1372 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1373 buildStructValue(Fields, CGM, RD, RL, Data); 1374 Fields.finishAndAddTo(Parent); 1375 } 1376 1377 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1378 bool AtCurrentPoint) { 1379 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1380 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1381 1382 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1383 if (AtCurrentPoint) { 1384 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1385 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1386 } else { 1387 Elem.second.ServiceInsertPt = 1388 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1389 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1390 } 1391 } 1392 1393 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1394 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1395 if (Elem.second.ServiceInsertPt) { 1396 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1397 Elem.second.ServiceInsertPt = nullptr; 1398 Ptr->eraseFromParent(); 1399 } 1400 } 1401 1402 static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, 1403 SourceLocation Loc, 1404 SmallString<128> &Buffer) { 1405 llvm::raw_svector_ostream OS(Buffer); 1406 // Build debug location 1407 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1408 OS << ";" << PLoc.getFilename() << ";"; 1409 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1410 OS << FD->getQualifiedNameAsString(); 1411 OS << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1412 return OS.str(); 1413 } 1414 1415 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1416 SourceLocation Loc, 1417 unsigned Flags) { 1418 uint32_t SrcLocStrSize; 1419 llvm::Constant *SrcLocStr; 1420 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1421 Loc.isInvalid()) { 1422 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize); 1423 } else { 1424 std::string FunctionName; 1425 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1426 FunctionName = FD->getQualifiedNameAsString(); 1427 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1428 const char *FileName = PLoc.getFilename(); 1429 unsigned Line = PLoc.getLine(); 1430 unsigned Column = PLoc.getColumn(); 1431 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FunctionName, FileName, Line, 1432 Column, SrcLocStrSize); 1433 } 1434 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1435 return OMPBuilder.getOrCreateIdent( 1436 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags); 1437 } 1438 1439 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1440 SourceLocation Loc) { 1441 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1442 // If the OpenMPIRBuilder is used we need to use it for all thread id calls as 1443 // the clang invariants used below might be broken. 1444 if (CGM.getLangOpts().OpenMPIRBuilder) { 1445 SmallString<128> Buffer; 1446 OMPBuilder.updateToLocation(CGF.Builder.saveIP()); 1447 uint32_t SrcLocStrSize; 1448 auto *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr( 1449 getIdentStringFromSourceLocation(CGF, Loc, Buffer), SrcLocStrSize); 1450 return OMPBuilder.getOrCreateThreadID( 1451 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize)); 1452 } 1453 1454 llvm::Value *ThreadID = nullptr; 1455 // Check whether we've already cached a load of the thread id in this 1456 // function. 1457 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1458 if (I != OpenMPLocThreadIDMap.end()) { 1459 ThreadID = I->second.ThreadID; 1460 if (ThreadID != nullptr) 1461 return ThreadID; 1462 } 1463 // If exceptions are enabled, do not use parameter to avoid possible crash. 1464 if (auto *OMPRegionInfo = 1465 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1466 if (OMPRegionInfo->getThreadIDVariable()) { 1467 // Check if this an outlined function with thread id passed as argument. 1468 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1469 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1470 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1471 !CGF.getLangOpts().CXXExceptions || 1472 CGF.Builder.GetInsertBlock() == TopBlock || 1473 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1474 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1475 TopBlock || 1476 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1477 CGF.Builder.GetInsertBlock()) { 1478 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1479 // If value loaded in entry block, cache it and use it everywhere in 1480 // function. 1481 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1482 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1483 Elem.second.ThreadID = ThreadID; 1484 } 1485 return ThreadID; 1486 } 1487 } 1488 } 1489 1490 // This is not an outlined function region - need to call __kmpc_int32 1491 // kmpc_global_thread_num(ident_t *loc). 1492 // Generate thread id value and cache this value for use across the 1493 // function. 1494 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1495 if (!Elem.second.ServiceInsertPt) 1496 setLocThreadIdInsertPt(CGF); 1497 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1498 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1499 llvm::CallInst *Call = CGF.Builder.CreateCall( 1500 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 1501 OMPRTL___kmpc_global_thread_num), 1502 emitUpdateLocation(CGF, Loc)); 1503 Call->setCallingConv(CGF.getRuntimeCC()); 1504 Elem.second.ThreadID = Call; 1505 return Call; 1506 } 1507 1508 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1509 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1510 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1511 clearLocThreadIdInsertPt(CGF); 1512 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1513 } 1514 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1515 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1516 UDRMap.erase(D); 1517 FunctionUDRMap.erase(CGF.CurFn); 1518 } 1519 auto I = FunctionUDMMap.find(CGF.CurFn); 1520 if (I != FunctionUDMMap.end()) { 1521 for(const auto *D : I->second) 1522 UDMMap.erase(D); 1523 FunctionUDMMap.erase(I); 1524 } 1525 LastprivateConditionalToTypes.erase(CGF.CurFn); 1526 FunctionToUntiedTaskStackMap.erase(CGF.CurFn); 1527 } 1528 1529 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1530 return OMPBuilder.IdentPtr; 1531 } 1532 1533 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1534 if (!Kmpc_MicroTy) { 1535 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1536 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1537 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1538 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1539 } 1540 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1541 } 1542 1543 llvm::FunctionCallee 1544 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned, 1545 bool IsGPUDistribute) { 1546 assert((IVSize == 32 || IVSize == 64) && 1547 "IV size is not compatible with the omp runtime"); 1548 StringRef Name; 1549 if (IsGPUDistribute) 1550 Name = IVSize == 32 ? (IVSigned ? "__kmpc_distribute_static_init_4" 1551 : "__kmpc_distribute_static_init_4u") 1552 : (IVSigned ? "__kmpc_distribute_static_init_8" 1553 : "__kmpc_distribute_static_init_8u"); 1554 else 1555 Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 1556 : "__kmpc_for_static_init_4u") 1557 : (IVSigned ? "__kmpc_for_static_init_8" 1558 : "__kmpc_for_static_init_8u"); 1559 1560 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1561 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1562 llvm::Type *TypeParams[] = { 1563 getIdentTyPointerTy(), // loc 1564 CGM.Int32Ty, // tid 1565 CGM.Int32Ty, // schedtype 1566 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1567 PtrTy, // p_lower 1568 PtrTy, // p_upper 1569 PtrTy, // p_stride 1570 ITy, // incr 1571 ITy // chunk 1572 }; 1573 auto *FnTy = 1574 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1575 return CGM.CreateRuntimeFunction(FnTy, Name); 1576 } 1577 1578 llvm::FunctionCallee 1579 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 1580 assert((IVSize == 32 || IVSize == 64) && 1581 "IV size is not compatible with the omp runtime"); 1582 StringRef Name = 1583 IVSize == 32 1584 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 1585 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 1586 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1587 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 1588 CGM.Int32Ty, // tid 1589 CGM.Int32Ty, // schedtype 1590 ITy, // lower 1591 ITy, // upper 1592 ITy, // stride 1593 ITy // chunk 1594 }; 1595 auto *FnTy = 1596 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1597 return CGM.CreateRuntimeFunction(FnTy, Name); 1598 } 1599 1600 llvm::FunctionCallee 1601 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 1602 assert((IVSize == 32 || IVSize == 64) && 1603 "IV size is not compatible with the omp runtime"); 1604 StringRef Name = 1605 IVSize == 32 1606 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 1607 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 1608 llvm::Type *TypeParams[] = { 1609 getIdentTyPointerTy(), // loc 1610 CGM.Int32Ty, // tid 1611 }; 1612 auto *FnTy = 1613 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1614 return CGM.CreateRuntimeFunction(FnTy, Name); 1615 } 1616 1617 llvm::FunctionCallee 1618 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 1619 assert((IVSize == 32 || IVSize == 64) && 1620 "IV size is not compatible with the omp runtime"); 1621 StringRef Name = 1622 IVSize == 32 1623 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 1624 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 1625 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1626 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1627 llvm::Type *TypeParams[] = { 1628 getIdentTyPointerTy(), // loc 1629 CGM.Int32Ty, // tid 1630 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1631 PtrTy, // p_lower 1632 PtrTy, // p_upper 1633 PtrTy // p_stride 1634 }; 1635 auto *FnTy = 1636 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1637 return CGM.CreateRuntimeFunction(FnTy, Name); 1638 } 1639 1640 /// Obtain information that uniquely identifies a target entry. This 1641 /// consists of the file and device IDs as well as line number associated with 1642 /// the relevant entry source location. 1643 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 1644 unsigned &DeviceID, unsigned &FileID, 1645 unsigned &LineNum) { 1646 SourceManager &SM = C.getSourceManager(); 1647 1648 // The loc should be always valid and have a file ID (the user cannot use 1649 // #pragma directives in macros) 1650 1651 assert(Loc.isValid() && "Source location is expected to be always valid."); 1652 1653 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 1654 assert(PLoc.isValid() && "Source location is expected to be always valid."); 1655 1656 llvm::sys::fs::UniqueID ID; 1657 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) { 1658 PLoc = SM.getPresumedLoc(Loc, /*UseLineDirectives=*/false); 1659 assert(PLoc.isValid() && "Source location is expected to be always valid."); 1660 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 1661 SM.getDiagnostics().Report(diag::err_cannot_open_file) 1662 << PLoc.getFilename() << EC.message(); 1663 } 1664 1665 DeviceID = ID.getDevice(); 1666 FileID = ID.getFile(); 1667 LineNum = PLoc.getLine(); 1668 } 1669 1670 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 1671 if (CGM.getLangOpts().OpenMPSimd) 1672 return Address::invalid(); 1673 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1674 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1675 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 1676 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1677 HasRequiresUnifiedSharedMemory))) { 1678 SmallString<64> PtrName; 1679 { 1680 llvm::raw_svector_ostream OS(PtrName); 1681 OS << CGM.getMangledName(GlobalDecl(VD)); 1682 if (!VD->isExternallyVisible()) { 1683 unsigned DeviceID, FileID, Line; 1684 getTargetEntryUniqueInfo(CGM.getContext(), 1685 VD->getCanonicalDecl()->getBeginLoc(), 1686 DeviceID, FileID, Line); 1687 OS << llvm::format("_%x", FileID); 1688 } 1689 OS << "_decl_tgt_ref_ptr"; 1690 } 1691 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 1692 if (!Ptr) { 1693 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 1694 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 1695 PtrName); 1696 1697 auto *GV = cast<llvm::GlobalVariable>(Ptr); 1698 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 1699 1700 if (!CGM.getLangOpts().OpenMPIsDevice) 1701 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 1702 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 1703 } 1704 return Address::deprecated(Ptr, CGM.getContext().getDeclAlign(VD)); 1705 } 1706 return Address::invalid(); 1707 } 1708 1709 llvm::Constant * 1710 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 1711 assert(!CGM.getLangOpts().OpenMPUseTLS || 1712 !CGM.getContext().getTargetInfo().isTLSSupported()); 1713 // Lookup the entry, lazily creating it if necessary. 1714 std::string Suffix = getName({"cache", ""}); 1715 return getOrCreateInternalVariable( 1716 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 1717 } 1718 1719 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 1720 const VarDecl *VD, 1721 Address VDAddr, 1722 SourceLocation Loc) { 1723 if (CGM.getLangOpts().OpenMPUseTLS && 1724 CGM.getContext().getTargetInfo().isTLSSupported()) 1725 return VDAddr; 1726 1727 llvm::Type *VarTy = VDAddr.getElementType(); 1728 llvm::Value *Args[] = { 1729 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1730 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy), 1731 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 1732 getOrCreateThreadPrivateCache(VD)}; 1733 return Address::deprecated( 1734 CGF.EmitRuntimeCall( 1735 OMPBuilder.getOrCreateRuntimeFunction( 1736 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 1737 Args), 1738 VDAddr.getAlignment()); 1739 } 1740 1741 void CGOpenMPRuntime::emitThreadPrivateVarInit( 1742 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 1743 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 1744 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 1745 // library. 1746 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 1747 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1748 CGM.getModule(), OMPRTL___kmpc_global_thread_num), 1749 OMPLoc); 1750 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 1751 // to register constructor/destructor for variable. 1752 llvm::Value *Args[] = { 1753 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 1754 Ctor, CopyCtor, Dtor}; 1755 CGF.EmitRuntimeCall( 1756 OMPBuilder.getOrCreateRuntimeFunction( 1757 CGM.getModule(), OMPRTL___kmpc_threadprivate_register), 1758 Args); 1759 } 1760 1761 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 1762 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 1763 bool PerformInit, CodeGenFunction *CGF) { 1764 if (CGM.getLangOpts().OpenMPUseTLS && 1765 CGM.getContext().getTargetInfo().isTLSSupported()) 1766 return nullptr; 1767 1768 VD = VD->getDefinition(CGM.getContext()); 1769 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 1770 QualType ASTTy = VD->getType(); 1771 1772 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 1773 const Expr *Init = VD->getAnyInitializer(); 1774 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1775 // Generate function that re-emits the declaration's initializer into the 1776 // threadprivate copy of the variable VD 1777 CodeGenFunction CtorCGF(CGM); 1778 FunctionArgList Args; 1779 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1780 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1781 ImplicitParamDecl::Other); 1782 Args.push_back(&Dst); 1783 1784 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1785 CGM.getContext().VoidPtrTy, Args); 1786 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1787 std::string Name = getName({"__kmpc_global_ctor_", ""}); 1788 llvm::Function *Fn = 1789 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1790 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 1791 Args, Loc, Loc); 1792 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 1793 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1794 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1795 Address Arg = Address::deprecated(ArgVal, VDAddr.getAlignment()); 1796 Arg = CtorCGF.Builder.CreateElementBitCast( 1797 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 1798 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 1799 /*IsInitializer=*/true); 1800 ArgVal = CtorCGF.EmitLoadOfScalar( 1801 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1802 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1803 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 1804 CtorCGF.FinishFunction(); 1805 Ctor = Fn; 1806 } 1807 if (VD->getType().isDestructedType() != QualType::DK_none) { 1808 // Generate function that emits destructor call for the threadprivate copy 1809 // of the variable VD 1810 CodeGenFunction DtorCGF(CGM); 1811 FunctionArgList Args; 1812 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1813 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1814 ImplicitParamDecl::Other); 1815 Args.push_back(&Dst); 1816 1817 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1818 CGM.getContext().VoidTy, Args); 1819 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1820 std::string Name = getName({"__kmpc_global_dtor_", ""}); 1821 llvm::Function *Fn = 1822 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1823 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1824 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 1825 Loc, Loc); 1826 // Create a scope with an artificial location for the body of this function. 1827 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1828 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 1829 DtorCGF.GetAddrOfLocalVar(&Dst), 1830 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 1831 DtorCGF.emitDestroy(Address::deprecated(ArgVal, VDAddr.getAlignment()), 1832 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1833 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1834 DtorCGF.FinishFunction(); 1835 Dtor = Fn; 1836 } 1837 // Do not emit init function if it is not required. 1838 if (!Ctor && !Dtor) 1839 return nullptr; 1840 1841 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1842 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 1843 /*isVarArg=*/false) 1844 ->getPointerTo(); 1845 // Copying constructor for the threadprivate variable. 1846 // Must be NULL - reserved by runtime, but currently it requires that this 1847 // parameter is always NULL. Otherwise it fires assertion. 1848 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 1849 if (Ctor == nullptr) { 1850 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1851 /*isVarArg=*/false) 1852 ->getPointerTo(); 1853 Ctor = llvm::Constant::getNullValue(CtorTy); 1854 } 1855 if (Dtor == nullptr) { 1856 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 1857 /*isVarArg=*/false) 1858 ->getPointerTo(); 1859 Dtor = llvm::Constant::getNullValue(DtorTy); 1860 } 1861 if (!CGF) { 1862 auto *InitFunctionTy = 1863 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 1864 std::string Name = getName({"__omp_threadprivate_init_", ""}); 1865 llvm::Function *InitFunction = CGM.CreateGlobalInitOrCleanUpFunction( 1866 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 1867 CodeGenFunction InitCGF(CGM); 1868 FunctionArgList ArgList; 1869 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 1870 CGM.getTypes().arrangeNullaryFunction(), ArgList, 1871 Loc, Loc); 1872 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1873 InitCGF.FinishFunction(); 1874 return InitFunction; 1875 } 1876 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1877 } 1878 return nullptr; 1879 } 1880 1881 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 1882 llvm::GlobalVariable *Addr, 1883 bool PerformInit) { 1884 if (CGM.getLangOpts().OMPTargetTriples.empty() && 1885 !CGM.getLangOpts().OpenMPIsDevice) 1886 return false; 1887 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1888 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1889 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 1890 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1891 HasRequiresUnifiedSharedMemory)) 1892 return CGM.getLangOpts().OpenMPIsDevice; 1893 VD = VD->getDefinition(CGM.getContext()); 1894 assert(VD && "Unknown VarDecl"); 1895 1896 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 1897 return CGM.getLangOpts().OpenMPIsDevice; 1898 1899 QualType ASTTy = VD->getType(); 1900 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 1901 1902 // Produce the unique prefix to identify the new target regions. We use 1903 // the source location of the variable declaration which we know to not 1904 // conflict with any target region. 1905 unsigned DeviceID; 1906 unsigned FileID; 1907 unsigned Line; 1908 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 1909 SmallString<128> Buffer, Out; 1910 { 1911 llvm::raw_svector_ostream OS(Buffer); 1912 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 1913 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 1914 } 1915 1916 const Expr *Init = VD->getAnyInitializer(); 1917 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1918 llvm::Constant *Ctor; 1919 llvm::Constant *ID; 1920 if (CGM.getLangOpts().OpenMPIsDevice) { 1921 // Generate function that re-emits the declaration's initializer into 1922 // the threadprivate copy of the variable VD 1923 CodeGenFunction CtorCGF(CGM); 1924 1925 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1926 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1927 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1928 FTy, Twine(Buffer, "_ctor"), FI, Loc); 1929 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 1930 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1931 FunctionArgList(), Loc, Loc); 1932 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 1933 llvm::Constant *AddrInAS0 = Addr; 1934 if (Addr->getAddressSpace() != 0) 1935 AddrInAS0 = llvm::ConstantExpr::getAddrSpaceCast( 1936 Addr, llvm::PointerType::getWithSamePointeeType( 1937 cast<llvm::PointerType>(Addr->getType()), 0)); 1938 CtorCGF.EmitAnyExprToMem( 1939 Init, 1940 Address::deprecated(AddrInAS0, CGM.getContext().getDeclAlign(VD)), 1941 Init->getType().getQualifiers(), 1942 /*IsInitializer=*/true); 1943 CtorCGF.FinishFunction(); 1944 Ctor = Fn; 1945 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1946 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 1947 } else { 1948 Ctor = new llvm::GlobalVariable( 1949 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1950 llvm::GlobalValue::PrivateLinkage, 1951 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 1952 ID = Ctor; 1953 } 1954 1955 // Register the information for the entry associated with the constructor. 1956 Out.clear(); 1957 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 1958 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 1959 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 1960 } 1961 if (VD->getType().isDestructedType() != QualType::DK_none) { 1962 llvm::Constant *Dtor; 1963 llvm::Constant *ID; 1964 if (CGM.getLangOpts().OpenMPIsDevice) { 1965 // Generate function that emits destructor call for the threadprivate 1966 // copy of the variable VD 1967 CodeGenFunction DtorCGF(CGM); 1968 1969 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1970 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1971 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1972 FTy, Twine(Buffer, "_dtor"), FI, Loc); 1973 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1974 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1975 FunctionArgList(), Loc, Loc); 1976 // Create a scope with an artificial location for the body of this 1977 // function. 1978 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1979 llvm::Constant *AddrInAS0 = Addr; 1980 if (Addr->getAddressSpace() != 0) 1981 AddrInAS0 = llvm::ConstantExpr::getAddrSpaceCast( 1982 Addr, llvm::PointerType::getWithSamePointeeType( 1983 cast<llvm::PointerType>(Addr->getType()), 0)); 1984 DtorCGF.emitDestroy( 1985 Address::deprecated(AddrInAS0, CGM.getContext().getDeclAlign(VD)), 1986 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1987 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1988 DtorCGF.FinishFunction(); 1989 Dtor = Fn; 1990 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1991 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 1992 } else { 1993 Dtor = new llvm::GlobalVariable( 1994 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1995 llvm::GlobalValue::PrivateLinkage, 1996 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 1997 ID = Dtor; 1998 } 1999 // Register the information for the entry associated with the destructor. 2000 Out.clear(); 2001 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2002 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 2003 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 2004 } 2005 return CGM.getLangOpts().OpenMPIsDevice; 2006 } 2007 2008 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2009 QualType VarType, 2010 StringRef Name) { 2011 std::string Suffix = getName({"artificial", ""}); 2012 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2013 llvm::GlobalVariable *GAddr = 2014 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 2015 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 2016 CGM.getTarget().isTLSSupported()) { 2017 GAddr->setThreadLocal(/*Val=*/true); 2018 return Address(GAddr, GAddr->getValueType(), 2019 CGM.getContext().getTypeAlignInChars(VarType)); 2020 } 2021 std::string CacheSuffix = getName({"cache", ""}); 2022 llvm::Value *Args[] = { 2023 emitUpdateLocation(CGF, SourceLocation()), 2024 getThreadID(CGF, SourceLocation()), 2025 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 2026 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 2027 /*isSigned=*/false), 2028 getOrCreateInternalVariable( 2029 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 2030 return Address( 2031 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2032 CGF.EmitRuntimeCall( 2033 OMPBuilder.getOrCreateRuntimeFunction( 2034 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 2035 Args), 2036 VarLVType->getPointerTo(/*AddrSpace=*/0)), 2037 VarLVType, CGM.getContext().getTypeAlignInChars(VarType)); 2038 } 2039 2040 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 2041 const RegionCodeGenTy &ThenGen, 2042 const RegionCodeGenTy &ElseGen) { 2043 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 2044 2045 // If the condition constant folds and can be elided, try to avoid emitting 2046 // the condition and the dead arm of the if/else. 2047 bool CondConstant; 2048 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 2049 if (CondConstant) 2050 ThenGen(CGF); 2051 else 2052 ElseGen(CGF); 2053 return; 2054 } 2055 2056 // Otherwise, the condition did not fold, or we couldn't elide it. Just 2057 // emit the conditional branch. 2058 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2059 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 2060 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 2061 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 2062 2063 // Emit the 'then' code. 2064 CGF.EmitBlock(ThenBlock); 2065 ThenGen(CGF); 2066 CGF.EmitBranch(ContBlock); 2067 // Emit the 'else' code if present. 2068 // There is no need to emit line number for unconditional branch. 2069 (void)ApplyDebugLocation::CreateEmpty(CGF); 2070 CGF.EmitBlock(ElseBlock); 2071 ElseGen(CGF); 2072 // There is no need to emit line number for unconditional branch. 2073 (void)ApplyDebugLocation::CreateEmpty(CGF); 2074 CGF.EmitBranch(ContBlock); 2075 // Emit the continuation block for code after the if. 2076 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 2077 } 2078 2079 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 2080 llvm::Function *OutlinedFn, 2081 ArrayRef<llvm::Value *> CapturedVars, 2082 const Expr *IfCond, 2083 llvm::Value *NumThreads) { 2084 if (!CGF.HaveInsertPoint()) 2085 return; 2086 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 2087 auto &M = CGM.getModule(); 2088 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc, 2089 this](CodeGenFunction &CGF, PrePostActionTy &) { 2090 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 2091 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2092 llvm::Value *Args[] = { 2093 RTLoc, 2094 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 2095 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 2096 llvm::SmallVector<llvm::Value *, 16> RealArgs; 2097 RealArgs.append(std::begin(Args), std::end(Args)); 2098 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 2099 2100 llvm::FunctionCallee RTLFn = 2101 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call); 2102 CGF.EmitRuntimeCall(RTLFn, RealArgs); 2103 }; 2104 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc, 2105 this](CodeGenFunction &CGF, PrePostActionTy &) { 2106 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2107 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 2108 // Build calls: 2109 // __kmpc_serialized_parallel(&Loc, GTid); 2110 llvm::Value *Args[] = {RTLoc, ThreadID}; 2111 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2112 M, OMPRTL___kmpc_serialized_parallel), 2113 Args); 2114 2115 // OutlinedFn(>id, &zero_bound, CapturedStruct); 2116 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 2117 Address ZeroAddrBound = 2118 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 2119 /*Name=*/".bound.zero.addr"); 2120 CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddrBound); 2121 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 2122 // ThreadId for serialized parallels is 0. 2123 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 2124 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 2125 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 2126 2127 // Ensure we do not inline the function. This is trivially true for the ones 2128 // passed to __kmpc_fork_call but the ones called in serialized regions 2129 // could be inlined. This is not a perfect but it is closer to the invariant 2130 // we want, namely, every data environment starts with a new function. 2131 // TODO: We should pass the if condition to the runtime function and do the 2132 // handling there. Much cleaner code. 2133 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline); 2134 OutlinedFn->addFnAttr(llvm::Attribute::NoInline); 2135 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 2136 2137 // __kmpc_end_serialized_parallel(&Loc, GTid); 2138 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 2139 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2140 M, OMPRTL___kmpc_end_serialized_parallel), 2141 EndArgs); 2142 }; 2143 if (IfCond) { 2144 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 2145 } else { 2146 RegionCodeGenTy ThenRCG(ThenGen); 2147 ThenRCG(CGF); 2148 } 2149 } 2150 2151 // If we're inside an (outlined) parallel region, use the region info's 2152 // thread-ID variable (it is passed in a first argument of the outlined function 2153 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 2154 // regular serial code region, get thread ID by calling kmp_int32 2155 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 2156 // return the address of that temp. 2157 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 2158 SourceLocation Loc) { 2159 if (auto *OMPRegionInfo = 2160 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2161 if (OMPRegionInfo->getThreadIDVariable()) 2162 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 2163 2164 llvm::Value *ThreadID = getThreadID(CGF, Loc); 2165 QualType Int32Ty = 2166 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 2167 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 2168 CGF.EmitStoreOfScalar(ThreadID, 2169 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 2170 2171 return ThreadIDTemp; 2172 } 2173 2174 llvm::GlobalVariable *CGOpenMPRuntime::getOrCreateInternalVariable( 2175 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 2176 SmallString<256> Buffer; 2177 llvm::raw_svector_ostream Out(Buffer); 2178 Out << Name; 2179 StringRef RuntimeName = Out.str(); 2180 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 2181 if (Elem.second) { 2182 assert(Elem.second->getType()->isOpaqueOrPointeeTypeMatches(Ty) && 2183 "OMP internal variable has different type than requested"); 2184 return &*Elem.second; 2185 } 2186 2187 return Elem.second = new llvm::GlobalVariable( 2188 CGM.getModule(), Ty, /*IsConstant*/ false, 2189 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 2190 Elem.first(), /*InsertBefore=*/nullptr, 2191 llvm::GlobalValue::NotThreadLocal, AddressSpace); 2192 } 2193 2194 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 2195 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 2196 std::string Name = getName({Prefix, "var"}); 2197 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 2198 } 2199 2200 namespace { 2201 /// Common pre(post)-action for different OpenMP constructs. 2202 class CommonActionTy final : public PrePostActionTy { 2203 llvm::FunctionCallee EnterCallee; 2204 ArrayRef<llvm::Value *> EnterArgs; 2205 llvm::FunctionCallee ExitCallee; 2206 ArrayRef<llvm::Value *> ExitArgs; 2207 bool Conditional; 2208 llvm::BasicBlock *ContBlock = nullptr; 2209 2210 public: 2211 CommonActionTy(llvm::FunctionCallee EnterCallee, 2212 ArrayRef<llvm::Value *> EnterArgs, 2213 llvm::FunctionCallee ExitCallee, 2214 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 2215 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 2216 ExitArgs(ExitArgs), Conditional(Conditional) {} 2217 void Enter(CodeGenFunction &CGF) override { 2218 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 2219 if (Conditional) { 2220 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 2221 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2222 ContBlock = CGF.createBasicBlock("omp_if.end"); 2223 // Generate the branch (If-stmt) 2224 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 2225 CGF.EmitBlock(ThenBlock); 2226 } 2227 } 2228 void Done(CodeGenFunction &CGF) { 2229 // Emit the rest of blocks/branches 2230 CGF.EmitBranch(ContBlock); 2231 CGF.EmitBlock(ContBlock, true); 2232 } 2233 void Exit(CodeGenFunction &CGF) override { 2234 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 2235 } 2236 }; 2237 } // anonymous namespace 2238 2239 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 2240 StringRef CriticalName, 2241 const RegionCodeGenTy &CriticalOpGen, 2242 SourceLocation Loc, const Expr *Hint) { 2243 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 2244 // CriticalOpGen(); 2245 // __kmpc_end_critical(ident_t *, gtid, Lock); 2246 // Prepare arguments and build a call to __kmpc_critical 2247 if (!CGF.HaveInsertPoint()) 2248 return; 2249 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2250 getCriticalRegionLock(CriticalName)}; 2251 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 2252 std::end(Args)); 2253 if (Hint) { 2254 EnterArgs.push_back(CGF.Builder.CreateIntCast( 2255 CGF.EmitScalarExpr(Hint), CGM.Int32Ty, /*isSigned=*/false)); 2256 } 2257 CommonActionTy Action( 2258 OMPBuilder.getOrCreateRuntimeFunction( 2259 CGM.getModule(), 2260 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical), 2261 EnterArgs, 2262 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2263 OMPRTL___kmpc_end_critical), 2264 Args); 2265 CriticalOpGen.setAction(Action); 2266 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 2267 } 2268 2269 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 2270 const RegionCodeGenTy &MasterOpGen, 2271 SourceLocation Loc) { 2272 if (!CGF.HaveInsertPoint()) 2273 return; 2274 // if(__kmpc_master(ident_t *, gtid)) { 2275 // MasterOpGen(); 2276 // __kmpc_end_master(ident_t *, gtid); 2277 // } 2278 // Prepare arguments and build a call to __kmpc_master 2279 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2280 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2281 CGM.getModule(), OMPRTL___kmpc_master), 2282 Args, 2283 OMPBuilder.getOrCreateRuntimeFunction( 2284 CGM.getModule(), OMPRTL___kmpc_end_master), 2285 Args, 2286 /*Conditional=*/true); 2287 MasterOpGen.setAction(Action); 2288 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 2289 Action.Done(CGF); 2290 } 2291 2292 void CGOpenMPRuntime::emitMaskedRegion(CodeGenFunction &CGF, 2293 const RegionCodeGenTy &MaskedOpGen, 2294 SourceLocation Loc, const Expr *Filter) { 2295 if (!CGF.HaveInsertPoint()) 2296 return; 2297 // if(__kmpc_masked(ident_t *, gtid, filter)) { 2298 // MaskedOpGen(); 2299 // __kmpc_end_masked(iden_t *, gtid); 2300 // } 2301 // Prepare arguments and build a call to __kmpc_masked 2302 llvm::Value *FilterVal = Filter 2303 ? CGF.EmitScalarExpr(Filter, CGF.Int32Ty) 2304 : llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/0); 2305 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2306 FilterVal}; 2307 llvm::Value *ArgsEnd[] = {emitUpdateLocation(CGF, Loc), 2308 getThreadID(CGF, Loc)}; 2309 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2310 CGM.getModule(), OMPRTL___kmpc_masked), 2311 Args, 2312 OMPBuilder.getOrCreateRuntimeFunction( 2313 CGM.getModule(), OMPRTL___kmpc_end_masked), 2314 ArgsEnd, 2315 /*Conditional=*/true); 2316 MaskedOpGen.setAction(Action); 2317 emitInlinedDirective(CGF, OMPD_masked, MaskedOpGen); 2318 Action.Done(CGF); 2319 } 2320 2321 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 2322 SourceLocation Loc) { 2323 if (!CGF.HaveInsertPoint()) 2324 return; 2325 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2326 OMPBuilder.createTaskyield(CGF.Builder); 2327 } else { 2328 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 2329 llvm::Value *Args[] = { 2330 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2331 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 2332 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2333 CGM.getModule(), OMPRTL___kmpc_omp_taskyield), 2334 Args); 2335 } 2336 2337 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2338 Region->emitUntiedSwitch(CGF); 2339 } 2340 2341 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 2342 const RegionCodeGenTy &TaskgroupOpGen, 2343 SourceLocation Loc) { 2344 if (!CGF.HaveInsertPoint()) 2345 return; 2346 // __kmpc_taskgroup(ident_t *, gtid); 2347 // TaskgroupOpGen(); 2348 // __kmpc_end_taskgroup(ident_t *, gtid); 2349 // Prepare arguments and build a call to __kmpc_taskgroup 2350 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2351 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2352 CGM.getModule(), OMPRTL___kmpc_taskgroup), 2353 Args, 2354 OMPBuilder.getOrCreateRuntimeFunction( 2355 CGM.getModule(), OMPRTL___kmpc_end_taskgroup), 2356 Args); 2357 TaskgroupOpGen.setAction(Action); 2358 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 2359 } 2360 2361 /// Given an array of pointers to variables, project the address of a 2362 /// given variable. 2363 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 2364 unsigned Index, const VarDecl *Var) { 2365 // Pull out the pointer to the variable. 2366 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 2367 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 2368 2369 Address Addr = Address::deprecated(Ptr, CGF.getContext().getDeclAlign(Var)); 2370 Addr = CGF.Builder.CreateElementBitCast( 2371 Addr, CGF.ConvertTypeForMem(Var->getType())); 2372 return Addr; 2373 } 2374 2375 static llvm::Value *emitCopyprivateCopyFunction( 2376 CodeGenModule &CGM, llvm::Type *ArgsType, 2377 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 2378 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 2379 SourceLocation Loc) { 2380 ASTContext &C = CGM.getContext(); 2381 // void copy_func(void *LHSArg, void *RHSArg); 2382 FunctionArgList Args; 2383 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2384 ImplicitParamDecl::Other); 2385 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2386 ImplicitParamDecl::Other); 2387 Args.push_back(&LHSArg); 2388 Args.push_back(&RHSArg); 2389 const auto &CGFI = 2390 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 2391 std::string Name = 2392 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 2393 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 2394 llvm::GlobalValue::InternalLinkage, Name, 2395 &CGM.getModule()); 2396 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 2397 Fn->setDoesNotRecurse(); 2398 CodeGenFunction CGF(CGM); 2399 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 2400 // Dest = (void*[n])(LHSArg); 2401 // Src = (void*[n])(RHSArg); 2402 Address LHS = Address::deprecated( 2403 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2404 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), ArgsType), 2405 CGF.getPointerAlign()); 2406 Address RHS = Address::deprecated( 2407 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2408 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), ArgsType), 2409 CGF.getPointerAlign()); 2410 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 2411 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 2412 // ... 2413 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 2414 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 2415 const auto *DestVar = 2416 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 2417 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 2418 2419 const auto *SrcVar = 2420 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 2421 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 2422 2423 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 2424 QualType Type = VD->getType(); 2425 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 2426 } 2427 CGF.FinishFunction(); 2428 return Fn; 2429 } 2430 2431 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 2432 const RegionCodeGenTy &SingleOpGen, 2433 SourceLocation Loc, 2434 ArrayRef<const Expr *> CopyprivateVars, 2435 ArrayRef<const Expr *> SrcExprs, 2436 ArrayRef<const Expr *> DstExprs, 2437 ArrayRef<const Expr *> AssignmentOps) { 2438 if (!CGF.HaveInsertPoint()) 2439 return; 2440 assert(CopyprivateVars.size() == SrcExprs.size() && 2441 CopyprivateVars.size() == DstExprs.size() && 2442 CopyprivateVars.size() == AssignmentOps.size()); 2443 ASTContext &C = CGM.getContext(); 2444 // int32 did_it = 0; 2445 // if(__kmpc_single(ident_t *, gtid)) { 2446 // SingleOpGen(); 2447 // __kmpc_end_single(ident_t *, gtid); 2448 // did_it = 1; 2449 // } 2450 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2451 // <copy_func>, did_it); 2452 2453 Address DidIt = Address::invalid(); 2454 if (!CopyprivateVars.empty()) { 2455 // int32 did_it = 0; 2456 QualType KmpInt32Ty = 2457 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2458 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 2459 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 2460 } 2461 // Prepare arguments and build a call to __kmpc_single 2462 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2463 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2464 CGM.getModule(), OMPRTL___kmpc_single), 2465 Args, 2466 OMPBuilder.getOrCreateRuntimeFunction( 2467 CGM.getModule(), OMPRTL___kmpc_end_single), 2468 Args, 2469 /*Conditional=*/true); 2470 SingleOpGen.setAction(Action); 2471 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 2472 if (DidIt.isValid()) { 2473 // did_it = 1; 2474 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 2475 } 2476 Action.Done(CGF); 2477 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2478 // <copy_func>, did_it); 2479 if (DidIt.isValid()) { 2480 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 2481 QualType CopyprivateArrayTy = C.getConstantArrayType( 2482 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 2483 /*IndexTypeQuals=*/0); 2484 // Create a list of all private variables for copyprivate. 2485 Address CopyprivateList = 2486 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 2487 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 2488 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 2489 CGF.Builder.CreateStore( 2490 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2491 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 2492 CGF.VoidPtrTy), 2493 Elem); 2494 } 2495 // Build function that copies private values from single region to all other 2496 // threads in the corresponding parallel region. 2497 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 2498 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 2499 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 2500 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 2501 Address CL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2502 CopyprivateList, CGF.VoidPtrTy, CGF.Int8Ty); 2503 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 2504 llvm::Value *Args[] = { 2505 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 2506 getThreadID(CGF, Loc), // i32 <gtid> 2507 BufSize, // size_t <buf_size> 2508 CL.getPointer(), // void *<copyprivate list> 2509 CpyFn, // void (*) (void *, void *) <copy_func> 2510 DidItVal // i32 did_it 2511 }; 2512 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2513 CGM.getModule(), OMPRTL___kmpc_copyprivate), 2514 Args); 2515 } 2516 } 2517 2518 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 2519 const RegionCodeGenTy &OrderedOpGen, 2520 SourceLocation Loc, bool IsThreads) { 2521 if (!CGF.HaveInsertPoint()) 2522 return; 2523 // __kmpc_ordered(ident_t *, gtid); 2524 // OrderedOpGen(); 2525 // __kmpc_end_ordered(ident_t *, gtid); 2526 // Prepare arguments and build a call to __kmpc_ordered 2527 if (IsThreads) { 2528 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2529 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2530 CGM.getModule(), OMPRTL___kmpc_ordered), 2531 Args, 2532 OMPBuilder.getOrCreateRuntimeFunction( 2533 CGM.getModule(), OMPRTL___kmpc_end_ordered), 2534 Args); 2535 OrderedOpGen.setAction(Action); 2536 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2537 return; 2538 } 2539 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2540 } 2541 2542 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 2543 unsigned Flags; 2544 if (Kind == OMPD_for) 2545 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 2546 else if (Kind == OMPD_sections) 2547 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 2548 else if (Kind == OMPD_single) 2549 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 2550 else if (Kind == OMPD_barrier) 2551 Flags = OMP_IDENT_BARRIER_EXPL; 2552 else 2553 Flags = OMP_IDENT_BARRIER_IMPL; 2554 return Flags; 2555 } 2556 2557 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 2558 CodeGenFunction &CGF, const OMPLoopDirective &S, 2559 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 2560 // Check if the loop directive is actually a doacross loop directive. In this 2561 // case choose static, 1 schedule. 2562 if (llvm::any_of( 2563 S.getClausesOfKind<OMPOrderedClause>(), 2564 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 2565 ScheduleKind = OMPC_SCHEDULE_static; 2566 // Chunk size is 1 in this case. 2567 llvm::APInt ChunkSize(32, 1); 2568 ChunkExpr = IntegerLiteral::Create( 2569 CGF.getContext(), ChunkSize, 2570 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 2571 SourceLocation()); 2572 } 2573 } 2574 2575 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 2576 OpenMPDirectiveKind Kind, bool EmitChecks, 2577 bool ForceSimpleCall) { 2578 // Check if we should use the OMPBuilder 2579 auto *OMPRegionInfo = 2580 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 2581 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2582 CGF.Builder.restoreIP(OMPBuilder.createBarrier( 2583 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 2584 return; 2585 } 2586 2587 if (!CGF.HaveInsertPoint()) 2588 return; 2589 // Build call __kmpc_cancel_barrier(loc, thread_id); 2590 // Build call __kmpc_barrier(loc, thread_id); 2591 unsigned Flags = getDefaultFlagsForBarriers(Kind); 2592 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 2593 // thread_id); 2594 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 2595 getThreadID(CGF, Loc)}; 2596 if (OMPRegionInfo) { 2597 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 2598 llvm::Value *Result = CGF.EmitRuntimeCall( 2599 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2600 OMPRTL___kmpc_cancel_barrier), 2601 Args); 2602 if (EmitChecks) { 2603 // if (__kmpc_cancel_barrier()) { 2604 // exit from construct; 2605 // } 2606 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 2607 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 2608 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 2609 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 2610 CGF.EmitBlock(ExitBB); 2611 // exit from construct; 2612 CodeGenFunction::JumpDest CancelDestination = 2613 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 2614 CGF.EmitBranchThroughCleanup(CancelDestination); 2615 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 2616 } 2617 return; 2618 } 2619 } 2620 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2621 CGM.getModule(), OMPRTL___kmpc_barrier), 2622 Args); 2623 } 2624 2625 /// Map the OpenMP loop schedule to the runtime enumeration. 2626 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 2627 bool Chunked, bool Ordered) { 2628 switch (ScheduleKind) { 2629 case OMPC_SCHEDULE_static: 2630 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 2631 : (Ordered ? OMP_ord_static : OMP_sch_static); 2632 case OMPC_SCHEDULE_dynamic: 2633 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 2634 case OMPC_SCHEDULE_guided: 2635 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 2636 case OMPC_SCHEDULE_runtime: 2637 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 2638 case OMPC_SCHEDULE_auto: 2639 return Ordered ? OMP_ord_auto : OMP_sch_auto; 2640 case OMPC_SCHEDULE_unknown: 2641 assert(!Chunked && "chunk was specified but schedule kind not known"); 2642 return Ordered ? OMP_ord_static : OMP_sch_static; 2643 } 2644 llvm_unreachable("Unexpected runtime schedule"); 2645 } 2646 2647 /// Map the OpenMP distribute schedule to the runtime enumeration. 2648 static OpenMPSchedType 2649 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 2650 // only static is allowed for dist_schedule 2651 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 2652 } 2653 2654 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 2655 bool Chunked) const { 2656 OpenMPSchedType Schedule = 2657 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2658 return Schedule == OMP_sch_static; 2659 } 2660 2661 bool CGOpenMPRuntime::isStaticNonchunked( 2662 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2663 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2664 return Schedule == OMP_dist_sch_static; 2665 } 2666 2667 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 2668 bool Chunked) const { 2669 OpenMPSchedType Schedule = 2670 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2671 return Schedule == OMP_sch_static_chunked; 2672 } 2673 2674 bool CGOpenMPRuntime::isStaticChunked( 2675 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2676 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2677 return Schedule == OMP_dist_sch_static_chunked; 2678 } 2679 2680 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 2681 OpenMPSchedType Schedule = 2682 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 2683 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 2684 return Schedule != OMP_sch_static; 2685 } 2686 2687 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 2688 OpenMPScheduleClauseModifier M1, 2689 OpenMPScheduleClauseModifier M2) { 2690 int Modifier = 0; 2691 switch (M1) { 2692 case OMPC_SCHEDULE_MODIFIER_monotonic: 2693 Modifier = OMP_sch_modifier_monotonic; 2694 break; 2695 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2696 Modifier = OMP_sch_modifier_nonmonotonic; 2697 break; 2698 case OMPC_SCHEDULE_MODIFIER_simd: 2699 if (Schedule == OMP_sch_static_chunked) 2700 Schedule = OMP_sch_static_balanced_chunked; 2701 break; 2702 case OMPC_SCHEDULE_MODIFIER_last: 2703 case OMPC_SCHEDULE_MODIFIER_unknown: 2704 break; 2705 } 2706 switch (M2) { 2707 case OMPC_SCHEDULE_MODIFIER_monotonic: 2708 Modifier = OMP_sch_modifier_monotonic; 2709 break; 2710 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2711 Modifier = OMP_sch_modifier_nonmonotonic; 2712 break; 2713 case OMPC_SCHEDULE_MODIFIER_simd: 2714 if (Schedule == OMP_sch_static_chunked) 2715 Schedule = OMP_sch_static_balanced_chunked; 2716 break; 2717 case OMPC_SCHEDULE_MODIFIER_last: 2718 case OMPC_SCHEDULE_MODIFIER_unknown: 2719 break; 2720 } 2721 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 2722 // If the static schedule kind is specified or if the ordered clause is 2723 // specified, and if the nonmonotonic modifier is not specified, the effect is 2724 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 2725 // modifier is specified, the effect is as if the nonmonotonic modifier is 2726 // specified. 2727 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 2728 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 2729 Schedule == OMP_sch_static_balanced_chunked || 2730 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 2731 Schedule == OMP_dist_sch_static_chunked || 2732 Schedule == OMP_dist_sch_static)) 2733 Modifier = OMP_sch_modifier_nonmonotonic; 2734 } 2735 return Schedule | Modifier; 2736 } 2737 2738 void CGOpenMPRuntime::emitForDispatchInit( 2739 CodeGenFunction &CGF, SourceLocation Loc, 2740 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 2741 bool Ordered, const DispatchRTInput &DispatchValues) { 2742 if (!CGF.HaveInsertPoint()) 2743 return; 2744 OpenMPSchedType Schedule = getRuntimeSchedule( 2745 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 2746 assert(Ordered || 2747 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 2748 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 2749 Schedule != OMP_sch_static_balanced_chunked)); 2750 // Call __kmpc_dispatch_init( 2751 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 2752 // kmp_int[32|64] lower, kmp_int[32|64] upper, 2753 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 2754 2755 // If the Chunk was not specified in the clause - use default value 1. 2756 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 2757 : CGF.Builder.getIntN(IVSize, 1); 2758 llvm::Value *Args[] = { 2759 emitUpdateLocation(CGF, Loc), 2760 getThreadID(CGF, Loc), 2761 CGF.Builder.getInt32(addMonoNonMonoModifier( 2762 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 2763 DispatchValues.LB, // Lower 2764 DispatchValues.UB, // Upper 2765 CGF.Builder.getIntN(IVSize, 1), // Stride 2766 Chunk // Chunk 2767 }; 2768 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 2769 } 2770 2771 static void emitForStaticInitCall( 2772 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 2773 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 2774 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 2775 const CGOpenMPRuntime::StaticRTInput &Values) { 2776 if (!CGF.HaveInsertPoint()) 2777 return; 2778 2779 assert(!Values.Ordered); 2780 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 2781 Schedule == OMP_sch_static_balanced_chunked || 2782 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 2783 Schedule == OMP_dist_sch_static || 2784 Schedule == OMP_dist_sch_static_chunked); 2785 2786 // Call __kmpc_for_static_init( 2787 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 2788 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 2789 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 2790 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 2791 llvm::Value *Chunk = Values.Chunk; 2792 if (Chunk == nullptr) { 2793 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 2794 Schedule == OMP_dist_sch_static) && 2795 "expected static non-chunked schedule"); 2796 // If the Chunk was not specified in the clause - use default value 1. 2797 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 2798 } else { 2799 assert((Schedule == OMP_sch_static_chunked || 2800 Schedule == OMP_sch_static_balanced_chunked || 2801 Schedule == OMP_ord_static_chunked || 2802 Schedule == OMP_dist_sch_static_chunked) && 2803 "expected static chunked schedule"); 2804 } 2805 llvm::Value *Args[] = { 2806 UpdateLocation, 2807 ThreadId, 2808 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 2809 M2)), // Schedule type 2810 Values.IL.getPointer(), // &isLastIter 2811 Values.LB.getPointer(), // &LB 2812 Values.UB.getPointer(), // &UB 2813 Values.ST.getPointer(), // &Stride 2814 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 2815 Chunk // Chunk 2816 }; 2817 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 2818 } 2819 2820 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 2821 SourceLocation Loc, 2822 OpenMPDirectiveKind DKind, 2823 const OpenMPScheduleTy &ScheduleKind, 2824 const StaticRTInput &Values) { 2825 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 2826 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 2827 assert(isOpenMPWorksharingDirective(DKind) && 2828 "Expected loop-based or sections-based directive."); 2829 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 2830 isOpenMPLoopDirective(DKind) 2831 ? OMP_IDENT_WORK_LOOP 2832 : OMP_IDENT_WORK_SECTIONS); 2833 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2834 llvm::FunctionCallee StaticInitFunction = 2835 createForStaticInitFunction(Values.IVSize, Values.IVSigned, false); 2836 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2837 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2838 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 2839 } 2840 2841 void CGOpenMPRuntime::emitDistributeStaticInit( 2842 CodeGenFunction &CGF, SourceLocation Loc, 2843 OpenMPDistScheduleClauseKind SchedKind, 2844 const CGOpenMPRuntime::StaticRTInput &Values) { 2845 OpenMPSchedType ScheduleNum = 2846 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 2847 llvm::Value *UpdatedLocation = 2848 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 2849 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2850 llvm::FunctionCallee StaticInitFunction; 2851 bool isGPUDistribute = 2852 CGM.getLangOpts().OpenMPIsDevice && 2853 (CGM.getTriple().isAMDGCN() || CGM.getTriple().isNVPTX()); 2854 StaticInitFunction = createForStaticInitFunction( 2855 Values.IVSize, Values.IVSigned, isGPUDistribute); 2856 2857 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2858 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 2859 OMPC_SCHEDULE_MODIFIER_unknown, Values); 2860 } 2861 2862 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 2863 SourceLocation Loc, 2864 OpenMPDirectiveKind DKind) { 2865 if (!CGF.HaveInsertPoint()) 2866 return; 2867 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 2868 llvm::Value *Args[] = { 2869 emitUpdateLocation(CGF, Loc, 2870 isOpenMPDistributeDirective(DKind) 2871 ? OMP_IDENT_WORK_DISTRIBUTE 2872 : isOpenMPLoopDirective(DKind) 2873 ? OMP_IDENT_WORK_LOOP 2874 : OMP_IDENT_WORK_SECTIONS), 2875 getThreadID(CGF, Loc)}; 2876 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2877 if (isOpenMPDistributeDirective(DKind) && CGM.getLangOpts().OpenMPIsDevice && 2878 (CGM.getTriple().isAMDGCN() || CGM.getTriple().isNVPTX())) 2879 CGF.EmitRuntimeCall( 2880 OMPBuilder.getOrCreateRuntimeFunction( 2881 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini), 2882 Args); 2883 else 2884 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2885 CGM.getModule(), OMPRTL___kmpc_for_static_fini), 2886 Args); 2887 } 2888 2889 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 2890 SourceLocation Loc, 2891 unsigned IVSize, 2892 bool IVSigned) { 2893 if (!CGF.HaveInsertPoint()) 2894 return; 2895 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 2896 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2897 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 2898 } 2899 2900 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 2901 SourceLocation Loc, unsigned IVSize, 2902 bool IVSigned, Address IL, 2903 Address LB, Address UB, 2904 Address ST) { 2905 // Call __kmpc_dispatch_next( 2906 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 2907 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 2908 // kmp_int[32|64] *p_stride); 2909 llvm::Value *Args[] = { 2910 emitUpdateLocation(CGF, Loc), 2911 getThreadID(CGF, Loc), 2912 IL.getPointer(), // &isLastIter 2913 LB.getPointer(), // &Lower 2914 UB.getPointer(), // &Upper 2915 ST.getPointer() // &Stride 2916 }; 2917 llvm::Value *Call = 2918 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 2919 return CGF.EmitScalarConversion( 2920 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 2921 CGF.getContext().BoolTy, Loc); 2922 } 2923 2924 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 2925 llvm::Value *NumThreads, 2926 SourceLocation Loc) { 2927 if (!CGF.HaveInsertPoint()) 2928 return; 2929 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 2930 llvm::Value *Args[] = { 2931 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2932 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 2933 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2934 CGM.getModule(), OMPRTL___kmpc_push_num_threads), 2935 Args); 2936 } 2937 2938 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 2939 ProcBindKind ProcBind, 2940 SourceLocation Loc) { 2941 if (!CGF.HaveInsertPoint()) 2942 return; 2943 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 2944 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 2945 llvm::Value *Args[] = { 2946 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2947 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 2948 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2949 CGM.getModule(), OMPRTL___kmpc_push_proc_bind), 2950 Args); 2951 } 2952 2953 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 2954 SourceLocation Loc, llvm::AtomicOrdering AO) { 2955 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2956 OMPBuilder.createFlush(CGF.Builder); 2957 } else { 2958 if (!CGF.HaveInsertPoint()) 2959 return; 2960 // Build call void __kmpc_flush(ident_t *loc) 2961 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2962 CGM.getModule(), OMPRTL___kmpc_flush), 2963 emitUpdateLocation(CGF, Loc)); 2964 } 2965 } 2966 2967 namespace { 2968 /// Indexes of fields for type kmp_task_t. 2969 enum KmpTaskTFields { 2970 /// List of shared variables. 2971 KmpTaskTShareds, 2972 /// Task routine. 2973 KmpTaskTRoutine, 2974 /// Partition id for the untied tasks. 2975 KmpTaskTPartId, 2976 /// Function with call of destructors for private variables. 2977 Data1, 2978 /// Task priority. 2979 Data2, 2980 /// (Taskloops only) Lower bound. 2981 KmpTaskTLowerBound, 2982 /// (Taskloops only) Upper bound. 2983 KmpTaskTUpperBound, 2984 /// (Taskloops only) Stride. 2985 KmpTaskTStride, 2986 /// (Taskloops only) Is last iteration flag. 2987 KmpTaskTLastIter, 2988 /// (Taskloops only) Reduction data. 2989 KmpTaskTReductions, 2990 }; 2991 } // anonymous namespace 2992 2993 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 2994 return OffloadEntriesTargetRegion.empty() && 2995 OffloadEntriesDeviceGlobalVar.empty(); 2996 } 2997 2998 /// Initialize target region entry. 2999 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3000 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3001 StringRef ParentName, unsigned LineNum, 3002 unsigned Order) { 3003 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3004 "only required for the device " 3005 "code generation."); 3006 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3007 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3008 OMPTargetRegionEntryTargetRegion); 3009 ++OffloadingEntriesNum; 3010 } 3011 3012 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3013 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3014 StringRef ParentName, unsigned LineNum, 3015 llvm::Constant *Addr, llvm::Constant *ID, 3016 OMPTargetRegionEntryKind Flags) { 3017 // If we are emitting code for a target, the entry is already initialized, 3018 // only has to be registered. 3019 if (CGM.getLangOpts().OpenMPIsDevice) { 3020 // This could happen if the device compilation is invoked standalone. 3021 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) 3022 return; 3023 auto &Entry = 3024 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3025 Entry.setAddress(Addr); 3026 Entry.setID(ID); 3027 Entry.setFlags(Flags); 3028 } else { 3029 if (Flags == 3030 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion && 3031 hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum, 3032 /*IgnoreAddressId*/ true)) 3033 return; 3034 assert(!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) && 3035 "Target region entry already registered!"); 3036 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3037 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3038 ++OffloadingEntriesNum; 3039 } 3040 } 3041 3042 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3043 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned LineNum, 3044 bool IgnoreAddressId) const { 3045 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3046 if (PerDevice == OffloadEntriesTargetRegion.end()) 3047 return false; 3048 auto PerFile = PerDevice->second.find(FileID); 3049 if (PerFile == PerDevice->second.end()) 3050 return false; 3051 auto PerParentName = PerFile->second.find(ParentName); 3052 if (PerParentName == PerFile->second.end()) 3053 return false; 3054 auto PerLine = PerParentName->second.find(LineNum); 3055 if (PerLine == PerParentName->second.end()) 3056 return false; 3057 // Fail if this entry is already registered. 3058 if (!IgnoreAddressId && 3059 (PerLine->second.getAddress() || PerLine->second.getID())) 3060 return false; 3061 return true; 3062 } 3063 3064 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3065 const OffloadTargetRegionEntryInfoActTy &Action) { 3066 // Scan all target region entries and perform the provided action. 3067 for (const auto &D : OffloadEntriesTargetRegion) 3068 for (const auto &F : D.second) 3069 for (const auto &P : F.second) 3070 for (const auto &L : P.second) 3071 Action(D.first, F.first, P.first(), L.first, L.second); 3072 } 3073 3074 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3075 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3076 OMPTargetGlobalVarEntryKind Flags, 3077 unsigned Order) { 3078 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3079 "only required for the device " 3080 "code generation."); 3081 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3082 ++OffloadingEntriesNum; 3083 } 3084 3085 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3086 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3087 CharUnits VarSize, 3088 OMPTargetGlobalVarEntryKind Flags, 3089 llvm::GlobalValue::LinkageTypes Linkage) { 3090 if (CGM.getLangOpts().OpenMPIsDevice) { 3091 // This could happen if the device compilation is invoked standalone. 3092 if (!hasDeviceGlobalVarEntryInfo(VarName)) 3093 return; 3094 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3095 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3096 if (Entry.getVarSize().isZero()) { 3097 Entry.setVarSize(VarSize); 3098 Entry.setLinkage(Linkage); 3099 } 3100 return; 3101 } 3102 Entry.setVarSize(VarSize); 3103 Entry.setLinkage(Linkage); 3104 Entry.setAddress(Addr); 3105 } else { 3106 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3107 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3108 assert(Entry.isValid() && Entry.getFlags() == Flags && 3109 "Entry not initialized!"); 3110 if (Entry.getVarSize().isZero()) { 3111 Entry.setVarSize(VarSize); 3112 Entry.setLinkage(Linkage); 3113 } 3114 return; 3115 } 3116 OffloadEntriesDeviceGlobalVar.try_emplace( 3117 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 3118 ++OffloadingEntriesNum; 3119 } 3120 } 3121 3122 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3123 actOnDeviceGlobalVarEntriesInfo( 3124 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 3125 // Scan all target region entries and perform the provided action. 3126 for (const auto &E : OffloadEntriesDeviceGlobalVar) 3127 Action(E.getKey(), E.getValue()); 3128 } 3129 3130 void CGOpenMPRuntime::createOffloadEntry( 3131 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 3132 llvm::GlobalValue::LinkageTypes Linkage) { 3133 StringRef Name = Addr->getName(); 3134 llvm::Module &M = CGM.getModule(); 3135 llvm::LLVMContext &C = M.getContext(); 3136 3137 // Create constant string with the name. 3138 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 3139 3140 std::string StringName = getName({"omp_offloading", "entry_name"}); 3141 auto *Str = new llvm::GlobalVariable( 3142 M, StrPtrInit->getType(), /*isConstant=*/true, 3143 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 3144 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 3145 3146 llvm::Constant *Data[] = { 3147 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(ID, CGM.VoidPtrTy), 3148 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, CGM.Int8PtrTy), 3149 llvm::ConstantInt::get(CGM.SizeTy, Size), 3150 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 3151 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 3152 std::string EntryName = getName({"omp_offloading", "entry", ""}); 3153 llvm::GlobalVariable *Entry = createGlobalStruct( 3154 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 3155 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 3156 3157 // The entry has to be created in the section the linker expects it to be. 3158 Entry->setSection("omp_offloading_entries"); 3159 } 3160 3161 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 3162 // Emit the offloading entries and metadata so that the device codegen side 3163 // can easily figure out what to emit. The produced metadata looks like 3164 // this: 3165 // 3166 // !omp_offload.info = !{!1, ...} 3167 // 3168 // Right now we only generate metadata for function that contain target 3169 // regions. 3170 3171 // If we are in simd mode or there are no entries, we don't need to do 3172 // anything. 3173 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 3174 return; 3175 3176 llvm::Module &M = CGM.getModule(); 3177 llvm::LLVMContext &C = M.getContext(); 3178 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 3179 SourceLocation, StringRef>, 3180 16> 3181 OrderedEntries(OffloadEntriesInfoManager.size()); 3182 llvm::SmallVector<StringRef, 16> ParentFunctions( 3183 OffloadEntriesInfoManager.size()); 3184 3185 // Auxiliary methods to create metadata values and strings. 3186 auto &&GetMDInt = [this](unsigned V) { 3187 return llvm::ConstantAsMetadata::get( 3188 llvm::ConstantInt::get(CGM.Int32Ty, V)); 3189 }; 3190 3191 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 3192 3193 // Create the offloading info metadata node. 3194 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 3195 3196 // Create function that emits metadata for each target region entry; 3197 auto &&TargetRegionMetadataEmitter = 3198 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 3199 &GetMDString]( 3200 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3201 unsigned Line, 3202 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 3203 // Generate metadata for target regions. Each entry of this metadata 3204 // contains: 3205 // - Entry 0 -> Kind of this type of metadata (0). 3206 // - Entry 1 -> Device ID of the file where the entry was identified. 3207 // - Entry 2 -> File ID of the file where the entry was identified. 3208 // - Entry 3 -> Mangled name of the function where the entry was 3209 // identified. 3210 // - Entry 4 -> Line in the file where the entry was identified. 3211 // - Entry 5 -> Order the entry was created. 3212 // The first element of the metadata node is the kind. 3213 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 3214 GetMDInt(FileID), GetMDString(ParentName), 3215 GetMDInt(Line), GetMDInt(E.getOrder())}; 3216 3217 SourceLocation Loc; 3218 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 3219 E = CGM.getContext().getSourceManager().fileinfo_end(); 3220 I != E; ++I) { 3221 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 3222 I->getFirst()->getUniqueID().getFile() == FileID) { 3223 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 3224 I->getFirst(), Line, 1); 3225 break; 3226 } 3227 } 3228 // Save this entry in the right position of the ordered entries array. 3229 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 3230 ParentFunctions[E.getOrder()] = ParentName; 3231 3232 // Add metadata to the named metadata node. 3233 MD->addOperand(llvm::MDNode::get(C, Ops)); 3234 }; 3235 3236 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 3237 TargetRegionMetadataEmitter); 3238 3239 // Create function that emits metadata for each device global variable entry; 3240 auto &&DeviceGlobalVarMetadataEmitter = 3241 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 3242 MD](StringRef MangledName, 3243 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 3244 &E) { 3245 // Generate metadata for global variables. Each entry of this metadata 3246 // contains: 3247 // - Entry 0 -> Kind of this type of metadata (1). 3248 // - Entry 1 -> Mangled name of the variable. 3249 // - Entry 2 -> Declare target kind. 3250 // - Entry 3 -> Order the entry was created. 3251 // The first element of the metadata node is the kind. 3252 llvm::Metadata *Ops[] = { 3253 GetMDInt(E.getKind()), GetMDString(MangledName), 3254 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 3255 3256 // Save this entry in the right position of the ordered entries array. 3257 OrderedEntries[E.getOrder()] = 3258 std::make_tuple(&E, SourceLocation(), MangledName); 3259 3260 // Add metadata to the named metadata node. 3261 MD->addOperand(llvm::MDNode::get(C, Ops)); 3262 }; 3263 3264 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 3265 DeviceGlobalVarMetadataEmitter); 3266 3267 for (const auto &E : OrderedEntries) { 3268 assert(std::get<0>(E) && "All ordered entries must exist!"); 3269 if (const auto *CE = 3270 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 3271 std::get<0>(E))) { 3272 if (!CE->getID() || !CE->getAddress()) { 3273 // Do not blame the entry if the parent funtion is not emitted. 3274 StringRef FnName = ParentFunctions[CE->getOrder()]; 3275 if (!CGM.GetGlobalValue(FnName)) 3276 continue; 3277 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3278 DiagnosticsEngine::Error, 3279 "Offloading entry for target region in %0 is incorrect: either the " 3280 "address or the ID is invalid."); 3281 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 3282 continue; 3283 } 3284 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 3285 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 3286 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 3287 OffloadEntryInfoDeviceGlobalVar>( 3288 std::get<0>(E))) { 3289 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 3290 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3291 CE->getFlags()); 3292 switch (Flags) { 3293 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 3294 if (CGM.getLangOpts().OpenMPIsDevice && 3295 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 3296 continue; 3297 if (!CE->getAddress()) { 3298 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3299 DiagnosticsEngine::Error, "Offloading entry for declare target " 3300 "variable %0 is incorrect: the " 3301 "address is invalid."); 3302 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 3303 continue; 3304 } 3305 // The vaiable has no definition - no need to add the entry. 3306 if (CE->getVarSize().isZero()) 3307 continue; 3308 break; 3309 } 3310 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 3311 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 3312 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 3313 "Declaret target link address is set."); 3314 if (CGM.getLangOpts().OpenMPIsDevice) 3315 continue; 3316 if (!CE->getAddress()) { 3317 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3318 DiagnosticsEngine::Error, 3319 "Offloading entry for declare target variable is incorrect: the " 3320 "address is invalid."); 3321 CGM.getDiags().Report(DiagID); 3322 continue; 3323 } 3324 break; 3325 } 3326 createOffloadEntry(CE->getAddress(), CE->getAddress(), 3327 CE->getVarSize().getQuantity(), Flags, 3328 CE->getLinkage()); 3329 } else { 3330 llvm_unreachable("Unsupported entry kind."); 3331 } 3332 } 3333 } 3334 3335 /// Loads all the offload entries information from the host IR 3336 /// metadata. 3337 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 3338 // If we are in target mode, load the metadata from the host IR. This code has 3339 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 3340 3341 if (!CGM.getLangOpts().OpenMPIsDevice) 3342 return; 3343 3344 if (CGM.getLangOpts().OMPHostIRFile.empty()) 3345 return; 3346 3347 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 3348 if (auto EC = Buf.getError()) { 3349 CGM.getDiags().Report(diag::err_cannot_open_file) 3350 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3351 return; 3352 } 3353 3354 llvm::LLVMContext C; 3355 auto ME = expectedToErrorOrAndEmitErrors( 3356 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 3357 3358 if (auto EC = ME.getError()) { 3359 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3360 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 3361 CGM.getDiags().Report(DiagID) 3362 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3363 return; 3364 } 3365 3366 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 3367 if (!MD) 3368 return; 3369 3370 for (llvm::MDNode *MN : MD->operands()) { 3371 auto &&GetMDInt = [MN](unsigned Idx) { 3372 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 3373 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 3374 }; 3375 3376 auto &&GetMDString = [MN](unsigned Idx) { 3377 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 3378 return V->getString(); 3379 }; 3380 3381 switch (GetMDInt(0)) { 3382 default: 3383 llvm_unreachable("Unexpected metadata!"); 3384 break; 3385 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3386 OffloadingEntryInfoTargetRegion: 3387 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 3388 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 3389 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 3390 /*Order=*/GetMDInt(5)); 3391 break; 3392 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3393 OffloadingEntryInfoDeviceGlobalVar: 3394 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 3395 /*MangledName=*/GetMDString(1), 3396 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3397 /*Flags=*/GetMDInt(2)), 3398 /*Order=*/GetMDInt(3)); 3399 break; 3400 } 3401 } 3402 } 3403 3404 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 3405 if (!KmpRoutineEntryPtrTy) { 3406 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 3407 ASTContext &C = CGM.getContext(); 3408 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 3409 FunctionProtoType::ExtProtoInfo EPI; 3410 KmpRoutineEntryPtrQTy = C.getPointerType( 3411 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 3412 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 3413 } 3414 } 3415 3416 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 3417 // Make sure the type of the entry is already created. This is the type we 3418 // have to create: 3419 // struct __tgt_offload_entry{ 3420 // void *addr; // Pointer to the offload entry info. 3421 // // (function or global) 3422 // char *name; // Name of the function or global. 3423 // size_t size; // Size of the entry info (0 if it a function). 3424 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 3425 // int32_t reserved; // Reserved, to use by the runtime library. 3426 // }; 3427 if (TgtOffloadEntryQTy.isNull()) { 3428 ASTContext &C = CGM.getContext(); 3429 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 3430 RD->startDefinition(); 3431 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3432 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 3433 addFieldToRecordDecl(C, RD, C.getSizeType()); 3434 addFieldToRecordDecl( 3435 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3436 addFieldToRecordDecl( 3437 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3438 RD->completeDefinition(); 3439 RD->addAttr(PackedAttr::CreateImplicit(C)); 3440 TgtOffloadEntryQTy = C.getRecordType(RD); 3441 } 3442 return TgtOffloadEntryQTy; 3443 } 3444 3445 namespace { 3446 struct PrivateHelpersTy { 3447 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original, 3448 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit) 3449 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy), 3450 PrivateElemInit(PrivateElemInit) {} 3451 PrivateHelpersTy(const VarDecl *Original) : Original(Original) {} 3452 const Expr *OriginalRef = nullptr; 3453 const VarDecl *Original = nullptr; 3454 const VarDecl *PrivateCopy = nullptr; 3455 const VarDecl *PrivateElemInit = nullptr; 3456 bool isLocalPrivate() const { 3457 return !OriginalRef && !PrivateCopy && !PrivateElemInit; 3458 } 3459 }; 3460 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 3461 } // anonymous namespace 3462 3463 static bool isAllocatableDecl(const VarDecl *VD) { 3464 const VarDecl *CVD = VD->getCanonicalDecl(); 3465 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 3466 return false; 3467 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 3468 // Use the default allocation. 3469 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 3470 !AA->getAllocator()); 3471 } 3472 3473 static RecordDecl * 3474 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 3475 if (!Privates.empty()) { 3476 ASTContext &C = CGM.getContext(); 3477 // Build struct .kmp_privates_t. { 3478 // /* private vars */ 3479 // }; 3480 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 3481 RD->startDefinition(); 3482 for (const auto &Pair : Privates) { 3483 const VarDecl *VD = Pair.second.Original; 3484 QualType Type = VD->getType().getNonReferenceType(); 3485 // If the private variable is a local variable with lvalue ref type, 3486 // allocate the pointer instead of the pointee type. 3487 if (Pair.second.isLocalPrivate()) { 3488 if (VD->getType()->isLValueReferenceType()) 3489 Type = C.getPointerType(Type); 3490 if (isAllocatableDecl(VD)) 3491 Type = C.getPointerType(Type); 3492 } 3493 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 3494 if (VD->hasAttrs()) { 3495 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 3496 E(VD->getAttrs().end()); 3497 I != E; ++I) 3498 FD->addAttr(*I); 3499 } 3500 } 3501 RD->completeDefinition(); 3502 return RD; 3503 } 3504 return nullptr; 3505 } 3506 3507 static RecordDecl * 3508 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 3509 QualType KmpInt32Ty, 3510 QualType KmpRoutineEntryPointerQTy) { 3511 ASTContext &C = CGM.getContext(); 3512 // Build struct kmp_task_t { 3513 // void * shareds; 3514 // kmp_routine_entry_t routine; 3515 // kmp_int32 part_id; 3516 // kmp_cmplrdata_t data1; 3517 // kmp_cmplrdata_t data2; 3518 // For taskloops additional fields: 3519 // kmp_uint64 lb; 3520 // kmp_uint64 ub; 3521 // kmp_int64 st; 3522 // kmp_int32 liter; 3523 // void * reductions; 3524 // }; 3525 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 3526 UD->startDefinition(); 3527 addFieldToRecordDecl(C, UD, KmpInt32Ty); 3528 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 3529 UD->completeDefinition(); 3530 QualType KmpCmplrdataTy = C.getRecordType(UD); 3531 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 3532 RD->startDefinition(); 3533 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3534 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 3535 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3536 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3537 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3538 if (isOpenMPTaskLoopDirective(Kind)) { 3539 QualType KmpUInt64Ty = 3540 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 3541 QualType KmpInt64Ty = 3542 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 3543 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3544 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3545 addFieldToRecordDecl(C, RD, KmpInt64Ty); 3546 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3547 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3548 } 3549 RD->completeDefinition(); 3550 return RD; 3551 } 3552 3553 static RecordDecl * 3554 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 3555 ArrayRef<PrivateDataTy> Privates) { 3556 ASTContext &C = CGM.getContext(); 3557 // Build struct kmp_task_t_with_privates { 3558 // kmp_task_t task_data; 3559 // .kmp_privates_t. privates; 3560 // }; 3561 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 3562 RD->startDefinition(); 3563 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 3564 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 3565 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 3566 RD->completeDefinition(); 3567 return RD; 3568 } 3569 3570 /// Emit a proxy function which accepts kmp_task_t as the second 3571 /// argument. 3572 /// \code 3573 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 3574 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 3575 /// For taskloops: 3576 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3577 /// tt->reductions, tt->shareds); 3578 /// return 0; 3579 /// } 3580 /// \endcode 3581 static llvm::Function * 3582 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 3583 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 3584 QualType KmpTaskTWithPrivatesPtrQTy, 3585 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 3586 QualType SharedsPtrTy, llvm::Function *TaskFunction, 3587 llvm::Value *TaskPrivatesMap) { 3588 ASTContext &C = CGM.getContext(); 3589 FunctionArgList Args; 3590 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3591 ImplicitParamDecl::Other); 3592 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3593 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3594 ImplicitParamDecl::Other); 3595 Args.push_back(&GtidArg); 3596 Args.push_back(&TaskTypeArg); 3597 const auto &TaskEntryFnInfo = 3598 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3599 llvm::FunctionType *TaskEntryTy = 3600 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 3601 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 3602 auto *TaskEntry = llvm::Function::Create( 3603 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 3604 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 3605 TaskEntry->setDoesNotRecurse(); 3606 CodeGenFunction CGF(CGM); 3607 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 3608 Loc, Loc); 3609 3610 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 3611 // tt, 3612 // For taskloops: 3613 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3614 // tt->task_data.shareds); 3615 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 3616 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 3617 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3618 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3619 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3620 const auto *KmpTaskTWithPrivatesQTyRD = 3621 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3622 LValue Base = 3623 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3624 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 3625 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 3626 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 3627 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 3628 3629 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 3630 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 3631 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3632 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 3633 CGF.ConvertTypeForMem(SharedsPtrTy)); 3634 3635 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 3636 llvm::Value *PrivatesParam; 3637 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 3638 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 3639 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3640 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 3641 } else { 3642 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3643 } 3644 3645 llvm::Value *CommonArgs[] = { 3646 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap, 3647 CGF.Builder 3648 .CreatePointerBitCastOrAddrSpaceCast(TDBase.getAddress(CGF), 3649 CGF.VoidPtrTy, CGF.Int8Ty) 3650 .getPointer()}; 3651 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 3652 std::end(CommonArgs)); 3653 if (isOpenMPTaskLoopDirective(Kind)) { 3654 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 3655 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 3656 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 3657 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 3658 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 3659 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 3660 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 3661 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 3662 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 3663 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3664 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 3665 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 3666 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 3667 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 3668 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 3669 CallArgs.push_back(LBParam); 3670 CallArgs.push_back(UBParam); 3671 CallArgs.push_back(StParam); 3672 CallArgs.push_back(LIParam); 3673 CallArgs.push_back(RParam); 3674 } 3675 CallArgs.push_back(SharedsParam); 3676 3677 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 3678 CallArgs); 3679 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 3680 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 3681 CGF.FinishFunction(); 3682 return TaskEntry; 3683 } 3684 3685 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 3686 SourceLocation Loc, 3687 QualType KmpInt32Ty, 3688 QualType KmpTaskTWithPrivatesPtrQTy, 3689 QualType KmpTaskTWithPrivatesQTy) { 3690 ASTContext &C = CGM.getContext(); 3691 FunctionArgList Args; 3692 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3693 ImplicitParamDecl::Other); 3694 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3695 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3696 ImplicitParamDecl::Other); 3697 Args.push_back(&GtidArg); 3698 Args.push_back(&TaskTypeArg); 3699 const auto &DestructorFnInfo = 3700 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3701 llvm::FunctionType *DestructorFnTy = 3702 CGM.getTypes().GetFunctionType(DestructorFnInfo); 3703 std::string Name = 3704 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 3705 auto *DestructorFn = 3706 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 3707 Name, &CGM.getModule()); 3708 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 3709 DestructorFnInfo); 3710 DestructorFn->setDoesNotRecurse(); 3711 CodeGenFunction CGF(CGM); 3712 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 3713 Args, Loc, Loc); 3714 3715 LValue Base = CGF.EmitLoadOfPointerLValue( 3716 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3717 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3718 const auto *KmpTaskTWithPrivatesQTyRD = 3719 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3720 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3721 Base = CGF.EmitLValueForField(Base, *FI); 3722 for (const auto *Field : 3723 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 3724 if (QualType::DestructionKind DtorKind = 3725 Field->getType().isDestructedType()) { 3726 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 3727 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 3728 } 3729 } 3730 CGF.FinishFunction(); 3731 return DestructorFn; 3732 } 3733 3734 /// Emit a privates mapping function for correct handling of private and 3735 /// firstprivate variables. 3736 /// \code 3737 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 3738 /// **noalias priv1,..., <tyn> **noalias privn) { 3739 /// *priv1 = &.privates.priv1; 3740 /// ...; 3741 /// *privn = &.privates.privn; 3742 /// } 3743 /// \endcode 3744 static llvm::Value * 3745 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 3746 const OMPTaskDataTy &Data, QualType PrivatesQTy, 3747 ArrayRef<PrivateDataTy> Privates) { 3748 ASTContext &C = CGM.getContext(); 3749 FunctionArgList Args; 3750 ImplicitParamDecl TaskPrivatesArg( 3751 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3752 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 3753 ImplicitParamDecl::Other); 3754 Args.push_back(&TaskPrivatesArg); 3755 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, unsigned> PrivateVarsPos; 3756 unsigned Counter = 1; 3757 for (const Expr *E : Data.PrivateVars) { 3758 Args.push_back(ImplicitParamDecl::Create( 3759 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3760 C.getPointerType(C.getPointerType(E->getType())) 3761 .withConst() 3762 .withRestrict(), 3763 ImplicitParamDecl::Other)); 3764 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3765 PrivateVarsPos[VD] = Counter; 3766 ++Counter; 3767 } 3768 for (const Expr *E : Data.FirstprivateVars) { 3769 Args.push_back(ImplicitParamDecl::Create( 3770 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3771 C.getPointerType(C.getPointerType(E->getType())) 3772 .withConst() 3773 .withRestrict(), 3774 ImplicitParamDecl::Other)); 3775 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3776 PrivateVarsPos[VD] = Counter; 3777 ++Counter; 3778 } 3779 for (const Expr *E : Data.LastprivateVars) { 3780 Args.push_back(ImplicitParamDecl::Create( 3781 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3782 C.getPointerType(C.getPointerType(E->getType())) 3783 .withConst() 3784 .withRestrict(), 3785 ImplicitParamDecl::Other)); 3786 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3787 PrivateVarsPos[VD] = Counter; 3788 ++Counter; 3789 } 3790 for (const VarDecl *VD : Data.PrivateLocals) { 3791 QualType Ty = VD->getType().getNonReferenceType(); 3792 if (VD->getType()->isLValueReferenceType()) 3793 Ty = C.getPointerType(Ty); 3794 if (isAllocatableDecl(VD)) 3795 Ty = C.getPointerType(Ty); 3796 Args.push_back(ImplicitParamDecl::Create( 3797 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3798 C.getPointerType(C.getPointerType(Ty)).withConst().withRestrict(), 3799 ImplicitParamDecl::Other)); 3800 PrivateVarsPos[VD] = Counter; 3801 ++Counter; 3802 } 3803 const auto &TaskPrivatesMapFnInfo = 3804 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3805 llvm::FunctionType *TaskPrivatesMapTy = 3806 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 3807 std::string Name = 3808 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 3809 auto *TaskPrivatesMap = llvm::Function::Create( 3810 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 3811 &CGM.getModule()); 3812 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 3813 TaskPrivatesMapFnInfo); 3814 if (CGM.getLangOpts().Optimize) { 3815 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 3816 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 3817 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 3818 } 3819 CodeGenFunction CGF(CGM); 3820 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 3821 TaskPrivatesMapFnInfo, Args, Loc, Loc); 3822 3823 // *privi = &.privates.privi; 3824 LValue Base = CGF.EmitLoadOfPointerLValue( 3825 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 3826 TaskPrivatesArg.getType()->castAs<PointerType>()); 3827 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 3828 Counter = 0; 3829 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 3830 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 3831 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 3832 LValue RefLVal = 3833 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 3834 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 3835 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 3836 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 3837 ++Counter; 3838 } 3839 CGF.FinishFunction(); 3840 return TaskPrivatesMap; 3841 } 3842 3843 /// Emit initialization for private variables in task-based directives. 3844 static void emitPrivatesInit(CodeGenFunction &CGF, 3845 const OMPExecutableDirective &D, 3846 Address KmpTaskSharedsPtr, LValue TDBase, 3847 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3848 QualType SharedsTy, QualType SharedsPtrTy, 3849 const OMPTaskDataTy &Data, 3850 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 3851 ASTContext &C = CGF.getContext(); 3852 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3853 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 3854 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 3855 ? OMPD_taskloop 3856 : OMPD_task; 3857 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 3858 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 3859 LValue SrcBase; 3860 bool IsTargetTask = 3861 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 3862 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 3863 // For target-based directives skip 4 firstprivate arrays BasePointersArray, 3864 // PointersArray, SizesArray, and MappersArray. The original variables for 3865 // these arrays are not captured and we get their addresses explicitly. 3866 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) || 3867 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 3868 SrcBase = CGF.MakeAddrLValue( 3869 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3870 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy), 3871 CGF.ConvertTypeForMem(SharedsTy)), 3872 SharedsTy); 3873 } 3874 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 3875 for (const PrivateDataTy &Pair : Privates) { 3876 // Do not initialize private locals. 3877 if (Pair.second.isLocalPrivate()) { 3878 ++FI; 3879 continue; 3880 } 3881 const VarDecl *VD = Pair.second.PrivateCopy; 3882 const Expr *Init = VD->getAnyInitializer(); 3883 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 3884 !CGF.isTrivialInitializer(Init)))) { 3885 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 3886 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 3887 const VarDecl *OriginalVD = Pair.second.Original; 3888 // Check if the variable is the target-based BasePointersArray, 3889 // PointersArray, SizesArray, or MappersArray. 3890 LValue SharedRefLValue; 3891 QualType Type = PrivateLValue.getType(); 3892 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 3893 if (IsTargetTask && !SharedField) { 3894 assert(isa<ImplicitParamDecl>(OriginalVD) && 3895 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 3896 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3897 ->getNumParams() == 0 && 3898 isa<TranslationUnitDecl>( 3899 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3900 ->getDeclContext()) && 3901 "Expected artificial target data variable."); 3902 SharedRefLValue = 3903 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 3904 } else if (ForDup) { 3905 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 3906 SharedRefLValue = CGF.MakeAddrLValue( 3907 SharedRefLValue.getAddress(CGF).withAlignment( 3908 C.getDeclAlign(OriginalVD)), 3909 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 3910 SharedRefLValue.getTBAAInfo()); 3911 } else if (CGF.LambdaCaptureFields.count( 3912 Pair.second.Original->getCanonicalDecl()) > 0 || 3913 isa_and_nonnull<BlockDecl>(CGF.CurCodeDecl)) { 3914 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3915 } else { 3916 // Processing for implicitly captured variables. 3917 InlinedOpenMPRegionRAII Region( 3918 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown, 3919 /*HasCancel=*/false, /*NoInheritance=*/true); 3920 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3921 } 3922 if (Type->isArrayType()) { 3923 // Initialize firstprivate array. 3924 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 3925 // Perform simple memcpy. 3926 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 3927 } else { 3928 // Initialize firstprivate array using element-by-element 3929 // initialization. 3930 CGF.EmitOMPAggregateAssign( 3931 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 3932 Type, 3933 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 3934 Address SrcElement) { 3935 // Clean up any temporaries needed by the initialization. 3936 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3937 InitScope.addPrivate(Elem, SrcElement); 3938 (void)InitScope.Privatize(); 3939 // Emit initialization for single element. 3940 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 3941 CGF, &CapturesInfo); 3942 CGF.EmitAnyExprToMem(Init, DestElement, 3943 Init->getType().getQualifiers(), 3944 /*IsInitializer=*/false); 3945 }); 3946 } 3947 } else { 3948 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3949 InitScope.addPrivate(Elem, SharedRefLValue.getAddress(CGF)); 3950 (void)InitScope.Privatize(); 3951 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 3952 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 3953 /*capturedByInit=*/false); 3954 } 3955 } else { 3956 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 3957 } 3958 } 3959 ++FI; 3960 } 3961 } 3962 3963 /// Check if duplication function is required for taskloops. 3964 static bool checkInitIsRequired(CodeGenFunction &CGF, 3965 ArrayRef<PrivateDataTy> Privates) { 3966 bool InitRequired = false; 3967 for (const PrivateDataTy &Pair : Privates) { 3968 if (Pair.second.isLocalPrivate()) 3969 continue; 3970 const VarDecl *VD = Pair.second.PrivateCopy; 3971 const Expr *Init = VD->getAnyInitializer(); 3972 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(Init) && 3973 !CGF.isTrivialInitializer(Init)); 3974 if (InitRequired) 3975 break; 3976 } 3977 return InitRequired; 3978 } 3979 3980 3981 /// Emit task_dup function (for initialization of 3982 /// private/firstprivate/lastprivate vars and last_iter flag) 3983 /// \code 3984 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 3985 /// lastpriv) { 3986 /// // setup lastprivate flag 3987 /// task_dst->last = lastpriv; 3988 /// // could be constructor calls here... 3989 /// } 3990 /// \endcode 3991 static llvm::Value * 3992 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 3993 const OMPExecutableDirective &D, 3994 QualType KmpTaskTWithPrivatesPtrQTy, 3995 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3996 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 3997 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 3998 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 3999 ASTContext &C = CGM.getContext(); 4000 FunctionArgList Args; 4001 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4002 KmpTaskTWithPrivatesPtrQTy, 4003 ImplicitParamDecl::Other); 4004 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4005 KmpTaskTWithPrivatesPtrQTy, 4006 ImplicitParamDecl::Other); 4007 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4008 ImplicitParamDecl::Other); 4009 Args.push_back(&DstArg); 4010 Args.push_back(&SrcArg); 4011 Args.push_back(&LastprivArg); 4012 const auto &TaskDupFnInfo = 4013 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4014 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4015 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4016 auto *TaskDup = llvm::Function::Create( 4017 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4018 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4019 TaskDup->setDoesNotRecurse(); 4020 CodeGenFunction CGF(CGM); 4021 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4022 Loc); 4023 4024 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4025 CGF.GetAddrOfLocalVar(&DstArg), 4026 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4027 // task_dst->liter = lastpriv; 4028 if (WithLastIter) { 4029 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4030 LValue Base = CGF.EmitLValueForField( 4031 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4032 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4033 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4034 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4035 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4036 } 4037 4038 // Emit initial values for private copies (if any). 4039 assert(!Privates.empty()); 4040 Address KmpTaskSharedsPtr = Address::invalid(); 4041 if (!Data.FirstprivateVars.empty()) { 4042 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4043 CGF.GetAddrOfLocalVar(&SrcArg), 4044 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4045 LValue Base = CGF.EmitLValueForField( 4046 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4047 KmpTaskSharedsPtr = Address::deprecated( 4048 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4049 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4050 KmpTaskTShareds)), 4051 Loc), 4052 CGM.getNaturalTypeAlignment(SharedsTy)); 4053 } 4054 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4055 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4056 CGF.FinishFunction(); 4057 return TaskDup; 4058 } 4059 4060 /// Checks if destructor function is required to be generated. 4061 /// \return true if cleanups are required, false otherwise. 4062 static bool 4063 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4064 ArrayRef<PrivateDataTy> Privates) { 4065 for (const PrivateDataTy &P : Privates) { 4066 if (P.second.isLocalPrivate()) 4067 continue; 4068 QualType Ty = P.second.Original->getType().getNonReferenceType(); 4069 if (Ty.isDestructedType()) 4070 return true; 4071 } 4072 return false; 4073 } 4074 4075 namespace { 4076 /// Loop generator for OpenMP iterator expression. 4077 class OMPIteratorGeneratorScope final 4078 : public CodeGenFunction::OMPPrivateScope { 4079 CodeGenFunction &CGF; 4080 const OMPIteratorExpr *E = nullptr; 4081 SmallVector<CodeGenFunction::JumpDest, 4> ContDests; 4082 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests; 4083 OMPIteratorGeneratorScope() = delete; 4084 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete; 4085 4086 public: 4087 OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E) 4088 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) { 4089 if (!E) 4090 return; 4091 SmallVector<llvm::Value *, 4> Uppers; 4092 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4093 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper)); 4094 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I)); 4095 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName())); 4096 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4097 addPrivate( 4098 HelperData.CounterVD, 4099 CGF.CreateMemTemp(HelperData.CounterVD->getType(), "counter.addr")); 4100 } 4101 Privatize(); 4102 4103 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4104 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4105 LValue CLVal = 4106 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD), 4107 HelperData.CounterVD->getType()); 4108 // Counter = 0; 4109 CGF.EmitStoreOfScalar( 4110 llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0), 4111 CLVal); 4112 CodeGenFunction::JumpDest &ContDest = 4113 ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont")); 4114 CodeGenFunction::JumpDest &ExitDest = 4115 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit")); 4116 // N = <number-of_iterations>; 4117 llvm::Value *N = Uppers[I]; 4118 // cont: 4119 // if (Counter < N) goto body; else goto exit; 4120 CGF.EmitBlock(ContDest.getBlock()); 4121 auto *CVal = 4122 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation()); 4123 llvm::Value *Cmp = 4124 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType() 4125 ? CGF.Builder.CreateICmpSLT(CVal, N) 4126 : CGF.Builder.CreateICmpULT(CVal, N); 4127 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body"); 4128 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock()); 4129 // body: 4130 CGF.EmitBlock(BodyBB); 4131 // Iteri = Begini + Counter * Stepi; 4132 CGF.EmitIgnoredExpr(HelperData.Update); 4133 } 4134 } 4135 ~OMPIteratorGeneratorScope() { 4136 if (!E) 4137 return; 4138 for (unsigned I = E->numOfIterators(); I > 0; --I) { 4139 // Counter = Counter + 1; 4140 const OMPIteratorHelperData &HelperData = E->getHelper(I - 1); 4141 CGF.EmitIgnoredExpr(HelperData.CounterUpdate); 4142 // goto cont; 4143 CGF.EmitBranchThroughCleanup(ContDests[I - 1]); 4144 // exit: 4145 CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1); 4146 } 4147 } 4148 }; 4149 } // namespace 4150 4151 static std::pair<llvm::Value *, llvm::Value *> 4152 getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { 4153 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E); 4154 llvm::Value *Addr; 4155 if (OASE) { 4156 const Expr *Base = OASE->getBase(); 4157 Addr = CGF.EmitScalarExpr(Base); 4158 } else { 4159 Addr = CGF.EmitLValue(E).getPointer(CGF); 4160 } 4161 llvm::Value *SizeVal; 4162 QualType Ty = E->getType(); 4163 if (OASE) { 4164 SizeVal = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType()); 4165 for (const Expr *SE : OASE->getDimensions()) { 4166 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 4167 Sz = CGF.EmitScalarConversion( 4168 Sz, SE->getType(), CGF.getContext().getSizeType(), SE->getExprLoc()); 4169 SizeVal = CGF.Builder.CreateNUWMul(SizeVal, Sz); 4170 } 4171 } else if (const auto *ASE = 4172 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 4173 LValue UpAddrLVal = 4174 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 4175 Address UpAddrAddress = UpAddrLVal.getAddress(CGF); 4176 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 4177 UpAddrAddress.getElementType(), UpAddrAddress.getPointer(), /*Idx0=*/1); 4178 llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); 4179 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); 4180 SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 4181 } else { 4182 SizeVal = CGF.getTypeSize(Ty); 4183 } 4184 return std::make_pair(Addr, SizeVal); 4185 } 4186 4187 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4188 static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) { 4189 QualType FlagsTy = C.getIntTypeForBitwidth(32, /*Signed=*/false); 4190 if (KmpTaskAffinityInfoTy.isNull()) { 4191 RecordDecl *KmpAffinityInfoRD = 4192 C.buildImplicitRecord("kmp_task_affinity_info_t"); 4193 KmpAffinityInfoRD->startDefinition(); 4194 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getIntPtrType()); 4195 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType()); 4196 addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy); 4197 KmpAffinityInfoRD->completeDefinition(); 4198 KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD); 4199 } 4200 } 4201 4202 CGOpenMPRuntime::TaskResultTy 4203 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4204 const OMPExecutableDirective &D, 4205 llvm::Function *TaskFunction, QualType SharedsTy, 4206 Address Shareds, const OMPTaskDataTy &Data) { 4207 ASTContext &C = CGM.getContext(); 4208 llvm::SmallVector<PrivateDataTy, 4> Privates; 4209 // Aggregate privates and sort them by the alignment. 4210 const auto *I = Data.PrivateCopies.begin(); 4211 for (const Expr *E : Data.PrivateVars) { 4212 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4213 Privates.emplace_back( 4214 C.getDeclAlign(VD), 4215 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4216 /*PrivateElemInit=*/nullptr)); 4217 ++I; 4218 } 4219 I = Data.FirstprivateCopies.begin(); 4220 const auto *IElemInitRef = Data.FirstprivateInits.begin(); 4221 for (const Expr *E : Data.FirstprivateVars) { 4222 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4223 Privates.emplace_back( 4224 C.getDeclAlign(VD), 4225 PrivateHelpersTy( 4226 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4227 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4228 ++I; 4229 ++IElemInitRef; 4230 } 4231 I = Data.LastprivateCopies.begin(); 4232 for (const Expr *E : Data.LastprivateVars) { 4233 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4234 Privates.emplace_back( 4235 C.getDeclAlign(VD), 4236 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4237 /*PrivateElemInit=*/nullptr)); 4238 ++I; 4239 } 4240 for (const VarDecl *VD : Data.PrivateLocals) { 4241 if (isAllocatableDecl(VD)) 4242 Privates.emplace_back(CGM.getPointerAlign(), PrivateHelpersTy(VD)); 4243 else 4244 Privates.emplace_back(C.getDeclAlign(VD), PrivateHelpersTy(VD)); 4245 } 4246 llvm::stable_sort(Privates, 4247 [](const PrivateDataTy &L, const PrivateDataTy &R) { 4248 return L.first > R.first; 4249 }); 4250 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 4251 // Build type kmp_routine_entry_t (if not built yet). 4252 emitKmpRoutineEntryT(KmpInt32Ty); 4253 // Build type kmp_task_t (if not built yet). 4254 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 4255 if (SavedKmpTaskloopTQTy.isNull()) { 4256 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4257 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4258 } 4259 KmpTaskTQTy = SavedKmpTaskloopTQTy; 4260 } else { 4261 assert((D.getDirectiveKind() == OMPD_task || 4262 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 4263 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 4264 "Expected taskloop, task or target directive"); 4265 if (SavedKmpTaskTQTy.isNull()) { 4266 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4267 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4268 } 4269 KmpTaskTQTy = SavedKmpTaskTQTy; 4270 } 4271 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4272 // Build particular struct kmp_task_t for the given task. 4273 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 4274 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 4275 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 4276 QualType KmpTaskTWithPrivatesPtrQTy = 4277 C.getPointerType(KmpTaskTWithPrivatesQTy); 4278 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 4279 llvm::Type *KmpTaskTWithPrivatesPtrTy = 4280 KmpTaskTWithPrivatesTy->getPointerTo(); 4281 llvm::Value *KmpTaskTWithPrivatesTySize = 4282 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 4283 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 4284 4285 // Emit initial values for private copies (if any). 4286 llvm::Value *TaskPrivatesMap = nullptr; 4287 llvm::Type *TaskPrivatesMapTy = 4288 std::next(TaskFunction->arg_begin(), 3)->getType(); 4289 if (!Privates.empty()) { 4290 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4291 TaskPrivatesMap = 4292 emitTaskPrivateMappingFunction(CGM, Loc, Data, FI->getType(), Privates); 4293 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4294 TaskPrivatesMap, TaskPrivatesMapTy); 4295 } else { 4296 TaskPrivatesMap = llvm::ConstantPointerNull::get( 4297 cast<llvm::PointerType>(TaskPrivatesMapTy)); 4298 } 4299 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 4300 // kmp_task_t *tt); 4301 llvm::Function *TaskEntry = emitProxyTaskFunction( 4302 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4303 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 4304 TaskPrivatesMap); 4305 4306 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 4307 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 4308 // kmp_routine_entry_t *task_entry); 4309 // Task flags. Format is taken from 4310 // https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h, 4311 // description of kmp_tasking_flags struct. 4312 enum { 4313 TiedFlag = 0x1, 4314 FinalFlag = 0x2, 4315 DestructorsFlag = 0x8, 4316 PriorityFlag = 0x20, 4317 DetachableFlag = 0x40, 4318 }; 4319 unsigned Flags = Data.Tied ? TiedFlag : 0; 4320 bool NeedsCleanup = false; 4321 if (!Privates.empty()) { 4322 NeedsCleanup = 4323 checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD, Privates); 4324 if (NeedsCleanup) 4325 Flags = Flags | DestructorsFlag; 4326 } 4327 if (Data.Priority.getInt()) 4328 Flags = Flags | PriorityFlag; 4329 if (D.hasClausesOfKind<OMPDetachClause>()) 4330 Flags = Flags | DetachableFlag; 4331 llvm::Value *TaskFlags = 4332 Data.Final.getPointer() 4333 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 4334 CGF.Builder.getInt32(FinalFlag), 4335 CGF.Builder.getInt32(/*C=*/0)) 4336 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 4337 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 4338 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 4339 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 4340 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 4341 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4342 TaskEntry, KmpRoutineEntryPtrTy)}; 4343 llvm::Value *NewTask; 4344 if (D.hasClausesOfKind<OMPNowaitClause>()) { 4345 // Check if we have any device clause associated with the directive. 4346 const Expr *Device = nullptr; 4347 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 4348 Device = C->getDevice(); 4349 // Emit device ID if any otherwise use default value. 4350 llvm::Value *DeviceID; 4351 if (Device) 4352 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 4353 CGF.Int64Ty, /*isSigned=*/true); 4354 else 4355 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 4356 AllocArgs.push_back(DeviceID); 4357 NewTask = CGF.EmitRuntimeCall( 4358 OMPBuilder.getOrCreateRuntimeFunction( 4359 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc), 4360 AllocArgs); 4361 } else { 4362 NewTask = 4363 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 4364 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc), 4365 AllocArgs); 4366 } 4367 // Emit detach clause initialization. 4368 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid, 4369 // task_descriptor); 4370 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) { 4371 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts(); 4372 LValue EvtLVal = CGF.EmitLValue(Evt); 4373 4374 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 4375 // int gtid, kmp_task_t *task); 4376 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc()); 4377 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc()); 4378 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false); 4379 llvm::Value *EvtVal = CGF.EmitRuntimeCall( 4380 OMPBuilder.getOrCreateRuntimeFunction( 4381 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event), 4382 {Loc, Tid, NewTask}); 4383 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(), 4384 Evt->getExprLoc()); 4385 CGF.EmitStoreOfScalar(EvtVal, EvtLVal); 4386 } 4387 // Process affinity clauses. 4388 if (D.hasClausesOfKind<OMPAffinityClause>()) { 4389 // Process list of affinity data. 4390 ASTContext &C = CGM.getContext(); 4391 Address AffinitiesArray = Address::invalid(); 4392 // Calculate number of elements to form the array of affinity data. 4393 llvm::Value *NumOfElements = nullptr; 4394 unsigned NumAffinities = 0; 4395 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4396 if (const Expr *Modifier = C->getModifier()) { 4397 const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts()); 4398 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4399 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4400 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4401 NumOfElements = 4402 NumOfElements ? CGF.Builder.CreateNUWMul(NumOfElements, Sz) : Sz; 4403 } 4404 } else { 4405 NumAffinities += C->varlist_size(); 4406 } 4407 } 4408 getKmpAffinityType(CGM.getContext(), KmpTaskAffinityInfoTy); 4409 // Fields ids in kmp_task_affinity_info record. 4410 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags }; 4411 4412 QualType KmpTaskAffinityInfoArrayTy; 4413 if (NumOfElements) { 4414 NumOfElements = CGF.Builder.CreateNUWAdd( 4415 llvm::ConstantInt::get(CGF.SizeTy, NumAffinities), NumOfElements); 4416 auto *OVE = new (C) OpaqueValueExpr( 4417 Loc, 4418 C.getIntTypeForBitwidth(C.getTypeSize(C.getSizeType()), /*Signed=*/0), 4419 VK_PRValue); 4420 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, OVE, 4421 RValue::get(NumOfElements)); 4422 KmpTaskAffinityInfoArrayTy = 4423 C.getVariableArrayType(KmpTaskAffinityInfoTy, OVE, ArrayType::Normal, 4424 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4425 // Properly emit variable-sized array. 4426 auto *PD = ImplicitParamDecl::Create(C, KmpTaskAffinityInfoArrayTy, 4427 ImplicitParamDecl::Other); 4428 CGF.EmitVarDecl(*PD); 4429 AffinitiesArray = CGF.GetAddrOfLocalVar(PD); 4430 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4431 /*isSigned=*/false); 4432 } else { 4433 KmpTaskAffinityInfoArrayTy = C.getConstantArrayType( 4434 KmpTaskAffinityInfoTy, 4435 llvm::APInt(C.getTypeSize(C.getSizeType()), NumAffinities), nullptr, 4436 ArrayType::Normal, /*IndexTypeQuals=*/0); 4437 AffinitiesArray = 4438 CGF.CreateMemTemp(KmpTaskAffinityInfoArrayTy, ".affs.arr.addr"); 4439 AffinitiesArray = CGF.Builder.CreateConstArrayGEP(AffinitiesArray, 0); 4440 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumAffinities, 4441 /*isSigned=*/false); 4442 } 4443 4444 const auto *KmpAffinityInfoRD = KmpTaskAffinityInfoTy->getAsRecordDecl(); 4445 // Fill array by elements without iterators. 4446 unsigned Pos = 0; 4447 bool HasIterator = false; 4448 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4449 if (C->getModifier()) { 4450 HasIterator = true; 4451 continue; 4452 } 4453 for (const Expr *E : C->varlists()) { 4454 llvm::Value *Addr; 4455 llvm::Value *Size; 4456 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4457 LValue Base = 4458 CGF.MakeAddrLValue(CGF.Builder.CreateConstGEP(AffinitiesArray, Pos), 4459 KmpTaskAffinityInfoTy); 4460 // affs[i].base_addr = &<Affinities[i].second>; 4461 LValue BaseAddrLVal = CGF.EmitLValueForField( 4462 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4463 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4464 BaseAddrLVal); 4465 // affs[i].len = sizeof(<Affinities[i].second>); 4466 LValue LenLVal = CGF.EmitLValueForField( 4467 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4468 CGF.EmitStoreOfScalar(Size, LenLVal); 4469 ++Pos; 4470 } 4471 } 4472 LValue PosLVal; 4473 if (HasIterator) { 4474 PosLVal = CGF.MakeAddrLValue( 4475 CGF.CreateMemTemp(C.getSizeType(), "affs.counter.addr"), 4476 C.getSizeType()); 4477 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4478 } 4479 // Process elements with iterators. 4480 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4481 const Expr *Modifier = C->getModifier(); 4482 if (!Modifier) 4483 continue; 4484 OMPIteratorGeneratorScope IteratorScope( 4485 CGF, cast_or_null<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts())); 4486 for (const Expr *E : C->varlists()) { 4487 llvm::Value *Addr; 4488 llvm::Value *Size; 4489 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4490 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4491 LValue Base = CGF.MakeAddrLValue( 4492 CGF.Builder.CreateGEP(AffinitiesArray, Idx), KmpTaskAffinityInfoTy); 4493 // affs[i].base_addr = &<Affinities[i].second>; 4494 LValue BaseAddrLVal = CGF.EmitLValueForField( 4495 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4496 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4497 BaseAddrLVal); 4498 // affs[i].len = sizeof(<Affinities[i].second>); 4499 LValue LenLVal = CGF.EmitLValueForField( 4500 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4501 CGF.EmitStoreOfScalar(Size, LenLVal); 4502 Idx = CGF.Builder.CreateNUWAdd( 4503 Idx, llvm::ConstantInt::get(Idx->getType(), 1)); 4504 CGF.EmitStoreOfScalar(Idx, PosLVal); 4505 } 4506 } 4507 // Call to kmp_int32 __kmpc_omp_reg_task_with_affinity(ident_t *loc_ref, 4508 // kmp_int32 gtid, kmp_task_t *new_task, kmp_int32 4509 // naffins, kmp_task_affinity_info_t *affin_list); 4510 llvm::Value *LocRef = emitUpdateLocation(CGF, Loc); 4511 llvm::Value *GTid = getThreadID(CGF, Loc); 4512 llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4513 AffinitiesArray.getPointer(), CGM.VoidPtrTy); 4514 // FIXME: Emit the function and ignore its result for now unless the 4515 // runtime function is properly implemented. 4516 (void)CGF.EmitRuntimeCall( 4517 OMPBuilder.getOrCreateRuntimeFunction( 4518 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity), 4519 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr}); 4520 } 4521 llvm::Value *NewTaskNewTaskTTy = 4522 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4523 NewTask, KmpTaskTWithPrivatesPtrTy); 4524 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 4525 KmpTaskTWithPrivatesQTy); 4526 LValue TDBase = 4527 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4528 // Fill the data in the resulting kmp_task_t record. 4529 // Copy shareds if there are any. 4530 Address KmpTaskSharedsPtr = Address::invalid(); 4531 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 4532 KmpTaskSharedsPtr = Address::deprecated( 4533 CGF.EmitLoadOfScalar( 4534 CGF.EmitLValueForField( 4535 TDBase, 4536 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)), 4537 Loc), 4538 CGM.getNaturalTypeAlignment(SharedsTy)); 4539 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 4540 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 4541 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 4542 } 4543 // Emit initial values for private copies (if any). 4544 TaskResultTy Result; 4545 if (!Privates.empty()) { 4546 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 4547 SharedsTy, SharedsPtrTy, Data, Privates, 4548 /*ForDup=*/false); 4549 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 4550 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 4551 Result.TaskDupFn = emitTaskDupFunction( 4552 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 4553 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 4554 /*WithLastIter=*/!Data.LastprivateVars.empty()); 4555 } 4556 } 4557 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 4558 enum { Priority = 0, Destructors = 1 }; 4559 // Provide pointer to function with destructors for privates. 4560 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 4561 const RecordDecl *KmpCmplrdataUD = 4562 (*FI)->getType()->getAsUnionType()->getDecl(); 4563 if (NeedsCleanup) { 4564 llvm::Value *DestructorFn = emitDestructorsFunction( 4565 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4566 KmpTaskTWithPrivatesQTy); 4567 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 4568 LValue DestructorsLV = CGF.EmitLValueForField( 4569 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 4570 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4571 DestructorFn, KmpRoutineEntryPtrTy), 4572 DestructorsLV); 4573 } 4574 // Set priority. 4575 if (Data.Priority.getInt()) { 4576 LValue Data2LV = CGF.EmitLValueForField( 4577 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 4578 LValue PriorityLV = CGF.EmitLValueForField( 4579 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 4580 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 4581 } 4582 Result.NewTask = NewTask; 4583 Result.TaskEntry = TaskEntry; 4584 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 4585 Result.TDBase = TDBase; 4586 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 4587 return Result; 4588 } 4589 4590 namespace { 4591 /// Dependence kind for RTL. 4592 enum RTLDependenceKindTy { 4593 DepIn = 0x01, 4594 DepInOut = 0x3, 4595 DepMutexInOutSet = 0x4, 4596 DepInOutSet = 0x8 4597 }; 4598 /// Fields ids in kmp_depend_info record. 4599 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 4600 } // namespace 4601 4602 /// Translates internal dependency kind into the runtime kind. 4603 static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) { 4604 RTLDependenceKindTy DepKind; 4605 switch (K) { 4606 case OMPC_DEPEND_in: 4607 DepKind = DepIn; 4608 break; 4609 // Out and InOut dependencies must use the same code. 4610 case OMPC_DEPEND_out: 4611 case OMPC_DEPEND_inout: 4612 DepKind = DepInOut; 4613 break; 4614 case OMPC_DEPEND_mutexinoutset: 4615 DepKind = DepMutexInOutSet; 4616 break; 4617 case OMPC_DEPEND_inoutset: 4618 DepKind = DepInOutSet; 4619 break; 4620 case OMPC_DEPEND_source: 4621 case OMPC_DEPEND_sink: 4622 case OMPC_DEPEND_depobj: 4623 case OMPC_DEPEND_unknown: 4624 llvm_unreachable("Unknown task dependence type"); 4625 } 4626 return DepKind; 4627 } 4628 4629 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4630 static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, 4631 QualType &FlagsTy) { 4632 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 4633 if (KmpDependInfoTy.isNull()) { 4634 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 4635 KmpDependInfoRD->startDefinition(); 4636 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 4637 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 4638 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 4639 KmpDependInfoRD->completeDefinition(); 4640 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 4641 } 4642 } 4643 4644 std::pair<llvm::Value *, LValue> 4645 CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, 4646 SourceLocation Loc) { 4647 ASTContext &C = CGM.getContext(); 4648 QualType FlagsTy; 4649 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4650 RecordDecl *KmpDependInfoRD = 4651 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4652 LValue Base = CGF.EmitLoadOfPointerLValue( 4653 DepobjLVal.getAddress(CGF), 4654 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4655 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4656 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4657 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy), 4658 CGF.ConvertTypeForMem(KmpDependInfoTy)); 4659 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4660 Base.getTBAAInfo()); 4661 Address DepObjAddr = CGF.Builder.CreateGEP( 4662 Addr, llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4663 LValue NumDepsBase = CGF.MakeAddrLValue( 4664 DepObjAddr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); 4665 // NumDeps = deps[i].base_addr; 4666 LValue BaseAddrLVal = CGF.EmitLValueForField( 4667 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4668 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc); 4669 return std::make_pair(NumDeps, Base); 4670 } 4671 4672 static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4673 llvm::PointerUnion<unsigned *, LValue *> Pos, 4674 const OMPTaskDataTy::DependData &Data, 4675 Address DependenciesArray) { 4676 CodeGenModule &CGM = CGF.CGM; 4677 ASTContext &C = CGM.getContext(); 4678 QualType FlagsTy; 4679 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4680 RecordDecl *KmpDependInfoRD = 4681 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4682 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 4683 4684 OMPIteratorGeneratorScope IteratorScope( 4685 CGF, cast_or_null<OMPIteratorExpr>( 4686 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4687 : nullptr)); 4688 for (const Expr *E : Data.DepExprs) { 4689 llvm::Value *Addr; 4690 llvm::Value *Size; 4691 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4692 LValue Base; 4693 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4694 Base = CGF.MakeAddrLValue( 4695 CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy); 4696 } else { 4697 LValue &PosLVal = *Pos.get<LValue *>(); 4698 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4699 Base = CGF.MakeAddrLValue( 4700 CGF.Builder.CreateGEP(DependenciesArray, Idx), KmpDependInfoTy); 4701 } 4702 // deps[i].base_addr = &<Dependencies[i].second>; 4703 LValue BaseAddrLVal = CGF.EmitLValueForField( 4704 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4705 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4706 BaseAddrLVal); 4707 // deps[i].len = sizeof(<Dependencies[i].second>); 4708 LValue LenLVal = CGF.EmitLValueForField( 4709 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 4710 CGF.EmitStoreOfScalar(Size, LenLVal); 4711 // deps[i].flags = <Dependencies[i].first>; 4712 RTLDependenceKindTy DepKind = translateDependencyKind(Data.DepKind); 4713 LValue FlagsLVal = CGF.EmitLValueForField( 4714 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 4715 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 4716 FlagsLVal); 4717 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4718 ++(*P); 4719 } else { 4720 LValue &PosLVal = *Pos.get<LValue *>(); 4721 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4722 Idx = CGF.Builder.CreateNUWAdd(Idx, 4723 llvm::ConstantInt::get(Idx->getType(), 1)); 4724 CGF.EmitStoreOfScalar(Idx, PosLVal); 4725 } 4726 } 4727 } 4728 4729 static SmallVector<llvm::Value *, 4> 4730 emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4731 const OMPTaskDataTy::DependData &Data) { 4732 assert(Data.DepKind == OMPC_DEPEND_depobj && 4733 "Expected depobj dependecy kind."); 4734 SmallVector<llvm::Value *, 4> Sizes; 4735 SmallVector<LValue, 4> SizeLVals; 4736 ASTContext &C = CGF.getContext(); 4737 QualType FlagsTy; 4738 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4739 RecordDecl *KmpDependInfoRD = 4740 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4741 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4742 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4743 { 4744 OMPIteratorGeneratorScope IteratorScope( 4745 CGF, cast_or_null<OMPIteratorExpr>( 4746 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4747 : nullptr)); 4748 for (const Expr *E : Data.DepExprs) { 4749 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4750 LValue Base = CGF.EmitLoadOfPointerLValue( 4751 DepobjLVal.getAddress(CGF), 4752 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4753 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4754 Base.getAddress(CGF), KmpDependInfoPtrT, 4755 CGF.ConvertTypeForMem(KmpDependInfoTy)); 4756 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4757 Base.getTBAAInfo()); 4758 Address DepObjAddr = CGF.Builder.CreateGEP( 4759 Addr, llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4760 LValue NumDepsBase = CGF.MakeAddrLValue( 4761 DepObjAddr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); 4762 // NumDeps = deps[i].base_addr; 4763 LValue BaseAddrLVal = CGF.EmitLValueForField( 4764 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4765 llvm::Value *NumDeps = 4766 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4767 LValue NumLVal = CGF.MakeAddrLValue( 4768 CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"), 4769 C.getUIntPtrType()); 4770 CGF.Builder.CreateStore(llvm::ConstantInt::get(CGF.IntPtrTy, 0), 4771 NumLVal.getAddress(CGF)); 4772 llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc()); 4773 llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps); 4774 CGF.EmitStoreOfScalar(Add, NumLVal); 4775 SizeLVals.push_back(NumLVal); 4776 } 4777 } 4778 for (unsigned I = 0, E = SizeLVals.size(); I < E; ++I) { 4779 llvm::Value *Size = 4780 CGF.EmitLoadOfScalar(SizeLVals[I], Data.DepExprs[I]->getExprLoc()); 4781 Sizes.push_back(Size); 4782 } 4783 return Sizes; 4784 } 4785 4786 static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4787 LValue PosLVal, 4788 const OMPTaskDataTy::DependData &Data, 4789 Address DependenciesArray) { 4790 assert(Data.DepKind == OMPC_DEPEND_depobj && 4791 "Expected depobj dependecy kind."); 4792 ASTContext &C = CGF.getContext(); 4793 QualType FlagsTy; 4794 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4795 RecordDecl *KmpDependInfoRD = 4796 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4797 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4798 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4799 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy); 4800 { 4801 OMPIteratorGeneratorScope IteratorScope( 4802 CGF, cast_or_null<OMPIteratorExpr>( 4803 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4804 : nullptr)); 4805 for (unsigned I = 0, End = Data.DepExprs.size(); I < End; ++I) { 4806 const Expr *E = Data.DepExprs[I]; 4807 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4808 LValue Base = CGF.EmitLoadOfPointerLValue( 4809 DepobjLVal.getAddress(CGF), 4810 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4811 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4812 Base.getAddress(CGF), KmpDependInfoPtrT, 4813 CGF.ConvertTypeForMem(KmpDependInfoTy)); 4814 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4815 Base.getTBAAInfo()); 4816 4817 // Get number of elements in a single depobj. 4818 Address DepObjAddr = CGF.Builder.CreateGEP( 4819 Addr, llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4820 LValue NumDepsBase = CGF.MakeAddrLValue( 4821 DepObjAddr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); 4822 // NumDeps = deps[i].base_addr; 4823 LValue BaseAddrLVal = CGF.EmitLValueForField( 4824 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4825 llvm::Value *NumDeps = 4826 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4827 4828 // memcopy dependency data. 4829 llvm::Value *Size = CGF.Builder.CreateNUWMul( 4830 ElSize, 4831 CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); 4832 llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4833 Address DepAddr = CGF.Builder.CreateGEP(DependenciesArray, Pos); 4834 CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); 4835 4836 // Increase pos. 4837 // pos += size; 4838 llvm::Value *Add = CGF.Builder.CreateNUWAdd(Pos, NumDeps); 4839 CGF.EmitStoreOfScalar(Add, PosLVal); 4840 } 4841 } 4842 } 4843 4844 std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause( 4845 CodeGenFunction &CGF, ArrayRef<OMPTaskDataTy::DependData> Dependencies, 4846 SourceLocation Loc) { 4847 if (llvm::all_of(Dependencies, [](const OMPTaskDataTy::DependData &D) { 4848 return D.DepExprs.empty(); 4849 })) 4850 return std::make_pair(nullptr, Address::invalid()); 4851 // Process list of dependencies. 4852 ASTContext &C = CGM.getContext(); 4853 Address DependenciesArray = Address::invalid(); 4854 llvm::Value *NumOfElements = nullptr; 4855 unsigned NumDependencies = std::accumulate( 4856 Dependencies.begin(), Dependencies.end(), 0, 4857 [](unsigned V, const OMPTaskDataTy::DependData &D) { 4858 return D.DepKind == OMPC_DEPEND_depobj 4859 ? V 4860 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size())); 4861 }); 4862 QualType FlagsTy; 4863 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4864 bool HasDepobjDeps = false; 4865 bool HasRegularWithIterators = false; 4866 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0); 4867 llvm::Value *NumOfRegularWithIterators = 4868 llvm::ConstantInt::get(CGF.IntPtrTy, 0); 4869 // Calculate number of depobj dependecies and regular deps with the iterators. 4870 for (const OMPTaskDataTy::DependData &D : Dependencies) { 4871 if (D.DepKind == OMPC_DEPEND_depobj) { 4872 SmallVector<llvm::Value *, 4> Sizes = 4873 emitDepobjElementsSizes(CGF, KmpDependInfoTy, D); 4874 for (llvm::Value *Size : Sizes) { 4875 NumOfDepobjElements = 4876 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, Size); 4877 } 4878 HasDepobjDeps = true; 4879 continue; 4880 } 4881 // Include number of iterations, if any. 4882 4883 if (const auto *IE = cast_or_null<OMPIteratorExpr>(D.IteratorExpr)) { 4884 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4885 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4886 Sz = CGF.Builder.CreateIntCast(Sz, CGF.IntPtrTy, /*isSigned=*/false); 4887 llvm::Value *NumClauseDeps = CGF.Builder.CreateNUWMul( 4888 Sz, llvm::ConstantInt::get(CGF.IntPtrTy, D.DepExprs.size())); 4889 NumOfRegularWithIterators = 4890 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps); 4891 } 4892 HasRegularWithIterators = true; 4893 continue; 4894 } 4895 } 4896 4897 QualType KmpDependInfoArrayTy; 4898 if (HasDepobjDeps || HasRegularWithIterators) { 4899 NumOfElements = llvm::ConstantInt::get(CGM.IntPtrTy, NumDependencies, 4900 /*isSigned=*/false); 4901 if (HasDepobjDeps) { 4902 NumOfElements = 4903 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements); 4904 } 4905 if (HasRegularWithIterators) { 4906 NumOfElements = 4907 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements); 4908 } 4909 auto *OVE = new (C) OpaqueValueExpr( 4910 Loc, C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0), 4911 VK_PRValue); 4912 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, OVE, 4913 RValue::get(NumOfElements)); 4914 KmpDependInfoArrayTy = 4915 C.getVariableArrayType(KmpDependInfoTy, OVE, ArrayType::Normal, 4916 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4917 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy); 4918 // Properly emit variable-sized array. 4919 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy, 4920 ImplicitParamDecl::Other); 4921 CGF.EmitVarDecl(*PD); 4922 DependenciesArray = CGF.GetAddrOfLocalVar(PD); 4923 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4924 /*isSigned=*/false); 4925 } else { 4926 KmpDependInfoArrayTy = C.getConstantArrayType( 4927 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), nullptr, 4928 ArrayType::Normal, /*IndexTypeQuals=*/0); 4929 DependenciesArray = 4930 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 4931 DependenciesArray = CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0); 4932 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 4933 /*isSigned=*/false); 4934 } 4935 unsigned Pos = 0; 4936 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4937 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4938 Dependencies[I].IteratorExpr) 4939 continue; 4940 emitDependData(CGF, KmpDependInfoTy, &Pos, Dependencies[I], 4941 DependenciesArray); 4942 } 4943 // Copy regular dependecies with iterators. 4944 LValue PosLVal = CGF.MakeAddrLValue( 4945 CGF.CreateMemTemp(C.getSizeType(), "dep.counter.addr"), C.getSizeType()); 4946 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4947 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4948 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4949 !Dependencies[I].IteratorExpr) 4950 continue; 4951 emitDependData(CGF, KmpDependInfoTy, &PosLVal, Dependencies[I], 4952 DependenciesArray); 4953 } 4954 // Copy final depobj arrays without iterators. 4955 if (HasDepobjDeps) { 4956 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4957 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj) 4958 continue; 4959 emitDepobjElements(CGF, KmpDependInfoTy, PosLVal, Dependencies[I], 4960 DependenciesArray); 4961 } 4962 } 4963 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4964 DependenciesArray, CGF.VoidPtrTy, CGF.Int8Ty); 4965 return std::make_pair(NumOfElements, DependenciesArray); 4966 } 4967 4968 Address CGOpenMPRuntime::emitDepobjDependClause( 4969 CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, 4970 SourceLocation Loc) { 4971 if (Dependencies.DepExprs.empty()) 4972 return Address::invalid(); 4973 // Process list of dependencies. 4974 ASTContext &C = CGM.getContext(); 4975 Address DependenciesArray = Address::invalid(); 4976 unsigned NumDependencies = Dependencies.DepExprs.size(); 4977 QualType FlagsTy; 4978 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4979 RecordDecl *KmpDependInfoRD = 4980 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4981 4982 llvm::Value *Size; 4983 // Define type kmp_depend_info[<Dependencies.size()>]; 4984 // For depobj reserve one extra element to store the number of elements. 4985 // It is required to handle depobj(x) update(in) construct. 4986 // kmp_depend_info[<Dependencies.size()>] deps; 4987 llvm::Value *NumDepsVal; 4988 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoTy); 4989 if (const auto *IE = 4990 cast_or_null<OMPIteratorExpr>(Dependencies.IteratorExpr)) { 4991 NumDepsVal = llvm::ConstantInt::get(CGF.SizeTy, 1); 4992 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4993 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4994 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4995 NumDepsVal = CGF.Builder.CreateNUWMul(NumDepsVal, Sz); 4996 } 4997 Size = CGF.Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.SizeTy, 1), 4998 NumDepsVal); 4999 CharUnits SizeInBytes = 5000 C.getTypeSizeInChars(KmpDependInfoTy).alignTo(Align); 5001 llvm::Value *RecSize = CGM.getSize(SizeInBytes); 5002 Size = CGF.Builder.CreateNUWMul(Size, RecSize); 5003 NumDepsVal = 5004 CGF.Builder.CreateIntCast(NumDepsVal, CGF.IntPtrTy, /*isSigned=*/false); 5005 } else { 5006 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5007 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1), 5008 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5009 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy); 5010 Size = CGM.getSize(Sz.alignTo(Align)); 5011 NumDepsVal = llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies); 5012 } 5013 // Need to allocate on the dynamic memory. 5014 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5015 // Use default allocator. 5016 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5017 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 5018 5019 llvm::Value *Addr = 5020 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5021 CGM.getModule(), OMPRTL___kmpc_alloc), 5022 Args, ".dep.arr.addr"); 5023 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5024 Addr, CGF.ConvertTypeForMem(KmpDependInfoTy)->getPointerTo()); 5025 DependenciesArray = Address::deprecated(Addr, Align); 5026 // Write number of elements in the first element of array for depobj. 5027 LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy); 5028 // deps[i].base_addr = NumDependencies; 5029 LValue BaseAddrLVal = CGF.EmitLValueForField( 5030 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5031 CGF.EmitStoreOfScalar(NumDepsVal, BaseAddrLVal); 5032 llvm::PointerUnion<unsigned *, LValue *> Pos; 5033 unsigned Idx = 1; 5034 LValue PosLVal; 5035 if (Dependencies.IteratorExpr) { 5036 PosLVal = CGF.MakeAddrLValue( 5037 CGF.CreateMemTemp(C.getSizeType(), "iterator.counter.addr"), 5038 C.getSizeType()); 5039 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Idx), PosLVal, 5040 /*IsInit=*/true); 5041 Pos = &PosLVal; 5042 } else { 5043 Pos = &Idx; 5044 } 5045 emitDependData(CGF, KmpDependInfoTy, Pos, Dependencies, DependenciesArray); 5046 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5047 CGF.Builder.CreateConstGEP(DependenciesArray, 1), CGF.VoidPtrTy, 5048 CGF.Int8Ty); 5049 return DependenciesArray; 5050 } 5051 5052 void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, 5053 SourceLocation Loc) { 5054 ASTContext &C = CGM.getContext(); 5055 QualType FlagsTy; 5056 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5057 LValue Base = CGF.EmitLoadOfPointerLValue( 5058 DepobjLVal.getAddress(CGF), 5059 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5060 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5061 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5062 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy), 5063 CGF.ConvertTypeForMem(KmpDependInfoTy)); 5064 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5065 Addr.getElementType(), Addr.getPointer(), 5066 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5067 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, 5068 CGF.VoidPtrTy); 5069 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5070 // Use default allocator. 5071 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5072 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator}; 5073 5074 // _kmpc_free(gtid, addr, nullptr); 5075 (void)CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5076 CGM.getModule(), OMPRTL___kmpc_free), 5077 Args); 5078 } 5079 5080 void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, 5081 OpenMPDependClauseKind NewDepKind, 5082 SourceLocation Loc) { 5083 ASTContext &C = CGM.getContext(); 5084 QualType FlagsTy; 5085 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5086 RecordDecl *KmpDependInfoRD = 5087 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5088 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5089 llvm::Value *NumDeps; 5090 LValue Base; 5091 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 5092 5093 Address Begin = Base.getAddress(CGF); 5094 // Cast from pointer to array type to pointer to single element. 5095 llvm::Value *End = CGF.Builder.CreateGEP( 5096 Begin.getElementType(), Begin.getPointer(), NumDeps); 5097 // The basic structure here is a while-do loop. 5098 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); 5099 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); 5100 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5101 CGF.EmitBlock(BodyBB); 5102 llvm::PHINode *ElementPHI = 5103 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); 5104 ElementPHI->addIncoming(Begin.getPointer(), EntryBB); 5105 Begin = Begin.withPointer(ElementPHI); 5106 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), 5107 Base.getTBAAInfo()); 5108 // deps[i].flags = NewDepKind; 5109 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind); 5110 LValue FlagsLVal = CGF.EmitLValueForField( 5111 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5112 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5113 FlagsLVal); 5114 5115 // Shift the address forward by one element. 5116 Address ElementNext = 5117 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); 5118 ElementPHI->addIncoming(ElementNext.getPointer(), 5119 CGF.Builder.GetInsertBlock()); 5120 llvm::Value *IsEmpty = 5121 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); 5122 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5123 // Done. 5124 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5125 } 5126 5127 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5128 const OMPExecutableDirective &D, 5129 llvm::Function *TaskFunction, 5130 QualType SharedsTy, Address Shareds, 5131 const Expr *IfCond, 5132 const OMPTaskDataTy &Data) { 5133 if (!CGF.HaveInsertPoint()) 5134 return; 5135 5136 TaskResultTy Result = 5137 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5138 llvm::Value *NewTask = Result.NewTask; 5139 llvm::Function *TaskEntry = Result.TaskEntry; 5140 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5141 LValue TDBase = Result.TDBase; 5142 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5143 // Process list of dependences. 5144 Address DependenciesArray = Address::invalid(); 5145 llvm::Value *NumOfElements; 5146 std::tie(NumOfElements, DependenciesArray) = 5147 emitDependClause(CGF, Data.Dependences, Loc); 5148 5149 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5150 // libcall. 5151 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5152 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5153 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5154 // list is not empty 5155 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5156 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5157 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5158 llvm::Value *DepTaskArgs[7]; 5159 if (!Data.Dependences.empty()) { 5160 DepTaskArgs[0] = UpLoc; 5161 DepTaskArgs[1] = ThreadID; 5162 DepTaskArgs[2] = NewTask; 5163 DepTaskArgs[3] = NumOfElements; 5164 DepTaskArgs[4] = DependenciesArray.getPointer(); 5165 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5166 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5167 } 5168 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs, 5169 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5170 if (!Data.Tied) { 5171 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5172 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5173 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5174 } 5175 if (!Data.Dependences.empty()) { 5176 CGF.EmitRuntimeCall( 5177 OMPBuilder.getOrCreateRuntimeFunction( 5178 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps), 5179 DepTaskArgs); 5180 } else { 5181 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5182 CGM.getModule(), OMPRTL___kmpc_omp_task), 5183 TaskArgs); 5184 } 5185 // Check if parent region is untied and build return for untied task; 5186 if (auto *Region = 5187 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5188 Region->emitUntiedSwitch(CGF); 5189 }; 5190 5191 llvm::Value *DepWaitTaskArgs[6]; 5192 if (!Data.Dependences.empty()) { 5193 DepWaitTaskArgs[0] = UpLoc; 5194 DepWaitTaskArgs[1] = ThreadID; 5195 DepWaitTaskArgs[2] = NumOfElements; 5196 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5197 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5198 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5199 } 5200 auto &M = CGM.getModule(); 5201 auto &&ElseCodeGen = [this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy, 5202 TaskEntry, &Data, &DepWaitTaskArgs, 5203 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5204 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5205 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5206 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5207 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5208 // is specified. 5209 if (!Data.Dependences.empty()) 5210 CGF.EmitRuntimeCall( 5211 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_wait_deps), 5212 DepWaitTaskArgs); 5213 // Call proxy_task_entry(gtid, new_task); 5214 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5215 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5216 Action.Enter(CGF); 5217 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5218 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5219 OutlinedFnArgs); 5220 }; 5221 5222 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5223 // kmp_task_t *new_task); 5224 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5225 // kmp_task_t *new_task); 5226 RegionCodeGenTy RCG(CodeGen); 5227 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 5228 M, OMPRTL___kmpc_omp_task_begin_if0), 5229 TaskArgs, 5230 OMPBuilder.getOrCreateRuntimeFunction( 5231 M, OMPRTL___kmpc_omp_task_complete_if0), 5232 TaskArgs); 5233 RCG.setAction(Action); 5234 RCG(CGF); 5235 }; 5236 5237 if (IfCond) { 5238 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5239 } else { 5240 RegionCodeGenTy ThenRCG(ThenCodeGen); 5241 ThenRCG(CGF); 5242 } 5243 } 5244 5245 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5246 const OMPLoopDirective &D, 5247 llvm::Function *TaskFunction, 5248 QualType SharedsTy, Address Shareds, 5249 const Expr *IfCond, 5250 const OMPTaskDataTy &Data) { 5251 if (!CGF.HaveInsertPoint()) 5252 return; 5253 TaskResultTy Result = 5254 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5255 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5256 // libcall. 5257 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5258 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5259 // sched, kmp_uint64 grainsize, void *task_dup); 5260 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5261 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5262 llvm::Value *IfVal; 5263 if (IfCond) { 5264 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5265 /*isSigned=*/true); 5266 } else { 5267 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5268 } 5269 5270 LValue LBLVal = CGF.EmitLValueForField( 5271 Result.TDBase, 5272 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5273 const auto *LBVar = 5274 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5275 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5276 LBLVal.getQuals(), 5277 /*IsInitializer=*/true); 5278 LValue UBLVal = CGF.EmitLValueForField( 5279 Result.TDBase, 5280 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5281 const auto *UBVar = 5282 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5283 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5284 UBLVal.getQuals(), 5285 /*IsInitializer=*/true); 5286 LValue StLVal = CGF.EmitLValueForField( 5287 Result.TDBase, 5288 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5289 const auto *StVar = 5290 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5291 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5292 StLVal.getQuals(), 5293 /*IsInitializer=*/true); 5294 // Store reductions address. 5295 LValue RedLVal = CGF.EmitLValueForField( 5296 Result.TDBase, 5297 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5298 if (Data.Reductions) { 5299 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5300 } else { 5301 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5302 CGF.getContext().VoidPtrTy); 5303 } 5304 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5305 llvm::Value *TaskArgs[] = { 5306 UpLoc, 5307 ThreadID, 5308 Result.NewTask, 5309 IfVal, 5310 LBLVal.getPointer(CGF), 5311 UBLVal.getPointer(CGF), 5312 CGF.EmitLoadOfScalar(StLVal, Loc), 5313 llvm::ConstantInt::getSigned( 5314 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5315 llvm::ConstantInt::getSigned( 5316 CGF.IntTy, Data.Schedule.getPointer() 5317 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5318 : NoSchedule), 5319 Data.Schedule.getPointer() 5320 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5321 /*isSigned=*/false) 5322 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5323 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5324 Result.TaskDupFn, CGF.VoidPtrTy) 5325 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5326 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5327 CGM.getModule(), OMPRTL___kmpc_taskloop), 5328 TaskArgs); 5329 } 5330 5331 /// Emit reduction operation for each element of array (required for 5332 /// array sections) LHS op = RHS. 5333 /// \param Type Type of array. 5334 /// \param LHSVar Variable on the left side of the reduction operation 5335 /// (references element of array in original variable). 5336 /// \param RHSVar Variable on the right side of the reduction operation 5337 /// (references element of array in original variable). 5338 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5339 /// RHSVar. 5340 static void EmitOMPAggregateReduction( 5341 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5342 const VarDecl *RHSVar, 5343 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5344 const Expr *, const Expr *)> &RedOpGen, 5345 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5346 const Expr *UpExpr = nullptr) { 5347 // Perform element-by-element initialization. 5348 QualType ElementTy; 5349 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5350 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5351 5352 // Drill down to the base element type on both arrays. 5353 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5354 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5355 5356 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5357 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5358 // Cast from pointer to array type to pointer to single element. 5359 llvm::Value *LHSEnd = 5360 CGF.Builder.CreateGEP(LHSAddr.getElementType(), LHSBegin, NumElements); 5361 // The basic structure here is a while-do loop. 5362 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5363 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5364 llvm::Value *IsEmpty = 5365 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5366 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5367 5368 // Enter the loop body, making that address the current address. 5369 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5370 CGF.EmitBlock(BodyBB); 5371 5372 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5373 5374 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5375 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5376 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5377 Address RHSElementCurrent = Address::deprecated( 5378 RHSElementPHI, 5379 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5380 5381 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5382 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5383 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5384 Address LHSElementCurrent = Address::deprecated( 5385 LHSElementPHI, 5386 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5387 5388 // Emit copy. 5389 CodeGenFunction::OMPPrivateScope Scope(CGF); 5390 Scope.addPrivate(LHSVar, LHSElementCurrent); 5391 Scope.addPrivate(RHSVar, RHSElementCurrent); 5392 Scope.Privatize(); 5393 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5394 Scope.ForceCleanup(); 5395 5396 // Shift the address forward by one element. 5397 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5398 LHSAddr.getElementType(), LHSElementPHI, /*Idx0=*/1, 5399 "omp.arraycpy.dest.element"); 5400 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5401 RHSAddr.getElementType(), RHSElementPHI, /*Idx0=*/1, 5402 "omp.arraycpy.src.element"); 5403 // Check whether we've reached the end. 5404 llvm::Value *Done = 5405 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5406 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5407 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5408 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5409 5410 // Done. 5411 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5412 } 5413 5414 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5415 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5416 /// UDR combiner function. 5417 static void emitReductionCombiner(CodeGenFunction &CGF, 5418 const Expr *ReductionOp) { 5419 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5420 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5421 if (const auto *DRE = 5422 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5423 if (const auto *DRD = 5424 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5425 std::pair<llvm::Function *, llvm::Function *> Reduction = 5426 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5427 RValue Func = RValue::get(Reduction.first); 5428 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5429 CGF.EmitIgnoredExpr(ReductionOp); 5430 return; 5431 } 5432 CGF.EmitIgnoredExpr(ReductionOp); 5433 } 5434 5435 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5436 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5437 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5438 ArrayRef<const Expr *> ReductionOps) { 5439 ASTContext &C = CGM.getContext(); 5440 5441 // void reduction_func(void *LHSArg, void *RHSArg); 5442 FunctionArgList Args; 5443 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5444 ImplicitParamDecl::Other); 5445 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5446 ImplicitParamDecl::Other); 5447 Args.push_back(&LHSArg); 5448 Args.push_back(&RHSArg); 5449 const auto &CGFI = 5450 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5451 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5452 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5453 llvm::GlobalValue::InternalLinkage, Name, 5454 &CGM.getModule()); 5455 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5456 Fn->setDoesNotRecurse(); 5457 CodeGenFunction CGF(CGM); 5458 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5459 5460 // Dst = (void*[n])(LHSArg); 5461 // Src = (void*[n])(RHSArg); 5462 Address LHS = Address::deprecated( 5463 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5464 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), ArgsType), 5465 CGF.getPointerAlign()); 5466 Address RHS = Address::deprecated( 5467 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5468 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), ArgsType), 5469 CGF.getPointerAlign()); 5470 5471 // ... 5472 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5473 // ... 5474 CodeGenFunction::OMPPrivateScope Scope(CGF); 5475 const auto *IPriv = Privates.begin(); 5476 unsigned Idx = 0; 5477 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5478 const auto *RHSVar = 5479 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5480 Scope.addPrivate(RHSVar, emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar)); 5481 const auto *LHSVar = 5482 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5483 Scope.addPrivate(LHSVar, emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar)); 5484 QualType PrivTy = (*IPriv)->getType(); 5485 if (PrivTy->isVariablyModifiedType()) { 5486 // Get array size and emit VLA type. 5487 ++Idx; 5488 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5489 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5490 const VariableArrayType *VLA = 5491 CGF.getContext().getAsVariableArrayType(PrivTy); 5492 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5493 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5494 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5495 CGF.EmitVariablyModifiedType(PrivTy); 5496 } 5497 } 5498 Scope.Privatize(); 5499 IPriv = Privates.begin(); 5500 const auto *ILHS = LHSExprs.begin(); 5501 const auto *IRHS = RHSExprs.begin(); 5502 for (const Expr *E : ReductionOps) { 5503 if ((*IPriv)->getType()->isArrayType()) { 5504 // Emit reduction for array section. 5505 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5506 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5507 EmitOMPAggregateReduction( 5508 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5509 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5510 emitReductionCombiner(CGF, E); 5511 }); 5512 } else { 5513 // Emit reduction for array subscript or single variable. 5514 emitReductionCombiner(CGF, E); 5515 } 5516 ++IPriv; 5517 ++ILHS; 5518 ++IRHS; 5519 } 5520 Scope.ForceCleanup(); 5521 CGF.FinishFunction(); 5522 return Fn; 5523 } 5524 5525 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5526 const Expr *ReductionOp, 5527 const Expr *PrivateRef, 5528 const DeclRefExpr *LHS, 5529 const DeclRefExpr *RHS) { 5530 if (PrivateRef->getType()->isArrayType()) { 5531 // Emit reduction for array section. 5532 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5533 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5534 EmitOMPAggregateReduction( 5535 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5536 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5537 emitReductionCombiner(CGF, ReductionOp); 5538 }); 5539 } else { 5540 // Emit reduction for array subscript or single variable. 5541 emitReductionCombiner(CGF, ReductionOp); 5542 } 5543 } 5544 5545 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5546 ArrayRef<const Expr *> Privates, 5547 ArrayRef<const Expr *> LHSExprs, 5548 ArrayRef<const Expr *> RHSExprs, 5549 ArrayRef<const Expr *> ReductionOps, 5550 ReductionOptionsTy Options) { 5551 if (!CGF.HaveInsertPoint()) 5552 return; 5553 5554 bool WithNowait = Options.WithNowait; 5555 bool SimpleReduction = Options.SimpleReduction; 5556 5557 // Next code should be emitted for reduction: 5558 // 5559 // static kmp_critical_name lock = { 0 }; 5560 // 5561 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5562 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5563 // ... 5564 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5565 // *(Type<n>-1*)rhs[<n>-1]); 5566 // } 5567 // 5568 // ... 5569 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5570 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5571 // RedList, reduce_func, &<lock>)) { 5572 // case 1: 5573 // ... 5574 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5575 // ... 5576 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5577 // break; 5578 // case 2: 5579 // ... 5580 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5581 // ... 5582 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5583 // break; 5584 // default:; 5585 // } 5586 // 5587 // if SimpleReduction is true, only the next code is generated: 5588 // ... 5589 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5590 // ... 5591 5592 ASTContext &C = CGM.getContext(); 5593 5594 if (SimpleReduction) { 5595 CodeGenFunction::RunCleanupsScope Scope(CGF); 5596 const auto *IPriv = Privates.begin(); 5597 const auto *ILHS = LHSExprs.begin(); 5598 const auto *IRHS = RHSExprs.begin(); 5599 for (const Expr *E : ReductionOps) { 5600 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5601 cast<DeclRefExpr>(*IRHS)); 5602 ++IPriv; 5603 ++ILHS; 5604 ++IRHS; 5605 } 5606 return; 5607 } 5608 5609 // 1. Build a list of reduction variables. 5610 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5611 auto Size = RHSExprs.size(); 5612 for (const Expr *E : Privates) { 5613 if (E->getType()->isVariablyModifiedType()) 5614 // Reserve place for array size. 5615 ++Size; 5616 } 5617 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5618 QualType ReductionArrayTy = 5619 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5620 /*IndexTypeQuals=*/0); 5621 Address ReductionList = 5622 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5623 const auto *IPriv = Privates.begin(); 5624 unsigned Idx = 0; 5625 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5626 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5627 CGF.Builder.CreateStore( 5628 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5629 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5630 Elem); 5631 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5632 // Store array size. 5633 ++Idx; 5634 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5635 llvm::Value *Size = CGF.Builder.CreateIntCast( 5636 CGF.getVLASize( 5637 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5638 .NumElts, 5639 CGF.SizeTy, /*isSigned=*/false); 5640 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5641 Elem); 5642 } 5643 } 5644 5645 // 2. Emit reduce_func(). 5646 llvm::Function *ReductionFn = emitReductionFunction( 5647 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5648 LHSExprs, RHSExprs, ReductionOps); 5649 5650 // 3. Create static kmp_critical_name lock = { 0 }; 5651 std::string Name = getName({"reduction"}); 5652 llvm::Value *Lock = getCriticalRegionLock(Name); 5653 5654 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5655 // RedList, reduce_func, &<lock>); 5656 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5657 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5658 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5659 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5660 ReductionList.getPointer(), CGF.VoidPtrTy); 5661 llvm::Value *Args[] = { 5662 IdentTLoc, // ident_t *<loc> 5663 ThreadId, // i32 <gtid> 5664 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5665 ReductionArrayTySize, // size_type sizeof(RedList) 5666 RL, // void *RedList 5667 ReductionFn, // void (*) (void *, void *) <reduce_func> 5668 Lock // kmp_critical_name *&<lock> 5669 }; 5670 llvm::Value *Res = CGF.EmitRuntimeCall( 5671 OMPBuilder.getOrCreateRuntimeFunction( 5672 CGM.getModule(), 5673 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce), 5674 Args); 5675 5676 // 5. Build switch(res) 5677 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5678 llvm::SwitchInst *SwInst = 5679 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5680 5681 // 6. Build case 1: 5682 // ... 5683 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5684 // ... 5685 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5686 // break; 5687 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5688 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5689 CGF.EmitBlock(Case1BB); 5690 5691 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5692 llvm::Value *EndArgs[] = { 5693 IdentTLoc, // ident_t *<loc> 5694 ThreadId, // i32 <gtid> 5695 Lock // kmp_critical_name *&<lock> 5696 }; 5697 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5698 CodeGenFunction &CGF, PrePostActionTy &Action) { 5699 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5700 const auto *IPriv = Privates.begin(); 5701 const auto *ILHS = LHSExprs.begin(); 5702 const auto *IRHS = RHSExprs.begin(); 5703 for (const Expr *E : ReductionOps) { 5704 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5705 cast<DeclRefExpr>(*IRHS)); 5706 ++IPriv; 5707 ++ILHS; 5708 ++IRHS; 5709 } 5710 }; 5711 RegionCodeGenTy RCG(CodeGen); 5712 CommonActionTy Action( 5713 nullptr, llvm::None, 5714 OMPBuilder.getOrCreateRuntimeFunction( 5715 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait 5716 : OMPRTL___kmpc_end_reduce), 5717 EndArgs); 5718 RCG.setAction(Action); 5719 RCG(CGF); 5720 5721 CGF.EmitBranch(DefaultBB); 5722 5723 // 7. Build case 2: 5724 // ... 5725 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5726 // ... 5727 // break; 5728 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5729 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5730 CGF.EmitBlock(Case2BB); 5731 5732 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5733 CodeGenFunction &CGF, PrePostActionTy &Action) { 5734 const auto *ILHS = LHSExprs.begin(); 5735 const auto *IRHS = RHSExprs.begin(); 5736 const auto *IPriv = Privates.begin(); 5737 for (const Expr *E : ReductionOps) { 5738 const Expr *XExpr = nullptr; 5739 const Expr *EExpr = nullptr; 5740 const Expr *UpExpr = nullptr; 5741 BinaryOperatorKind BO = BO_Comma; 5742 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5743 if (BO->getOpcode() == BO_Assign) { 5744 XExpr = BO->getLHS(); 5745 UpExpr = BO->getRHS(); 5746 } 5747 } 5748 // Try to emit update expression as a simple atomic. 5749 const Expr *RHSExpr = UpExpr; 5750 if (RHSExpr) { 5751 // Analyze RHS part of the whole expression. 5752 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5753 RHSExpr->IgnoreParenImpCasts())) { 5754 // If this is a conditional operator, analyze its condition for 5755 // min/max reduction operator. 5756 RHSExpr = ACO->getCond(); 5757 } 5758 if (const auto *BORHS = 5759 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5760 EExpr = BORHS->getRHS(); 5761 BO = BORHS->getOpcode(); 5762 } 5763 } 5764 if (XExpr) { 5765 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5766 auto &&AtomicRedGen = [BO, VD, 5767 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5768 const Expr *EExpr, const Expr *UpExpr) { 5769 LValue X = CGF.EmitLValue(XExpr); 5770 RValue E; 5771 if (EExpr) 5772 E = CGF.EmitAnyExpr(EExpr); 5773 CGF.EmitOMPAtomicSimpleUpdateExpr( 5774 X, E, BO, /*IsXLHSInRHSPart=*/true, 5775 llvm::AtomicOrdering::Monotonic, Loc, 5776 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5777 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5778 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5779 CGF.emitOMPSimpleStore( 5780 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5781 VD->getType().getNonReferenceType(), Loc); 5782 PrivateScope.addPrivate(VD, LHSTemp); 5783 (void)PrivateScope.Privatize(); 5784 return CGF.EmitAnyExpr(UpExpr); 5785 }); 5786 }; 5787 if ((*IPriv)->getType()->isArrayType()) { 5788 // Emit atomic reduction for array section. 5789 const auto *RHSVar = 5790 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5791 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5792 AtomicRedGen, XExpr, EExpr, UpExpr); 5793 } else { 5794 // Emit atomic reduction for array subscript or single variable. 5795 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5796 } 5797 } else { 5798 // Emit as a critical region. 5799 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5800 const Expr *, const Expr *) { 5801 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5802 std::string Name = RT.getName({"atomic_reduction"}); 5803 RT.emitCriticalRegion( 5804 CGF, Name, 5805 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5806 Action.Enter(CGF); 5807 emitReductionCombiner(CGF, E); 5808 }, 5809 Loc); 5810 }; 5811 if ((*IPriv)->getType()->isArrayType()) { 5812 const auto *LHSVar = 5813 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5814 const auto *RHSVar = 5815 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5816 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5817 CritRedGen); 5818 } else { 5819 CritRedGen(CGF, nullptr, nullptr, nullptr); 5820 } 5821 } 5822 ++ILHS; 5823 ++IRHS; 5824 ++IPriv; 5825 } 5826 }; 5827 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5828 if (!WithNowait) { 5829 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5830 llvm::Value *EndArgs[] = { 5831 IdentTLoc, // ident_t *<loc> 5832 ThreadId, // i32 <gtid> 5833 Lock // kmp_critical_name *&<lock> 5834 }; 5835 CommonActionTy Action(nullptr, llvm::None, 5836 OMPBuilder.getOrCreateRuntimeFunction( 5837 CGM.getModule(), OMPRTL___kmpc_end_reduce), 5838 EndArgs); 5839 AtomicRCG.setAction(Action); 5840 AtomicRCG(CGF); 5841 } else { 5842 AtomicRCG(CGF); 5843 } 5844 5845 CGF.EmitBranch(DefaultBB); 5846 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5847 } 5848 5849 /// Generates unique name for artificial threadprivate variables. 5850 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5851 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5852 const Expr *Ref) { 5853 SmallString<256> Buffer; 5854 llvm::raw_svector_ostream Out(Buffer); 5855 const clang::DeclRefExpr *DE; 5856 const VarDecl *D = ::getBaseDecl(Ref, DE); 5857 if (!D) 5858 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5859 D = D->getCanonicalDecl(); 5860 std::string Name = CGM.getOpenMPRuntime().getName( 5861 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5862 Out << Prefix << Name << "_" 5863 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5864 return std::string(Out.str()); 5865 } 5866 5867 /// Emits reduction initializer function: 5868 /// \code 5869 /// void @.red_init(void* %arg, void* %orig) { 5870 /// %0 = bitcast void* %arg to <type>* 5871 /// store <type> <init>, <type>* %0 5872 /// ret void 5873 /// } 5874 /// \endcode 5875 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 5876 SourceLocation Loc, 5877 ReductionCodeGen &RCG, unsigned N) { 5878 ASTContext &C = CGM.getContext(); 5879 QualType VoidPtrTy = C.VoidPtrTy; 5880 VoidPtrTy.addRestrict(); 5881 FunctionArgList Args; 5882 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5883 ImplicitParamDecl::Other); 5884 ImplicitParamDecl ParamOrig(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5885 ImplicitParamDecl::Other); 5886 Args.emplace_back(&Param); 5887 Args.emplace_back(&ParamOrig); 5888 const auto &FnInfo = 5889 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5890 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5891 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 5892 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5893 Name, &CGM.getModule()); 5894 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5895 Fn->setDoesNotRecurse(); 5896 CodeGenFunction CGF(CGM); 5897 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5898 QualType PrivateType = RCG.getPrivateType(N); 5899 Address PrivateAddr = CGF.EmitLoadOfPointer( 5900 CGF.Builder.CreateElementBitCast( 5901 CGF.GetAddrOfLocalVar(&Param), 5902 CGF.ConvertTypeForMem(PrivateType)->getPointerTo()), 5903 C.getPointerType(PrivateType)->castAs<PointerType>()); 5904 llvm::Value *Size = nullptr; 5905 // If the size of the reduction item is non-constant, load it from global 5906 // threadprivate variable. 5907 if (RCG.getSizes(N).second) { 5908 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5909 CGF, CGM.getContext().getSizeType(), 5910 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5911 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5912 CGM.getContext().getSizeType(), Loc); 5913 } 5914 RCG.emitAggregateType(CGF, N, Size); 5915 Address OrigAddr = Address::invalid(); 5916 // If initializer uses initializer from declare reduction construct, emit a 5917 // pointer to the address of the original reduction item (reuired by reduction 5918 // initializer) 5919 if (RCG.usesReductionInitializer(N)) { 5920 Address SharedAddr = CGF.GetAddrOfLocalVar(&ParamOrig); 5921 OrigAddr = CGF.EmitLoadOfPointer( 5922 SharedAddr, 5923 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 5924 } 5925 // Emit the initializer: 5926 // %0 = bitcast void* %arg to <type>* 5927 // store <type> <init>, <type>* %0 5928 RCG.emitInitialization(CGF, N, PrivateAddr, OrigAddr, 5929 [](CodeGenFunction &) { return false; }); 5930 CGF.FinishFunction(); 5931 return Fn; 5932 } 5933 5934 /// Emits reduction combiner function: 5935 /// \code 5936 /// void @.red_comb(void* %arg0, void* %arg1) { 5937 /// %lhs = bitcast void* %arg0 to <type>* 5938 /// %rhs = bitcast void* %arg1 to <type>* 5939 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 5940 /// store <type> %2, <type>* %lhs 5941 /// ret void 5942 /// } 5943 /// \endcode 5944 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 5945 SourceLocation Loc, 5946 ReductionCodeGen &RCG, unsigned N, 5947 const Expr *ReductionOp, 5948 const Expr *LHS, const Expr *RHS, 5949 const Expr *PrivateRef) { 5950 ASTContext &C = CGM.getContext(); 5951 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 5952 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 5953 FunctionArgList Args; 5954 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 5955 C.VoidPtrTy, ImplicitParamDecl::Other); 5956 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5957 ImplicitParamDecl::Other); 5958 Args.emplace_back(&ParamInOut); 5959 Args.emplace_back(&ParamIn); 5960 const auto &FnInfo = 5961 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5962 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5963 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 5964 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5965 Name, &CGM.getModule()); 5966 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5967 Fn->setDoesNotRecurse(); 5968 CodeGenFunction CGF(CGM); 5969 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5970 llvm::Value *Size = nullptr; 5971 // If the size of the reduction item is non-constant, load it from global 5972 // threadprivate variable. 5973 if (RCG.getSizes(N).second) { 5974 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5975 CGF, CGM.getContext().getSizeType(), 5976 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5977 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5978 CGM.getContext().getSizeType(), Loc); 5979 } 5980 RCG.emitAggregateType(CGF, N, Size); 5981 // Remap lhs and rhs variables to the addresses of the function arguments. 5982 // %lhs = bitcast void* %arg0 to <type>* 5983 // %rhs = bitcast void* %arg1 to <type>* 5984 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5985 PrivateScope.addPrivate( 5986 LHSVD, 5987 // Pull out the pointer to the variable. 5988 CGF.EmitLoadOfPointer( 5989 CGF.Builder.CreateElementBitCast( 5990 CGF.GetAddrOfLocalVar(&ParamInOut), 5991 CGF.ConvertTypeForMem(LHSVD->getType())->getPointerTo()), 5992 C.getPointerType(LHSVD->getType())->castAs<PointerType>())); 5993 PrivateScope.addPrivate( 5994 RHSVD, 5995 // Pull out the pointer to the variable. 5996 CGF.EmitLoadOfPointer( 5997 CGF.Builder.CreateElementBitCast( 5998 CGF.GetAddrOfLocalVar(&ParamIn), 5999 CGF.ConvertTypeForMem(RHSVD->getType())->getPointerTo()), 6000 C.getPointerType(RHSVD->getType())->castAs<PointerType>())); 6001 PrivateScope.Privatize(); 6002 // Emit the combiner body: 6003 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6004 // store <type> %2, <type>* %lhs 6005 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6006 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6007 cast<DeclRefExpr>(RHS)); 6008 CGF.FinishFunction(); 6009 return Fn; 6010 } 6011 6012 /// Emits reduction finalizer function: 6013 /// \code 6014 /// void @.red_fini(void* %arg) { 6015 /// %0 = bitcast void* %arg to <type>* 6016 /// <destroy>(<type>* %0) 6017 /// ret void 6018 /// } 6019 /// \endcode 6020 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6021 SourceLocation Loc, 6022 ReductionCodeGen &RCG, unsigned N) { 6023 if (!RCG.needCleanups(N)) 6024 return nullptr; 6025 ASTContext &C = CGM.getContext(); 6026 FunctionArgList Args; 6027 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6028 ImplicitParamDecl::Other); 6029 Args.emplace_back(&Param); 6030 const auto &FnInfo = 6031 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6032 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6033 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6034 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6035 Name, &CGM.getModule()); 6036 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6037 Fn->setDoesNotRecurse(); 6038 CodeGenFunction CGF(CGM); 6039 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6040 Address PrivateAddr = CGF.EmitLoadOfPointer( 6041 CGF.GetAddrOfLocalVar(&Param), 6042 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6043 llvm::Value *Size = nullptr; 6044 // If the size of the reduction item is non-constant, load it from global 6045 // threadprivate variable. 6046 if (RCG.getSizes(N).second) { 6047 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6048 CGF, CGM.getContext().getSizeType(), 6049 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6050 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6051 CGM.getContext().getSizeType(), Loc); 6052 } 6053 RCG.emitAggregateType(CGF, N, Size); 6054 // Emit the finalizer body: 6055 // <destroy>(<type>* %0) 6056 RCG.emitCleanups(CGF, N, PrivateAddr); 6057 CGF.FinishFunction(Loc); 6058 return Fn; 6059 } 6060 6061 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6062 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6063 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6064 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6065 return nullptr; 6066 6067 // Build typedef struct: 6068 // kmp_taskred_input { 6069 // void *reduce_shar; // shared reduction item 6070 // void *reduce_orig; // original reduction item used for initialization 6071 // size_t reduce_size; // size of data item 6072 // void *reduce_init; // data initialization routine 6073 // void *reduce_fini; // data finalization routine 6074 // void *reduce_comb; // data combiner routine 6075 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6076 // } kmp_taskred_input_t; 6077 ASTContext &C = CGM.getContext(); 6078 RecordDecl *RD = C.buildImplicitRecord("kmp_taskred_input_t"); 6079 RD->startDefinition(); 6080 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6081 const FieldDecl *OrigFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6082 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6083 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6084 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6085 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6086 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6087 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6088 RD->completeDefinition(); 6089 QualType RDType = C.getRecordType(RD); 6090 unsigned Size = Data.ReductionVars.size(); 6091 llvm::APInt ArraySize(/*numBits=*/64, Size); 6092 QualType ArrayRDType = C.getConstantArrayType( 6093 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6094 // kmp_task_red_input_t .rd_input.[Size]; 6095 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6096 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, 6097 Data.ReductionCopies, Data.ReductionOps); 6098 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6099 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6100 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6101 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6102 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6103 TaskRedInput.getElementType(), TaskRedInput.getPointer(), Idxs, 6104 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6105 ".rd_input.gep."); 6106 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6107 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6108 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6109 RCG.emitSharedOrigLValue(CGF, Cnt); 6110 llvm::Value *CastedShared = 6111 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6112 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6113 // ElemLVal.reduce_orig = &Origs[Cnt]; 6114 LValue OrigLVal = CGF.EmitLValueForField(ElemLVal, OrigFD); 6115 llvm::Value *CastedOrig = 6116 CGF.EmitCastToVoidPtr(RCG.getOrigLValue(Cnt).getPointer(CGF)); 6117 CGF.EmitStoreOfScalar(CastedOrig, OrigLVal); 6118 RCG.emitAggregateType(CGF, Cnt); 6119 llvm::Value *SizeValInChars; 6120 llvm::Value *SizeVal; 6121 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6122 // We use delayed creation/initialization for VLAs and array sections. It is 6123 // required because runtime does not provide the way to pass the sizes of 6124 // VLAs/array sections to initializer/combiner/finalizer functions. Instead 6125 // threadprivate global variables are used to store these values and use 6126 // them in the functions. 6127 bool DelayedCreation = !!SizeVal; 6128 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6129 /*isSigned=*/false); 6130 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6131 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6132 // ElemLVal.reduce_init = init; 6133 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6134 llvm::Value *InitAddr = 6135 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6136 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6137 // ElemLVal.reduce_fini = fini; 6138 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6139 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6140 llvm::Value *FiniAddr = Fini 6141 ? CGF.EmitCastToVoidPtr(Fini) 6142 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6143 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6144 // ElemLVal.reduce_comb = comb; 6145 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6146 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6147 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6148 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6149 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6150 // ElemLVal.flags = 0; 6151 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6152 if (DelayedCreation) { 6153 CGF.EmitStoreOfScalar( 6154 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6155 FlagsLVal); 6156 } else 6157 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6158 FlagsLVal.getType()); 6159 } 6160 if (Data.IsReductionWithTaskMod) { 6161 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6162 // is_ws, int num, void *data); 6163 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6164 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6165 CGM.IntTy, /*isSigned=*/true); 6166 llvm::Value *Args[] = { 6167 IdentTLoc, GTid, 6168 llvm::ConstantInt::get(CGM.IntTy, Data.IsWorksharingReduction ? 1 : 0, 6169 /*isSigned=*/true), 6170 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6171 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6172 TaskRedInput.getPointer(), CGM.VoidPtrTy)}; 6173 return CGF.EmitRuntimeCall( 6174 OMPBuilder.getOrCreateRuntimeFunction( 6175 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init), 6176 Args); 6177 } 6178 // Build call void *__kmpc_taskred_init(int gtid, int num_data, void *data); 6179 llvm::Value *Args[] = { 6180 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6181 /*isSigned=*/true), 6182 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6183 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6184 CGM.VoidPtrTy)}; 6185 return CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6186 CGM.getModule(), OMPRTL___kmpc_taskred_init), 6187 Args); 6188 } 6189 6190 void CGOpenMPRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 6191 SourceLocation Loc, 6192 bool IsWorksharingReduction) { 6193 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6194 // is_ws, int num, void *data); 6195 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6196 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6197 CGM.IntTy, /*isSigned=*/true); 6198 llvm::Value *Args[] = {IdentTLoc, GTid, 6199 llvm::ConstantInt::get(CGM.IntTy, 6200 IsWorksharingReduction ? 1 : 0, 6201 /*isSigned=*/true)}; 6202 (void)CGF.EmitRuntimeCall( 6203 OMPBuilder.getOrCreateRuntimeFunction( 6204 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini), 6205 Args); 6206 } 6207 6208 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6209 SourceLocation Loc, 6210 ReductionCodeGen &RCG, 6211 unsigned N) { 6212 auto Sizes = RCG.getSizes(N); 6213 // Emit threadprivate global variable if the type is non-constant 6214 // (Sizes.second = nullptr). 6215 if (Sizes.second) { 6216 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6217 /*isSigned=*/false); 6218 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6219 CGF, CGM.getContext().getSizeType(), 6220 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6221 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6222 } 6223 } 6224 6225 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6226 SourceLocation Loc, 6227 llvm::Value *ReductionsPtr, 6228 LValue SharedLVal) { 6229 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6230 // *d); 6231 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6232 CGM.IntTy, 6233 /*isSigned=*/true), 6234 ReductionsPtr, 6235 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6236 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6237 return Address::deprecated( 6238 CGF.EmitRuntimeCall( 6239 OMPBuilder.getOrCreateRuntimeFunction( 6240 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data), 6241 Args), 6242 SharedLVal.getAlignment()); 6243 } 6244 6245 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, 6246 const OMPTaskDataTy &Data) { 6247 if (!CGF.HaveInsertPoint()) 6248 return; 6249 6250 if (CGF.CGM.getLangOpts().OpenMPIRBuilder && Data.Dependences.empty()) { 6251 // TODO: Need to support taskwait with dependences in the OpenMPIRBuilder. 6252 OMPBuilder.createTaskwait(CGF.Builder); 6253 } else { 6254 llvm::Value *ThreadID = getThreadID(CGF, Loc); 6255 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 6256 auto &M = CGM.getModule(); 6257 Address DependenciesArray = Address::invalid(); 6258 llvm::Value *NumOfElements; 6259 std::tie(NumOfElements, DependenciesArray) = 6260 emitDependClause(CGF, Data.Dependences, Loc); 6261 llvm::Value *DepWaitTaskArgs[6]; 6262 if (!Data.Dependences.empty()) { 6263 DepWaitTaskArgs[0] = UpLoc; 6264 DepWaitTaskArgs[1] = ThreadID; 6265 DepWaitTaskArgs[2] = NumOfElements; 6266 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 6267 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 6268 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 6269 6270 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 6271 6272 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 6273 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 6274 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 6275 // is specified. 6276 CGF.EmitRuntimeCall( 6277 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_wait_deps), 6278 DepWaitTaskArgs); 6279 6280 } else { 6281 6282 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6283 // global_tid); 6284 llvm::Value *Args[] = {UpLoc, ThreadID}; 6285 // Ignore return result until untied tasks are supported. 6286 CGF.EmitRuntimeCall( 6287 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait), 6288 Args); 6289 } 6290 } 6291 6292 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6293 Region->emitUntiedSwitch(CGF); 6294 } 6295 6296 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6297 OpenMPDirectiveKind InnerKind, 6298 const RegionCodeGenTy &CodeGen, 6299 bool HasCancel) { 6300 if (!CGF.HaveInsertPoint()) 6301 return; 6302 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel, 6303 InnerKind != OMPD_critical && 6304 InnerKind != OMPD_master && 6305 InnerKind != OMPD_masked); 6306 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6307 } 6308 6309 namespace { 6310 enum RTCancelKind { 6311 CancelNoreq = 0, 6312 CancelParallel = 1, 6313 CancelLoop = 2, 6314 CancelSections = 3, 6315 CancelTaskgroup = 4 6316 }; 6317 } // anonymous namespace 6318 6319 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6320 RTCancelKind CancelKind = CancelNoreq; 6321 if (CancelRegion == OMPD_parallel) 6322 CancelKind = CancelParallel; 6323 else if (CancelRegion == OMPD_for) 6324 CancelKind = CancelLoop; 6325 else if (CancelRegion == OMPD_sections) 6326 CancelKind = CancelSections; 6327 else { 6328 assert(CancelRegion == OMPD_taskgroup); 6329 CancelKind = CancelTaskgroup; 6330 } 6331 return CancelKind; 6332 } 6333 6334 void CGOpenMPRuntime::emitCancellationPointCall( 6335 CodeGenFunction &CGF, SourceLocation Loc, 6336 OpenMPDirectiveKind CancelRegion) { 6337 if (!CGF.HaveInsertPoint()) 6338 return; 6339 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6340 // global_tid, kmp_int32 cncl_kind); 6341 if (auto *OMPRegionInfo = 6342 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6343 // For 'cancellation point taskgroup', the task region info may not have a 6344 // cancel. This may instead happen in another adjacent task. 6345 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6346 llvm::Value *Args[] = { 6347 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6348 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6349 // Ignore return result until untied tasks are supported. 6350 llvm::Value *Result = CGF.EmitRuntimeCall( 6351 OMPBuilder.getOrCreateRuntimeFunction( 6352 CGM.getModule(), OMPRTL___kmpc_cancellationpoint), 6353 Args); 6354 // if (__kmpc_cancellationpoint()) { 6355 // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only 6356 // exit from construct; 6357 // } 6358 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6359 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6360 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6361 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6362 CGF.EmitBlock(ExitBB); 6363 if (CancelRegion == OMPD_parallel) 6364 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 6365 // exit from construct; 6366 CodeGenFunction::JumpDest CancelDest = 6367 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6368 CGF.EmitBranchThroughCleanup(CancelDest); 6369 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6370 } 6371 } 6372 } 6373 6374 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6375 const Expr *IfCond, 6376 OpenMPDirectiveKind CancelRegion) { 6377 if (!CGF.HaveInsertPoint()) 6378 return; 6379 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6380 // kmp_int32 cncl_kind); 6381 auto &M = CGM.getModule(); 6382 if (auto *OMPRegionInfo = 6383 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6384 auto &&ThenGen = [this, &M, Loc, CancelRegion, 6385 OMPRegionInfo](CodeGenFunction &CGF, PrePostActionTy &) { 6386 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6387 llvm::Value *Args[] = { 6388 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6389 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6390 // Ignore return result until untied tasks are supported. 6391 llvm::Value *Result = CGF.EmitRuntimeCall( 6392 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args); 6393 // if (__kmpc_cancel()) { 6394 // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only 6395 // exit from construct; 6396 // } 6397 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6398 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6399 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6400 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6401 CGF.EmitBlock(ExitBB); 6402 if (CancelRegion == OMPD_parallel) 6403 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 6404 // exit from construct; 6405 CodeGenFunction::JumpDest CancelDest = 6406 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6407 CGF.EmitBranchThroughCleanup(CancelDest); 6408 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6409 }; 6410 if (IfCond) { 6411 emitIfClause(CGF, IfCond, ThenGen, 6412 [](CodeGenFunction &, PrePostActionTy &) {}); 6413 } else { 6414 RegionCodeGenTy ThenRCG(ThenGen); 6415 ThenRCG(CGF); 6416 } 6417 } 6418 } 6419 6420 namespace { 6421 /// Cleanup action for uses_allocators support. 6422 class OMPUsesAllocatorsActionTy final : public PrePostActionTy { 6423 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators; 6424 6425 public: 6426 OMPUsesAllocatorsActionTy( 6427 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators) 6428 : Allocators(Allocators) {} 6429 void Enter(CodeGenFunction &CGF) override { 6430 if (!CGF.HaveInsertPoint()) 6431 return; 6432 for (const auto &AllocatorData : Allocators) { 6433 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsInit( 6434 CGF, AllocatorData.first, AllocatorData.second); 6435 } 6436 } 6437 void Exit(CodeGenFunction &CGF) override { 6438 if (!CGF.HaveInsertPoint()) 6439 return; 6440 for (const auto &AllocatorData : Allocators) { 6441 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsFini(CGF, 6442 AllocatorData.first); 6443 } 6444 } 6445 }; 6446 } // namespace 6447 6448 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6449 const OMPExecutableDirective &D, StringRef ParentName, 6450 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6451 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6452 assert(!ParentName.empty() && "Invalid target region parent name!"); 6453 HasEmittedTargetRegion = true; 6454 SmallVector<std::pair<const Expr *, const Expr *>, 4> Allocators; 6455 for (const auto *C : D.getClausesOfKind<OMPUsesAllocatorsClause>()) { 6456 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 6457 const OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 6458 if (!D.AllocatorTraits) 6459 continue; 6460 Allocators.emplace_back(D.Allocator, D.AllocatorTraits); 6461 } 6462 } 6463 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators); 6464 CodeGen.setAction(UsesAllocatorAction); 6465 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6466 IsOffloadEntry, CodeGen); 6467 } 6468 6469 void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, 6470 const Expr *Allocator, 6471 const Expr *AllocatorTraits) { 6472 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6473 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6474 // Use default memspace handle. 6475 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 6476 llvm::Value *NumTraits = llvm::ConstantInt::get( 6477 CGF.IntTy, cast<ConstantArrayType>( 6478 AllocatorTraits->getType()->getAsArrayTypeUnsafe()) 6479 ->getSize() 6480 .getLimitedValue()); 6481 LValue AllocatorTraitsLVal = CGF.EmitLValue(AllocatorTraits); 6482 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6483 AllocatorTraitsLVal.getAddress(CGF), CGF.VoidPtrPtrTy, CGF.VoidPtrTy); 6484 AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, 6485 AllocatorTraitsLVal.getBaseInfo(), 6486 AllocatorTraitsLVal.getTBAAInfo()); 6487 llvm::Value *Traits = 6488 CGF.EmitLoadOfScalar(AllocatorTraitsLVal, AllocatorTraits->getExprLoc()); 6489 6490 llvm::Value *AllocatorVal = 6491 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6492 CGM.getModule(), OMPRTL___kmpc_init_allocator), 6493 {ThreadId, MemSpaceHandle, NumTraits, Traits}); 6494 // Store to allocator. 6495 CGF.EmitVarDecl(*cast<VarDecl>( 6496 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl())); 6497 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6498 AllocatorVal = 6499 CGF.EmitScalarConversion(AllocatorVal, CGF.getContext().VoidPtrTy, 6500 Allocator->getType(), Allocator->getExprLoc()); 6501 CGF.EmitStoreOfScalar(AllocatorVal, AllocatorLVal); 6502 } 6503 6504 void CGOpenMPRuntime::emitUsesAllocatorsFini(CodeGenFunction &CGF, 6505 const Expr *Allocator) { 6506 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6507 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6508 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6509 llvm::Value *AllocatorVal = 6510 CGF.EmitLoadOfScalar(AllocatorLVal, Allocator->getExprLoc()); 6511 AllocatorVal = CGF.EmitScalarConversion(AllocatorVal, Allocator->getType(), 6512 CGF.getContext().VoidPtrTy, 6513 Allocator->getExprLoc()); 6514 (void)CGF.EmitRuntimeCall( 6515 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 6516 OMPRTL___kmpc_destroy_allocator), 6517 {ThreadId, AllocatorVal}); 6518 } 6519 6520 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6521 const OMPExecutableDirective &D, StringRef ParentName, 6522 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6523 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6524 // Create a unique name for the entry function using the source location 6525 // information of the current target region. The name will be something like: 6526 // 6527 // __omp_offloading_DD_FFFF_PP_lBB 6528 // 6529 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6530 // mangled name of the function that encloses the target region and BB is the 6531 // line number of the target region. 6532 6533 const bool BuildOutlinedFn = CGM.getLangOpts().OpenMPIsDevice || 6534 !CGM.getLangOpts().OpenMPOffloadMandatory; 6535 unsigned DeviceID; 6536 unsigned FileID; 6537 unsigned Line; 6538 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6539 Line); 6540 SmallString<64> EntryFnName; 6541 { 6542 llvm::raw_svector_ostream OS(EntryFnName); 6543 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6544 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6545 } 6546 6547 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6548 6549 CodeGenFunction CGF(CGM, true); 6550 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6551 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6552 6553 if (BuildOutlinedFn) 6554 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6555 6556 // If this target outline function is not an offload entry, we don't need to 6557 // register it. 6558 if (!IsOffloadEntry) 6559 return; 6560 6561 // The target region ID is used by the runtime library to identify the current 6562 // target region, so it only has to be unique and not necessarily point to 6563 // anything. It could be the pointer to the outlined function that implements 6564 // the target region, but we aren't using that so that the compiler doesn't 6565 // need to keep that, and could therefore inline the host function if proven 6566 // worthwhile during optimization. In the other hand, if emitting code for the 6567 // device, the ID has to be the function address so that it can retrieved from 6568 // the offloading entry and launched by the runtime library. We also mark the 6569 // outlined function to have external linkage in case we are emitting code for 6570 // the device, because these functions will be entry points to the device. 6571 6572 if (CGM.getLangOpts().OpenMPIsDevice) { 6573 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6574 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6575 OutlinedFn->setDSOLocal(false); 6576 if (CGM.getTriple().isAMDGCN()) 6577 OutlinedFn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); 6578 } else { 6579 std::string Name = getName({EntryFnName, "region_id"}); 6580 OutlinedFnID = new llvm::GlobalVariable( 6581 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6582 llvm::GlobalValue::WeakAnyLinkage, 6583 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6584 } 6585 6586 // If we do not allow host fallback we still need a named address to use. 6587 llvm::Constant *TargetRegionEntryAddr = OutlinedFn; 6588 if (!BuildOutlinedFn) { 6589 assert(!CGM.getModule().getGlobalVariable(EntryFnName, true) && 6590 "Named kernel already exists?"); 6591 TargetRegionEntryAddr = new llvm::GlobalVariable( 6592 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6593 llvm::GlobalValue::InternalLinkage, 6594 llvm::Constant::getNullValue(CGM.Int8Ty), EntryFnName); 6595 } 6596 6597 // Register the information for the entry associated with this target region. 6598 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6599 DeviceID, FileID, ParentName, Line, TargetRegionEntryAddr, OutlinedFnID, 6600 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6601 6602 // Add NumTeams and ThreadLimit attributes to the outlined GPU function 6603 int32_t DefaultValTeams = -1; 6604 getNumTeamsExprForTargetDirective(CGF, D, DefaultValTeams); 6605 if (DefaultValTeams > 0 && OutlinedFn) { 6606 OutlinedFn->addFnAttr("omp_target_num_teams", 6607 std::to_string(DefaultValTeams)); 6608 } 6609 int32_t DefaultValThreads = -1; 6610 getNumThreadsExprForTargetDirective(CGF, D, DefaultValThreads); 6611 if (DefaultValThreads > 0 && OutlinedFn) { 6612 OutlinedFn->addFnAttr("omp_target_thread_limit", 6613 std::to_string(DefaultValThreads)); 6614 } 6615 6616 if (BuildOutlinedFn) 6617 CGM.getTargetCodeGenInfo().setTargetAttributes(nullptr, OutlinedFn, CGM); 6618 } 6619 6620 /// Checks if the expression is constant or does not have non-trivial function 6621 /// calls. 6622 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6623 // We can skip constant expressions. 6624 // We can skip expressions with trivial calls or simple expressions. 6625 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6626 !E->hasNonTrivialCall(Ctx)) && 6627 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6628 } 6629 6630 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6631 const Stmt *Body) { 6632 const Stmt *Child = Body->IgnoreContainers(); 6633 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6634 Child = nullptr; 6635 for (const Stmt *S : C->body()) { 6636 if (const auto *E = dyn_cast<Expr>(S)) { 6637 if (isTrivial(Ctx, E)) 6638 continue; 6639 } 6640 // Some of the statements can be ignored. 6641 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6642 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6643 continue; 6644 // Analyze declarations. 6645 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6646 if (llvm::all_of(DS->decls(), [](const Decl *D) { 6647 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6648 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6649 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6650 isa<UsingDirectiveDecl>(D) || 6651 isa<OMPDeclareReductionDecl>(D) || 6652 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6653 return true; 6654 const auto *VD = dyn_cast<VarDecl>(D); 6655 if (!VD) 6656 return false; 6657 return VD->hasGlobalStorage() || !VD->isUsed(); 6658 })) 6659 continue; 6660 } 6661 // Found multiple children - cannot get the one child only. 6662 if (Child) 6663 return nullptr; 6664 Child = S; 6665 } 6666 if (Child) 6667 Child = Child->IgnoreContainers(); 6668 } 6669 return Child; 6670 } 6671 6672 const Expr *CGOpenMPRuntime::getNumTeamsExprForTargetDirective( 6673 CodeGenFunction &CGF, const OMPExecutableDirective &D, 6674 int32_t &DefaultVal) { 6675 6676 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6677 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6678 "Expected target-based executable directive."); 6679 switch (DirectiveKind) { 6680 case OMPD_target: { 6681 const auto *CS = D.getInnermostCapturedStmt(); 6682 const auto *Body = 6683 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6684 const Stmt *ChildStmt = 6685 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6686 if (const auto *NestedDir = 6687 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6688 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6689 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6690 const Expr *NumTeams = 6691 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6692 if (NumTeams->isIntegerConstantExpr(CGF.getContext())) 6693 if (auto Constant = 6694 NumTeams->getIntegerConstantExpr(CGF.getContext())) 6695 DefaultVal = Constant->getExtValue(); 6696 return NumTeams; 6697 } 6698 DefaultVal = 0; 6699 return nullptr; 6700 } 6701 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6702 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) { 6703 DefaultVal = 1; 6704 return nullptr; 6705 } 6706 DefaultVal = 1; 6707 return nullptr; 6708 } 6709 // A value of -1 is used to check if we need to emit no teams region 6710 DefaultVal = -1; 6711 return nullptr; 6712 } 6713 case OMPD_target_teams: 6714 case OMPD_target_teams_distribute: 6715 case OMPD_target_teams_distribute_simd: 6716 case OMPD_target_teams_distribute_parallel_for: 6717 case OMPD_target_teams_distribute_parallel_for_simd: { 6718 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6719 const Expr *NumTeams = 6720 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6721 if (NumTeams->isIntegerConstantExpr(CGF.getContext())) 6722 if (auto Constant = NumTeams->getIntegerConstantExpr(CGF.getContext())) 6723 DefaultVal = Constant->getExtValue(); 6724 return NumTeams; 6725 } 6726 DefaultVal = 0; 6727 return nullptr; 6728 } 6729 case OMPD_target_parallel: 6730 case OMPD_target_parallel_for: 6731 case OMPD_target_parallel_for_simd: 6732 case OMPD_target_simd: 6733 DefaultVal = 1; 6734 return nullptr; 6735 case OMPD_parallel: 6736 case OMPD_for: 6737 case OMPD_parallel_for: 6738 case OMPD_parallel_master: 6739 case OMPD_parallel_sections: 6740 case OMPD_for_simd: 6741 case OMPD_parallel_for_simd: 6742 case OMPD_cancel: 6743 case OMPD_cancellation_point: 6744 case OMPD_ordered: 6745 case OMPD_threadprivate: 6746 case OMPD_allocate: 6747 case OMPD_task: 6748 case OMPD_simd: 6749 case OMPD_tile: 6750 case OMPD_unroll: 6751 case OMPD_sections: 6752 case OMPD_section: 6753 case OMPD_single: 6754 case OMPD_master: 6755 case OMPD_critical: 6756 case OMPD_taskyield: 6757 case OMPD_barrier: 6758 case OMPD_taskwait: 6759 case OMPD_taskgroup: 6760 case OMPD_atomic: 6761 case OMPD_flush: 6762 case OMPD_depobj: 6763 case OMPD_scan: 6764 case OMPD_teams: 6765 case OMPD_target_data: 6766 case OMPD_target_exit_data: 6767 case OMPD_target_enter_data: 6768 case OMPD_distribute: 6769 case OMPD_distribute_simd: 6770 case OMPD_distribute_parallel_for: 6771 case OMPD_distribute_parallel_for_simd: 6772 case OMPD_teams_distribute: 6773 case OMPD_teams_distribute_simd: 6774 case OMPD_teams_distribute_parallel_for: 6775 case OMPD_teams_distribute_parallel_for_simd: 6776 case OMPD_target_update: 6777 case OMPD_declare_simd: 6778 case OMPD_declare_variant: 6779 case OMPD_begin_declare_variant: 6780 case OMPD_end_declare_variant: 6781 case OMPD_declare_target: 6782 case OMPD_end_declare_target: 6783 case OMPD_declare_reduction: 6784 case OMPD_declare_mapper: 6785 case OMPD_taskloop: 6786 case OMPD_taskloop_simd: 6787 case OMPD_master_taskloop: 6788 case OMPD_master_taskloop_simd: 6789 case OMPD_parallel_master_taskloop: 6790 case OMPD_parallel_master_taskloop_simd: 6791 case OMPD_requires: 6792 case OMPD_metadirective: 6793 case OMPD_unknown: 6794 break; 6795 default: 6796 break; 6797 } 6798 llvm_unreachable("Unexpected directive kind."); 6799 } 6800 6801 llvm::Value *CGOpenMPRuntime::emitNumTeamsForTargetDirective( 6802 CodeGenFunction &CGF, const OMPExecutableDirective &D) { 6803 assert(!CGF.getLangOpts().OpenMPIsDevice && 6804 "Clauses associated with the teams directive expected to be emitted " 6805 "only for the host!"); 6806 CGBuilderTy &Bld = CGF.Builder; 6807 int32_t DefaultNT = -1; 6808 const Expr *NumTeams = getNumTeamsExprForTargetDirective(CGF, D, DefaultNT); 6809 if (NumTeams != nullptr) { 6810 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6811 6812 switch (DirectiveKind) { 6813 case OMPD_target: { 6814 const auto *CS = D.getInnermostCapturedStmt(); 6815 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6816 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6817 llvm::Value *NumTeamsVal = CGF.EmitScalarExpr(NumTeams, 6818 /*IgnoreResultAssign*/ true); 6819 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6820 /*isSigned=*/true); 6821 } 6822 case OMPD_target_teams: 6823 case OMPD_target_teams_distribute: 6824 case OMPD_target_teams_distribute_simd: 6825 case OMPD_target_teams_distribute_parallel_for: 6826 case OMPD_target_teams_distribute_parallel_for_simd: { 6827 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6828 llvm::Value *NumTeamsVal = CGF.EmitScalarExpr(NumTeams, 6829 /*IgnoreResultAssign*/ true); 6830 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6831 /*isSigned=*/true); 6832 } 6833 default: 6834 break; 6835 } 6836 } else if (DefaultNT == -1) { 6837 return nullptr; 6838 } 6839 6840 return Bld.getInt32(DefaultNT); 6841 } 6842 6843 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6844 llvm::Value *DefaultThreadLimitVal) { 6845 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6846 CGF.getContext(), CS->getCapturedStmt()); 6847 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6848 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6849 llvm::Value *NumThreads = nullptr; 6850 llvm::Value *CondVal = nullptr; 6851 // Handle if clause. If if clause present, the number of threads is 6852 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6853 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6854 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6855 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6856 const OMPIfClause *IfClause = nullptr; 6857 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6858 if (C->getNameModifier() == OMPD_unknown || 6859 C->getNameModifier() == OMPD_parallel) { 6860 IfClause = C; 6861 break; 6862 } 6863 } 6864 if (IfClause) { 6865 const Expr *Cond = IfClause->getCondition(); 6866 bool Result; 6867 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6868 if (!Result) 6869 return CGF.Builder.getInt32(1); 6870 } else { 6871 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6872 if (const auto *PreInit = 6873 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6874 for (const auto *I : PreInit->decls()) { 6875 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6876 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6877 } else { 6878 CodeGenFunction::AutoVarEmission Emission = 6879 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6880 CGF.EmitAutoVarCleanups(Emission); 6881 } 6882 } 6883 } 6884 CondVal = CGF.EvaluateExprAsBool(Cond); 6885 } 6886 } 6887 } 6888 // Check the value of num_threads clause iff if clause was not specified 6889 // or is not evaluated to false. 6890 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6891 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6892 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6893 const auto *NumThreadsClause = 6894 Dir->getSingleClause<OMPNumThreadsClause>(); 6895 CodeGenFunction::LexicalScope Scope( 6896 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6897 if (const auto *PreInit = 6898 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6899 for (const auto *I : PreInit->decls()) { 6900 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6901 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6902 } else { 6903 CodeGenFunction::AutoVarEmission Emission = 6904 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6905 CGF.EmitAutoVarCleanups(Emission); 6906 } 6907 } 6908 } 6909 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6910 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6911 /*isSigned=*/false); 6912 if (DefaultThreadLimitVal) 6913 NumThreads = CGF.Builder.CreateSelect( 6914 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6915 DefaultThreadLimitVal, NumThreads); 6916 } else { 6917 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6918 : CGF.Builder.getInt32(0); 6919 } 6920 // Process condition of the if clause. 6921 if (CondVal) { 6922 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6923 CGF.Builder.getInt32(1)); 6924 } 6925 return NumThreads; 6926 } 6927 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6928 return CGF.Builder.getInt32(1); 6929 return DefaultThreadLimitVal; 6930 } 6931 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6932 : CGF.Builder.getInt32(0); 6933 } 6934 6935 const Expr *CGOpenMPRuntime::getNumThreadsExprForTargetDirective( 6936 CodeGenFunction &CGF, const OMPExecutableDirective &D, 6937 int32_t &DefaultVal) { 6938 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6939 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6940 "Expected target-based executable directive."); 6941 6942 switch (DirectiveKind) { 6943 case OMPD_target: 6944 // Teams have no clause thread_limit 6945 return nullptr; 6946 case OMPD_target_teams: 6947 case OMPD_target_teams_distribute: 6948 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6949 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6950 const Expr *ThreadLimit = ThreadLimitClause->getThreadLimit(); 6951 if (ThreadLimit->isIntegerConstantExpr(CGF.getContext())) 6952 if (auto Constant = 6953 ThreadLimit->getIntegerConstantExpr(CGF.getContext())) 6954 DefaultVal = Constant->getExtValue(); 6955 return ThreadLimit; 6956 } 6957 return nullptr; 6958 case OMPD_target_parallel: 6959 case OMPD_target_parallel_for: 6960 case OMPD_target_parallel_for_simd: 6961 case OMPD_target_teams_distribute_parallel_for: 6962 case OMPD_target_teams_distribute_parallel_for_simd: { 6963 Expr *ThreadLimit = nullptr; 6964 Expr *NumThreads = nullptr; 6965 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6966 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6967 ThreadLimit = ThreadLimitClause->getThreadLimit(); 6968 if (ThreadLimit->isIntegerConstantExpr(CGF.getContext())) 6969 if (auto Constant = 6970 ThreadLimit->getIntegerConstantExpr(CGF.getContext())) 6971 DefaultVal = Constant->getExtValue(); 6972 } 6973 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6974 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6975 NumThreads = NumThreadsClause->getNumThreads(); 6976 if (NumThreads->isIntegerConstantExpr(CGF.getContext())) { 6977 if (auto Constant = 6978 NumThreads->getIntegerConstantExpr(CGF.getContext())) { 6979 if (Constant->getExtValue() < DefaultVal) { 6980 DefaultVal = Constant->getExtValue(); 6981 ThreadLimit = NumThreads; 6982 } 6983 } 6984 } 6985 } 6986 return ThreadLimit; 6987 } 6988 case OMPD_target_teams_distribute_simd: 6989 case OMPD_target_simd: 6990 DefaultVal = 1; 6991 return nullptr; 6992 case OMPD_parallel: 6993 case OMPD_for: 6994 case OMPD_parallel_for: 6995 case OMPD_parallel_master: 6996 case OMPD_parallel_sections: 6997 case OMPD_for_simd: 6998 case OMPD_parallel_for_simd: 6999 case OMPD_cancel: 7000 case OMPD_cancellation_point: 7001 case OMPD_ordered: 7002 case OMPD_threadprivate: 7003 case OMPD_allocate: 7004 case OMPD_task: 7005 case OMPD_simd: 7006 case OMPD_tile: 7007 case OMPD_unroll: 7008 case OMPD_sections: 7009 case OMPD_section: 7010 case OMPD_single: 7011 case OMPD_master: 7012 case OMPD_critical: 7013 case OMPD_taskyield: 7014 case OMPD_barrier: 7015 case OMPD_taskwait: 7016 case OMPD_taskgroup: 7017 case OMPD_atomic: 7018 case OMPD_flush: 7019 case OMPD_depobj: 7020 case OMPD_scan: 7021 case OMPD_teams: 7022 case OMPD_target_data: 7023 case OMPD_target_exit_data: 7024 case OMPD_target_enter_data: 7025 case OMPD_distribute: 7026 case OMPD_distribute_simd: 7027 case OMPD_distribute_parallel_for: 7028 case OMPD_distribute_parallel_for_simd: 7029 case OMPD_teams_distribute: 7030 case OMPD_teams_distribute_simd: 7031 case OMPD_teams_distribute_parallel_for: 7032 case OMPD_teams_distribute_parallel_for_simd: 7033 case OMPD_target_update: 7034 case OMPD_declare_simd: 7035 case OMPD_declare_variant: 7036 case OMPD_begin_declare_variant: 7037 case OMPD_end_declare_variant: 7038 case OMPD_declare_target: 7039 case OMPD_end_declare_target: 7040 case OMPD_declare_reduction: 7041 case OMPD_declare_mapper: 7042 case OMPD_taskloop: 7043 case OMPD_taskloop_simd: 7044 case OMPD_master_taskloop: 7045 case OMPD_master_taskloop_simd: 7046 case OMPD_parallel_master_taskloop: 7047 case OMPD_parallel_master_taskloop_simd: 7048 case OMPD_requires: 7049 case OMPD_unknown: 7050 break; 7051 default: 7052 break; 7053 } 7054 llvm_unreachable("Unsupported directive kind."); 7055 } 7056 7057 llvm::Value *CGOpenMPRuntime::emitNumThreadsForTargetDirective( 7058 CodeGenFunction &CGF, const OMPExecutableDirective &D) { 7059 assert(!CGF.getLangOpts().OpenMPIsDevice && 7060 "Clauses associated with the teams directive expected to be emitted " 7061 "only for the host!"); 7062 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 7063 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 7064 "Expected target-based executable directive."); 7065 CGBuilderTy &Bld = CGF.Builder; 7066 llvm::Value *ThreadLimitVal = nullptr; 7067 llvm::Value *NumThreadsVal = nullptr; 7068 switch (DirectiveKind) { 7069 case OMPD_target: { 7070 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7071 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7072 return NumThreads; 7073 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7074 CGF.getContext(), CS->getCapturedStmt()); 7075 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7076 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 7077 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7078 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7079 const auto *ThreadLimitClause = 7080 Dir->getSingleClause<OMPThreadLimitClause>(); 7081 CodeGenFunction::LexicalScope Scope( 7082 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 7083 if (const auto *PreInit = 7084 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 7085 for (const auto *I : PreInit->decls()) { 7086 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7087 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7088 } else { 7089 CodeGenFunction::AutoVarEmission Emission = 7090 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7091 CGF.EmitAutoVarCleanups(Emission); 7092 } 7093 } 7094 } 7095 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7096 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7097 ThreadLimitVal = 7098 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7099 } 7100 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 7101 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 7102 CS = Dir->getInnermostCapturedStmt(); 7103 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7104 CGF.getContext(), CS->getCapturedStmt()); 7105 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 7106 } 7107 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 7108 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 7109 CS = Dir->getInnermostCapturedStmt(); 7110 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7111 return NumThreads; 7112 } 7113 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 7114 return Bld.getInt32(1); 7115 } 7116 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7117 } 7118 case OMPD_target_teams: { 7119 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7120 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7121 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7122 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7123 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7124 ThreadLimitVal = 7125 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7126 } 7127 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7128 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7129 return NumThreads; 7130 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7131 CGF.getContext(), CS->getCapturedStmt()); 7132 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7133 if (Dir->getDirectiveKind() == OMPD_distribute) { 7134 CS = Dir->getInnermostCapturedStmt(); 7135 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7136 return NumThreads; 7137 } 7138 } 7139 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7140 } 7141 case OMPD_target_teams_distribute: 7142 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7143 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7144 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7145 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7146 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7147 ThreadLimitVal = 7148 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7149 } 7150 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 7151 case OMPD_target_parallel: 7152 case OMPD_target_parallel_for: 7153 case OMPD_target_parallel_for_simd: 7154 case OMPD_target_teams_distribute_parallel_for: 7155 case OMPD_target_teams_distribute_parallel_for_simd: { 7156 llvm::Value *CondVal = nullptr; 7157 // Handle if clause. If if clause present, the number of threads is 7158 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 7159 if (D.hasClausesOfKind<OMPIfClause>()) { 7160 const OMPIfClause *IfClause = nullptr; 7161 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 7162 if (C->getNameModifier() == OMPD_unknown || 7163 C->getNameModifier() == OMPD_parallel) { 7164 IfClause = C; 7165 break; 7166 } 7167 } 7168 if (IfClause) { 7169 const Expr *Cond = IfClause->getCondition(); 7170 bool Result; 7171 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 7172 if (!Result) 7173 return Bld.getInt32(1); 7174 } else { 7175 CodeGenFunction::RunCleanupsScope Scope(CGF); 7176 CondVal = CGF.EvaluateExprAsBool(Cond); 7177 } 7178 } 7179 } 7180 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7181 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7182 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7183 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7184 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7185 ThreadLimitVal = 7186 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7187 } 7188 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 7189 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 7190 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 7191 llvm::Value *NumThreads = CGF.EmitScalarExpr( 7192 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 7193 NumThreadsVal = 7194 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 7195 ThreadLimitVal = ThreadLimitVal 7196 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 7197 ThreadLimitVal), 7198 NumThreadsVal, ThreadLimitVal) 7199 : NumThreadsVal; 7200 } 7201 if (!ThreadLimitVal) 7202 ThreadLimitVal = Bld.getInt32(0); 7203 if (CondVal) 7204 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 7205 return ThreadLimitVal; 7206 } 7207 case OMPD_target_teams_distribute_simd: 7208 case OMPD_target_simd: 7209 return Bld.getInt32(1); 7210 case OMPD_parallel: 7211 case OMPD_for: 7212 case OMPD_parallel_for: 7213 case OMPD_parallel_master: 7214 case OMPD_parallel_sections: 7215 case OMPD_for_simd: 7216 case OMPD_parallel_for_simd: 7217 case OMPD_cancel: 7218 case OMPD_cancellation_point: 7219 case OMPD_ordered: 7220 case OMPD_threadprivate: 7221 case OMPD_allocate: 7222 case OMPD_task: 7223 case OMPD_simd: 7224 case OMPD_tile: 7225 case OMPD_unroll: 7226 case OMPD_sections: 7227 case OMPD_section: 7228 case OMPD_single: 7229 case OMPD_master: 7230 case OMPD_critical: 7231 case OMPD_taskyield: 7232 case OMPD_barrier: 7233 case OMPD_taskwait: 7234 case OMPD_taskgroup: 7235 case OMPD_atomic: 7236 case OMPD_flush: 7237 case OMPD_depobj: 7238 case OMPD_scan: 7239 case OMPD_teams: 7240 case OMPD_target_data: 7241 case OMPD_target_exit_data: 7242 case OMPD_target_enter_data: 7243 case OMPD_distribute: 7244 case OMPD_distribute_simd: 7245 case OMPD_distribute_parallel_for: 7246 case OMPD_distribute_parallel_for_simd: 7247 case OMPD_teams_distribute: 7248 case OMPD_teams_distribute_simd: 7249 case OMPD_teams_distribute_parallel_for: 7250 case OMPD_teams_distribute_parallel_for_simd: 7251 case OMPD_target_update: 7252 case OMPD_declare_simd: 7253 case OMPD_declare_variant: 7254 case OMPD_begin_declare_variant: 7255 case OMPD_end_declare_variant: 7256 case OMPD_declare_target: 7257 case OMPD_end_declare_target: 7258 case OMPD_declare_reduction: 7259 case OMPD_declare_mapper: 7260 case OMPD_taskloop: 7261 case OMPD_taskloop_simd: 7262 case OMPD_master_taskloop: 7263 case OMPD_master_taskloop_simd: 7264 case OMPD_parallel_master_taskloop: 7265 case OMPD_parallel_master_taskloop_simd: 7266 case OMPD_requires: 7267 case OMPD_metadirective: 7268 case OMPD_unknown: 7269 break; 7270 default: 7271 break; 7272 } 7273 llvm_unreachable("Unsupported directive kind."); 7274 } 7275 7276 namespace { 7277 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7278 7279 // Utility to handle information from clauses associated with a given 7280 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7281 // It provides a convenient interface to obtain the information and generate 7282 // code for that information. 7283 class MappableExprsHandler { 7284 public: 7285 /// Values for bit flags used to specify the mapping type for 7286 /// offloading. 7287 enum OpenMPOffloadMappingFlags : uint64_t { 7288 /// No flags 7289 OMP_MAP_NONE = 0x0, 7290 /// Allocate memory on the device and move data from host to device. 7291 OMP_MAP_TO = 0x01, 7292 /// Allocate memory on the device and move data from device to host. 7293 OMP_MAP_FROM = 0x02, 7294 /// Always perform the requested mapping action on the element, even 7295 /// if it was already mapped before. 7296 OMP_MAP_ALWAYS = 0x04, 7297 /// Delete the element from the device environment, ignoring the 7298 /// current reference count associated with the element. 7299 OMP_MAP_DELETE = 0x08, 7300 /// The element being mapped is a pointer-pointee pair; both the 7301 /// pointer and the pointee should be mapped. 7302 OMP_MAP_PTR_AND_OBJ = 0x10, 7303 /// This flags signals that the base address of an entry should be 7304 /// passed to the target kernel as an argument. 7305 OMP_MAP_TARGET_PARAM = 0x20, 7306 /// Signal that the runtime library has to return the device pointer 7307 /// in the current position for the data being mapped. Used when we have the 7308 /// use_device_ptr or use_device_addr clause. 7309 OMP_MAP_RETURN_PARAM = 0x40, 7310 /// This flag signals that the reference being passed is a pointer to 7311 /// private data. 7312 OMP_MAP_PRIVATE = 0x80, 7313 /// Pass the element to the device by value. 7314 OMP_MAP_LITERAL = 0x100, 7315 /// Implicit map 7316 OMP_MAP_IMPLICIT = 0x200, 7317 /// Close is a hint to the runtime to allocate memory close to 7318 /// the target device. 7319 OMP_MAP_CLOSE = 0x400, 7320 /// 0x800 is reserved for compatibility with XLC. 7321 /// Produce a runtime error if the data is not already allocated. 7322 OMP_MAP_PRESENT = 0x1000, 7323 // Increment and decrement a separate reference counter so that the data 7324 // cannot be unmapped within the associated region. Thus, this flag is 7325 // intended to be used on 'target' and 'target data' directives because they 7326 // are inherently structured. It is not intended to be used on 'target 7327 // enter data' and 'target exit data' directives because they are inherently 7328 // dynamic. 7329 // This is an OpenMP extension for the sake of OpenACC support. 7330 OMP_MAP_OMPX_HOLD = 0x2000, 7331 /// Signal that the runtime library should use args as an array of 7332 /// descriptor_dim pointers and use args_size as dims. Used when we have 7333 /// non-contiguous list items in target update directive 7334 OMP_MAP_NON_CONTIG = 0x100000000000, 7335 /// The 16 MSBs of the flags indicate whether the entry is member of some 7336 /// struct/class. 7337 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7338 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7339 }; 7340 7341 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7342 static unsigned getFlagMemberOffset() { 7343 unsigned Offset = 0; 7344 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7345 Remain = Remain >> 1) 7346 Offset++; 7347 return Offset; 7348 } 7349 7350 /// Class that holds debugging information for a data mapping to be passed to 7351 /// the runtime library. 7352 class MappingExprInfo { 7353 /// The variable declaration used for the data mapping. 7354 const ValueDecl *MapDecl = nullptr; 7355 /// The original expression used in the map clause, or null if there is 7356 /// none. 7357 const Expr *MapExpr = nullptr; 7358 7359 public: 7360 MappingExprInfo(const ValueDecl *MapDecl, const Expr *MapExpr = nullptr) 7361 : MapDecl(MapDecl), MapExpr(MapExpr) {} 7362 7363 const ValueDecl *getMapDecl() const { return MapDecl; } 7364 const Expr *getMapExpr() const { return MapExpr; } 7365 }; 7366 7367 /// Class that associates information with a base pointer to be passed to the 7368 /// runtime library. 7369 class BasePointerInfo { 7370 /// The base pointer. 7371 llvm::Value *Ptr = nullptr; 7372 /// The base declaration that refers to this device pointer, or null if 7373 /// there is none. 7374 const ValueDecl *DevPtrDecl = nullptr; 7375 7376 public: 7377 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7378 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7379 llvm::Value *operator*() const { return Ptr; } 7380 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7381 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7382 }; 7383 7384 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>; 7385 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7386 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7387 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7388 using MapMappersArrayTy = SmallVector<const ValueDecl *, 4>; 7389 using MapDimArrayTy = SmallVector<uint64_t, 4>; 7390 using MapNonContiguousArrayTy = SmallVector<MapValuesArrayTy, 4>; 7391 7392 /// This structure contains combined information generated for mappable 7393 /// clauses, including base pointers, pointers, sizes, map types, user-defined 7394 /// mappers, and non-contiguous information. 7395 struct MapCombinedInfoTy { 7396 struct StructNonContiguousInfo { 7397 bool IsNonContiguous = false; 7398 MapDimArrayTy Dims; 7399 MapNonContiguousArrayTy Offsets; 7400 MapNonContiguousArrayTy Counts; 7401 MapNonContiguousArrayTy Strides; 7402 }; 7403 MapExprsArrayTy Exprs; 7404 MapBaseValuesArrayTy BasePointers; 7405 MapValuesArrayTy Pointers; 7406 MapValuesArrayTy Sizes; 7407 MapFlagsArrayTy Types; 7408 MapMappersArrayTy Mappers; 7409 StructNonContiguousInfo NonContigInfo; 7410 7411 /// Append arrays in \a CurInfo. 7412 void append(MapCombinedInfoTy &CurInfo) { 7413 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end()); 7414 BasePointers.append(CurInfo.BasePointers.begin(), 7415 CurInfo.BasePointers.end()); 7416 Pointers.append(CurInfo.Pointers.begin(), CurInfo.Pointers.end()); 7417 Sizes.append(CurInfo.Sizes.begin(), CurInfo.Sizes.end()); 7418 Types.append(CurInfo.Types.begin(), CurInfo.Types.end()); 7419 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end()); 7420 NonContigInfo.Dims.append(CurInfo.NonContigInfo.Dims.begin(), 7421 CurInfo.NonContigInfo.Dims.end()); 7422 NonContigInfo.Offsets.append(CurInfo.NonContigInfo.Offsets.begin(), 7423 CurInfo.NonContigInfo.Offsets.end()); 7424 NonContigInfo.Counts.append(CurInfo.NonContigInfo.Counts.begin(), 7425 CurInfo.NonContigInfo.Counts.end()); 7426 NonContigInfo.Strides.append(CurInfo.NonContigInfo.Strides.begin(), 7427 CurInfo.NonContigInfo.Strides.end()); 7428 } 7429 }; 7430 7431 /// Map between a struct and the its lowest & highest elements which have been 7432 /// mapped. 7433 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7434 /// HE(FieldIndex, Pointer)} 7435 struct StructRangeInfoTy { 7436 MapCombinedInfoTy PreliminaryMapData; 7437 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7438 0, Address::invalid()}; 7439 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7440 0, Address::invalid()}; 7441 Address Base = Address::invalid(); 7442 Address LB = Address::invalid(); 7443 bool IsArraySection = false; 7444 bool HasCompleteRecord = false; 7445 }; 7446 7447 private: 7448 /// Kind that defines how a device pointer has to be returned. 7449 struct MapInfo { 7450 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7451 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7452 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7453 ArrayRef<OpenMPMotionModifierKind> MotionModifiers; 7454 bool ReturnDevicePointer = false; 7455 bool IsImplicit = false; 7456 const ValueDecl *Mapper = nullptr; 7457 const Expr *VarRef = nullptr; 7458 bool ForDeviceAddr = false; 7459 7460 MapInfo() = default; 7461 MapInfo( 7462 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7463 OpenMPMapClauseKind MapType, 7464 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7465 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7466 bool ReturnDevicePointer, bool IsImplicit, 7467 const ValueDecl *Mapper = nullptr, const Expr *VarRef = nullptr, 7468 bool ForDeviceAddr = false) 7469 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7470 MotionModifiers(MotionModifiers), 7471 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit), 7472 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {} 7473 }; 7474 7475 /// If use_device_ptr or use_device_addr is used on a decl which is a struct 7476 /// member and there is no map information about it, then emission of that 7477 /// entry is deferred until the whole struct has been processed. 7478 struct DeferredDevicePtrEntryTy { 7479 const Expr *IE = nullptr; 7480 const ValueDecl *VD = nullptr; 7481 bool ForDeviceAddr = false; 7482 7483 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD, 7484 bool ForDeviceAddr) 7485 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {} 7486 }; 7487 7488 /// The target directive from where the mappable clauses were extracted. It 7489 /// is either a executable directive or a user-defined mapper directive. 7490 llvm::PointerUnion<const OMPExecutableDirective *, 7491 const OMPDeclareMapperDecl *> 7492 CurDir; 7493 7494 /// Function the directive is being generated for. 7495 CodeGenFunction &CGF; 7496 7497 /// Set of all first private variables in the current directive. 7498 /// bool data is set to true if the variable is implicitly marked as 7499 /// firstprivate, false otherwise. 7500 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7501 7502 /// Map between device pointer declarations and their expression components. 7503 /// The key value for declarations in 'this' is null. 7504 llvm::DenseMap< 7505 const ValueDecl *, 7506 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7507 DevPointersMap; 7508 7509 /// Map between lambda declarations and their map type. 7510 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap; 7511 7512 llvm::Value *getExprTypeSize(const Expr *E) const { 7513 QualType ExprTy = E->getType().getCanonicalType(); 7514 7515 // Calculate the size for array shaping expression. 7516 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) { 7517 llvm::Value *Size = 7518 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType()); 7519 for (const Expr *SE : OAE->getDimensions()) { 7520 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 7521 Sz = CGF.EmitScalarConversion(Sz, SE->getType(), 7522 CGF.getContext().getSizeType(), 7523 SE->getExprLoc()); 7524 Size = CGF.Builder.CreateNUWMul(Size, Sz); 7525 } 7526 return Size; 7527 } 7528 7529 // Reference types are ignored for mapping purposes. 7530 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7531 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7532 7533 // Given that an array section is considered a built-in type, we need to 7534 // do the calculation based on the length of the section instead of relying 7535 // on CGF.getTypeSize(E->getType()). 7536 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7537 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7538 OAE->getBase()->IgnoreParenImpCasts()) 7539 .getCanonicalType(); 7540 7541 // If there is no length associated with the expression and lower bound is 7542 // not specified too, that means we are using the whole length of the 7543 // base. 7544 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7545 !OAE->getLowerBound()) 7546 return CGF.getTypeSize(BaseTy); 7547 7548 llvm::Value *ElemSize; 7549 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7550 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7551 } else { 7552 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7553 assert(ATy && "Expecting array type if not a pointer type."); 7554 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7555 } 7556 7557 // If we don't have a length at this point, that is because we have an 7558 // array section with a single element. 7559 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid()) 7560 return ElemSize; 7561 7562 if (const Expr *LenExpr = OAE->getLength()) { 7563 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7564 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7565 CGF.getContext().getSizeType(), 7566 LenExpr->getExprLoc()); 7567 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7568 } 7569 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7570 OAE->getLowerBound() && "expected array_section[lb:]."); 7571 // Size = sizetype - lb * elemtype; 7572 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7573 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7574 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7575 CGF.getContext().getSizeType(), 7576 OAE->getLowerBound()->getExprLoc()); 7577 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7578 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7579 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7580 LengthVal = CGF.Builder.CreateSelect( 7581 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7582 return LengthVal; 7583 } 7584 return CGF.getTypeSize(ExprTy); 7585 } 7586 7587 /// Return the corresponding bits for a given map clause modifier. Add 7588 /// a flag marking the map as a pointer if requested. Add a flag marking the 7589 /// map as the first one of a series of maps that relate to the same map 7590 /// expression. 7591 OpenMPOffloadMappingFlags getMapTypeBits( 7592 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7593 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit, 7594 bool AddPtrFlag, bool AddIsTargetParamFlag, bool IsNonContiguous) const { 7595 OpenMPOffloadMappingFlags Bits = 7596 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7597 switch (MapType) { 7598 case OMPC_MAP_alloc: 7599 case OMPC_MAP_release: 7600 // alloc and release is the default behavior in the runtime library, i.e. 7601 // if we don't pass any bits alloc/release that is what the runtime is 7602 // going to do. Therefore, we don't need to signal anything for these two 7603 // type modifiers. 7604 break; 7605 case OMPC_MAP_to: 7606 Bits |= OMP_MAP_TO; 7607 break; 7608 case OMPC_MAP_from: 7609 Bits |= OMP_MAP_FROM; 7610 break; 7611 case OMPC_MAP_tofrom: 7612 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7613 break; 7614 case OMPC_MAP_delete: 7615 Bits |= OMP_MAP_DELETE; 7616 break; 7617 case OMPC_MAP_unknown: 7618 llvm_unreachable("Unexpected map type!"); 7619 } 7620 if (AddPtrFlag) 7621 Bits |= OMP_MAP_PTR_AND_OBJ; 7622 if (AddIsTargetParamFlag) 7623 Bits |= OMP_MAP_TARGET_PARAM; 7624 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always)) 7625 Bits |= OMP_MAP_ALWAYS; 7626 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close)) 7627 Bits |= OMP_MAP_CLOSE; 7628 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) || 7629 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present)) 7630 Bits |= OMP_MAP_PRESENT; 7631 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold)) 7632 Bits |= OMP_MAP_OMPX_HOLD; 7633 if (IsNonContiguous) 7634 Bits |= OMP_MAP_NON_CONTIG; 7635 return Bits; 7636 } 7637 7638 /// Return true if the provided expression is a final array section. A 7639 /// final array section, is one whose length can't be proved to be one. 7640 bool isFinalArraySectionExpression(const Expr *E) const { 7641 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7642 7643 // It is not an array section and therefore not a unity-size one. 7644 if (!OASE) 7645 return false; 7646 7647 // An array section with no colon always refer to a single element. 7648 if (OASE->getColonLocFirst().isInvalid()) 7649 return false; 7650 7651 const Expr *Length = OASE->getLength(); 7652 7653 // If we don't have a length we have to check if the array has size 1 7654 // for this dimension. Also, we should always expect a length if the 7655 // base type is pointer. 7656 if (!Length) { 7657 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7658 OASE->getBase()->IgnoreParenImpCasts()) 7659 .getCanonicalType(); 7660 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7661 return ATy->getSize().getSExtValue() != 1; 7662 // If we don't have a constant dimension length, we have to consider 7663 // the current section as having any size, so it is not necessarily 7664 // unitary. If it happen to be unity size, that's user fault. 7665 return true; 7666 } 7667 7668 // Check if the length evaluates to 1. 7669 Expr::EvalResult Result; 7670 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7671 return true; // Can have more that size 1. 7672 7673 llvm::APSInt ConstLength = Result.Val.getInt(); 7674 return ConstLength.getSExtValue() != 1; 7675 } 7676 7677 /// Generate the base pointers, section pointers, sizes, map type bits, and 7678 /// user-defined mappers (all included in \a CombinedInfo) for the provided 7679 /// map type, map or motion modifiers, and expression components. 7680 /// \a IsFirstComponent should be set to true if the provided set of 7681 /// components is the first associated with a capture. 7682 void generateInfoForComponentList( 7683 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7684 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7685 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7686 MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct, 7687 bool IsFirstComponentList, bool IsImplicit, 7688 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false, 7689 const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr, 7690 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7691 OverlappedElements = llvm::None) const { 7692 // The following summarizes what has to be generated for each map and the 7693 // types below. The generated information is expressed in this order: 7694 // base pointer, section pointer, size, flags 7695 // (to add to the ones that come from the map type and modifier). 7696 // 7697 // double d; 7698 // int i[100]; 7699 // float *p; 7700 // 7701 // struct S1 { 7702 // int i; 7703 // float f[50]; 7704 // } 7705 // struct S2 { 7706 // int i; 7707 // float f[50]; 7708 // S1 s; 7709 // double *p; 7710 // struct S2 *ps; 7711 // int &ref; 7712 // } 7713 // S2 s; 7714 // S2 *ps; 7715 // 7716 // map(d) 7717 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7718 // 7719 // map(i) 7720 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7721 // 7722 // map(i[1:23]) 7723 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7724 // 7725 // map(p) 7726 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7727 // 7728 // map(p[1:24]) 7729 // &p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ 7730 // in unified shared memory mode or for local pointers 7731 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7732 // 7733 // map(s) 7734 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7735 // 7736 // map(s.i) 7737 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7738 // 7739 // map(s.s.f) 7740 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7741 // 7742 // map(s.p) 7743 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7744 // 7745 // map(to: s.p[:22]) 7746 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7747 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7748 // &(s.p), &(s.p[0]), 22*sizeof(double), 7749 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7750 // (*) alloc space for struct members, only this is a target parameter 7751 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7752 // optimizes this entry out, same in the examples below) 7753 // (***) map the pointee (map: to) 7754 // 7755 // map(to: s.ref) 7756 // &s, &(s.ref), sizeof(int*), TARGET_PARAM (*) 7757 // &s, &(s.ref), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7758 // (*) alloc space for struct members, only this is a target parameter 7759 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7760 // optimizes this entry out, same in the examples below) 7761 // (***) map the pointee (map: to) 7762 // 7763 // map(s.ps) 7764 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7765 // 7766 // map(from: s.ps->s.i) 7767 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7768 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7769 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7770 // 7771 // map(to: s.ps->ps) 7772 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7773 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7774 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7775 // 7776 // map(s.ps->ps->ps) 7777 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7778 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7779 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7780 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7781 // 7782 // map(to: s.ps->ps->s.f[:22]) 7783 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7784 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7785 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7786 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7787 // 7788 // map(ps) 7789 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7790 // 7791 // map(ps->i) 7792 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7793 // 7794 // map(ps->s.f) 7795 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7796 // 7797 // map(from: ps->p) 7798 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7799 // 7800 // map(to: ps->p[:22]) 7801 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7802 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7803 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7804 // 7805 // map(ps->ps) 7806 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7807 // 7808 // map(from: ps->ps->s.i) 7809 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7810 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7811 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7812 // 7813 // map(from: ps->ps->ps) 7814 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7815 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7816 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7817 // 7818 // map(ps->ps->ps->ps) 7819 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7820 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7821 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7822 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7823 // 7824 // map(to: ps->ps->ps->s.f[:22]) 7825 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7826 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7827 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7828 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7829 // 7830 // map(to: s.f[:22]) map(from: s.p[:33]) 7831 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7832 // sizeof(double*) (**), TARGET_PARAM 7833 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7834 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7835 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7836 // (*) allocate contiguous space needed to fit all mapped members even if 7837 // we allocate space for members not mapped (in this example, 7838 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7839 // them as well because they fall between &s.f[0] and &s.p) 7840 // 7841 // map(from: s.f[:22]) map(to: ps->p[:33]) 7842 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7843 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7844 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7845 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7846 // (*) the struct this entry pertains to is the 2nd element in the list of 7847 // arguments, hence MEMBER_OF(2) 7848 // 7849 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7850 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7851 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7852 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7853 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7854 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7855 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7856 // (*) the struct this entry pertains to is the 4th element in the list 7857 // of arguments, hence MEMBER_OF(4) 7858 7859 // Track if the map information being generated is the first for a capture. 7860 bool IsCaptureFirstInfo = IsFirstComponentList; 7861 // When the variable is on a declare target link or in a to clause with 7862 // unified memory, a reference is needed to hold the host/device address 7863 // of the variable. 7864 bool RequiresReference = false; 7865 7866 // Scan the components from the base to the complete expression. 7867 auto CI = Components.rbegin(); 7868 auto CE = Components.rend(); 7869 auto I = CI; 7870 7871 // Track if the map information being generated is the first for a list of 7872 // components. 7873 bool IsExpressionFirstInfo = true; 7874 bool FirstPointerInComplexData = false; 7875 Address BP = Address::invalid(); 7876 const Expr *AssocExpr = I->getAssociatedExpression(); 7877 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7878 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7879 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr); 7880 7881 if (isa<MemberExpr>(AssocExpr)) { 7882 // The base is the 'this' pointer. The content of the pointer is going 7883 // to be the base of the field being mapped. 7884 BP = CGF.LoadCXXThisAddress(); 7885 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7886 (OASE && 7887 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7888 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7889 } else if (OAShE && 7890 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) { 7891 BP = Address::deprecated( 7892 CGF.EmitScalarExpr(OAShE->getBase()), 7893 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType())); 7894 } else { 7895 // The base is the reference to the variable. 7896 // BP = &Var. 7897 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7898 if (const auto *VD = 7899 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7900 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7901 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7902 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7903 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7904 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7905 RequiresReference = true; 7906 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7907 } 7908 } 7909 } 7910 7911 // If the variable is a pointer and is being dereferenced (i.e. is not 7912 // the last component), the base has to be the pointer itself, not its 7913 // reference. References are ignored for mapping purposes. 7914 QualType Ty = 7915 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7916 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7917 // No need to generate individual map information for the pointer, it 7918 // can be associated with the combined storage if shared memory mode is 7919 // active or the base declaration is not global variable. 7920 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration()); 7921 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 7922 !VD || VD->hasLocalStorage()) 7923 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7924 else 7925 FirstPointerInComplexData = true; 7926 ++I; 7927 } 7928 } 7929 7930 // Track whether a component of the list should be marked as MEMBER_OF some 7931 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7932 // in a component list should be marked as MEMBER_OF, all subsequent entries 7933 // do not belong to the base struct. E.g. 7934 // struct S2 s; 7935 // s.ps->ps->ps->f[:] 7936 // (1) (2) (3) (4) 7937 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7938 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7939 // is the pointee of ps(2) which is not member of struct s, so it should not 7940 // be marked as such (it is still PTR_AND_OBJ). 7941 // The variable is initialized to false so that PTR_AND_OBJ entries which 7942 // are not struct members are not considered (e.g. array of pointers to 7943 // data). 7944 bool ShouldBeMemberOf = false; 7945 7946 // Variable keeping track of whether or not we have encountered a component 7947 // in the component list which is a member expression. Useful when we have a 7948 // pointer or a final array section, in which case it is the previous 7949 // component in the list which tells us whether we have a member expression. 7950 // E.g. X.f[:] 7951 // While processing the final array section "[:]" it is "f" which tells us 7952 // whether we are dealing with a member of a declared struct. 7953 const MemberExpr *EncounteredME = nullptr; 7954 7955 // Track for the total number of dimension. Start from one for the dummy 7956 // dimension. 7957 uint64_t DimSize = 1; 7958 7959 bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous; 7960 bool IsPrevMemberReference = false; 7961 7962 for (; I != CE; ++I) { 7963 // If the current component is member of a struct (parent struct) mark it. 7964 if (!EncounteredME) { 7965 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7966 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7967 // as MEMBER_OF the parent struct. 7968 if (EncounteredME) { 7969 ShouldBeMemberOf = true; 7970 // Do not emit as complex pointer if this is actually not array-like 7971 // expression. 7972 if (FirstPointerInComplexData) { 7973 QualType Ty = std::prev(I) 7974 ->getAssociatedDeclaration() 7975 ->getType() 7976 .getNonReferenceType(); 7977 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7978 FirstPointerInComplexData = false; 7979 } 7980 } 7981 } 7982 7983 auto Next = std::next(I); 7984 7985 // We need to generate the addresses and sizes if this is the last 7986 // component, if the component is a pointer or if it is an array section 7987 // whose length can't be proved to be one. If this is a pointer, it 7988 // becomes the base address for the following components. 7989 7990 // A final array section, is one whose length can't be proved to be one. 7991 // If the map item is non-contiguous then we don't treat any array section 7992 // as final array section. 7993 bool IsFinalArraySection = 7994 !IsNonContiguous && 7995 isFinalArraySectionExpression(I->getAssociatedExpression()); 7996 7997 // If we have a declaration for the mapping use that, otherwise use 7998 // the base declaration of the map clause. 7999 const ValueDecl *MapDecl = (I->getAssociatedDeclaration()) 8000 ? I->getAssociatedDeclaration() 8001 : BaseDecl; 8002 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression() 8003 : MapExpr; 8004 8005 // Get information on whether the element is a pointer. Have to do a 8006 // special treatment for array sections given that they are built-in 8007 // types. 8008 const auto *OASE = 8009 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 8010 const auto *OAShE = 8011 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression()); 8012 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression()); 8013 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression()); 8014 bool IsPointer = 8015 OAShE || 8016 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 8017 .getCanonicalType() 8018 ->isAnyPointerType()) || 8019 I->getAssociatedExpression()->getType()->isAnyPointerType(); 8020 bool IsMemberReference = isa<MemberExpr>(I->getAssociatedExpression()) && 8021 MapDecl && 8022 MapDecl->getType()->isLValueReferenceType(); 8023 bool IsNonDerefPointer = IsPointer && !UO && !BO && !IsNonContiguous; 8024 8025 if (OASE) 8026 ++DimSize; 8027 8028 if (Next == CE || IsMemberReference || IsNonDerefPointer || 8029 IsFinalArraySection) { 8030 // If this is not the last component, we expect the pointer to be 8031 // associated with an array expression or member expression. 8032 assert((Next == CE || 8033 isa<MemberExpr>(Next->getAssociatedExpression()) || 8034 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 8035 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || 8036 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || 8037 isa<UnaryOperator>(Next->getAssociatedExpression()) || 8038 isa<BinaryOperator>(Next->getAssociatedExpression())) && 8039 "Unexpected expression"); 8040 8041 Address LB = Address::invalid(); 8042 Address LowestElem = Address::invalid(); 8043 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF, 8044 const MemberExpr *E) { 8045 const Expr *BaseExpr = E->getBase(); 8046 // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a 8047 // scalar. 8048 LValue BaseLV; 8049 if (E->isArrow()) { 8050 LValueBaseInfo BaseInfo; 8051 TBAAAccessInfo TBAAInfo; 8052 Address Addr = 8053 CGF.EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo); 8054 QualType PtrTy = BaseExpr->getType()->getPointeeType(); 8055 BaseLV = CGF.MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); 8056 } else { 8057 BaseLV = CGF.EmitOMPSharedLValue(BaseExpr); 8058 } 8059 return BaseLV; 8060 }; 8061 if (OAShE) { 8062 LowestElem = LB = 8063 Address::deprecated(CGF.EmitScalarExpr(OAShE->getBase()), 8064 CGF.getContext().getTypeAlignInChars( 8065 OAShE->getBase()->getType())); 8066 } else if (IsMemberReference) { 8067 const auto *ME = cast<MemberExpr>(I->getAssociatedExpression()); 8068 LValue BaseLVal = EmitMemberExprBase(CGF, ME); 8069 LowestElem = CGF.EmitLValueForFieldInitialization( 8070 BaseLVal, cast<FieldDecl>(MapDecl)) 8071 .getAddress(CGF); 8072 LB = CGF.EmitLoadOfReferenceLValue(LowestElem, MapDecl->getType()) 8073 .getAddress(CGF); 8074 } else { 8075 LowestElem = LB = 8076 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 8077 .getAddress(CGF); 8078 } 8079 8080 // If this component is a pointer inside the base struct then we don't 8081 // need to create any entry for it - it will be combined with the object 8082 // it is pointing to into a single PTR_AND_OBJ entry. 8083 bool IsMemberPointerOrAddr = 8084 EncounteredME && 8085 (((IsPointer || ForDeviceAddr) && 8086 I->getAssociatedExpression() == EncounteredME) || 8087 (IsPrevMemberReference && !IsPointer) || 8088 (IsMemberReference && Next != CE && 8089 !Next->getAssociatedExpression()->getType()->isPointerType())); 8090 if (!OverlappedElements.empty() && Next == CE) { 8091 // Handle base element with the info for overlapped elements. 8092 assert(!PartialStruct.Base.isValid() && "The base element is set."); 8093 assert(!IsPointer && 8094 "Unexpected base element with the pointer type."); 8095 // Mark the whole struct as the struct that requires allocation on the 8096 // device. 8097 PartialStruct.LowestElem = {0, LowestElem}; 8098 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 8099 I->getAssociatedExpression()->getType()); 8100 Address HB = CGF.Builder.CreateConstGEP( 8101 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8102 LowestElem, CGF.VoidPtrTy, CGF.Int8Ty), 8103 TypeSize.getQuantity() - 1); 8104 PartialStruct.HighestElem = { 8105 std::numeric_limits<decltype( 8106 PartialStruct.HighestElem.first)>::max(), 8107 HB}; 8108 PartialStruct.Base = BP; 8109 PartialStruct.LB = LB; 8110 assert( 8111 PartialStruct.PreliminaryMapData.BasePointers.empty() && 8112 "Overlapped elements must be used only once for the variable."); 8113 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo); 8114 // Emit data for non-overlapped data. 8115 OpenMPOffloadMappingFlags Flags = 8116 OMP_MAP_MEMBER_OF | 8117 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit, 8118 /*AddPtrFlag=*/false, 8119 /*AddIsTargetParamFlag=*/false, IsNonContiguous); 8120 llvm::Value *Size = nullptr; 8121 // Do bitcopy of all non-overlapped structure elements. 8122 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 8123 Component : OverlappedElements) { 8124 Address ComponentLB = Address::invalid(); 8125 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 8126 Component) { 8127 if (const ValueDecl *VD = MC.getAssociatedDeclaration()) { 8128 const auto *FD = dyn_cast<FieldDecl>(VD); 8129 if (FD && FD->getType()->isLValueReferenceType()) { 8130 const auto *ME = 8131 cast<MemberExpr>(MC.getAssociatedExpression()); 8132 LValue BaseLVal = EmitMemberExprBase(CGF, ME); 8133 ComponentLB = 8134 CGF.EmitLValueForFieldInitialization(BaseLVal, FD) 8135 .getAddress(CGF); 8136 } else { 8137 ComponentLB = 8138 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 8139 .getAddress(CGF); 8140 } 8141 Size = CGF.Builder.CreatePtrDiff( 8142 CGF.Int8Ty, CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 8143 CGF.EmitCastToVoidPtr(LB.getPointer())); 8144 break; 8145 } 8146 } 8147 assert(Size && "Failed to determine structure size"); 8148 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8149 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8150 CombinedInfo.Pointers.push_back(LB.getPointer()); 8151 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8152 Size, CGF.Int64Ty, /*isSigned=*/true)); 8153 CombinedInfo.Types.push_back(Flags); 8154 CombinedInfo.Mappers.push_back(nullptr); 8155 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8156 : 1); 8157 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 8158 } 8159 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8160 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8161 CombinedInfo.Pointers.push_back(LB.getPointer()); 8162 Size = CGF.Builder.CreatePtrDiff( 8163 CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).getPointer(), 8164 CGF.EmitCastToVoidPtr(LB.getPointer())); 8165 CombinedInfo.Sizes.push_back( 8166 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 8167 CombinedInfo.Types.push_back(Flags); 8168 CombinedInfo.Mappers.push_back(nullptr); 8169 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8170 : 1); 8171 break; 8172 } 8173 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 8174 if (!IsMemberPointerOrAddr || 8175 (Next == CE && MapType != OMPC_MAP_unknown)) { 8176 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8177 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8178 CombinedInfo.Pointers.push_back(LB.getPointer()); 8179 CombinedInfo.Sizes.push_back( 8180 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 8181 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8182 : 1); 8183 8184 // If Mapper is valid, the last component inherits the mapper. 8185 bool HasMapper = Mapper && Next == CE; 8186 CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr); 8187 8188 // We need to add a pointer flag for each map that comes from the 8189 // same expression except for the first one. We also need to signal 8190 // this map is the first one that relates with the current capture 8191 // (there is a set of entries for each capture). 8192 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 8193 MapType, MapModifiers, MotionModifiers, IsImplicit, 8194 !IsExpressionFirstInfo || RequiresReference || 8195 FirstPointerInComplexData || IsMemberReference, 8196 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous); 8197 8198 if (!IsExpressionFirstInfo || IsMemberReference) { 8199 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 8200 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 8201 if (IsPointer || (IsMemberReference && Next != CE)) 8202 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 8203 OMP_MAP_DELETE | OMP_MAP_CLOSE); 8204 8205 if (ShouldBeMemberOf) { 8206 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 8207 // should be later updated with the correct value of MEMBER_OF. 8208 Flags |= OMP_MAP_MEMBER_OF; 8209 // From now on, all subsequent PTR_AND_OBJ entries should not be 8210 // marked as MEMBER_OF. 8211 ShouldBeMemberOf = false; 8212 } 8213 } 8214 8215 CombinedInfo.Types.push_back(Flags); 8216 } 8217 8218 // If we have encountered a member expression so far, keep track of the 8219 // mapped member. If the parent is "*this", then the value declaration 8220 // is nullptr. 8221 if (EncounteredME) { 8222 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl()); 8223 unsigned FieldIndex = FD->getFieldIndex(); 8224 8225 // Update info about the lowest and highest elements for this struct 8226 if (!PartialStruct.Base.isValid()) { 8227 PartialStruct.LowestElem = {FieldIndex, LowestElem}; 8228 if (IsFinalArraySection) { 8229 Address HB = 8230 CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false) 8231 .getAddress(CGF); 8232 PartialStruct.HighestElem = {FieldIndex, HB}; 8233 } else { 8234 PartialStruct.HighestElem = {FieldIndex, LowestElem}; 8235 } 8236 PartialStruct.Base = BP; 8237 PartialStruct.LB = BP; 8238 } else if (FieldIndex < PartialStruct.LowestElem.first) { 8239 PartialStruct.LowestElem = {FieldIndex, LowestElem}; 8240 } else if (FieldIndex > PartialStruct.HighestElem.first) { 8241 PartialStruct.HighestElem = {FieldIndex, LowestElem}; 8242 } 8243 } 8244 8245 // Need to emit combined struct for array sections. 8246 if (IsFinalArraySection || IsNonContiguous) 8247 PartialStruct.IsArraySection = true; 8248 8249 // If we have a final array section, we are done with this expression. 8250 if (IsFinalArraySection) 8251 break; 8252 8253 // The pointer becomes the base for the next element. 8254 if (Next != CE) 8255 BP = IsMemberReference ? LowestElem : LB; 8256 8257 IsExpressionFirstInfo = false; 8258 IsCaptureFirstInfo = false; 8259 FirstPointerInComplexData = false; 8260 IsPrevMemberReference = IsMemberReference; 8261 } else if (FirstPointerInComplexData) { 8262 QualType Ty = Components.rbegin() 8263 ->getAssociatedDeclaration() 8264 ->getType() 8265 .getNonReferenceType(); 8266 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 8267 FirstPointerInComplexData = false; 8268 } 8269 } 8270 // If ran into the whole component - allocate the space for the whole 8271 // record. 8272 if (!EncounteredME) 8273 PartialStruct.HasCompleteRecord = true; 8274 8275 if (!IsNonContiguous) 8276 return; 8277 8278 const ASTContext &Context = CGF.getContext(); 8279 8280 // For supporting stride in array section, we need to initialize the first 8281 // dimension size as 1, first offset as 0, and first count as 1 8282 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 0)}; 8283 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 8284 MapValuesArrayTy CurStrides; 8285 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 8286 uint64_t ElementTypeSize; 8287 8288 // Collect Size information for each dimension and get the element size as 8289 // the first Stride. For example, for `int arr[10][10]`, the DimSizes 8290 // should be [10, 10] and the first stride is 4 btyes. 8291 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 8292 Components) { 8293 const Expr *AssocExpr = Component.getAssociatedExpression(); 8294 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8295 8296 if (!OASE) 8297 continue; 8298 8299 QualType Ty = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase()); 8300 auto *CAT = Context.getAsConstantArrayType(Ty); 8301 auto *VAT = Context.getAsVariableArrayType(Ty); 8302 8303 // We need all the dimension size except for the last dimension. 8304 assert((VAT || CAT || &Component == &*Components.begin()) && 8305 "Should be either ConstantArray or VariableArray if not the " 8306 "first Component"); 8307 8308 // Get element size if CurStrides is empty. 8309 if (CurStrides.empty()) { 8310 const Type *ElementType = nullptr; 8311 if (CAT) 8312 ElementType = CAT->getElementType().getTypePtr(); 8313 else if (VAT) 8314 ElementType = VAT->getElementType().getTypePtr(); 8315 else 8316 assert(&Component == &*Components.begin() && 8317 "Only expect pointer (non CAT or VAT) when this is the " 8318 "first Component"); 8319 // If ElementType is null, then it means the base is a pointer 8320 // (neither CAT nor VAT) and we'll attempt to get ElementType again 8321 // for next iteration. 8322 if (ElementType) { 8323 // For the case that having pointer as base, we need to remove one 8324 // level of indirection. 8325 if (&Component != &*Components.begin()) 8326 ElementType = ElementType->getPointeeOrArrayElementType(); 8327 ElementTypeSize = 8328 Context.getTypeSizeInChars(ElementType).getQuantity(); 8329 CurStrides.push_back( 8330 llvm::ConstantInt::get(CGF.Int64Ty, ElementTypeSize)); 8331 } 8332 } 8333 // Get dimension value except for the last dimension since we don't need 8334 // it. 8335 if (DimSizes.size() < Components.size() - 1) { 8336 if (CAT) 8337 DimSizes.push_back(llvm::ConstantInt::get( 8338 CGF.Int64Ty, CAT->getSize().getZExtValue())); 8339 else if (VAT) 8340 DimSizes.push_back(CGF.Builder.CreateIntCast( 8341 CGF.EmitScalarExpr(VAT->getSizeExpr()), CGF.Int64Ty, 8342 /*IsSigned=*/false)); 8343 } 8344 } 8345 8346 // Skip the dummy dimension since we have already have its information. 8347 auto *DI = DimSizes.begin() + 1; 8348 // Product of dimension. 8349 llvm::Value *DimProd = 8350 llvm::ConstantInt::get(CGF.CGM.Int64Ty, ElementTypeSize); 8351 8352 // Collect info for non-contiguous. Notice that offset, count, and stride 8353 // are only meaningful for array-section, so we insert a null for anything 8354 // other than array-section. 8355 // Also, the size of offset, count, and stride are not the same as 8356 // pointers, base_pointers, sizes, or dims. Instead, the size of offset, 8357 // count, and stride are the same as the number of non-contiguous 8358 // declaration in target update to/from clause. 8359 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 8360 Components) { 8361 const Expr *AssocExpr = Component.getAssociatedExpression(); 8362 8363 if (const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) { 8364 llvm::Value *Offset = CGF.Builder.CreateIntCast( 8365 CGF.EmitScalarExpr(AE->getIdx()), CGF.Int64Ty, 8366 /*isSigned=*/false); 8367 CurOffsets.push_back(Offset); 8368 CurCounts.push_back(llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/1)); 8369 CurStrides.push_back(CurStrides.back()); 8370 continue; 8371 } 8372 8373 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8374 8375 if (!OASE) 8376 continue; 8377 8378 // Offset 8379 const Expr *OffsetExpr = OASE->getLowerBound(); 8380 llvm::Value *Offset = nullptr; 8381 if (!OffsetExpr) { 8382 // If offset is absent, then we just set it to zero. 8383 Offset = llvm::ConstantInt::get(CGF.Int64Ty, 0); 8384 } else { 8385 Offset = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(OffsetExpr), 8386 CGF.Int64Ty, 8387 /*isSigned=*/false); 8388 } 8389 CurOffsets.push_back(Offset); 8390 8391 // Count 8392 const Expr *CountExpr = OASE->getLength(); 8393 llvm::Value *Count = nullptr; 8394 if (!CountExpr) { 8395 // In Clang, once a high dimension is an array section, we construct all 8396 // the lower dimension as array section, however, for case like 8397 // arr[0:2][2], Clang construct the inner dimension as an array section 8398 // but it actually is not in an array section form according to spec. 8399 if (!OASE->getColonLocFirst().isValid() && 8400 !OASE->getColonLocSecond().isValid()) { 8401 Count = llvm::ConstantInt::get(CGF.Int64Ty, 1); 8402 } else { 8403 // OpenMP 5.0, 2.1.5 Array Sections, Description. 8404 // When the length is absent it defaults to ⌈(size − 8405 // lower-bound)/stride⌉, where size is the size of the array 8406 // dimension. 8407 const Expr *StrideExpr = OASE->getStride(); 8408 llvm::Value *Stride = 8409 StrideExpr 8410 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8411 CGF.Int64Ty, /*isSigned=*/false) 8412 : nullptr; 8413 if (Stride) 8414 Count = CGF.Builder.CreateUDiv( 8415 CGF.Builder.CreateNUWSub(*DI, Offset), Stride); 8416 else 8417 Count = CGF.Builder.CreateNUWSub(*DI, Offset); 8418 } 8419 } else { 8420 Count = CGF.EmitScalarExpr(CountExpr); 8421 } 8422 Count = CGF.Builder.CreateIntCast(Count, CGF.Int64Ty, /*isSigned=*/false); 8423 CurCounts.push_back(Count); 8424 8425 // Stride_n' = Stride_n * (D_0 * D_1 ... * D_n-1) * Unit size 8426 // Take `int arr[5][5][5]` and `arr[0:2:2][1:2:1][0:2:2]` as an example: 8427 // Offset Count Stride 8428 // D0 0 1 4 (int) <- dummy dimension 8429 // D1 0 2 8 (2 * (1) * 4) 8430 // D2 1 2 20 (1 * (1 * 5) * 4) 8431 // D3 0 2 200 (2 * (1 * 5 * 4) * 4) 8432 const Expr *StrideExpr = OASE->getStride(); 8433 llvm::Value *Stride = 8434 StrideExpr 8435 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8436 CGF.Int64Ty, /*isSigned=*/false) 8437 : nullptr; 8438 DimProd = CGF.Builder.CreateNUWMul(DimProd, *(DI - 1)); 8439 if (Stride) 8440 CurStrides.push_back(CGF.Builder.CreateNUWMul(DimProd, Stride)); 8441 else 8442 CurStrides.push_back(DimProd); 8443 if (DI != DimSizes.end()) 8444 ++DI; 8445 } 8446 8447 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets); 8448 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts); 8449 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides); 8450 } 8451 8452 /// Return the adjusted map modifiers if the declaration a capture refers to 8453 /// appears in a first-private clause. This is expected to be used only with 8454 /// directives that start with 'target'. 8455 MappableExprsHandler::OpenMPOffloadMappingFlags 8456 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 8457 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 8458 8459 // A first private variable captured by reference will use only the 8460 // 'private ptr' and 'map to' flag. Return the right flags if the captured 8461 // declaration is known as first-private in this handler. 8462 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 8463 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 8464 return MappableExprsHandler::OMP_MAP_TO | 8465 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 8466 return MappableExprsHandler::OMP_MAP_PRIVATE | 8467 MappableExprsHandler::OMP_MAP_TO; 8468 } 8469 auto I = LambdasMap.find(Cap.getCapturedVar()->getCanonicalDecl()); 8470 if (I != LambdasMap.end()) 8471 // for map(to: lambda): using user specified map type. 8472 return getMapTypeBits( 8473 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(), 8474 /*MotionModifiers=*/llvm::None, I->getSecond()->isImplicit(), 8475 /*AddPtrFlag=*/false, 8476 /*AddIsTargetParamFlag=*/false, 8477 /*isNonContiguous=*/false); 8478 return MappableExprsHandler::OMP_MAP_TO | 8479 MappableExprsHandler::OMP_MAP_FROM; 8480 } 8481 8482 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 8483 // Rotate by getFlagMemberOffset() bits. 8484 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 8485 << getFlagMemberOffset()); 8486 } 8487 8488 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 8489 OpenMPOffloadMappingFlags MemberOfFlag) { 8490 // If the entry is PTR_AND_OBJ but has not been marked with the special 8491 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 8492 // marked as MEMBER_OF. 8493 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 8494 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 8495 return; 8496 8497 // Reset the placeholder value to prepare the flag for the assignment of the 8498 // proper MEMBER_OF value. 8499 Flags &= ~OMP_MAP_MEMBER_OF; 8500 Flags |= MemberOfFlag; 8501 } 8502 8503 void getPlainLayout(const CXXRecordDecl *RD, 8504 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 8505 bool AsBase) const { 8506 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 8507 8508 llvm::StructType *St = 8509 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 8510 8511 unsigned NumElements = St->getNumElements(); 8512 llvm::SmallVector< 8513 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 8514 RecordLayout(NumElements); 8515 8516 // Fill bases. 8517 for (const auto &I : RD->bases()) { 8518 if (I.isVirtual()) 8519 continue; 8520 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8521 // Ignore empty bases. 8522 if (Base->isEmpty() || CGF.getContext() 8523 .getASTRecordLayout(Base) 8524 .getNonVirtualSize() 8525 .isZero()) 8526 continue; 8527 8528 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 8529 RecordLayout[FieldIndex] = Base; 8530 } 8531 // Fill in virtual bases. 8532 for (const auto &I : RD->vbases()) { 8533 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8534 // Ignore empty bases. 8535 if (Base->isEmpty()) 8536 continue; 8537 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 8538 if (RecordLayout[FieldIndex]) 8539 continue; 8540 RecordLayout[FieldIndex] = Base; 8541 } 8542 // Fill in all the fields. 8543 assert(!RD->isUnion() && "Unexpected union."); 8544 for (const auto *Field : RD->fields()) { 8545 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 8546 // will fill in later.) 8547 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 8548 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 8549 RecordLayout[FieldIndex] = Field; 8550 } 8551 } 8552 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 8553 &Data : RecordLayout) { 8554 if (Data.isNull()) 8555 continue; 8556 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 8557 getPlainLayout(Base, Layout, /*AsBase=*/true); 8558 else 8559 Layout.push_back(Data.get<const FieldDecl *>()); 8560 } 8561 } 8562 8563 /// Generate all the base pointers, section pointers, sizes, map types, and 8564 /// mappers for the extracted mappable expressions (all included in \a 8565 /// CombinedInfo). Also, for each item that relates with a device pointer, a 8566 /// pair of the relevant declaration and index where it occurs is appended to 8567 /// the device pointers info array. 8568 void generateAllInfoForClauses( 8569 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo, 8570 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 8571 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 8572 // We have to process the component lists that relate with the same 8573 // declaration in a single chunk so that we can generate the map flags 8574 // correctly. Therefore, we organize all lists in a map. 8575 enum MapKind { Present, Allocs, Other, Total }; 8576 llvm::MapVector<CanonicalDeclPtr<const Decl>, 8577 SmallVector<SmallVector<MapInfo, 8>, 4>> 8578 Info; 8579 8580 // Helper function to fill the information map for the different supported 8581 // clauses. 8582 auto &&InfoGen = 8583 [&Info, &SkipVarSet]( 8584 const ValueDecl *D, MapKind Kind, 8585 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8586 OpenMPMapClauseKind MapType, 8587 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8588 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 8589 bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper, 8590 const Expr *VarRef = nullptr, bool ForDeviceAddr = false) { 8591 if (SkipVarSet.contains(D)) 8592 return; 8593 auto It = Info.find(D); 8594 if (It == Info.end()) 8595 It = Info 8596 .insert(std::make_pair( 8597 D, SmallVector<SmallVector<MapInfo, 8>, 4>(Total))) 8598 .first; 8599 It->second[Kind].emplace_back( 8600 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer, 8601 IsImplicit, Mapper, VarRef, ForDeviceAddr); 8602 }; 8603 8604 for (const auto *Cl : Clauses) { 8605 const auto *C = dyn_cast<OMPMapClause>(Cl); 8606 if (!C) 8607 continue; 8608 MapKind Kind = Other; 8609 if (llvm::is_contained(C->getMapTypeModifiers(), 8610 OMPC_MAP_MODIFIER_present)) 8611 Kind = Present; 8612 else if (C->getMapType() == OMPC_MAP_alloc) 8613 Kind = Allocs; 8614 const auto *EI = C->getVarRefs().begin(); 8615 for (const auto L : C->component_lists()) { 8616 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 8617 InfoGen(std::get<0>(L), Kind, std::get<1>(L), C->getMapType(), 8618 C->getMapTypeModifiers(), llvm::None, 8619 /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L), 8620 E); 8621 ++EI; 8622 } 8623 } 8624 for (const auto *Cl : Clauses) { 8625 const auto *C = dyn_cast<OMPToClause>(Cl); 8626 if (!C) 8627 continue; 8628 MapKind Kind = Other; 8629 if (llvm::is_contained(C->getMotionModifiers(), 8630 OMPC_MOTION_MODIFIER_present)) 8631 Kind = Present; 8632 const auto *EI = C->getVarRefs().begin(); 8633 for (const auto L : C->component_lists()) { 8634 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, llvm::None, 8635 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8636 C->isImplicit(), std::get<2>(L), *EI); 8637 ++EI; 8638 } 8639 } 8640 for (const auto *Cl : Clauses) { 8641 const auto *C = dyn_cast<OMPFromClause>(Cl); 8642 if (!C) 8643 continue; 8644 MapKind Kind = Other; 8645 if (llvm::is_contained(C->getMotionModifiers(), 8646 OMPC_MOTION_MODIFIER_present)) 8647 Kind = Present; 8648 const auto *EI = C->getVarRefs().begin(); 8649 for (const auto L : C->component_lists()) { 8650 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, llvm::None, 8651 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8652 C->isImplicit(), std::get<2>(L), *EI); 8653 ++EI; 8654 } 8655 } 8656 8657 // Look at the use_device_ptr clause information and mark the existing map 8658 // entries as such. If there is no map information for an entry in the 8659 // use_device_ptr list, we create one with map type 'alloc' and zero size 8660 // section. It is the user fault if that was not mapped before. If there is 8661 // no map information and the pointer is a struct member, then we defer the 8662 // emission of that entry until the whole struct has been processed. 8663 llvm::MapVector<CanonicalDeclPtr<const Decl>, 8664 SmallVector<DeferredDevicePtrEntryTy, 4>> 8665 DeferredInfo; 8666 MapCombinedInfoTy UseDevicePtrCombinedInfo; 8667 8668 for (const auto *Cl : Clauses) { 8669 const auto *C = dyn_cast<OMPUseDevicePtrClause>(Cl); 8670 if (!C) 8671 continue; 8672 for (const auto L : C->component_lists()) { 8673 OMPClauseMappableExprCommon::MappableExprComponentListRef Components = 8674 std::get<1>(L); 8675 assert(!Components.empty() && 8676 "Not expecting empty list of components!"); 8677 const ValueDecl *VD = Components.back().getAssociatedDeclaration(); 8678 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8679 const Expr *IE = Components.back().getAssociatedExpression(); 8680 // If the first component is a member expression, we have to look into 8681 // 'this', which maps to null in the map of map information. Otherwise 8682 // look directly for the information. 8683 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8684 8685 // We potentially have map information for this declaration already. 8686 // Look for the first set of components that refer to it. 8687 if (It != Info.end()) { 8688 bool Found = false; 8689 for (auto &Data : It->second) { 8690 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) { 8691 return MI.Components.back().getAssociatedDeclaration() == VD; 8692 }); 8693 // If we found a map entry, signal that the pointer has to be 8694 // returned and move on to the next declaration. Exclude cases where 8695 // the base pointer is mapped as array subscript, array section or 8696 // array shaping. The base address is passed as a pointer to base in 8697 // this case and cannot be used as a base for use_device_ptr list 8698 // item. 8699 if (CI != Data.end()) { 8700 auto PrevCI = std::next(CI->Components.rbegin()); 8701 const auto *VarD = dyn_cast<VarDecl>(VD); 8702 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8703 isa<MemberExpr>(IE) || 8704 !VD->getType().getNonReferenceType()->isPointerType() || 8705 PrevCI == CI->Components.rend() || 8706 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD || 8707 VarD->hasLocalStorage()) { 8708 CI->ReturnDevicePointer = true; 8709 Found = true; 8710 break; 8711 } 8712 } 8713 } 8714 if (Found) 8715 continue; 8716 } 8717 8718 // We didn't find any match in our map information - generate a zero 8719 // size array section - if the pointer is a struct member we defer this 8720 // action until the whole struct has been processed. 8721 if (isa<MemberExpr>(IE)) { 8722 // Insert the pointer into Info to be processed by 8723 // generateInfoForComponentList. Because it is a member pointer 8724 // without a pointee, no entry will be generated for it, therefore 8725 // we need to generate one after the whole struct has been processed. 8726 // Nonetheless, generateInfoForComponentList must be called to take 8727 // the pointer into account for the calculation of the range of the 8728 // partial struct. 8729 InfoGen(nullptr, Other, Components, OMPC_MAP_unknown, llvm::None, 8730 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8731 nullptr); 8732 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/false); 8733 } else { 8734 llvm::Value *Ptr = 8735 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8736 UseDevicePtrCombinedInfo.Exprs.push_back(VD); 8737 UseDevicePtrCombinedInfo.BasePointers.emplace_back(Ptr, VD); 8738 UseDevicePtrCombinedInfo.Pointers.push_back(Ptr); 8739 UseDevicePtrCombinedInfo.Sizes.push_back( 8740 llvm::Constant::getNullValue(CGF.Int64Ty)); 8741 UseDevicePtrCombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM); 8742 UseDevicePtrCombinedInfo.Mappers.push_back(nullptr); 8743 } 8744 } 8745 } 8746 8747 // Look at the use_device_addr clause information and mark the existing map 8748 // entries as such. If there is no map information for an entry in the 8749 // use_device_addr list, we create one with map type 'alloc' and zero size 8750 // section. It is the user fault if that was not mapped before. If there is 8751 // no map information and the pointer is a struct member, then we defer the 8752 // emission of that entry until the whole struct has been processed. 8753 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed; 8754 for (const auto *Cl : Clauses) { 8755 const auto *C = dyn_cast<OMPUseDeviceAddrClause>(Cl); 8756 if (!C) 8757 continue; 8758 for (const auto L : C->component_lists()) { 8759 assert(!std::get<1>(L).empty() && 8760 "Not expecting empty list of components!"); 8761 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration(); 8762 if (!Processed.insert(VD).second) 8763 continue; 8764 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8765 const Expr *IE = std::get<1>(L).back().getAssociatedExpression(); 8766 // If the first component is a member expression, we have to look into 8767 // 'this', which maps to null in the map of map information. Otherwise 8768 // look directly for the information. 8769 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8770 8771 // We potentially have map information for this declaration already. 8772 // Look for the first set of components that refer to it. 8773 if (It != Info.end()) { 8774 bool Found = false; 8775 for (auto &Data : It->second) { 8776 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) { 8777 return MI.Components.back().getAssociatedDeclaration() == VD; 8778 }); 8779 // If we found a map entry, signal that the pointer has to be 8780 // returned and move on to the next declaration. 8781 if (CI != Data.end()) { 8782 CI->ReturnDevicePointer = true; 8783 Found = true; 8784 break; 8785 } 8786 } 8787 if (Found) 8788 continue; 8789 } 8790 8791 // We didn't find any match in our map information - generate a zero 8792 // size array section - if the pointer is a struct member we defer this 8793 // action until the whole struct has been processed. 8794 if (isa<MemberExpr>(IE)) { 8795 // Insert the pointer into Info to be processed by 8796 // generateInfoForComponentList. Because it is a member pointer 8797 // without a pointee, no entry will be generated for it, therefore 8798 // we need to generate one after the whole struct has been processed. 8799 // Nonetheless, generateInfoForComponentList must be called to take 8800 // the pointer into account for the calculation of the range of the 8801 // partial struct. 8802 InfoGen(nullptr, Other, std::get<1>(L), OMPC_MAP_unknown, llvm::None, 8803 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8804 nullptr, nullptr, /*ForDeviceAddr=*/true); 8805 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/true); 8806 } else { 8807 llvm::Value *Ptr; 8808 if (IE->isGLValue()) 8809 Ptr = CGF.EmitLValue(IE).getPointer(CGF); 8810 else 8811 Ptr = CGF.EmitScalarExpr(IE); 8812 CombinedInfo.Exprs.push_back(VD); 8813 CombinedInfo.BasePointers.emplace_back(Ptr, VD); 8814 CombinedInfo.Pointers.push_back(Ptr); 8815 CombinedInfo.Sizes.push_back( 8816 llvm::Constant::getNullValue(CGF.Int64Ty)); 8817 CombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM); 8818 CombinedInfo.Mappers.push_back(nullptr); 8819 } 8820 } 8821 } 8822 8823 for (const auto &Data : Info) { 8824 StructRangeInfoTy PartialStruct; 8825 // Temporary generated information. 8826 MapCombinedInfoTy CurInfo; 8827 const Decl *D = Data.first; 8828 const ValueDecl *VD = cast_or_null<ValueDecl>(D); 8829 for (const auto &M : Data.second) { 8830 for (const MapInfo &L : M) { 8831 assert(!L.Components.empty() && 8832 "Not expecting declaration with no component lists."); 8833 8834 // Remember the current base pointer index. 8835 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size(); 8836 CurInfo.NonContigInfo.IsNonContiguous = 8837 L.Components.back().isNonContiguous(); 8838 generateInfoForComponentList( 8839 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components, 8840 CurInfo, PartialStruct, /*IsFirstComponentList=*/false, 8841 L.IsImplicit, L.Mapper, L.ForDeviceAddr, VD, L.VarRef); 8842 8843 // If this entry relates with a device pointer, set the relevant 8844 // declaration and add the 'return pointer' flag. 8845 if (L.ReturnDevicePointer) { 8846 assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx && 8847 "Unexpected number of mapped base pointers."); 8848 8849 const ValueDecl *RelevantVD = 8850 L.Components.back().getAssociatedDeclaration(); 8851 assert(RelevantVD && 8852 "No relevant declaration related with device pointer??"); 8853 8854 CurInfo.BasePointers[CurrentBasePointersIdx].setDevicePtrDecl( 8855 RelevantVD); 8856 CurInfo.Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8857 } 8858 } 8859 } 8860 8861 // Append any pending zero-length pointers which are struct members and 8862 // used with use_device_ptr or use_device_addr. 8863 auto CI = DeferredInfo.find(Data.first); 8864 if (CI != DeferredInfo.end()) { 8865 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8866 llvm::Value *BasePtr; 8867 llvm::Value *Ptr; 8868 if (L.ForDeviceAddr) { 8869 if (L.IE->isGLValue()) 8870 Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8871 else 8872 Ptr = this->CGF.EmitScalarExpr(L.IE); 8873 BasePtr = Ptr; 8874 // Entry is RETURN_PARAM. Also, set the placeholder value 8875 // MEMBER_OF=FFFF so that the entry is later updated with the 8876 // correct value of MEMBER_OF. 8877 CurInfo.Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_MEMBER_OF); 8878 } else { 8879 BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8880 Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE), 8881 L.IE->getExprLoc()); 8882 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the 8883 // placeholder value MEMBER_OF=FFFF so that the entry is later 8884 // updated with the correct value of MEMBER_OF. 8885 CurInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8886 OMP_MAP_MEMBER_OF); 8887 } 8888 CurInfo.Exprs.push_back(L.VD); 8889 CurInfo.BasePointers.emplace_back(BasePtr, L.VD); 8890 CurInfo.Pointers.push_back(Ptr); 8891 CurInfo.Sizes.push_back( 8892 llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8893 CurInfo.Mappers.push_back(nullptr); 8894 } 8895 } 8896 // If there is an entry in PartialStruct it means we have a struct with 8897 // individual members mapped. Emit an extra combined entry. 8898 if (PartialStruct.Base.isValid()) { 8899 CurInfo.NonContigInfo.Dims.push_back(0); 8900 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, VD); 8901 } 8902 8903 // We need to append the results of this capture to what we already 8904 // have. 8905 CombinedInfo.append(CurInfo); 8906 } 8907 // Append data for use_device_ptr clauses. 8908 CombinedInfo.append(UseDevicePtrCombinedInfo); 8909 } 8910 8911 public: 8912 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 8913 : CurDir(&Dir), CGF(CGF) { 8914 // Extract firstprivate clause information. 8915 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 8916 for (const auto *D : C->varlists()) 8917 FirstPrivateDecls.try_emplace( 8918 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 8919 // Extract implicit firstprivates from uses_allocators clauses. 8920 for (const auto *C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) { 8921 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 8922 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 8923 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits)) 8924 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()), 8925 /*Implicit=*/true); 8926 else if (const auto *VD = dyn_cast<VarDecl>( 8927 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts()) 8928 ->getDecl())) 8929 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true); 8930 } 8931 } 8932 // Extract device pointer clause information. 8933 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 8934 for (auto L : C->component_lists()) 8935 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L)); 8936 // Extract map information. 8937 for (const auto *C : Dir.getClausesOfKind<OMPMapClause>()) { 8938 if (C->getMapType() != OMPC_MAP_to) 8939 continue; 8940 for (auto L : C->component_lists()) { 8941 const ValueDecl *VD = std::get<0>(L); 8942 const auto *RD = VD ? VD->getType() 8943 .getCanonicalType() 8944 .getNonReferenceType() 8945 ->getAsCXXRecordDecl() 8946 : nullptr; 8947 if (RD && RD->isLambda()) 8948 LambdasMap.try_emplace(std::get<0>(L), C); 8949 } 8950 } 8951 } 8952 8953 /// Constructor for the declare mapper directive. 8954 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 8955 : CurDir(&Dir), CGF(CGF) {} 8956 8957 /// Generate code for the combined entry if we have a partially mapped struct 8958 /// and take care of the mapping flags of the arguments corresponding to 8959 /// individual struct members. 8960 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo, 8961 MapFlagsArrayTy &CurTypes, 8962 const StructRangeInfoTy &PartialStruct, 8963 const ValueDecl *VD = nullptr, 8964 bool NotTargetParams = true) const { 8965 if (CurTypes.size() == 1 && 8966 ((CurTypes.back() & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF) && 8967 !PartialStruct.IsArraySection) 8968 return; 8969 Address LBAddr = PartialStruct.LowestElem.second; 8970 Address HBAddr = PartialStruct.HighestElem.second; 8971 if (PartialStruct.HasCompleteRecord) { 8972 LBAddr = PartialStruct.LB; 8973 HBAddr = PartialStruct.LB; 8974 } 8975 CombinedInfo.Exprs.push_back(VD); 8976 // Base is the base of the struct 8977 CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); 8978 // Pointer is the address of the lowest element 8979 llvm::Value *LB = LBAddr.getPointer(); 8980 CombinedInfo.Pointers.push_back(LB); 8981 // There should not be a mapper for a combined entry. 8982 CombinedInfo.Mappers.push_back(nullptr); 8983 // Size is (addr of {highest+1} element) - (addr of lowest element) 8984 llvm::Value *HB = HBAddr.getPointer(); 8985 llvm::Value *HAddr = 8986 CGF.Builder.CreateConstGEP1_32(HBAddr.getElementType(), HB, /*Idx0=*/1); 8987 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 8988 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 8989 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CGF.Int8Ty, CHAddr, CLAddr); 8990 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 8991 /*isSigned=*/false); 8992 CombinedInfo.Sizes.push_back(Size); 8993 // Map type is always TARGET_PARAM, if generate info for captures. 8994 CombinedInfo.Types.push_back(NotTargetParams ? OMP_MAP_NONE 8995 : OMP_MAP_TARGET_PARAM); 8996 // If any element has the present modifier, then make sure the runtime 8997 // doesn't attempt to allocate the struct. 8998 if (CurTypes.end() != 8999 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) { 9000 return Type & OMP_MAP_PRESENT; 9001 })) 9002 CombinedInfo.Types.back() |= OMP_MAP_PRESENT; 9003 // Remove TARGET_PARAM flag from the first element 9004 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 9005 // If any element has the ompx_hold modifier, then make sure the runtime 9006 // uses the hold reference count for the struct as a whole so that it won't 9007 // be unmapped by an extra dynamic reference count decrement. Add it to all 9008 // elements as well so the runtime knows which reference count to check 9009 // when determining whether it's time for device-to-host transfers of 9010 // individual elements. 9011 if (CurTypes.end() != 9012 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) { 9013 return Type & OMP_MAP_OMPX_HOLD; 9014 })) { 9015 CombinedInfo.Types.back() |= OMP_MAP_OMPX_HOLD; 9016 for (auto &M : CurTypes) 9017 M |= OMP_MAP_OMPX_HOLD; 9018 } 9019 9020 // All other current entries will be MEMBER_OF the combined entry 9021 // (except for PTR_AND_OBJ entries which do not have a placeholder value 9022 // 0xFFFF in the MEMBER_OF field). 9023 OpenMPOffloadMappingFlags MemberOfFlag = 9024 getMemberOfFlag(CombinedInfo.BasePointers.size() - 1); 9025 for (auto &M : CurTypes) 9026 setCorrectMemberOfFlag(M, MemberOfFlag); 9027 } 9028 9029 /// Generate all the base pointers, section pointers, sizes, map types, and 9030 /// mappers for the extracted mappable expressions (all included in \a 9031 /// CombinedInfo). Also, for each item that relates with a device pointer, a 9032 /// pair of the relevant declaration and index where it occurs is appended to 9033 /// the device pointers info array. 9034 void generateAllInfo( 9035 MapCombinedInfoTy &CombinedInfo, 9036 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 9037 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 9038 assert(CurDir.is<const OMPExecutableDirective *>() && 9039 "Expect a executable directive"); 9040 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 9041 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, SkipVarSet); 9042 } 9043 9044 /// Generate all the base pointers, section pointers, sizes, map types, and 9045 /// mappers for the extracted map clauses of user-defined mapper (all included 9046 /// in \a CombinedInfo). 9047 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo) const { 9048 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 9049 "Expect a declare mapper directive"); 9050 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 9051 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo); 9052 } 9053 9054 /// Emit capture info for lambdas for variables captured by reference. 9055 void generateInfoForLambdaCaptures( 9056 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 9057 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 9058 const auto *RD = VD->getType() 9059 .getCanonicalType() 9060 .getNonReferenceType() 9061 ->getAsCXXRecordDecl(); 9062 if (!RD || !RD->isLambda()) 9063 return; 9064 Address VDAddr = 9065 Address::deprecated(Arg, CGF.getContext().getDeclAlign(VD)); 9066 LValue VDLVal = CGF.MakeAddrLValue( 9067 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 9068 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 9069 FieldDecl *ThisCapture = nullptr; 9070 RD->getCaptureFields(Captures, ThisCapture); 9071 if (ThisCapture) { 9072 LValue ThisLVal = 9073 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 9074 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 9075 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 9076 VDLVal.getPointer(CGF)); 9077 CombinedInfo.Exprs.push_back(VD); 9078 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF)); 9079 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF)); 9080 CombinedInfo.Sizes.push_back( 9081 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 9082 CGF.Int64Ty, /*isSigned=*/true)); 9083 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 9084 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 9085 CombinedInfo.Mappers.push_back(nullptr); 9086 } 9087 for (const LambdaCapture &LC : RD->captures()) { 9088 if (!LC.capturesVariable()) 9089 continue; 9090 const VarDecl *VD = LC.getCapturedVar(); 9091 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 9092 continue; 9093 auto It = Captures.find(VD); 9094 assert(It != Captures.end() && "Found lambda capture without field."); 9095 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 9096 if (LC.getCaptureKind() == LCK_ByRef) { 9097 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 9098 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 9099 VDLVal.getPointer(CGF)); 9100 CombinedInfo.Exprs.push_back(VD); 9101 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 9102 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF)); 9103 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9104 CGF.getTypeSize( 9105 VD->getType().getCanonicalType().getNonReferenceType()), 9106 CGF.Int64Ty, /*isSigned=*/true)); 9107 } else { 9108 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 9109 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 9110 VDLVal.getPointer(CGF)); 9111 CombinedInfo.Exprs.push_back(VD); 9112 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 9113 CombinedInfo.Pointers.push_back(VarRVal.getScalarVal()); 9114 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 9115 } 9116 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 9117 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 9118 CombinedInfo.Mappers.push_back(nullptr); 9119 } 9120 } 9121 9122 /// Set correct indices for lambdas captures. 9123 void adjustMemberOfForLambdaCaptures( 9124 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 9125 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 9126 MapFlagsArrayTy &Types) const { 9127 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 9128 // Set correct member_of idx for all implicit lambda captures. 9129 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 9130 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 9131 continue; 9132 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 9133 assert(BasePtr && "Unable to find base lambda address."); 9134 int TgtIdx = -1; 9135 for (unsigned J = I; J > 0; --J) { 9136 unsigned Idx = J - 1; 9137 if (Pointers[Idx] != BasePtr) 9138 continue; 9139 TgtIdx = Idx; 9140 break; 9141 } 9142 assert(TgtIdx != -1 && "Unable to find parent lambda."); 9143 // All other current entries will be MEMBER_OF the combined entry 9144 // (except for PTR_AND_OBJ entries which do not have a placeholder value 9145 // 0xFFFF in the MEMBER_OF field). 9146 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 9147 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 9148 } 9149 } 9150 9151 /// Generate the base pointers, section pointers, sizes, map types, and 9152 /// mappers associated to a given capture (all included in \a CombinedInfo). 9153 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 9154 llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 9155 StructRangeInfoTy &PartialStruct) const { 9156 assert(!Cap->capturesVariableArrayType() && 9157 "Not expecting to generate map info for a variable array type!"); 9158 9159 // We need to know when we generating information for the first component 9160 const ValueDecl *VD = Cap->capturesThis() 9161 ? nullptr 9162 : Cap->getCapturedVar()->getCanonicalDecl(); 9163 9164 // for map(to: lambda): skip here, processing it in 9165 // generateDefaultMapInfo 9166 if (LambdasMap.count(VD)) 9167 return; 9168 9169 // If this declaration appears in a is_device_ptr clause we just have to 9170 // pass the pointer by value. If it is a reference to a declaration, we just 9171 // pass its value. 9172 if (DevPointersMap.count(VD)) { 9173 CombinedInfo.Exprs.push_back(VD); 9174 CombinedInfo.BasePointers.emplace_back(Arg, VD); 9175 CombinedInfo.Pointers.push_back(Arg); 9176 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9177 CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty, 9178 /*isSigned=*/true)); 9179 CombinedInfo.Types.push_back( 9180 (Cap->capturesVariable() ? OMP_MAP_TO : OMP_MAP_LITERAL) | 9181 OMP_MAP_TARGET_PARAM); 9182 CombinedInfo.Mappers.push_back(nullptr); 9183 return; 9184 } 9185 9186 using MapData = 9187 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 9188 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool, 9189 const ValueDecl *, const Expr *>; 9190 SmallVector<MapData, 4> DeclComponentLists; 9191 assert(CurDir.is<const OMPExecutableDirective *>() && 9192 "Expect a executable directive"); 9193 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 9194 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 9195 const auto *EI = C->getVarRefs().begin(); 9196 for (const auto L : C->decl_component_lists(VD)) { 9197 const ValueDecl *VDecl, *Mapper; 9198 // The Expression is not correct if the mapping is implicit 9199 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 9200 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9201 std::tie(VDecl, Components, Mapper) = L; 9202 assert(VDecl == VD && "We got information for the wrong declaration??"); 9203 assert(!Components.empty() && 9204 "Not expecting declaration with no component lists."); 9205 DeclComponentLists.emplace_back(Components, C->getMapType(), 9206 C->getMapTypeModifiers(), 9207 C->isImplicit(), Mapper, E); 9208 ++EI; 9209 } 9210 } 9211 llvm::stable_sort(DeclComponentLists, [](const MapData &LHS, 9212 const MapData &RHS) { 9213 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS); 9214 OpenMPMapClauseKind MapType = std::get<1>(RHS); 9215 bool HasPresent = 9216 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present); 9217 bool HasAllocs = MapType == OMPC_MAP_alloc; 9218 MapModifiers = std::get<2>(RHS); 9219 MapType = std::get<1>(LHS); 9220 bool HasPresentR = 9221 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present); 9222 bool HasAllocsR = MapType == OMPC_MAP_alloc; 9223 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR); 9224 }); 9225 9226 // Find overlapping elements (including the offset from the base element). 9227 llvm::SmallDenseMap< 9228 const MapData *, 9229 llvm::SmallVector< 9230 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 9231 4> 9232 OverlappedData; 9233 size_t Count = 0; 9234 for (const MapData &L : DeclComponentLists) { 9235 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9236 OpenMPMapClauseKind MapType; 9237 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9238 bool IsImplicit; 9239 const ValueDecl *Mapper; 9240 const Expr *VarRef; 9241 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9242 L; 9243 ++Count; 9244 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 9245 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 9246 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper, 9247 VarRef) = L1; 9248 auto CI = Components.rbegin(); 9249 auto CE = Components.rend(); 9250 auto SI = Components1.rbegin(); 9251 auto SE = Components1.rend(); 9252 for (; CI != CE && SI != SE; ++CI, ++SI) { 9253 if (CI->getAssociatedExpression()->getStmtClass() != 9254 SI->getAssociatedExpression()->getStmtClass()) 9255 break; 9256 // Are we dealing with different variables/fields? 9257 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 9258 break; 9259 } 9260 // Found overlapping if, at least for one component, reached the head 9261 // of the components list. 9262 if (CI == CE || SI == SE) { 9263 // Ignore it if it is the same component. 9264 if (CI == CE && SI == SE) 9265 continue; 9266 const auto It = (SI == SE) ? CI : SI; 9267 // If one component is a pointer and another one is a kind of 9268 // dereference of this pointer (array subscript, section, dereference, 9269 // etc.), it is not an overlapping. 9270 // Same, if one component is a base and another component is a 9271 // dereferenced pointer memberexpr with the same base. 9272 if (!isa<MemberExpr>(It->getAssociatedExpression()) || 9273 (std::prev(It)->getAssociatedDeclaration() && 9274 std::prev(It) 9275 ->getAssociatedDeclaration() 9276 ->getType() 9277 ->isPointerType()) || 9278 (It->getAssociatedDeclaration() && 9279 It->getAssociatedDeclaration()->getType()->isPointerType() && 9280 std::next(It) != CE && std::next(It) != SE)) 9281 continue; 9282 const MapData &BaseData = CI == CE ? L : L1; 9283 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 9284 SI == SE ? Components : Components1; 9285 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 9286 OverlappedElements.getSecond().push_back(SubData); 9287 } 9288 } 9289 } 9290 // Sort the overlapped elements for each item. 9291 llvm::SmallVector<const FieldDecl *, 4> Layout; 9292 if (!OverlappedData.empty()) { 9293 const Type *BaseType = VD->getType().getCanonicalType().getTypePtr(); 9294 const Type *OrigType = BaseType->getPointeeOrArrayElementType(); 9295 while (BaseType != OrigType) { 9296 BaseType = OrigType->getCanonicalTypeInternal().getTypePtr(); 9297 OrigType = BaseType->getPointeeOrArrayElementType(); 9298 } 9299 9300 if (const auto *CRD = BaseType->getAsCXXRecordDecl()) 9301 getPlainLayout(CRD, Layout, /*AsBase=*/false); 9302 else { 9303 const auto *RD = BaseType->getAsRecordDecl(); 9304 Layout.append(RD->field_begin(), RD->field_end()); 9305 } 9306 } 9307 for (auto &Pair : OverlappedData) { 9308 llvm::stable_sort( 9309 Pair.getSecond(), 9310 [&Layout]( 9311 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 9312 OMPClauseMappableExprCommon::MappableExprComponentListRef 9313 Second) { 9314 auto CI = First.rbegin(); 9315 auto CE = First.rend(); 9316 auto SI = Second.rbegin(); 9317 auto SE = Second.rend(); 9318 for (; CI != CE && SI != SE; ++CI, ++SI) { 9319 if (CI->getAssociatedExpression()->getStmtClass() != 9320 SI->getAssociatedExpression()->getStmtClass()) 9321 break; 9322 // Are we dealing with different variables/fields? 9323 if (CI->getAssociatedDeclaration() != 9324 SI->getAssociatedDeclaration()) 9325 break; 9326 } 9327 9328 // Lists contain the same elements. 9329 if (CI == CE && SI == SE) 9330 return false; 9331 9332 // List with less elements is less than list with more elements. 9333 if (CI == CE || SI == SE) 9334 return CI == CE; 9335 9336 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 9337 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 9338 if (FD1->getParent() == FD2->getParent()) 9339 return FD1->getFieldIndex() < FD2->getFieldIndex(); 9340 const auto *It = 9341 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 9342 return FD == FD1 || FD == FD2; 9343 }); 9344 return *It == FD1; 9345 }); 9346 } 9347 9348 // Associated with a capture, because the mapping flags depend on it. 9349 // Go through all of the elements with the overlapped elements. 9350 bool IsFirstComponentList = true; 9351 for (const auto &Pair : OverlappedData) { 9352 const MapData &L = *Pair.getFirst(); 9353 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9354 OpenMPMapClauseKind MapType; 9355 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9356 bool IsImplicit; 9357 const ValueDecl *Mapper; 9358 const Expr *VarRef; 9359 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9360 L; 9361 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 9362 OverlappedComponents = Pair.getSecond(); 9363 generateInfoForComponentList( 9364 MapType, MapModifiers, llvm::None, Components, CombinedInfo, 9365 PartialStruct, IsFirstComponentList, IsImplicit, Mapper, 9366 /*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents); 9367 IsFirstComponentList = false; 9368 } 9369 // Go through other elements without overlapped elements. 9370 for (const MapData &L : DeclComponentLists) { 9371 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9372 OpenMPMapClauseKind MapType; 9373 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9374 bool IsImplicit; 9375 const ValueDecl *Mapper; 9376 const Expr *VarRef; 9377 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9378 L; 9379 auto It = OverlappedData.find(&L); 9380 if (It == OverlappedData.end()) 9381 generateInfoForComponentList(MapType, MapModifiers, llvm::None, 9382 Components, CombinedInfo, PartialStruct, 9383 IsFirstComponentList, IsImplicit, Mapper, 9384 /*ForDeviceAddr=*/false, VD, VarRef); 9385 IsFirstComponentList = false; 9386 } 9387 } 9388 9389 /// Generate the default map information for a given capture \a CI, 9390 /// record field declaration \a RI and captured value \a CV. 9391 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 9392 const FieldDecl &RI, llvm::Value *CV, 9393 MapCombinedInfoTy &CombinedInfo) const { 9394 bool IsImplicit = true; 9395 // Do the default mapping. 9396 if (CI.capturesThis()) { 9397 CombinedInfo.Exprs.push_back(nullptr); 9398 CombinedInfo.BasePointers.push_back(CV); 9399 CombinedInfo.Pointers.push_back(CV); 9400 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 9401 CombinedInfo.Sizes.push_back( 9402 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 9403 CGF.Int64Ty, /*isSigned=*/true)); 9404 // Default map type. 9405 CombinedInfo.Types.push_back(OMP_MAP_TO | OMP_MAP_FROM); 9406 } else if (CI.capturesVariableByCopy()) { 9407 const VarDecl *VD = CI.getCapturedVar(); 9408 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9409 CombinedInfo.BasePointers.push_back(CV); 9410 CombinedInfo.Pointers.push_back(CV); 9411 if (!RI.getType()->isAnyPointerType()) { 9412 // We have to signal to the runtime captures passed by value that are 9413 // not pointers. 9414 CombinedInfo.Types.push_back(OMP_MAP_LITERAL); 9415 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9416 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 9417 } else { 9418 // Pointers are implicitly mapped with a zero size and no flags 9419 // (other than first map that is added for all implicit maps). 9420 CombinedInfo.Types.push_back(OMP_MAP_NONE); 9421 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 9422 } 9423 auto I = FirstPrivateDecls.find(VD); 9424 if (I != FirstPrivateDecls.end()) 9425 IsImplicit = I->getSecond(); 9426 } else { 9427 assert(CI.capturesVariable() && "Expected captured reference."); 9428 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 9429 QualType ElementType = PtrTy->getPointeeType(); 9430 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9431 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 9432 // The default map type for a scalar/complex type is 'to' because by 9433 // default the value doesn't have to be retrieved. For an aggregate 9434 // type, the default is 'tofrom'. 9435 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI)); 9436 const VarDecl *VD = CI.getCapturedVar(); 9437 auto I = FirstPrivateDecls.find(VD); 9438 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9439 CombinedInfo.BasePointers.push_back(CV); 9440 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 9441 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 9442 CV, ElementType, CGF.getContext().getDeclAlign(VD), 9443 AlignmentSource::Decl)); 9444 CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); 9445 } else { 9446 CombinedInfo.Pointers.push_back(CV); 9447 } 9448 if (I != FirstPrivateDecls.end()) 9449 IsImplicit = I->getSecond(); 9450 } 9451 // Every default map produces a single argument which is a target parameter. 9452 CombinedInfo.Types.back() |= OMP_MAP_TARGET_PARAM; 9453 9454 // Add flag stating this is an implicit map. 9455 if (IsImplicit) 9456 CombinedInfo.Types.back() |= OMP_MAP_IMPLICIT; 9457 9458 // No user-defined mapper for default mapping. 9459 CombinedInfo.Mappers.push_back(nullptr); 9460 } 9461 }; 9462 } // anonymous namespace 9463 9464 static void emitNonContiguousDescriptor( 9465 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9466 CGOpenMPRuntime::TargetDataInfo &Info) { 9467 CodeGenModule &CGM = CGF.CGM; 9468 MappableExprsHandler::MapCombinedInfoTy::StructNonContiguousInfo 9469 &NonContigInfo = CombinedInfo.NonContigInfo; 9470 9471 // Build an array of struct descriptor_dim and then assign it to 9472 // offload_args. 9473 // 9474 // struct descriptor_dim { 9475 // uint64_t offset; 9476 // uint64_t count; 9477 // uint64_t stride 9478 // }; 9479 ASTContext &C = CGF.getContext(); 9480 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 9481 RecordDecl *RD; 9482 RD = C.buildImplicitRecord("descriptor_dim"); 9483 RD->startDefinition(); 9484 addFieldToRecordDecl(C, RD, Int64Ty); 9485 addFieldToRecordDecl(C, RD, Int64Ty); 9486 addFieldToRecordDecl(C, RD, Int64Ty); 9487 RD->completeDefinition(); 9488 QualType DimTy = C.getRecordType(RD); 9489 9490 enum { OffsetFD = 0, CountFD, StrideFD }; 9491 // We need two index variable here since the size of "Dims" is the same as the 9492 // size of Components, however, the size of offset, count, and stride is equal 9493 // to the size of base declaration that is non-contiguous. 9494 for (unsigned I = 0, L = 0, E = NonContigInfo.Dims.size(); I < E; ++I) { 9495 // Skip emitting ir if dimension size is 1 since it cannot be 9496 // non-contiguous. 9497 if (NonContigInfo.Dims[I] == 1) 9498 continue; 9499 llvm::APInt Size(/*numBits=*/32, NonContigInfo.Dims[I]); 9500 QualType ArrayTy = 9501 C.getConstantArrayType(DimTy, Size, nullptr, ArrayType::Normal, 0); 9502 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 9503 for (unsigned II = 0, EE = NonContigInfo.Dims[I]; II < EE; ++II) { 9504 unsigned RevIdx = EE - II - 1; 9505 LValue DimsLVal = CGF.MakeAddrLValue( 9506 CGF.Builder.CreateConstArrayGEP(DimsAddr, II), DimTy); 9507 // Offset 9508 LValue OffsetLVal = CGF.EmitLValueForField( 9509 DimsLVal, *std::next(RD->field_begin(), OffsetFD)); 9510 CGF.EmitStoreOfScalar(NonContigInfo.Offsets[L][RevIdx], OffsetLVal); 9511 // Count 9512 LValue CountLVal = CGF.EmitLValueForField( 9513 DimsLVal, *std::next(RD->field_begin(), CountFD)); 9514 CGF.EmitStoreOfScalar(NonContigInfo.Counts[L][RevIdx], CountLVal); 9515 // Stride 9516 LValue StrideLVal = CGF.EmitLValueForField( 9517 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 9518 CGF.EmitStoreOfScalar(NonContigInfo.Strides[L][RevIdx], StrideLVal); 9519 } 9520 // args[I] = &dims 9521 Address DAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9522 DimsAddr, CGM.Int8PtrTy, CGM.Int8Ty); 9523 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9524 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9525 Info.PointersArray, 0, I); 9526 Address PAddr = Address::deprecated(P, CGF.getPointerAlign()); 9527 CGF.Builder.CreateStore(DAddr.getPointer(), PAddr); 9528 ++L; 9529 } 9530 } 9531 9532 // Try to extract the base declaration from a `this->x` expression if possible. 9533 static ValueDecl *getDeclFromThisExpr(const Expr *E) { 9534 if (!E) 9535 return nullptr; 9536 9537 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenCasts())) 9538 if (const MemberExpr *ME = 9539 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts())) 9540 return ME->getMemberDecl(); 9541 return nullptr; 9542 } 9543 9544 /// Emit a string constant containing the names of the values mapped to the 9545 /// offloading runtime library. 9546 llvm::Constant * 9547 emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, 9548 MappableExprsHandler::MappingExprInfo &MapExprs) { 9549 9550 uint32_t SrcLocStrSize; 9551 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr()) 9552 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize); 9553 9554 SourceLocation Loc; 9555 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) { 9556 if (const ValueDecl *VD = getDeclFromThisExpr(MapExprs.getMapExpr())) 9557 Loc = VD->getLocation(); 9558 else 9559 Loc = MapExprs.getMapExpr()->getExprLoc(); 9560 } else { 9561 Loc = MapExprs.getMapDecl()->getLocation(); 9562 } 9563 9564 std::string ExprName; 9565 if (MapExprs.getMapExpr()) { 9566 PrintingPolicy P(CGF.getContext().getLangOpts()); 9567 llvm::raw_string_ostream OS(ExprName); 9568 MapExprs.getMapExpr()->printPretty(OS, nullptr, P); 9569 OS.flush(); 9570 } else { 9571 ExprName = MapExprs.getMapDecl()->getNameAsString(); 9572 } 9573 9574 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 9575 return OMPBuilder.getOrCreateSrcLocStr(PLoc.getFilename(), ExprName, 9576 PLoc.getLine(), PLoc.getColumn(), 9577 SrcLocStrSize); 9578 } 9579 9580 /// Emit the arrays used to pass the captures and map information to the 9581 /// offloading runtime library. If there is no map or capture information, 9582 /// return nullptr by reference. 9583 static void emitOffloadingArrays( 9584 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9585 CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, 9586 bool IsNonContiguous = false) { 9587 CodeGenModule &CGM = CGF.CGM; 9588 ASTContext &Ctx = CGF.getContext(); 9589 9590 // Reset the array information. 9591 Info.clearArrayInfo(); 9592 Info.NumberOfPtrs = CombinedInfo.BasePointers.size(); 9593 9594 if (Info.NumberOfPtrs) { 9595 // Detect if we have any capture size requiring runtime evaluation of the 9596 // size so that a constant array could be eventually used. 9597 9598 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 9599 QualType PointerArrayType = Ctx.getConstantArrayType( 9600 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 9601 /*IndexTypeQuals=*/0); 9602 9603 Info.BasePointersArray = 9604 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 9605 Info.PointersArray = 9606 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 9607 Address MappersArray = 9608 CGF.CreateMemTemp(PointerArrayType, ".offload_mappers"); 9609 Info.MappersArray = MappersArray.getPointer(); 9610 9611 // If we don't have any VLA types or other types that require runtime 9612 // evaluation, we can use a constant array for the map sizes, otherwise we 9613 // need to fill up the arrays as we do for the pointers. 9614 QualType Int64Ty = 9615 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 9616 SmallVector<llvm::Constant *> ConstSizes( 9617 CombinedInfo.Sizes.size(), llvm::ConstantInt::get(CGF.Int64Ty, 0)); 9618 llvm::SmallBitVector RuntimeSizes(CombinedInfo.Sizes.size()); 9619 for (unsigned I = 0, E = CombinedInfo.Sizes.size(); I < E; ++I) { 9620 if (auto *CI = dyn_cast<llvm::Constant>(CombinedInfo.Sizes[I])) { 9621 if (!isa<llvm::ConstantExpr>(CI) && !isa<llvm::GlobalValue>(CI)) { 9622 if (IsNonContiguous && (CombinedInfo.Types[I] & 9623 MappableExprsHandler::OMP_MAP_NON_CONTIG)) 9624 ConstSizes[I] = llvm::ConstantInt::get( 9625 CGF.Int64Ty, CombinedInfo.NonContigInfo.Dims[I]); 9626 else 9627 ConstSizes[I] = CI; 9628 continue; 9629 } 9630 } 9631 RuntimeSizes.set(I); 9632 } 9633 9634 if (RuntimeSizes.all()) { 9635 QualType SizeArrayType = Ctx.getConstantArrayType( 9636 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 9637 /*IndexTypeQuals=*/0); 9638 Info.SizesArray = 9639 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 9640 } else { 9641 auto *SizesArrayInit = llvm::ConstantArray::get( 9642 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 9643 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 9644 auto *SizesArrayGbl = new llvm::GlobalVariable( 9645 CGM.getModule(), SizesArrayInit->getType(), /*isConstant=*/true, 9646 llvm::GlobalValue::PrivateLinkage, SizesArrayInit, Name); 9647 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 9648 if (RuntimeSizes.any()) { 9649 QualType SizeArrayType = Ctx.getConstantArrayType( 9650 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 9651 /*IndexTypeQuals=*/0); 9652 Address Buffer = CGF.CreateMemTemp(SizeArrayType, ".offload_sizes"); 9653 llvm::Value *GblConstPtr = 9654 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9655 SizesArrayGbl, CGM.Int64Ty->getPointerTo()); 9656 CGF.Builder.CreateMemCpy( 9657 Buffer, 9658 Address(GblConstPtr, CGM.Int64Ty, 9659 CGM.getNaturalTypeAlignment(Ctx.getIntTypeForBitwidth( 9660 /*DestWidth=*/64, /*Signed=*/false))), 9661 CGF.getTypeSize(SizeArrayType)); 9662 Info.SizesArray = Buffer.getPointer(); 9663 } else { 9664 Info.SizesArray = SizesArrayGbl; 9665 } 9666 } 9667 9668 // The map types are always constant so we don't need to generate code to 9669 // fill arrays. Instead, we create an array constant. 9670 SmallVector<uint64_t, 4> Mapping(CombinedInfo.Types.size(), 0); 9671 llvm::copy(CombinedInfo.Types, Mapping.begin()); 9672 std::string MaptypesName = 9673 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 9674 auto *MapTypesArrayGbl = 9675 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName); 9676 Info.MapTypesArray = MapTypesArrayGbl; 9677 9678 // The information types are only built if there is debug information 9679 // requested. 9680 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) { 9681 Info.MapNamesArray = llvm::Constant::getNullValue( 9682 llvm::Type::getInt8Ty(CGF.Builder.getContext())->getPointerTo()); 9683 } else { 9684 auto fillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) { 9685 return emitMappingInformation(CGF, OMPBuilder, MapExpr); 9686 }; 9687 SmallVector<llvm::Constant *, 4> InfoMap(CombinedInfo.Exprs.size()); 9688 llvm::transform(CombinedInfo.Exprs, InfoMap.begin(), fillInfoMap); 9689 std::string MapnamesName = 9690 CGM.getOpenMPRuntime().getName({"offload_mapnames"}); 9691 auto *MapNamesArrayGbl = 9692 OMPBuilder.createOffloadMapnames(InfoMap, MapnamesName); 9693 Info.MapNamesArray = MapNamesArrayGbl; 9694 } 9695 9696 // If there's a present map type modifier, it must not be applied to the end 9697 // of a region, so generate a separate map type array in that case. 9698 if (Info.separateBeginEndCalls()) { 9699 bool EndMapTypesDiffer = false; 9700 for (uint64_t &Type : Mapping) { 9701 if (Type & MappableExprsHandler::OMP_MAP_PRESENT) { 9702 Type &= ~MappableExprsHandler::OMP_MAP_PRESENT; 9703 EndMapTypesDiffer = true; 9704 } 9705 } 9706 if (EndMapTypesDiffer) { 9707 MapTypesArrayGbl = 9708 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName); 9709 Info.MapTypesArrayEnd = MapTypesArrayGbl; 9710 } 9711 } 9712 9713 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 9714 llvm::Value *BPVal = *CombinedInfo.BasePointers[I]; 9715 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 9716 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9717 Info.BasePointersArray, 0, I); 9718 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9719 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9720 Address BPAddr = 9721 Address::deprecated(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9722 CGF.Builder.CreateStore(BPVal, BPAddr); 9723 9724 if (Info.requiresDevicePointerInfo()) 9725 if (const ValueDecl *DevVD = 9726 CombinedInfo.BasePointers[I].getDevicePtrDecl()) 9727 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 9728 9729 llvm::Value *PVal = CombinedInfo.Pointers[I]; 9730 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9731 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9732 Info.PointersArray, 0, I); 9733 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9734 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9735 Address PAddr = 9736 Address::deprecated(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9737 CGF.Builder.CreateStore(PVal, PAddr); 9738 9739 if (RuntimeSizes.test(I)) { 9740 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 9741 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9742 Info.SizesArray, 9743 /*Idx0=*/0, 9744 /*Idx1=*/I); 9745 Address SAddr = 9746 Address::deprecated(S, Ctx.getTypeAlignInChars(Int64Ty)); 9747 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(CombinedInfo.Sizes[I], 9748 CGM.Int64Ty, 9749 /*isSigned=*/true), 9750 SAddr); 9751 } 9752 9753 // Fill up the mapper array. 9754 llvm::Value *MFunc = llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 9755 if (CombinedInfo.Mappers[I]) { 9756 MFunc = CGM.getOpenMPRuntime().getOrCreateUserDefinedMapperFunc( 9757 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I])); 9758 MFunc = CGF.Builder.CreatePointerCast(MFunc, CGM.VoidPtrTy); 9759 Info.HasMapper = true; 9760 } 9761 Address MAddr = CGF.Builder.CreateConstArrayGEP(MappersArray, I); 9762 CGF.Builder.CreateStore(MFunc, MAddr); 9763 } 9764 } 9765 9766 if (!IsNonContiguous || CombinedInfo.NonContigInfo.Offsets.empty() || 9767 Info.NumberOfPtrs == 0) 9768 return; 9769 9770 emitNonContiguousDescriptor(CGF, CombinedInfo, Info); 9771 } 9772 9773 namespace { 9774 /// Additional arguments for emitOffloadingArraysArgument function. 9775 struct ArgumentsOptions { 9776 bool ForEndCall = false; 9777 ArgumentsOptions() = default; 9778 ArgumentsOptions(bool ForEndCall) : ForEndCall(ForEndCall) {} 9779 }; 9780 } // namespace 9781 9782 /// Emit the arguments to be passed to the runtime library based on the 9783 /// arrays of base pointers, pointers, sizes, map types, and mappers. If 9784 /// ForEndCall, emit map types to be passed for the end of the region instead of 9785 /// the beginning. 9786 static void emitOffloadingArraysArgument( 9787 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 9788 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 9789 llvm::Value *&MapTypesArrayArg, llvm::Value *&MapNamesArrayArg, 9790 llvm::Value *&MappersArrayArg, CGOpenMPRuntime::TargetDataInfo &Info, 9791 const ArgumentsOptions &Options = ArgumentsOptions()) { 9792 assert((!Options.ForEndCall || Info.separateBeginEndCalls()) && 9793 "expected region end call to runtime only when end call is separate"); 9794 CodeGenModule &CGM = CGF.CGM; 9795 if (Info.NumberOfPtrs) { 9796 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9797 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9798 Info.BasePointersArray, 9799 /*Idx0=*/0, /*Idx1=*/0); 9800 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9801 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9802 Info.PointersArray, 9803 /*Idx0=*/0, 9804 /*Idx1=*/0); 9805 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9806 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 9807 /*Idx0=*/0, /*Idx1=*/0); 9808 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9809 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9810 Options.ForEndCall && Info.MapTypesArrayEnd ? Info.MapTypesArrayEnd 9811 : Info.MapTypesArray, 9812 /*Idx0=*/0, 9813 /*Idx1=*/0); 9814 9815 // Only emit the mapper information arrays if debug information is 9816 // requested. 9817 if (CGF.CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) 9818 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9819 else 9820 MapNamesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9821 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9822 Info.MapNamesArray, 9823 /*Idx0=*/0, 9824 /*Idx1=*/0); 9825 // If there is no user-defined mapper, set the mapper array to nullptr to 9826 // avoid an unnecessary data privatization 9827 if (!Info.HasMapper) 9828 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9829 else 9830 MappersArrayArg = 9831 CGF.Builder.CreatePointerCast(Info.MappersArray, CGM.VoidPtrPtrTy); 9832 } else { 9833 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9834 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9835 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9836 MapTypesArrayArg = 9837 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9838 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9839 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9840 } 9841 } 9842 9843 /// Check for inner distribute directive. 9844 static const OMPExecutableDirective * 9845 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 9846 const auto *CS = D.getInnermostCapturedStmt(); 9847 const auto *Body = 9848 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 9849 const Stmt *ChildStmt = 9850 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9851 9852 if (const auto *NestedDir = 9853 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9854 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 9855 switch (D.getDirectiveKind()) { 9856 case OMPD_target: 9857 if (isOpenMPDistributeDirective(DKind)) 9858 return NestedDir; 9859 if (DKind == OMPD_teams) { 9860 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 9861 /*IgnoreCaptured=*/true); 9862 if (!Body) 9863 return nullptr; 9864 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9865 if (const auto *NND = 9866 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9867 DKind = NND->getDirectiveKind(); 9868 if (isOpenMPDistributeDirective(DKind)) 9869 return NND; 9870 } 9871 } 9872 return nullptr; 9873 case OMPD_target_teams: 9874 if (isOpenMPDistributeDirective(DKind)) 9875 return NestedDir; 9876 return nullptr; 9877 case OMPD_target_parallel: 9878 case OMPD_target_simd: 9879 case OMPD_target_parallel_for: 9880 case OMPD_target_parallel_for_simd: 9881 return nullptr; 9882 case OMPD_target_teams_distribute: 9883 case OMPD_target_teams_distribute_simd: 9884 case OMPD_target_teams_distribute_parallel_for: 9885 case OMPD_target_teams_distribute_parallel_for_simd: 9886 case OMPD_parallel: 9887 case OMPD_for: 9888 case OMPD_parallel_for: 9889 case OMPD_parallel_master: 9890 case OMPD_parallel_sections: 9891 case OMPD_for_simd: 9892 case OMPD_parallel_for_simd: 9893 case OMPD_cancel: 9894 case OMPD_cancellation_point: 9895 case OMPD_ordered: 9896 case OMPD_threadprivate: 9897 case OMPD_allocate: 9898 case OMPD_task: 9899 case OMPD_simd: 9900 case OMPD_tile: 9901 case OMPD_unroll: 9902 case OMPD_sections: 9903 case OMPD_section: 9904 case OMPD_single: 9905 case OMPD_master: 9906 case OMPD_critical: 9907 case OMPD_taskyield: 9908 case OMPD_barrier: 9909 case OMPD_taskwait: 9910 case OMPD_taskgroup: 9911 case OMPD_atomic: 9912 case OMPD_flush: 9913 case OMPD_depobj: 9914 case OMPD_scan: 9915 case OMPD_teams: 9916 case OMPD_target_data: 9917 case OMPD_target_exit_data: 9918 case OMPD_target_enter_data: 9919 case OMPD_distribute: 9920 case OMPD_distribute_simd: 9921 case OMPD_distribute_parallel_for: 9922 case OMPD_distribute_parallel_for_simd: 9923 case OMPD_teams_distribute: 9924 case OMPD_teams_distribute_simd: 9925 case OMPD_teams_distribute_parallel_for: 9926 case OMPD_teams_distribute_parallel_for_simd: 9927 case OMPD_target_update: 9928 case OMPD_declare_simd: 9929 case OMPD_declare_variant: 9930 case OMPD_begin_declare_variant: 9931 case OMPD_end_declare_variant: 9932 case OMPD_declare_target: 9933 case OMPD_end_declare_target: 9934 case OMPD_declare_reduction: 9935 case OMPD_declare_mapper: 9936 case OMPD_taskloop: 9937 case OMPD_taskloop_simd: 9938 case OMPD_master_taskloop: 9939 case OMPD_master_taskloop_simd: 9940 case OMPD_parallel_master_taskloop: 9941 case OMPD_parallel_master_taskloop_simd: 9942 case OMPD_requires: 9943 case OMPD_metadirective: 9944 case OMPD_unknown: 9945 default: 9946 llvm_unreachable("Unexpected directive."); 9947 } 9948 } 9949 9950 return nullptr; 9951 } 9952 9953 /// Emit the user-defined mapper function. The code generation follows the 9954 /// pattern in the example below. 9955 /// \code 9956 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 9957 /// void *base, void *begin, 9958 /// int64_t size, int64_t type, 9959 /// void *name = nullptr) { 9960 /// // Allocate space for an array section first or add a base/begin for 9961 /// // pointer dereference. 9962 /// if ((size > 1 || (base != begin && maptype.IsPtrAndObj)) && 9963 /// !maptype.IsDelete) 9964 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9965 /// size*sizeof(Ty), clearToFromMember(type)); 9966 /// // Map members. 9967 /// for (unsigned i = 0; i < size; i++) { 9968 /// // For each component specified by this mapper: 9969 /// for (auto c : begin[i]->all_components) { 9970 /// if (c.hasMapper()) 9971 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 9972 /// c.arg_type, c.arg_name); 9973 /// else 9974 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 9975 /// c.arg_begin, c.arg_size, c.arg_type, 9976 /// c.arg_name); 9977 /// } 9978 /// } 9979 /// // Delete the array section. 9980 /// if (size > 1 && maptype.IsDelete) 9981 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9982 /// size*sizeof(Ty), clearToFromMember(type)); 9983 /// } 9984 /// \endcode 9985 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 9986 CodeGenFunction *CGF) { 9987 if (UDMMap.count(D) > 0) 9988 return; 9989 ASTContext &C = CGM.getContext(); 9990 QualType Ty = D->getType(); 9991 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 9992 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 9993 auto *MapperVarDecl = 9994 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 9995 SourceLocation Loc = D->getLocation(); 9996 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 9997 llvm::Type *ElemTy = CGM.getTypes().ConvertTypeForMem(Ty); 9998 9999 // Prepare mapper function arguments and attributes. 10000 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 10001 C.VoidPtrTy, ImplicitParamDecl::Other); 10002 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 10003 ImplicitParamDecl::Other); 10004 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 10005 C.VoidPtrTy, ImplicitParamDecl::Other); 10006 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 10007 ImplicitParamDecl::Other); 10008 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 10009 ImplicitParamDecl::Other); 10010 ImplicitParamDecl NameArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 10011 ImplicitParamDecl::Other); 10012 FunctionArgList Args; 10013 Args.push_back(&HandleArg); 10014 Args.push_back(&BaseArg); 10015 Args.push_back(&BeginArg); 10016 Args.push_back(&SizeArg); 10017 Args.push_back(&TypeArg); 10018 Args.push_back(&NameArg); 10019 const CGFunctionInfo &FnInfo = 10020 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 10021 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 10022 SmallString<64> TyStr; 10023 llvm::raw_svector_ostream Out(TyStr); 10024 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 10025 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 10026 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 10027 Name, &CGM.getModule()); 10028 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 10029 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 10030 // Start the mapper function code generation. 10031 CodeGenFunction MapperCGF(CGM); 10032 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 10033 // Compute the starting and end addresses of array elements. 10034 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 10035 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 10036 C.getPointerType(Int64Ty), Loc); 10037 // Prepare common arguments for array initiation and deletion. 10038 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 10039 MapperCGF.GetAddrOfLocalVar(&HandleArg), 10040 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 10041 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 10042 MapperCGF.GetAddrOfLocalVar(&BaseArg), 10043 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 10044 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 10045 MapperCGF.GetAddrOfLocalVar(&BeginArg), 10046 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 10047 // Convert the size in bytes into the number of array elements. 10048 Size = MapperCGF.Builder.CreateExactUDiv( 10049 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 10050 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 10051 BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy)); 10052 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(ElemTy, PtrBegin, Size); 10053 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 10054 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 10055 C.getPointerType(Int64Ty), Loc); 10056 llvm::Value *MapName = MapperCGF.EmitLoadOfScalar( 10057 MapperCGF.GetAddrOfLocalVar(&NameArg), 10058 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 10059 10060 // Emit array initiation if this is an array section and \p MapType indicates 10061 // that memory allocation is required. 10062 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 10063 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 10064 MapName, ElementSize, HeadBB, /*IsInit=*/true); 10065 10066 // Emit a for loop to iterate through SizeArg of elements and map all of them. 10067 10068 // Emit the loop header block. 10069 MapperCGF.EmitBlock(HeadBB); 10070 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 10071 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 10072 // Evaluate whether the initial condition is satisfied. 10073 llvm::Value *IsEmpty = 10074 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 10075 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 10076 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 10077 10078 // Emit the loop body block. 10079 MapperCGF.EmitBlock(BodyBB); 10080 llvm::BasicBlock *LastBB = BodyBB; 10081 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 10082 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 10083 PtrPHI->addIncoming(PtrBegin, EntryBB); 10084 Address PtrCurrent(PtrPHI, ElemTy, 10085 MapperCGF.GetAddrOfLocalVar(&BeginArg) 10086 .getAlignment() 10087 .alignmentOfArrayElement(ElementSize)); 10088 // Privatize the declared variable of mapper to be the current array element. 10089 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 10090 Scope.addPrivate(MapperVarDecl, PtrCurrent); 10091 (void)Scope.Privatize(); 10092 10093 // Get map clause information. Fill up the arrays with all mapped variables. 10094 MappableExprsHandler::MapCombinedInfoTy Info; 10095 MappableExprsHandler MEHandler(*D, MapperCGF); 10096 MEHandler.generateAllInfoForMapper(Info); 10097 10098 // Call the runtime API __tgt_mapper_num_components to get the number of 10099 // pre-existing components. 10100 llvm::Value *OffloadingArgs[] = {Handle}; 10101 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 10102 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 10103 OMPRTL___tgt_mapper_num_components), 10104 OffloadingArgs); 10105 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 10106 PreviousSize, 10107 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 10108 10109 // Fill up the runtime mapper handle for all components. 10110 for (unsigned I = 0; I < Info.BasePointers.size(); ++I) { 10111 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 10112 *Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 10113 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 10114 Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 10115 llvm::Value *CurSizeArg = Info.Sizes[I]; 10116 llvm::Value *CurNameArg = 10117 (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) 10118 ? llvm::ConstantPointerNull::get(CGM.VoidPtrTy) 10119 : emitMappingInformation(MapperCGF, OMPBuilder, Info.Exprs[I]); 10120 10121 // Extract the MEMBER_OF field from the map type. 10122 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(Info.Types[I]); 10123 llvm::Value *MemberMapType = 10124 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 10125 10126 // Combine the map type inherited from user-defined mapper with that 10127 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 10128 // bits of the \a MapType, which is the input argument of the mapper 10129 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 10130 // bits of MemberMapType. 10131 // [OpenMP 5.0], 1.2.6. map-type decay. 10132 // | alloc | to | from | tofrom | release | delete 10133 // ---------------------------------------------------------- 10134 // alloc | alloc | alloc | alloc | alloc | release | delete 10135 // to | alloc | to | alloc | to | release | delete 10136 // from | alloc | alloc | from | from | release | delete 10137 // tofrom | alloc | to | from | tofrom | release | delete 10138 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 10139 MapType, 10140 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 10141 MappableExprsHandler::OMP_MAP_FROM)); 10142 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 10143 llvm::BasicBlock *AllocElseBB = 10144 MapperCGF.createBasicBlock("omp.type.alloc.else"); 10145 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 10146 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 10147 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 10148 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 10149 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 10150 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 10151 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 10152 MapperCGF.EmitBlock(AllocBB); 10153 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 10154 MemberMapType, 10155 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 10156 MappableExprsHandler::OMP_MAP_FROM))); 10157 MapperCGF.Builder.CreateBr(EndBB); 10158 MapperCGF.EmitBlock(AllocElseBB); 10159 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 10160 LeftToFrom, 10161 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 10162 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 10163 // In case of to, clear OMP_MAP_FROM. 10164 MapperCGF.EmitBlock(ToBB); 10165 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 10166 MemberMapType, 10167 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 10168 MapperCGF.Builder.CreateBr(EndBB); 10169 MapperCGF.EmitBlock(ToElseBB); 10170 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 10171 LeftToFrom, 10172 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 10173 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 10174 // In case of from, clear OMP_MAP_TO. 10175 MapperCGF.EmitBlock(FromBB); 10176 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 10177 MemberMapType, 10178 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 10179 // In case of tofrom, do nothing. 10180 MapperCGF.EmitBlock(EndBB); 10181 LastBB = EndBB; 10182 llvm::PHINode *CurMapType = 10183 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 10184 CurMapType->addIncoming(AllocMapType, AllocBB); 10185 CurMapType->addIncoming(ToMapType, ToBB); 10186 CurMapType->addIncoming(FromMapType, FromBB); 10187 CurMapType->addIncoming(MemberMapType, ToElseBB); 10188 10189 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 10190 CurSizeArg, CurMapType, CurNameArg}; 10191 if (Info.Mappers[I]) { 10192 // Call the corresponding mapper function. 10193 llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc( 10194 cast<OMPDeclareMapperDecl>(Info.Mappers[I])); 10195 assert(MapperFunc && "Expect a valid mapper function is available."); 10196 MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs); 10197 } else { 10198 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 10199 // data structure. 10200 MapperCGF.EmitRuntimeCall( 10201 OMPBuilder.getOrCreateRuntimeFunction( 10202 CGM.getModule(), OMPRTL___tgt_push_mapper_component), 10203 OffloadingArgs); 10204 } 10205 } 10206 10207 // Update the pointer to point to the next element that needs to be mapped, 10208 // and check whether we have mapped all elements. 10209 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 10210 ElemTy, PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 10211 PtrPHI->addIncoming(PtrNext, LastBB); 10212 llvm::Value *IsDone = 10213 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 10214 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 10215 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 10216 10217 MapperCGF.EmitBlock(ExitBB); 10218 // Emit array deletion if this is an array section and \p MapType indicates 10219 // that deletion is required. 10220 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 10221 MapName, ElementSize, DoneBB, /*IsInit=*/false); 10222 10223 // Emit the function exit block. 10224 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 10225 MapperCGF.FinishFunction(); 10226 UDMMap.try_emplace(D, Fn); 10227 if (CGF) { 10228 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 10229 Decls.second.push_back(D); 10230 } 10231 } 10232 10233 /// Emit the array initialization or deletion portion for user-defined mapper 10234 /// code generation. First, it evaluates whether an array section is mapped and 10235 /// whether the \a MapType instructs to delete this section. If \a IsInit is 10236 /// true, and \a MapType indicates to not delete this array, array 10237 /// initialization code is generated. If \a IsInit is false, and \a MapType 10238 /// indicates to not this array, array deletion code is generated. 10239 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 10240 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 10241 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 10242 llvm::Value *MapName, CharUnits ElementSize, llvm::BasicBlock *ExitBB, 10243 bool IsInit) { 10244 StringRef Prefix = IsInit ? ".init" : ".del"; 10245 10246 // Evaluate if this is an array section. 10247 llvm::BasicBlock *BodyBB = 10248 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 10249 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGT( 10250 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 10251 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 10252 MapType, 10253 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 10254 llvm::Value *DeleteCond; 10255 llvm::Value *Cond; 10256 if (IsInit) { 10257 // base != begin? 10258 llvm::Value *BaseIsBegin = MapperCGF.Builder.CreateICmpNE(Base, Begin); 10259 // IsPtrAndObj? 10260 llvm::Value *PtrAndObjBit = MapperCGF.Builder.CreateAnd( 10261 MapType, 10262 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_PTR_AND_OBJ)); 10263 PtrAndObjBit = MapperCGF.Builder.CreateIsNotNull(PtrAndObjBit); 10264 BaseIsBegin = MapperCGF.Builder.CreateAnd(BaseIsBegin, PtrAndObjBit); 10265 Cond = MapperCGF.Builder.CreateOr(IsArray, BaseIsBegin); 10266 DeleteCond = MapperCGF.Builder.CreateIsNull( 10267 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 10268 } else { 10269 Cond = IsArray; 10270 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 10271 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 10272 } 10273 Cond = MapperCGF.Builder.CreateAnd(Cond, DeleteCond); 10274 MapperCGF.Builder.CreateCondBr(Cond, BodyBB, ExitBB); 10275 10276 MapperCGF.EmitBlock(BodyBB); 10277 // Get the array size by multiplying element size and element number (i.e., \p 10278 // Size). 10279 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 10280 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 10281 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 10282 // memory allocation/deletion purpose only. 10283 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 10284 MapType, 10285 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 10286 MappableExprsHandler::OMP_MAP_FROM))); 10287 MapTypeArg = MapperCGF.Builder.CreateOr( 10288 MapTypeArg, 10289 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_IMPLICIT)); 10290 10291 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 10292 // data structure. 10293 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, 10294 ArraySize, MapTypeArg, MapName}; 10295 MapperCGF.EmitRuntimeCall( 10296 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 10297 OMPRTL___tgt_push_mapper_component), 10298 OffloadingArgs); 10299 } 10300 10301 llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc( 10302 const OMPDeclareMapperDecl *D) { 10303 auto I = UDMMap.find(D); 10304 if (I != UDMMap.end()) 10305 return I->second; 10306 emitUserDefinedMapper(D); 10307 return UDMMap.lookup(D); 10308 } 10309 10310 void CGOpenMPRuntime::emitTargetNumIterationsCall( 10311 CodeGenFunction &CGF, const OMPExecutableDirective &D, 10312 llvm::Value *DeviceID, 10313 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 10314 const OMPLoopDirective &D)> 10315 SizeEmitter) { 10316 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 10317 const OMPExecutableDirective *TD = &D; 10318 // Get nested teams distribute kind directive, if any. 10319 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 10320 TD = getNestedDistributeDirective(CGM.getContext(), D); 10321 if (!TD) 10322 return; 10323 const auto *LD = cast<OMPLoopDirective>(TD); 10324 auto &&CodeGen = [LD, DeviceID, SizeEmitter, &D, this](CodeGenFunction &CGF, 10325 PrePostActionTy &) { 10326 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 10327 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10328 llvm::Value *Args[] = {RTLoc, DeviceID, NumIterations}; 10329 CGF.EmitRuntimeCall( 10330 OMPBuilder.getOrCreateRuntimeFunction( 10331 CGM.getModule(), OMPRTL___kmpc_push_target_tripcount_mapper), 10332 Args); 10333 } 10334 }; 10335 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 10336 } 10337 10338 void CGOpenMPRuntime::emitTargetCall( 10339 CodeGenFunction &CGF, const OMPExecutableDirective &D, 10340 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 10341 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 10342 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 10343 const OMPLoopDirective &D)> 10344 SizeEmitter) { 10345 if (!CGF.HaveInsertPoint()) 10346 return; 10347 10348 const bool OffloadingMandatory = !CGM.getLangOpts().OpenMPIsDevice && 10349 CGM.getLangOpts().OpenMPOffloadMandatory; 10350 10351 assert((OffloadingMandatory || OutlinedFn) && "Invalid outlined function!"); 10352 10353 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 10354 D.hasClausesOfKind<OMPNowaitClause>(); 10355 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 10356 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 10357 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 10358 PrePostActionTy &) { 10359 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10360 }; 10361 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 10362 10363 CodeGenFunction::OMPTargetDataInfo InputInfo; 10364 llvm::Value *MapTypesArray = nullptr; 10365 llvm::Value *MapNamesArray = nullptr; 10366 // Generate code for the host fallback function. 10367 auto &&FallbackGen = [this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, 10368 &CS, OffloadingMandatory](CodeGenFunction &CGF) { 10369 if (OffloadingMandatory) { 10370 CGF.Builder.CreateUnreachable(); 10371 } else { 10372 if (RequiresOuterTask) { 10373 CapturedVars.clear(); 10374 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10375 } 10376 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10377 } 10378 }; 10379 // Fill up the pointer arrays and transfer execution to the device. 10380 auto &&ThenGen = [this, Device, OutlinedFnID, &D, &InputInfo, &MapTypesArray, 10381 &MapNamesArray, SizeEmitter, 10382 FallbackGen](CodeGenFunction &CGF, PrePostActionTy &) { 10383 if (Device.getInt() == OMPC_DEVICE_ancestor) { 10384 // Reverse offloading is not supported, so just execute on the host. 10385 FallbackGen(CGF); 10386 return; 10387 } 10388 10389 // On top of the arrays that were filled up, the target offloading call 10390 // takes as arguments the device id as well as the host pointer. The host 10391 // pointer is used by the runtime library to identify the current target 10392 // region, so it only has to be unique and not necessarily point to 10393 // anything. It could be the pointer to the outlined function that 10394 // implements the target region, but we aren't using that so that the 10395 // compiler doesn't need to keep that, and could therefore inline the host 10396 // function if proven worthwhile during optimization. 10397 10398 // From this point on, we need to have an ID of the target region defined. 10399 assert(OutlinedFnID && "Invalid outlined function ID!"); 10400 (void)OutlinedFnID; 10401 10402 // Emit device ID if any. 10403 llvm::Value *DeviceID; 10404 if (Device.getPointer()) { 10405 assert((Device.getInt() == OMPC_DEVICE_unknown || 10406 Device.getInt() == OMPC_DEVICE_device_num) && 10407 "Expected device_num modifier."); 10408 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer()); 10409 DeviceID = 10410 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true); 10411 } else { 10412 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10413 } 10414 10415 // Emit the number of elements in the offloading arrays. 10416 llvm::Value *PointerNum = 10417 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10418 10419 // Return value of the runtime offloading call. 10420 llvm::Value *Return; 10421 10422 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 10423 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 10424 10425 // Source location for the ident struct 10426 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10427 10428 // Emit tripcount for the target loop-based directive. 10429 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 10430 10431 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10432 // The target region is an outlined function launched by the runtime 10433 // via calls __tgt_target() or __tgt_target_teams(). 10434 // 10435 // __tgt_target() launches a target region with one team and one thread, 10436 // executing a serial region. This master thread may in turn launch 10437 // more threads within its team upon encountering a parallel region, 10438 // however, no additional teams can be launched on the device. 10439 // 10440 // __tgt_target_teams() launches a target region with one or more teams, 10441 // each with one or more threads. This call is required for target 10442 // constructs such as: 10443 // 'target teams' 10444 // 'target' / 'teams' 10445 // 'target teams distribute parallel for' 10446 // 'target parallel' 10447 // and so on. 10448 // 10449 // Note that on the host and CPU targets, the runtime implementation of 10450 // these calls simply call the outlined function without forking threads. 10451 // The outlined functions themselves have runtime calls to 10452 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 10453 // the compiler in emitTeamsCall() and emitParallelCall(). 10454 // 10455 // In contrast, on the NVPTX target, the implementation of 10456 // __tgt_target_teams() launches a GPU kernel with the requested number 10457 // of teams and threads so no additional calls to the runtime are required. 10458 if (NumTeams) { 10459 // If we have NumTeams defined this means that we have an enclosed teams 10460 // region. Therefore we also expect to have NumThreads defined. These two 10461 // values should be defined in the presence of a teams directive, 10462 // regardless of having any clauses associated. If the user is using teams 10463 // but no clauses, these two values will be the default that should be 10464 // passed to the runtime library - a 32-bit integer with the value zero. 10465 assert(NumThreads && "Thread limit expression should be available along " 10466 "with number of teams."); 10467 SmallVector<llvm::Value *> OffloadingArgs = { 10468 RTLoc, 10469 DeviceID, 10470 OutlinedFnID, 10471 PointerNum, 10472 InputInfo.BasePointersArray.getPointer(), 10473 InputInfo.PointersArray.getPointer(), 10474 InputInfo.SizesArray.getPointer(), 10475 MapTypesArray, 10476 MapNamesArray, 10477 InputInfo.MappersArray.getPointer(), 10478 NumTeams, 10479 NumThreads}; 10480 if (HasNowait) { 10481 // Add int32_t depNum = 0, void *depList = nullptr, int32_t 10482 // noAliasDepNum = 0, void *noAliasDepList = nullptr. 10483 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10484 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10485 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10486 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10487 } 10488 Return = CGF.EmitRuntimeCall( 10489 OMPBuilder.getOrCreateRuntimeFunction( 10490 CGM.getModule(), HasNowait 10491 ? OMPRTL___tgt_target_teams_nowait_mapper 10492 : OMPRTL___tgt_target_teams_mapper), 10493 OffloadingArgs); 10494 } else { 10495 SmallVector<llvm::Value *> OffloadingArgs = { 10496 RTLoc, 10497 DeviceID, 10498 OutlinedFnID, 10499 PointerNum, 10500 InputInfo.BasePointersArray.getPointer(), 10501 InputInfo.PointersArray.getPointer(), 10502 InputInfo.SizesArray.getPointer(), 10503 MapTypesArray, 10504 MapNamesArray, 10505 InputInfo.MappersArray.getPointer()}; 10506 if (HasNowait) { 10507 // Add int32_t depNum = 0, void *depList = nullptr, int32_t 10508 // noAliasDepNum = 0, void *noAliasDepList = nullptr. 10509 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10510 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10511 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10512 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10513 } 10514 Return = CGF.EmitRuntimeCall( 10515 OMPBuilder.getOrCreateRuntimeFunction( 10516 CGM.getModule(), HasNowait ? OMPRTL___tgt_target_nowait_mapper 10517 : OMPRTL___tgt_target_mapper), 10518 OffloadingArgs); 10519 } 10520 10521 // Check the error code and execute the host version if required. 10522 llvm::BasicBlock *OffloadFailedBlock = 10523 CGF.createBasicBlock("omp_offload.failed"); 10524 llvm::BasicBlock *OffloadContBlock = 10525 CGF.createBasicBlock("omp_offload.cont"); 10526 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 10527 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 10528 10529 CGF.EmitBlock(OffloadFailedBlock); 10530 FallbackGen(CGF); 10531 10532 CGF.EmitBranch(OffloadContBlock); 10533 10534 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 10535 }; 10536 10537 // Notify that the host version must be executed. 10538 auto &&ElseGen = [FallbackGen](CodeGenFunction &CGF, PrePostActionTy &) { 10539 FallbackGen(CGF); 10540 }; 10541 10542 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 10543 &MapNamesArray, &CapturedVars, RequiresOuterTask, 10544 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 10545 // Fill up the arrays with all the captured variables. 10546 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 10547 10548 // Get mappable expression information. 10549 MappableExprsHandler MEHandler(D, CGF); 10550 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 10551 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet; 10552 10553 auto RI = CS.getCapturedRecordDecl()->field_begin(); 10554 auto *CV = CapturedVars.begin(); 10555 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 10556 CE = CS.capture_end(); 10557 CI != CE; ++CI, ++RI, ++CV) { 10558 MappableExprsHandler::MapCombinedInfoTy CurInfo; 10559 MappableExprsHandler::StructRangeInfoTy PartialStruct; 10560 10561 // VLA sizes are passed to the outlined region by copy and do not have map 10562 // information associated. 10563 if (CI->capturesVariableArrayType()) { 10564 CurInfo.Exprs.push_back(nullptr); 10565 CurInfo.BasePointers.push_back(*CV); 10566 CurInfo.Pointers.push_back(*CV); 10567 CurInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 10568 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 10569 // Copy to the device as an argument. No need to retrieve it. 10570 CurInfo.Types.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 10571 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 10572 MappableExprsHandler::OMP_MAP_IMPLICIT); 10573 CurInfo.Mappers.push_back(nullptr); 10574 } else { 10575 // If we have any information in the map clause, we use it, otherwise we 10576 // just do a default mapping. 10577 MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct); 10578 if (!CI->capturesThis()) 10579 MappedVarSet.insert(CI->getCapturedVar()); 10580 else 10581 MappedVarSet.insert(nullptr); 10582 if (CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid()) 10583 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo); 10584 // Generate correct mapping for variables captured by reference in 10585 // lambdas. 10586 if (CI->capturesVariable()) 10587 MEHandler.generateInfoForLambdaCaptures(CI->getCapturedVar(), *CV, 10588 CurInfo, LambdaPointers); 10589 } 10590 // We expect to have at least an element of information for this capture. 10591 assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) && 10592 "Non-existing map pointer for capture!"); 10593 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() && 10594 CurInfo.BasePointers.size() == CurInfo.Sizes.size() && 10595 CurInfo.BasePointers.size() == CurInfo.Types.size() && 10596 CurInfo.BasePointers.size() == CurInfo.Mappers.size() && 10597 "Inconsistent map information sizes!"); 10598 10599 // If there is an entry in PartialStruct it means we have a struct with 10600 // individual members mapped. Emit an extra combined entry. 10601 if (PartialStruct.Base.isValid()) { 10602 CombinedInfo.append(PartialStruct.PreliminaryMapData); 10603 MEHandler.emitCombinedEntry( 10604 CombinedInfo, CurInfo.Types, PartialStruct, nullptr, 10605 !PartialStruct.PreliminaryMapData.BasePointers.empty()); 10606 } 10607 10608 // We need to append the results of this capture to what we already have. 10609 CombinedInfo.append(CurInfo); 10610 } 10611 // Adjust MEMBER_OF flags for the lambdas captures. 10612 MEHandler.adjustMemberOfForLambdaCaptures( 10613 LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers, 10614 CombinedInfo.Types); 10615 // Map any list items in a map clause that were not captures because they 10616 // weren't referenced within the construct. 10617 MEHandler.generateAllInfo(CombinedInfo, MappedVarSet); 10618 10619 TargetDataInfo Info; 10620 // Fill up the arrays and create the arguments. 10621 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder); 10622 emitOffloadingArraysArgument( 10623 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 10624 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 10625 {/*ForEndCall=*/false}); 10626 10627 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10628 InputInfo.BasePointersArray = 10629 Address::deprecated(Info.BasePointersArray, CGM.getPointerAlign()); 10630 InputInfo.PointersArray = 10631 Address::deprecated(Info.PointersArray, CGM.getPointerAlign()); 10632 InputInfo.SizesArray = 10633 Address::deprecated(Info.SizesArray, CGM.getPointerAlign()); 10634 InputInfo.MappersArray = 10635 Address::deprecated(Info.MappersArray, CGM.getPointerAlign()); 10636 MapTypesArray = Info.MapTypesArray; 10637 MapNamesArray = Info.MapNamesArray; 10638 if (RequiresOuterTask) 10639 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10640 else 10641 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10642 }; 10643 10644 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 10645 CodeGenFunction &CGF, PrePostActionTy &) { 10646 if (RequiresOuterTask) { 10647 CodeGenFunction::OMPTargetDataInfo InputInfo; 10648 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 10649 } else { 10650 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 10651 } 10652 }; 10653 10654 // If we have a target function ID it means that we need to support 10655 // offloading, otherwise, just execute on the host. We need to execute on host 10656 // regardless of the conditional in the if clause if, e.g., the user do not 10657 // specify target triples. 10658 if (OutlinedFnID) { 10659 if (IfCond) { 10660 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 10661 } else { 10662 RegionCodeGenTy ThenRCG(TargetThenGen); 10663 ThenRCG(CGF); 10664 } 10665 } else { 10666 RegionCodeGenTy ElseRCG(TargetElseGen); 10667 ElseRCG(CGF); 10668 } 10669 } 10670 10671 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 10672 StringRef ParentName) { 10673 if (!S) 10674 return; 10675 10676 // Codegen OMP target directives that offload compute to the device. 10677 bool RequiresDeviceCodegen = 10678 isa<OMPExecutableDirective>(S) && 10679 isOpenMPTargetExecutionDirective( 10680 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 10681 10682 if (RequiresDeviceCodegen) { 10683 const auto &E = *cast<OMPExecutableDirective>(S); 10684 unsigned DeviceID; 10685 unsigned FileID; 10686 unsigned Line; 10687 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 10688 FileID, Line); 10689 10690 // Is this a target region that should not be emitted as an entry point? If 10691 // so just signal we are done with this target region. 10692 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 10693 ParentName, Line)) 10694 return; 10695 10696 switch (E.getDirectiveKind()) { 10697 case OMPD_target: 10698 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 10699 cast<OMPTargetDirective>(E)); 10700 break; 10701 case OMPD_target_parallel: 10702 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 10703 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 10704 break; 10705 case OMPD_target_teams: 10706 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 10707 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 10708 break; 10709 case OMPD_target_teams_distribute: 10710 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 10711 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 10712 break; 10713 case OMPD_target_teams_distribute_simd: 10714 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 10715 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 10716 break; 10717 case OMPD_target_parallel_for: 10718 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 10719 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 10720 break; 10721 case OMPD_target_parallel_for_simd: 10722 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 10723 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 10724 break; 10725 case OMPD_target_simd: 10726 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 10727 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 10728 break; 10729 case OMPD_target_teams_distribute_parallel_for: 10730 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 10731 CGM, ParentName, 10732 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 10733 break; 10734 case OMPD_target_teams_distribute_parallel_for_simd: 10735 CodeGenFunction:: 10736 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 10737 CGM, ParentName, 10738 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 10739 break; 10740 case OMPD_parallel: 10741 case OMPD_for: 10742 case OMPD_parallel_for: 10743 case OMPD_parallel_master: 10744 case OMPD_parallel_sections: 10745 case OMPD_for_simd: 10746 case OMPD_parallel_for_simd: 10747 case OMPD_cancel: 10748 case OMPD_cancellation_point: 10749 case OMPD_ordered: 10750 case OMPD_threadprivate: 10751 case OMPD_allocate: 10752 case OMPD_task: 10753 case OMPD_simd: 10754 case OMPD_tile: 10755 case OMPD_unroll: 10756 case OMPD_sections: 10757 case OMPD_section: 10758 case OMPD_single: 10759 case OMPD_master: 10760 case OMPD_critical: 10761 case OMPD_taskyield: 10762 case OMPD_barrier: 10763 case OMPD_taskwait: 10764 case OMPD_taskgroup: 10765 case OMPD_atomic: 10766 case OMPD_flush: 10767 case OMPD_depobj: 10768 case OMPD_scan: 10769 case OMPD_teams: 10770 case OMPD_target_data: 10771 case OMPD_target_exit_data: 10772 case OMPD_target_enter_data: 10773 case OMPD_distribute: 10774 case OMPD_distribute_simd: 10775 case OMPD_distribute_parallel_for: 10776 case OMPD_distribute_parallel_for_simd: 10777 case OMPD_teams_distribute: 10778 case OMPD_teams_distribute_simd: 10779 case OMPD_teams_distribute_parallel_for: 10780 case OMPD_teams_distribute_parallel_for_simd: 10781 case OMPD_target_update: 10782 case OMPD_declare_simd: 10783 case OMPD_declare_variant: 10784 case OMPD_begin_declare_variant: 10785 case OMPD_end_declare_variant: 10786 case OMPD_declare_target: 10787 case OMPD_end_declare_target: 10788 case OMPD_declare_reduction: 10789 case OMPD_declare_mapper: 10790 case OMPD_taskloop: 10791 case OMPD_taskloop_simd: 10792 case OMPD_master_taskloop: 10793 case OMPD_master_taskloop_simd: 10794 case OMPD_parallel_master_taskloop: 10795 case OMPD_parallel_master_taskloop_simd: 10796 case OMPD_requires: 10797 case OMPD_metadirective: 10798 case OMPD_unknown: 10799 default: 10800 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 10801 } 10802 return; 10803 } 10804 10805 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 10806 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 10807 return; 10808 10809 scanForTargetRegionsFunctions(E->getRawStmt(), ParentName); 10810 return; 10811 } 10812 10813 // If this is a lambda function, look into its body. 10814 if (const auto *L = dyn_cast<LambdaExpr>(S)) 10815 S = L->getBody(); 10816 10817 // Keep looking for target regions recursively. 10818 for (const Stmt *II : S->children()) 10819 scanForTargetRegionsFunctions(II, ParentName); 10820 } 10821 10822 static bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice) { 10823 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10824 OMPDeclareTargetDeclAttr::getDeviceType(VD); 10825 if (!DevTy) 10826 return false; 10827 // Do not emit device_type(nohost) functions for the host. 10828 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 10829 return true; 10830 // Do not emit device_type(host) functions for the device. 10831 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host) 10832 return true; 10833 return false; 10834 } 10835 10836 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 10837 // If emitting code for the host, we do not process FD here. Instead we do 10838 // the normal code generation. 10839 if (!CGM.getLangOpts().OpenMPIsDevice) { 10840 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) 10841 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD), 10842 CGM.getLangOpts().OpenMPIsDevice)) 10843 return true; 10844 return false; 10845 } 10846 10847 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 10848 // Try to detect target regions in the function. 10849 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 10850 StringRef Name = CGM.getMangledName(GD); 10851 scanForTargetRegionsFunctions(FD->getBody(), Name); 10852 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD), 10853 CGM.getLangOpts().OpenMPIsDevice)) 10854 return true; 10855 } 10856 10857 // Do not to emit function if it is not marked as declare target. 10858 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 10859 AlreadyEmittedTargetDecls.count(VD) == 0; 10860 } 10861 10862 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 10863 if (isAssumedToBeNotEmitted(cast<ValueDecl>(GD.getDecl()), 10864 CGM.getLangOpts().OpenMPIsDevice)) 10865 return true; 10866 10867 if (!CGM.getLangOpts().OpenMPIsDevice) 10868 return false; 10869 10870 // Check if there are Ctors/Dtors in this declaration and look for target 10871 // regions in it. We use the complete variant to produce the kernel name 10872 // mangling. 10873 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 10874 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 10875 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 10876 StringRef ParentName = 10877 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 10878 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 10879 } 10880 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 10881 StringRef ParentName = 10882 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 10883 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 10884 } 10885 } 10886 10887 // Do not to emit variable if it is not marked as declare target. 10888 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10889 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 10890 cast<VarDecl>(GD.getDecl())); 10891 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 10892 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10893 HasRequiresUnifiedSharedMemory)) { 10894 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 10895 return true; 10896 } 10897 return false; 10898 } 10899 10900 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 10901 llvm::Constant *Addr) { 10902 if (CGM.getLangOpts().OMPTargetTriples.empty() && 10903 !CGM.getLangOpts().OpenMPIsDevice) 10904 return; 10905 10906 // If we have host/nohost variables, they do not need to be registered. 10907 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10908 OMPDeclareTargetDeclAttr::getDeviceType(VD); 10909 if (DevTy && DevTy.getValue() != OMPDeclareTargetDeclAttr::DT_Any) 10910 return; 10911 10912 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10913 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10914 if (!Res) { 10915 if (CGM.getLangOpts().OpenMPIsDevice) { 10916 // Register non-target variables being emitted in device code (debug info 10917 // may cause this). 10918 StringRef VarName = CGM.getMangledName(VD); 10919 EmittedNonTargetVariables.try_emplace(VarName, Addr); 10920 } 10921 return; 10922 } 10923 // Register declare target variables. 10924 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 10925 StringRef VarName; 10926 CharUnits VarSize; 10927 llvm::GlobalValue::LinkageTypes Linkage; 10928 10929 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10930 !HasRequiresUnifiedSharedMemory) { 10931 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10932 VarName = CGM.getMangledName(VD); 10933 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 10934 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 10935 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 10936 } else { 10937 VarSize = CharUnits::Zero(); 10938 } 10939 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 10940 // Temp solution to prevent optimizations of the internal variables. 10941 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 10942 // Do not create a "ref-variable" if the original is not also available 10943 // on the host. 10944 if (!OffloadEntriesInfoManager.hasDeviceGlobalVarEntryInfo(VarName)) 10945 return; 10946 std::string RefName = getName({VarName, "ref"}); 10947 if (!CGM.GetGlobalValue(RefName)) { 10948 llvm::Constant *AddrRef = 10949 getOrCreateInternalVariable(Addr->getType(), RefName); 10950 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 10951 GVAddrRef->setConstant(/*Val=*/true); 10952 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 10953 GVAddrRef->setInitializer(Addr); 10954 CGM.addCompilerUsedGlobal(GVAddrRef); 10955 } 10956 } 10957 } else { 10958 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 10959 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10960 HasRequiresUnifiedSharedMemory)) && 10961 "Declare target attribute must link or to with unified memory."); 10962 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 10963 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 10964 else 10965 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10966 10967 if (CGM.getLangOpts().OpenMPIsDevice) { 10968 VarName = Addr->getName(); 10969 Addr = nullptr; 10970 } else { 10971 VarName = getAddrOfDeclareTargetVar(VD).getName(); 10972 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 10973 } 10974 VarSize = CGM.getPointerSize(); 10975 Linkage = llvm::GlobalValue::WeakAnyLinkage; 10976 } 10977 10978 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10979 VarName, Addr, VarSize, Flags, Linkage); 10980 } 10981 10982 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 10983 if (isa<FunctionDecl>(GD.getDecl()) || 10984 isa<OMPDeclareReductionDecl>(GD.getDecl())) 10985 return emitTargetFunctions(GD); 10986 10987 return emitTargetGlobalVariable(GD); 10988 } 10989 10990 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 10991 for (const VarDecl *VD : DeferredGlobalVariables) { 10992 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10993 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10994 if (!Res) 10995 continue; 10996 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10997 !HasRequiresUnifiedSharedMemory) { 10998 CGM.EmitGlobal(VD); 10999 } else { 11000 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 11001 (*Res == OMPDeclareTargetDeclAttr::MT_To && 11002 HasRequiresUnifiedSharedMemory)) && 11003 "Expected link clause or to clause with unified memory."); 11004 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 11005 } 11006 } 11007 } 11008 11009 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 11010 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 11011 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 11012 " Expected target-based directive."); 11013 } 11014 11015 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 11016 for (const OMPClause *Clause : D->clauselists()) { 11017 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 11018 HasRequiresUnifiedSharedMemory = true; 11019 } else if (const auto *AC = 11020 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 11021 switch (AC->getAtomicDefaultMemOrderKind()) { 11022 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 11023 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 11024 break; 11025 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 11026 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 11027 break; 11028 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 11029 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 11030 break; 11031 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 11032 break; 11033 } 11034 } 11035 } 11036 } 11037 11038 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 11039 return RequiresAtomicOrdering; 11040 } 11041 11042 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 11043 LangAS &AS) { 11044 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 11045 return false; 11046 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 11047 switch(A->getAllocatorType()) { 11048 case OMPAllocateDeclAttr::OMPNullMemAlloc: 11049 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 11050 // Not supported, fallback to the default mem space. 11051 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 11052 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 11053 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 11054 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 11055 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 11056 case OMPAllocateDeclAttr::OMPConstMemAlloc: 11057 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 11058 AS = LangAS::Default; 11059 return true; 11060 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 11061 llvm_unreachable("Expected predefined allocator for the variables with the " 11062 "static storage."); 11063 } 11064 return false; 11065 } 11066 11067 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 11068 return HasRequiresUnifiedSharedMemory; 11069 } 11070 11071 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 11072 CodeGenModule &CGM) 11073 : CGM(CGM) { 11074 if (CGM.getLangOpts().OpenMPIsDevice) { 11075 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 11076 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 11077 } 11078 } 11079 11080 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 11081 if (CGM.getLangOpts().OpenMPIsDevice) 11082 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 11083 } 11084 11085 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 11086 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 11087 return true; 11088 11089 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11090 // Do not to emit function if it is marked as declare target as it was already 11091 // emitted. 11092 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 11093 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 11094 if (auto *F = dyn_cast_or_null<llvm::Function>( 11095 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 11096 return !F->isDeclaration(); 11097 return false; 11098 } 11099 return true; 11100 } 11101 11102 return !AlreadyEmittedTargetDecls.insert(D).second; 11103 } 11104 11105 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 11106 // If we don't have entries or if we are emitting code for the device, we 11107 // don't need to do anything. 11108 if (CGM.getLangOpts().OMPTargetTriples.empty() || 11109 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 11110 (OffloadEntriesInfoManager.empty() && 11111 !HasEmittedDeclareTargetRegion && 11112 !HasEmittedTargetRegion)) 11113 return nullptr; 11114 11115 // Create and register the function that handles the requires directives. 11116 ASTContext &C = CGM.getContext(); 11117 11118 llvm::Function *RequiresRegFn; 11119 { 11120 CodeGenFunction CGF(CGM); 11121 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 11122 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 11123 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 11124 RequiresRegFn = CGM.CreateGlobalInitOrCleanUpFunction(FTy, ReqName, FI); 11125 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 11126 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 11127 // TODO: check for other requires clauses. 11128 // The requires directive takes effect only when a target region is 11129 // present in the compilation unit. Otherwise it is ignored and not 11130 // passed to the runtime. This avoids the runtime from throwing an error 11131 // for mismatching requires clauses across compilation units that don't 11132 // contain at least 1 target region. 11133 assert((HasEmittedTargetRegion || 11134 HasEmittedDeclareTargetRegion || 11135 !OffloadEntriesInfoManager.empty()) && 11136 "Target or declare target region expected."); 11137 if (HasRequiresUnifiedSharedMemory) 11138 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 11139 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 11140 CGM.getModule(), OMPRTL___tgt_register_requires), 11141 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 11142 CGF.FinishFunction(); 11143 } 11144 return RequiresRegFn; 11145 } 11146 11147 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 11148 const OMPExecutableDirective &D, 11149 SourceLocation Loc, 11150 llvm::Function *OutlinedFn, 11151 ArrayRef<llvm::Value *> CapturedVars) { 11152 if (!CGF.HaveInsertPoint()) 11153 return; 11154 11155 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 11156 CodeGenFunction::RunCleanupsScope Scope(CGF); 11157 11158 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 11159 llvm::Value *Args[] = { 11160 RTLoc, 11161 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 11162 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 11163 llvm::SmallVector<llvm::Value *, 16> RealArgs; 11164 RealArgs.append(std::begin(Args), std::end(Args)); 11165 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 11166 11167 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11168 CGM.getModule(), OMPRTL___kmpc_fork_teams); 11169 CGF.EmitRuntimeCall(RTLFn, RealArgs); 11170 } 11171 11172 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11173 const Expr *NumTeams, 11174 const Expr *ThreadLimit, 11175 SourceLocation Loc) { 11176 if (!CGF.HaveInsertPoint()) 11177 return; 11178 11179 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 11180 11181 llvm::Value *NumTeamsVal = 11182 NumTeams 11183 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 11184 CGF.CGM.Int32Ty, /* isSigned = */ true) 11185 : CGF.Builder.getInt32(0); 11186 11187 llvm::Value *ThreadLimitVal = 11188 ThreadLimit 11189 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 11190 CGF.CGM.Int32Ty, /* isSigned = */ true) 11191 : CGF.Builder.getInt32(0); 11192 11193 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 11194 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 11195 ThreadLimitVal}; 11196 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 11197 CGM.getModule(), OMPRTL___kmpc_push_num_teams), 11198 PushNumTeamsArgs); 11199 } 11200 11201 void CGOpenMPRuntime::emitTargetDataCalls( 11202 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11203 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11204 if (!CGF.HaveInsertPoint()) 11205 return; 11206 11207 // Action used to replace the default codegen action and turn privatization 11208 // off. 11209 PrePostActionTy NoPrivAction; 11210 11211 // Generate the code for the opening of the data environment. Capture all the 11212 // arguments of the runtime call by reference because they are used in the 11213 // closing of the region. 11214 auto &&BeginThenGen = [this, &D, Device, &Info, 11215 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 11216 // Fill up the arrays with all the mapped variables. 11217 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 11218 11219 // Get map clause information. 11220 MappableExprsHandler MEHandler(D, CGF); 11221 MEHandler.generateAllInfo(CombinedInfo); 11222 11223 // Fill up the arrays and create the arguments. 11224 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 11225 /*IsNonContiguous=*/true); 11226 11227 llvm::Value *BasePointersArrayArg = nullptr; 11228 llvm::Value *PointersArrayArg = nullptr; 11229 llvm::Value *SizesArrayArg = nullptr; 11230 llvm::Value *MapTypesArrayArg = nullptr; 11231 llvm::Value *MapNamesArrayArg = nullptr; 11232 llvm::Value *MappersArrayArg = nullptr; 11233 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 11234 SizesArrayArg, MapTypesArrayArg, 11235 MapNamesArrayArg, MappersArrayArg, Info); 11236 11237 // Emit device ID if any. 11238 llvm::Value *DeviceID = nullptr; 11239 if (Device) { 11240 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11241 CGF.Int64Ty, /*isSigned=*/true); 11242 } else { 11243 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11244 } 11245 11246 // Emit the number of elements in the offloading arrays. 11247 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 11248 // 11249 // Source location for the ident struct 11250 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11251 11252 llvm::Value *OffloadingArgs[] = {RTLoc, 11253 DeviceID, 11254 PointerNum, 11255 BasePointersArrayArg, 11256 PointersArrayArg, 11257 SizesArrayArg, 11258 MapTypesArrayArg, 11259 MapNamesArrayArg, 11260 MappersArrayArg}; 11261 CGF.EmitRuntimeCall( 11262 OMPBuilder.getOrCreateRuntimeFunction( 11263 CGM.getModule(), OMPRTL___tgt_target_data_begin_mapper), 11264 OffloadingArgs); 11265 11266 // If device pointer privatization is required, emit the body of the region 11267 // here. It will have to be duplicated: with and without privatization. 11268 if (!Info.CaptureDeviceAddrMap.empty()) 11269 CodeGen(CGF); 11270 }; 11271 11272 // Generate code for the closing of the data region. 11273 auto &&EndThenGen = [this, Device, &Info, &D](CodeGenFunction &CGF, 11274 PrePostActionTy &) { 11275 assert(Info.isValid() && "Invalid data environment closing arguments."); 11276 11277 llvm::Value *BasePointersArrayArg = nullptr; 11278 llvm::Value *PointersArrayArg = nullptr; 11279 llvm::Value *SizesArrayArg = nullptr; 11280 llvm::Value *MapTypesArrayArg = nullptr; 11281 llvm::Value *MapNamesArrayArg = nullptr; 11282 llvm::Value *MappersArrayArg = nullptr; 11283 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 11284 SizesArrayArg, MapTypesArrayArg, 11285 MapNamesArrayArg, MappersArrayArg, Info, 11286 {/*ForEndCall=*/true}); 11287 11288 // Emit device ID if any. 11289 llvm::Value *DeviceID = nullptr; 11290 if (Device) { 11291 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11292 CGF.Int64Ty, /*isSigned=*/true); 11293 } else { 11294 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11295 } 11296 11297 // Emit the number of elements in the offloading arrays. 11298 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 11299 11300 // Source location for the ident struct 11301 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11302 11303 llvm::Value *OffloadingArgs[] = {RTLoc, 11304 DeviceID, 11305 PointerNum, 11306 BasePointersArrayArg, 11307 PointersArrayArg, 11308 SizesArrayArg, 11309 MapTypesArrayArg, 11310 MapNamesArrayArg, 11311 MappersArrayArg}; 11312 CGF.EmitRuntimeCall( 11313 OMPBuilder.getOrCreateRuntimeFunction( 11314 CGM.getModule(), OMPRTL___tgt_target_data_end_mapper), 11315 OffloadingArgs); 11316 }; 11317 11318 // If we need device pointer privatization, we need to emit the body of the 11319 // region with no privatization in the 'else' branch of the conditional. 11320 // Otherwise, we don't have to do anything. 11321 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 11322 PrePostActionTy &) { 11323 if (!Info.CaptureDeviceAddrMap.empty()) { 11324 CodeGen.setAction(NoPrivAction); 11325 CodeGen(CGF); 11326 } 11327 }; 11328 11329 // We don't have to do anything to close the region if the if clause evaluates 11330 // to false. 11331 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 11332 11333 if (IfCond) { 11334 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 11335 } else { 11336 RegionCodeGenTy RCG(BeginThenGen); 11337 RCG(CGF); 11338 } 11339 11340 // If we don't require privatization of device pointers, we emit the body in 11341 // between the runtime calls. This avoids duplicating the body code. 11342 if (Info.CaptureDeviceAddrMap.empty()) { 11343 CodeGen.setAction(NoPrivAction); 11344 CodeGen(CGF); 11345 } 11346 11347 if (IfCond) { 11348 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 11349 } else { 11350 RegionCodeGenTy RCG(EndThenGen); 11351 RCG(CGF); 11352 } 11353 } 11354 11355 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 11356 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11357 const Expr *Device) { 11358 if (!CGF.HaveInsertPoint()) 11359 return; 11360 11361 assert((isa<OMPTargetEnterDataDirective>(D) || 11362 isa<OMPTargetExitDataDirective>(D) || 11363 isa<OMPTargetUpdateDirective>(D)) && 11364 "Expecting either target enter, exit data, or update directives."); 11365 11366 CodeGenFunction::OMPTargetDataInfo InputInfo; 11367 llvm::Value *MapTypesArray = nullptr; 11368 llvm::Value *MapNamesArray = nullptr; 11369 // Generate the code for the opening of the data environment. 11370 auto &&ThenGen = [this, &D, Device, &InputInfo, &MapTypesArray, 11371 &MapNamesArray](CodeGenFunction &CGF, PrePostActionTy &) { 11372 // Emit device ID if any. 11373 llvm::Value *DeviceID = nullptr; 11374 if (Device) { 11375 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11376 CGF.Int64Ty, /*isSigned=*/true); 11377 } else { 11378 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11379 } 11380 11381 // Emit the number of elements in the offloading arrays. 11382 llvm::Constant *PointerNum = 11383 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 11384 11385 // Source location for the ident struct 11386 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11387 11388 llvm::Value *OffloadingArgs[] = {RTLoc, 11389 DeviceID, 11390 PointerNum, 11391 InputInfo.BasePointersArray.getPointer(), 11392 InputInfo.PointersArray.getPointer(), 11393 InputInfo.SizesArray.getPointer(), 11394 MapTypesArray, 11395 MapNamesArray, 11396 InputInfo.MappersArray.getPointer()}; 11397 11398 // Select the right runtime function call for each standalone 11399 // directive. 11400 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 11401 RuntimeFunction RTLFn; 11402 switch (D.getDirectiveKind()) { 11403 case OMPD_target_enter_data: 11404 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper 11405 : OMPRTL___tgt_target_data_begin_mapper; 11406 break; 11407 case OMPD_target_exit_data: 11408 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper 11409 : OMPRTL___tgt_target_data_end_mapper; 11410 break; 11411 case OMPD_target_update: 11412 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper 11413 : OMPRTL___tgt_target_data_update_mapper; 11414 break; 11415 case OMPD_parallel: 11416 case OMPD_for: 11417 case OMPD_parallel_for: 11418 case OMPD_parallel_master: 11419 case OMPD_parallel_sections: 11420 case OMPD_for_simd: 11421 case OMPD_parallel_for_simd: 11422 case OMPD_cancel: 11423 case OMPD_cancellation_point: 11424 case OMPD_ordered: 11425 case OMPD_threadprivate: 11426 case OMPD_allocate: 11427 case OMPD_task: 11428 case OMPD_simd: 11429 case OMPD_tile: 11430 case OMPD_unroll: 11431 case OMPD_sections: 11432 case OMPD_section: 11433 case OMPD_single: 11434 case OMPD_master: 11435 case OMPD_critical: 11436 case OMPD_taskyield: 11437 case OMPD_barrier: 11438 case OMPD_taskwait: 11439 case OMPD_taskgroup: 11440 case OMPD_atomic: 11441 case OMPD_flush: 11442 case OMPD_depobj: 11443 case OMPD_scan: 11444 case OMPD_teams: 11445 case OMPD_target_data: 11446 case OMPD_distribute: 11447 case OMPD_distribute_simd: 11448 case OMPD_distribute_parallel_for: 11449 case OMPD_distribute_parallel_for_simd: 11450 case OMPD_teams_distribute: 11451 case OMPD_teams_distribute_simd: 11452 case OMPD_teams_distribute_parallel_for: 11453 case OMPD_teams_distribute_parallel_for_simd: 11454 case OMPD_declare_simd: 11455 case OMPD_declare_variant: 11456 case OMPD_begin_declare_variant: 11457 case OMPD_end_declare_variant: 11458 case OMPD_declare_target: 11459 case OMPD_end_declare_target: 11460 case OMPD_declare_reduction: 11461 case OMPD_declare_mapper: 11462 case OMPD_taskloop: 11463 case OMPD_taskloop_simd: 11464 case OMPD_master_taskloop: 11465 case OMPD_master_taskloop_simd: 11466 case OMPD_parallel_master_taskloop: 11467 case OMPD_parallel_master_taskloop_simd: 11468 case OMPD_target: 11469 case OMPD_target_simd: 11470 case OMPD_target_teams_distribute: 11471 case OMPD_target_teams_distribute_simd: 11472 case OMPD_target_teams_distribute_parallel_for: 11473 case OMPD_target_teams_distribute_parallel_for_simd: 11474 case OMPD_target_teams: 11475 case OMPD_target_parallel: 11476 case OMPD_target_parallel_for: 11477 case OMPD_target_parallel_for_simd: 11478 case OMPD_requires: 11479 case OMPD_metadirective: 11480 case OMPD_unknown: 11481 default: 11482 llvm_unreachable("Unexpected standalone target data directive."); 11483 break; 11484 } 11485 CGF.EmitRuntimeCall( 11486 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), RTLFn), 11487 OffloadingArgs); 11488 }; 11489 11490 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 11491 &MapNamesArray](CodeGenFunction &CGF, 11492 PrePostActionTy &) { 11493 // Fill up the arrays with all the mapped variables. 11494 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 11495 11496 // Get map clause information. 11497 MappableExprsHandler MEHandler(D, CGF); 11498 MEHandler.generateAllInfo(CombinedInfo); 11499 11500 TargetDataInfo Info; 11501 // Fill up the arrays and create the arguments. 11502 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 11503 /*IsNonContiguous=*/true); 11504 bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 11505 D.hasClausesOfKind<OMPNowaitClause>(); 11506 emitOffloadingArraysArgument( 11507 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 11508 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 11509 {/*ForEndCall=*/false}); 11510 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 11511 InputInfo.BasePointersArray = 11512 Address::deprecated(Info.BasePointersArray, CGM.getPointerAlign()); 11513 InputInfo.PointersArray = 11514 Address::deprecated(Info.PointersArray, CGM.getPointerAlign()); 11515 InputInfo.SizesArray = 11516 Address::deprecated(Info.SizesArray, CGM.getPointerAlign()); 11517 InputInfo.MappersArray = 11518 Address::deprecated(Info.MappersArray, CGM.getPointerAlign()); 11519 MapTypesArray = Info.MapTypesArray; 11520 MapNamesArray = Info.MapNamesArray; 11521 if (RequiresOuterTask) 11522 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 11523 else 11524 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 11525 }; 11526 11527 if (IfCond) { 11528 emitIfClause(CGF, IfCond, TargetThenGen, 11529 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 11530 } else { 11531 RegionCodeGenTy ThenRCG(TargetThenGen); 11532 ThenRCG(CGF); 11533 } 11534 } 11535 11536 namespace { 11537 /// Kind of parameter in a function with 'declare simd' directive. 11538 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 11539 /// Attribute set of the parameter. 11540 struct ParamAttrTy { 11541 ParamKindTy Kind = Vector; 11542 llvm::APSInt StrideOrArg; 11543 llvm::APSInt Alignment; 11544 }; 11545 } // namespace 11546 11547 static unsigned evaluateCDTSize(const FunctionDecl *FD, 11548 ArrayRef<ParamAttrTy> ParamAttrs) { 11549 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 11550 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 11551 // of that clause. The VLEN value must be power of 2. 11552 // In other case the notion of the function`s "characteristic data type" (CDT) 11553 // is used to compute the vector length. 11554 // CDT is defined in the following order: 11555 // a) For non-void function, the CDT is the return type. 11556 // b) If the function has any non-uniform, non-linear parameters, then the 11557 // CDT is the type of the first such parameter. 11558 // c) If the CDT determined by a) or b) above is struct, union, or class 11559 // type which is pass-by-value (except for the type that maps to the 11560 // built-in complex data type), the characteristic data type is int. 11561 // d) If none of the above three cases is applicable, the CDT is int. 11562 // The VLEN is then determined based on the CDT and the size of vector 11563 // register of that ISA for which current vector version is generated. The 11564 // VLEN is computed using the formula below: 11565 // VLEN = sizeof(vector_register) / sizeof(CDT), 11566 // where vector register size specified in section 3.2.1 Registers and the 11567 // Stack Frame of original AMD64 ABI document. 11568 QualType RetType = FD->getReturnType(); 11569 if (RetType.isNull()) 11570 return 0; 11571 ASTContext &C = FD->getASTContext(); 11572 QualType CDT; 11573 if (!RetType.isNull() && !RetType->isVoidType()) { 11574 CDT = RetType; 11575 } else { 11576 unsigned Offset = 0; 11577 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 11578 if (ParamAttrs[Offset].Kind == Vector) 11579 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 11580 ++Offset; 11581 } 11582 if (CDT.isNull()) { 11583 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11584 if (ParamAttrs[I + Offset].Kind == Vector) { 11585 CDT = FD->getParamDecl(I)->getType(); 11586 break; 11587 } 11588 } 11589 } 11590 } 11591 if (CDT.isNull()) 11592 CDT = C.IntTy; 11593 CDT = CDT->getCanonicalTypeUnqualified(); 11594 if (CDT->isRecordType() || CDT->isUnionType()) 11595 CDT = C.IntTy; 11596 return C.getTypeSize(CDT); 11597 } 11598 11599 static void 11600 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 11601 const llvm::APSInt &VLENVal, 11602 ArrayRef<ParamAttrTy> ParamAttrs, 11603 OMPDeclareSimdDeclAttr::BranchStateTy State) { 11604 struct ISADataTy { 11605 char ISA; 11606 unsigned VecRegSize; 11607 }; 11608 ISADataTy ISAData[] = { 11609 { 11610 'b', 128 11611 }, // SSE 11612 { 11613 'c', 256 11614 }, // AVX 11615 { 11616 'd', 256 11617 }, // AVX2 11618 { 11619 'e', 512 11620 }, // AVX512 11621 }; 11622 llvm::SmallVector<char, 2> Masked; 11623 switch (State) { 11624 case OMPDeclareSimdDeclAttr::BS_Undefined: 11625 Masked.push_back('N'); 11626 Masked.push_back('M'); 11627 break; 11628 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11629 Masked.push_back('N'); 11630 break; 11631 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11632 Masked.push_back('M'); 11633 break; 11634 } 11635 for (char Mask : Masked) { 11636 for (const ISADataTy &Data : ISAData) { 11637 SmallString<256> Buffer; 11638 llvm::raw_svector_ostream Out(Buffer); 11639 Out << "_ZGV" << Data.ISA << Mask; 11640 if (!VLENVal) { 11641 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 11642 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 11643 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 11644 } else { 11645 Out << VLENVal; 11646 } 11647 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 11648 switch (ParamAttr.Kind){ 11649 case LinearWithVarStride: 11650 Out << 's' << ParamAttr.StrideOrArg; 11651 break; 11652 case Linear: 11653 Out << 'l'; 11654 if (ParamAttr.StrideOrArg != 1) 11655 Out << ParamAttr.StrideOrArg; 11656 break; 11657 case Uniform: 11658 Out << 'u'; 11659 break; 11660 case Vector: 11661 Out << 'v'; 11662 break; 11663 } 11664 if (!!ParamAttr.Alignment) 11665 Out << 'a' << ParamAttr.Alignment; 11666 } 11667 Out << '_' << Fn->getName(); 11668 Fn->addFnAttr(Out.str()); 11669 } 11670 } 11671 } 11672 11673 // This are the Functions that are needed to mangle the name of the 11674 // vector functions generated by the compiler, according to the rules 11675 // defined in the "Vector Function ABI specifications for AArch64", 11676 // available at 11677 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 11678 11679 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 11680 /// 11681 /// TODO: Need to implement the behavior for reference marked with a 11682 /// var or no linear modifiers (1.b in the section). For this, we 11683 /// need to extend ParamKindTy to support the linear modifiers. 11684 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 11685 QT = QT.getCanonicalType(); 11686 11687 if (QT->isVoidType()) 11688 return false; 11689 11690 if (Kind == ParamKindTy::Uniform) 11691 return false; 11692 11693 if (Kind == ParamKindTy::Linear) 11694 return false; 11695 11696 // TODO: Handle linear references with modifiers 11697 11698 if (Kind == ParamKindTy::LinearWithVarStride) 11699 return false; 11700 11701 return true; 11702 } 11703 11704 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 11705 static bool getAArch64PBV(QualType QT, ASTContext &C) { 11706 QT = QT.getCanonicalType(); 11707 unsigned Size = C.getTypeSize(QT); 11708 11709 // Only scalars and complex within 16 bytes wide set PVB to true. 11710 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 11711 return false; 11712 11713 if (QT->isFloatingType()) 11714 return true; 11715 11716 if (QT->isIntegerType()) 11717 return true; 11718 11719 if (QT->isPointerType()) 11720 return true; 11721 11722 // TODO: Add support for complex types (section 3.1.2, item 2). 11723 11724 return false; 11725 } 11726 11727 /// Computes the lane size (LS) of a return type or of an input parameter, 11728 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 11729 /// TODO: Add support for references, section 3.2.1, item 1. 11730 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 11731 if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 11732 QualType PTy = QT.getCanonicalType()->getPointeeType(); 11733 if (getAArch64PBV(PTy, C)) 11734 return C.getTypeSize(PTy); 11735 } 11736 if (getAArch64PBV(QT, C)) 11737 return C.getTypeSize(QT); 11738 11739 return C.getTypeSize(C.getUIntPtrType()); 11740 } 11741 11742 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 11743 // signature of the scalar function, as defined in 3.2.2 of the 11744 // AAVFABI. 11745 static std::tuple<unsigned, unsigned, bool> 11746 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 11747 QualType RetType = FD->getReturnType().getCanonicalType(); 11748 11749 ASTContext &C = FD->getASTContext(); 11750 11751 bool OutputBecomesInput = false; 11752 11753 llvm::SmallVector<unsigned, 8> Sizes; 11754 if (!RetType->isVoidType()) { 11755 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 11756 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 11757 OutputBecomesInput = true; 11758 } 11759 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11760 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 11761 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 11762 } 11763 11764 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 11765 // The LS of a function parameter / return value can only be a power 11766 // of 2, starting from 8 bits, up to 128. 11767 assert(llvm::all_of(Sizes, 11768 [](unsigned Size) { 11769 return Size == 8 || Size == 16 || Size == 32 || 11770 Size == 64 || Size == 128; 11771 }) && 11772 "Invalid size"); 11773 11774 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 11775 *std::max_element(std::begin(Sizes), std::end(Sizes)), 11776 OutputBecomesInput); 11777 } 11778 11779 /// Mangle the parameter part of the vector function name according to 11780 /// their OpenMP classification. The mangling function is defined in 11781 /// section 3.5 of the AAVFABI. 11782 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 11783 SmallString<256> Buffer; 11784 llvm::raw_svector_ostream Out(Buffer); 11785 for (const auto &ParamAttr : ParamAttrs) { 11786 switch (ParamAttr.Kind) { 11787 case LinearWithVarStride: 11788 Out << "ls" << ParamAttr.StrideOrArg; 11789 break; 11790 case Linear: 11791 Out << 'l'; 11792 // Don't print the step value if it is not present or if it is 11793 // equal to 1. 11794 if (ParamAttr.StrideOrArg != 1) 11795 Out << ParamAttr.StrideOrArg; 11796 break; 11797 case Uniform: 11798 Out << 'u'; 11799 break; 11800 case Vector: 11801 Out << 'v'; 11802 break; 11803 } 11804 11805 if (!!ParamAttr.Alignment) 11806 Out << 'a' << ParamAttr.Alignment; 11807 } 11808 11809 return std::string(Out.str()); 11810 } 11811 11812 // Function used to add the attribute. The parameter `VLEN` is 11813 // templated to allow the use of "x" when targeting scalable functions 11814 // for SVE. 11815 template <typename T> 11816 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 11817 char ISA, StringRef ParSeq, 11818 StringRef MangledName, bool OutputBecomesInput, 11819 llvm::Function *Fn) { 11820 SmallString<256> Buffer; 11821 llvm::raw_svector_ostream Out(Buffer); 11822 Out << Prefix << ISA << LMask << VLEN; 11823 if (OutputBecomesInput) 11824 Out << "v"; 11825 Out << ParSeq << "_" << MangledName; 11826 Fn->addFnAttr(Out.str()); 11827 } 11828 11829 // Helper function to generate the Advanced SIMD names depending on 11830 // the value of the NDS when simdlen is not present. 11831 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 11832 StringRef Prefix, char ISA, 11833 StringRef ParSeq, StringRef MangledName, 11834 bool OutputBecomesInput, 11835 llvm::Function *Fn) { 11836 switch (NDS) { 11837 case 8: 11838 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11839 OutputBecomesInput, Fn); 11840 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 11841 OutputBecomesInput, Fn); 11842 break; 11843 case 16: 11844 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11845 OutputBecomesInput, Fn); 11846 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11847 OutputBecomesInput, Fn); 11848 break; 11849 case 32: 11850 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11851 OutputBecomesInput, Fn); 11852 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11853 OutputBecomesInput, Fn); 11854 break; 11855 case 64: 11856 case 128: 11857 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11858 OutputBecomesInput, Fn); 11859 break; 11860 default: 11861 llvm_unreachable("Scalar type is too wide."); 11862 } 11863 } 11864 11865 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 11866 static void emitAArch64DeclareSimdFunction( 11867 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 11868 ArrayRef<ParamAttrTy> ParamAttrs, 11869 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 11870 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 11871 11872 // Get basic data for building the vector signature. 11873 const auto Data = getNDSWDS(FD, ParamAttrs); 11874 const unsigned NDS = std::get<0>(Data); 11875 const unsigned WDS = std::get<1>(Data); 11876 const bool OutputBecomesInput = std::get<2>(Data); 11877 11878 // Check the values provided via `simdlen` by the user. 11879 // 1. A `simdlen(1)` doesn't produce vector signatures, 11880 if (UserVLEN == 1) { 11881 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11882 DiagnosticsEngine::Warning, 11883 "The clause simdlen(1) has no effect when targeting aarch64."); 11884 CGM.getDiags().Report(SLoc, DiagID); 11885 return; 11886 } 11887 11888 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 11889 // Advanced SIMD output. 11890 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 11891 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11892 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 11893 "power of 2 when targeting Advanced SIMD."); 11894 CGM.getDiags().Report(SLoc, DiagID); 11895 return; 11896 } 11897 11898 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 11899 // limits. 11900 if (ISA == 's' && UserVLEN != 0) { 11901 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 11902 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11903 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 11904 "lanes in the architectural constraints " 11905 "for SVE (min is 128-bit, max is " 11906 "2048-bit, by steps of 128-bit)"); 11907 CGM.getDiags().Report(SLoc, DiagID) << WDS; 11908 return; 11909 } 11910 } 11911 11912 // Sort out parameter sequence. 11913 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 11914 StringRef Prefix = "_ZGV"; 11915 // Generate simdlen from user input (if any). 11916 if (UserVLEN) { 11917 if (ISA == 's') { 11918 // SVE generates only a masked function. 11919 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11920 OutputBecomesInput, Fn); 11921 } else { 11922 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11923 // Advanced SIMD generates one or two functions, depending on 11924 // the `[not]inbranch` clause. 11925 switch (State) { 11926 case OMPDeclareSimdDeclAttr::BS_Undefined: 11927 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11928 OutputBecomesInput, Fn); 11929 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11930 OutputBecomesInput, Fn); 11931 break; 11932 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11933 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11934 OutputBecomesInput, Fn); 11935 break; 11936 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11937 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11938 OutputBecomesInput, Fn); 11939 break; 11940 } 11941 } 11942 } else { 11943 // If no user simdlen is provided, follow the AAVFABI rules for 11944 // generating the vector length. 11945 if (ISA == 's') { 11946 // SVE, section 3.4.1, item 1. 11947 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 11948 OutputBecomesInput, Fn); 11949 } else { 11950 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11951 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 11952 // two vector names depending on the use of the clause 11953 // `[not]inbranch`. 11954 switch (State) { 11955 case OMPDeclareSimdDeclAttr::BS_Undefined: 11956 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11957 OutputBecomesInput, Fn); 11958 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11959 OutputBecomesInput, Fn); 11960 break; 11961 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11962 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11963 OutputBecomesInput, Fn); 11964 break; 11965 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11966 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11967 OutputBecomesInput, Fn); 11968 break; 11969 } 11970 } 11971 } 11972 } 11973 11974 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 11975 llvm::Function *Fn) { 11976 ASTContext &C = CGM.getContext(); 11977 FD = FD->getMostRecentDecl(); 11978 // Map params to their positions in function decl. 11979 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 11980 if (isa<CXXMethodDecl>(FD)) 11981 ParamPositions.try_emplace(FD, 0); 11982 unsigned ParamPos = ParamPositions.size(); 11983 for (const ParmVarDecl *P : FD->parameters()) { 11984 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 11985 ++ParamPos; 11986 } 11987 while (FD) { 11988 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 11989 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 11990 // Mark uniform parameters. 11991 for (const Expr *E : Attr->uniforms()) { 11992 E = E->IgnoreParenImpCasts(); 11993 unsigned Pos; 11994 if (isa<CXXThisExpr>(E)) { 11995 Pos = ParamPositions[FD]; 11996 } else { 11997 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11998 ->getCanonicalDecl(); 11999 Pos = ParamPositions[PVD]; 12000 } 12001 ParamAttrs[Pos].Kind = Uniform; 12002 } 12003 // Get alignment info. 12004 auto *NI = Attr->alignments_begin(); 12005 for (const Expr *E : Attr->aligneds()) { 12006 E = E->IgnoreParenImpCasts(); 12007 unsigned Pos; 12008 QualType ParmTy; 12009 if (isa<CXXThisExpr>(E)) { 12010 Pos = ParamPositions[FD]; 12011 ParmTy = E->getType(); 12012 } else { 12013 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 12014 ->getCanonicalDecl(); 12015 Pos = ParamPositions[PVD]; 12016 ParmTy = PVD->getType(); 12017 } 12018 ParamAttrs[Pos].Alignment = 12019 (*NI) 12020 ? (*NI)->EvaluateKnownConstInt(C) 12021 : llvm::APSInt::getUnsigned( 12022 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 12023 .getQuantity()); 12024 ++NI; 12025 } 12026 // Mark linear parameters. 12027 auto *SI = Attr->steps_begin(); 12028 auto *MI = Attr->modifiers_begin(); 12029 for (const Expr *E : Attr->linears()) { 12030 E = E->IgnoreParenImpCasts(); 12031 unsigned Pos; 12032 // Rescaling factor needed to compute the linear parameter 12033 // value in the mangled name. 12034 unsigned PtrRescalingFactor = 1; 12035 if (isa<CXXThisExpr>(E)) { 12036 Pos = ParamPositions[FD]; 12037 } else { 12038 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 12039 ->getCanonicalDecl(); 12040 Pos = ParamPositions[PVD]; 12041 if (auto *P = dyn_cast<PointerType>(PVD->getType())) 12042 PtrRescalingFactor = CGM.getContext() 12043 .getTypeSizeInChars(P->getPointeeType()) 12044 .getQuantity(); 12045 } 12046 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 12047 ParamAttr.Kind = Linear; 12048 // Assuming a stride of 1, for `linear` without modifiers. 12049 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1); 12050 if (*SI) { 12051 Expr::EvalResult Result; 12052 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 12053 if (const auto *DRE = 12054 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 12055 if (const auto *StridePVD = 12056 dyn_cast<ParmVarDecl>(DRE->getDecl())) { 12057 ParamAttr.Kind = LinearWithVarStride; 12058 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 12059 ParamPositions[StridePVD->getCanonicalDecl()]); 12060 } 12061 } 12062 } else { 12063 ParamAttr.StrideOrArg = Result.Val.getInt(); 12064 } 12065 } 12066 // If we are using a linear clause on a pointer, we need to 12067 // rescale the value of linear_step with the byte size of the 12068 // pointee type. 12069 if (Linear == ParamAttr.Kind) 12070 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor; 12071 ++SI; 12072 ++MI; 12073 } 12074 llvm::APSInt VLENVal; 12075 SourceLocation ExprLoc; 12076 const Expr *VLENExpr = Attr->getSimdlen(); 12077 if (VLENExpr) { 12078 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 12079 ExprLoc = VLENExpr->getExprLoc(); 12080 } 12081 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 12082 if (CGM.getTriple().isX86()) { 12083 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 12084 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 12085 unsigned VLEN = VLENVal.getExtValue(); 12086 StringRef MangledName = Fn->getName(); 12087 if (CGM.getTarget().hasFeature("sve")) 12088 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 12089 MangledName, 's', 128, Fn, ExprLoc); 12090 if (CGM.getTarget().hasFeature("neon")) 12091 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 12092 MangledName, 'n', 128, Fn, ExprLoc); 12093 } 12094 } 12095 FD = FD->getPreviousDecl(); 12096 } 12097 } 12098 12099 namespace { 12100 /// Cleanup action for doacross support. 12101 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 12102 public: 12103 static const int DoacrossFinArgs = 2; 12104 12105 private: 12106 llvm::FunctionCallee RTLFn; 12107 llvm::Value *Args[DoacrossFinArgs]; 12108 12109 public: 12110 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 12111 ArrayRef<llvm::Value *> CallArgs) 12112 : RTLFn(RTLFn) { 12113 assert(CallArgs.size() == DoacrossFinArgs); 12114 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 12115 } 12116 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 12117 if (!CGF.HaveInsertPoint()) 12118 return; 12119 CGF.EmitRuntimeCall(RTLFn, Args); 12120 } 12121 }; 12122 } // namespace 12123 12124 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 12125 const OMPLoopDirective &D, 12126 ArrayRef<Expr *> NumIterations) { 12127 if (!CGF.HaveInsertPoint()) 12128 return; 12129 12130 ASTContext &C = CGM.getContext(); 12131 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 12132 RecordDecl *RD; 12133 if (KmpDimTy.isNull()) { 12134 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 12135 // kmp_int64 lo; // lower 12136 // kmp_int64 up; // upper 12137 // kmp_int64 st; // stride 12138 // }; 12139 RD = C.buildImplicitRecord("kmp_dim"); 12140 RD->startDefinition(); 12141 addFieldToRecordDecl(C, RD, Int64Ty); 12142 addFieldToRecordDecl(C, RD, Int64Ty); 12143 addFieldToRecordDecl(C, RD, Int64Ty); 12144 RD->completeDefinition(); 12145 KmpDimTy = C.getRecordType(RD); 12146 } else { 12147 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 12148 } 12149 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 12150 QualType ArrayTy = 12151 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 12152 12153 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 12154 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 12155 enum { LowerFD = 0, UpperFD, StrideFD }; 12156 // Fill dims with data. 12157 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 12158 LValue DimsLVal = CGF.MakeAddrLValue( 12159 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 12160 // dims.upper = num_iterations; 12161 LValue UpperLVal = CGF.EmitLValueForField( 12162 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 12163 llvm::Value *NumIterVal = CGF.EmitScalarConversion( 12164 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(), 12165 Int64Ty, NumIterations[I]->getExprLoc()); 12166 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 12167 // dims.stride = 1; 12168 LValue StrideLVal = CGF.EmitLValueForField( 12169 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 12170 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 12171 StrideLVal); 12172 } 12173 12174 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 12175 // kmp_int32 num_dims, struct kmp_dim * dims); 12176 llvm::Value *Args[] = { 12177 emitUpdateLocation(CGF, D.getBeginLoc()), 12178 getThreadID(CGF, D.getBeginLoc()), 12179 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 12180 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12181 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 12182 CGM.VoidPtrTy)}; 12183 12184 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12185 CGM.getModule(), OMPRTL___kmpc_doacross_init); 12186 CGF.EmitRuntimeCall(RTLFn, Args); 12187 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 12188 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 12189 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12190 CGM.getModule(), OMPRTL___kmpc_doacross_fini); 12191 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 12192 llvm::makeArrayRef(FiniArgs)); 12193 } 12194 12195 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12196 const OMPDependClause *C) { 12197 QualType Int64Ty = 12198 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 12199 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 12200 QualType ArrayTy = CGM.getContext().getConstantArrayType( 12201 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 12202 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 12203 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 12204 const Expr *CounterVal = C->getLoopData(I); 12205 assert(CounterVal); 12206 llvm::Value *CntVal = CGF.EmitScalarConversion( 12207 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 12208 CounterVal->getExprLoc()); 12209 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 12210 /*Volatile=*/false, Int64Ty); 12211 } 12212 llvm::Value *Args[] = { 12213 emitUpdateLocation(CGF, C->getBeginLoc()), 12214 getThreadID(CGF, C->getBeginLoc()), 12215 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 12216 llvm::FunctionCallee RTLFn; 12217 if (C->getDependencyKind() == OMPC_DEPEND_source) { 12218 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 12219 OMPRTL___kmpc_doacross_post); 12220 } else { 12221 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 12222 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 12223 OMPRTL___kmpc_doacross_wait); 12224 } 12225 CGF.EmitRuntimeCall(RTLFn, Args); 12226 } 12227 12228 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 12229 llvm::FunctionCallee Callee, 12230 ArrayRef<llvm::Value *> Args) const { 12231 assert(Loc.isValid() && "Outlined function call location must be valid."); 12232 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 12233 12234 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 12235 if (Fn->doesNotThrow()) { 12236 CGF.EmitNounwindRuntimeCall(Fn, Args); 12237 return; 12238 } 12239 } 12240 CGF.EmitRuntimeCall(Callee, Args); 12241 } 12242 12243 void CGOpenMPRuntime::emitOutlinedFunctionCall( 12244 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 12245 ArrayRef<llvm::Value *> Args) const { 12246 emitCall(CGF, Loc, OutlinedFn, Args); 12247 } 12248 12249 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 12250 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 12251 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 12252 HasEmittedDeclareTargetRegion = true; 12253 } 12254 12255 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 12256 const VarDecl *NativeParam, 12257 const VarDecl *TargetParam) const { 12258 return CGF.GetAddrOfLocalVar(NativeParam); 12259 } 12260 12261 /// Return allocator value from expression, or return a null allocator (default 12262 /// when no allocator specified). 12263 static llvm::Value *getAllocatorVal(CodeGenFunction &CGF, 12264 const Expr *Allocator) { 12265 llvm::Value *AllocVal; 12266 if (Allocator) { 12267 AllocVal = CGF.EmitScalarExpr(Allocator); 12268 // According to the standard, the original allocator type is a enum 12269 // (integer). Convert to pointer type, if required. 12270 AllocVal = CGF.EmitScalarConversion(AllocVal, Allocator->getType(), 12271 CGF.getContext().VoidPtrTy, 12272 Allocator->getExprLoc()); 12273 } else { 12274 // If no allocator specified, it defaults to the null allocator. 12275 AllocVal = llvm::Constant::getNullValue( 12276 CGF.CGM.getTypes().ConvertType(CGF.getContext().VoidPtrTy)); 12277 } 12278 return AllocVal; 12279 } 12280 12281 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 12282 const VarDecl *VD) { 12283 if (!VD) 12284 return Address::invalid(); 12285 Address UntiedAddr = Address::invalid(); 12286 Address UntiedRealAddr = Address::invalid(); 12287 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 12288 if (It != FunctionToUntiedTaskStackMap.end()) { 12289 const UntiedLocalVarsAddressesMap &UntiedData = 12290 UntiedLocalVarsStack[It->second]; 12291 auto I = UntiedData.find(VD); 12292 if (I != UntiedData.end()) { 12293 UntiedAddr = I->second.first; 12294 UntiedRealAddr = I->second.second; 12295 } 12296 } 12297 const VarDecl *CVD = VD->getCanonicalDecl(); 12298 if (CVD->hasAttr<OMPAllocateDeclAttr>()) { 12299 // Use the default allocation. 12300 if (!isAllocatableDecl(VD)) 12301 return UntiedAddr; 12302 llvm::Value *Size; 12303 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 12304 if (CVD->getType()->isVariablyModifiedType()) { 12305 Size = CGF.getTypeSize(CVD->getType()); 12306 // Align the size: ((size + align - 1) / align) * align 12307 Size = CGF.Builder.CreateNUWAdd( 12308 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 12309 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 12310 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 12311 } else { 12312 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 12313 Size = CGM.getSize(Sz.alignTo(Align)); 12314 } 12315 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 12316 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 12317 const Expr *Allocator = AA->getAllocator(); 12318 llvm::Value *AllocVal = getAllocatorVal(CGF, Allocator); 12319 llvm::Value *Alignment = 12320 AA->getAlignment() 12321 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(AA->getAlignment()), 12322 CGM.SizeTy, /*isSigned=*/false) 12323 : nullptr; 12324 SmallVector<llvm::Value *, 4> Args; 12325 Args.push_back(ThreadID); 12326 if (Alignment) 12327 Args.push_back(Alignment); 12328 Args.push_back(Size); 12329 Args.push_back(AllocVal); 12330 llvm::omp::RuntimeFunction FnID = 12331 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc; 12332 llvm::Value *Addr = CGF.EmitRuntimeCall( 12333 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), FnID), Args, 12334 getName({CVD->getName(), ".void.addr"})); 12335 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12336 CGM.getModule(), OMPRTL___kmpc_free); 12337 QualType Ty = CGM.getContext().getPointerType(CVD->getType()); 12338 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12339 Addr, CGF.ConvertTypeForMem(Ty), getName({CVD->getName(), ".addr"})); 12340 if (UntiedAddr.isValid()) 12341 CGF.EmitStoreOfScalar(Addr, UntiedAddr, /*Volatile=*/false, Ty); 12342 12343 // Cleanup action for allocate support. 12344 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 12345 llvm::FunctionCallee RTLFn; 12346 SourceLocation::UIntTy LocEncoding; 12347 Address Addr; 12348 const Expr *AllocExpr; 12349 12350 public: 12351 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 12352 SourceLocation::UIntTy LocEncoding, Address Addr, 12353 const Expr *AllocExpr) 12354 : RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr), 12355 AllocExpr(AllocExpr) {} 12356 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 12357 if (!CGF.HaveInsertPoint()) 12358 return; 12359 llvm::Value *Args[3]; 12360 Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID( 12361 CGF, SourceLocation::getFromRawEncoding(LocEncoding)); 12362 Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12363 Addr.getPointer(), CGF.VoidPtrTy); 12364 llvm::Value *AllocVal = getAllocatorVal(CGF, AllocExpr); 12365 Args[2] = AllocVal; 12366 CGF.EmitRuntimeCall(RTLFn, Args); 12367 } 12368 }; 12369 Address VDAddr = UntiedRealAddr.isValid() 12370 ? UntiedRealAddr 12371 : Address::deprecated(Addr, Align); 12372 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>( 12373 NormalAndEHCleanup, FiniRTLFn, CVD->getLocation().getRawEncoding(), 12374 VDAddr, Allocator); 12375 if (UntiedRealAddr.isValid()) 12376 if (auto *Region = 12377 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 12378 Region->emitUntiedSwitch(CGF); 12379 return VDAddr; 12380 } 12381 return UntiedAddr; 12382 } 12383 12384 bool CGOpenMPRuntime::isLocalVarInUntiedTask(CodeGenFunction &CGF, 12385 const VarDecl *VD) const { 12386 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 12387 if (It == FunctionToUntiedTaskStackMap.end()) 12388 return false; 12389 return UntiedLocalVarsStack[It->second].count(VD) > 0; 12390 } 12391 12392 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 12393 CodeGenModule &CGM, const OMPLoopDirective &S) 12394 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 12395 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12396 if (!NeedToPush) 12397 return; 12398 NontemporalDeclsSet &DS = 12399 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 12400 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 12401 for (const Stmt *Ref : C->private_refs()) { 12402 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 12403 const ValueDecl *VD; 12404 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 12405 VD = DRE->getDecl(); 12406 } else { 12407 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 12408 assert((ME->isImplicitCXXThis() || 12409 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 12410 "Expected member of current class."); 12411 VD = ME->getMemberDecl(); 12412 } 12413 DS.insert(VD); 12414 } 12415 } 12416 } 12417 12418 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 12419 if (!NeedToPush) 12420 return; 12421 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 12422 } 12423 12424 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::UntiedTaskLocalDeclsRAII( 12425 CodeGenFunction &CGF, 12426 const llvm::MapVector<CanonicalDeclPtr<const VarDecl>, 12427 std::pair<Address, Address>> &LocalVars) 12428 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) { 12429 if (!NeedToPush) 12430 return; 12431 CGM.getOpenMPRuntime().FunctionToUntiedTaskStackMap.try_emplace( 12432 CGF.CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size()); 12433 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars); 12434 } 12435 12436 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::~UntiedTaskLocalDeclsRAII() { 12437 if (!NeedToPush) 12438 return; 12439 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back(); 12440 } 12441 12442 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 12443 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12444 12445 return llvm::any_of( 12446 CGM.getOpenMPRuntime().NontemporalDeclsStack, 12447 [VD](const NontemporalDeclsSet &Set) { return Set.contains(VD); }); 12448 } 12449 12450 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 12451 const OMPExecutableDirective &S, 12452 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 12453 const { 12454 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 12455 // Vars in target/task regions must be excluded completely. 12456 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 12457 isOpenMPTaskingDirective(S.getDirectiveKind())) { 12458 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12459 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 12460 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 12461 for (const CapturedStmt::Capture &Cap : CS->captures()) { 12462 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 12463 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 12464 } 12465 } 12466 // Exclude vars in private clauses. 12467 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 12468 for (const Expr *Ref : C->varlists()) { 12469 if (!Ref->getType()->isScalarType()) 12470 continue; 12471 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12472 if (!DRE) 12473 continue; 12474 NeedToCheckForLPCs.insert(DRE->getDecl()); 12475 } 12476 } 12477 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 12478 for (const Expr *Ref : C->varlists()) { 12479 if (!Ref->getType()->isScalarType()) 12480 continue; 12481 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12482 if (!DRE) 12483 continue; 12484 NeedToCheckForLPCs.insert(DRE->getDecl()); 12485 } 12486 } 12487 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 12488 for (const Expr *Ref : C->varlists()) { 12489 if (!Ref->getType()->isScalarType()) 12490 continue; 12491 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12492 if (!DRE) 12493 continue; 12494 NeedToCheckForLPCs.insert(DRE->getDecl()); 12495 } 12496 } 12497 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 12498 for (const Expr *Ref : C->varlists()) { 12499 if (!Ref->getType()->isScalarType()) 12500 continue; 12501 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12502 if (!DRE) 12503 continue; 12504 NeedToCheckForLPCs.insert(DRE->getDecl()); 12505 } 12506 } 12507 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 12508 for (const Expr *Ref : C->varlists()) { 12509 if (!Ref->getType()->isScalarType()) 12510 continue; 12511 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12512 if (!DRE) 12513 continue; 12514 NeedToCheckForLPCs.insert(DRE->getDecl()); 12515 } 12516 } 12517 for (const Decl *VD : NeedToCheckForLPCs) { 12518 for (const LastprivateConditionalData &Data : 12519 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 12520 if (Data.DeclToUniqueName.count(VD) > 0) { 12521 if (!Data.Disabled) 12522 NeedToAddForLPCsAsDisabled.insert(VD); 12523 break; 12524 } 12525 } 12526 } 12527 } 12528 12529 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12530 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 12531 : CGM(CGF.CGM), 12532 Action((CGM.getLangOpts().OpenMP >= 50 && 12533 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 12534 [](const OMPLastprivateClause *C) { 12535 return C->getKind() == 12536 OMPC_LASTPRIVATE_conditional; 12537 })) 12538 ? ActionToDo::PushAsLastprivateConditional 12539 : ActionToDo::DoNotPush) { 12540 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12541 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 12542 return; 12543 assert(Action == ActionToDo::PushAsLastprivateConditional && 12544 "Expected a push action."); 12545 LastprivateConditionalData &Data = 12546 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12547 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 12548 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 12549 continue; 12550 12551 for (const Expr *Ref : C->varlists()) { 12552 Data.DeclToUniqueName.insert(std::make_pair( 12553 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 12554 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 12555 } 12556 } 12557 Data.IVLVal = IVLVal; 12558 Data.Fn = CGF.CurFn; 12559 } 12560 12561 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12562 CodeGenFunction &CGF, const OMPExecutableDirective &S) 12563 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 12564 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12565 if (CGM.getLangOpts().OpenMP < 50) 12566 return; 12567 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 12568 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 12569 if (!NeedToAddForLPCsAsDisabled.empty()) { 12570 Action = ActionToDo::DisableLastprivateConditional; 12571 LastprivateConditionalData &Data = 12572 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12573 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 12574 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 12575 Data.Fn = CGF.CurFn; 12576 Data.Disabled = true; 12577 } 12578 } 12579 12580 CGOpenMPRuntime::LastprivateConditionalRAII 12581 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 12582 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 12583 return LastprivateConditionalRAII(CGF, S); 12584 } 12585 12586 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 12587 if (CGM.getLangOpts().OpenMP < 50) 12588 return; 12589 if (Action == ActionToDo::DisableLastprivateConditional) { 12590 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12591 "Expected list of disabled private vars."); 12592 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12593 } 12594 if (Action == ActionToDo::PushAsLastprivateConditional) { 12595 assert( 12596 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12597 "Expected list of lastprivate conditional vars."); 12598 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12599 } 12600 } 12601 12602 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 12603 const VarDecl *VD) { 12604 ASTContext &C = CGM.getContext(); 12605 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 12606 if (I == LastprivateConditionalToTypes.end()) 12607 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 12608 QualType NewType; 12609 const FieldDecl *VDField; 12610 const FieldDecl *FiredField; 12611 LValue BaseLVal; 12612 auto VI = I->getSecond().find(VD); 12613 if (VI == I->getSecond().end()) { 12614 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 12615 RD->startDefinition(); 12616 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 12617 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 12618 RD->completeDefinition(); 12619 NewType = C.getRecordType(RD); 12620 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 12621 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 12622 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 12623 } else { 12624 NewType = std::get<0>(VI->getSecond()); 12625 VDField = std::get<1>(VI->getSecond()); 12626 FiredField = std::get<2>(VI->getSecond()); 12627 BaseLVal = std::get<3>(VI->getSecond()); 12628 } 12629 LValue FiredLVal = 12630 CGF.EmitLValueForField(BaseLVal, FiredField); 12631 CGF.EmitStoreOfScalar( 12632 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 12633 FiredLVal); 12634 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 12635 } 12636 12637 namespace { 12638 /// Checks if the lastprivate conditional variable is referenced in LHS. 12639 class LastprivateConditionalRefChecker final 12640 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 12641 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 12642 const Expr *FoundE = nullptr; 12643 const Decl *FoundD = nullptr; 12644 StringRef UniqueDeclName; 12645 LValue IVLVal; 12646 llvm::Function *FoundFn = nullptr; 12647 SourceLocation Loc; 12648 12649 public: 12650 bool VisitDeclRefExpr(const DeclRefExpr *E) { 12651 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12652 llvm::reverse(LPM)) { 12653 auto It = D.DeclToUniqueName.find(E->getDecl()); 12654 if (It == D.DeclToUniqueName.end()) 12655 continue; 12656 if (D.Disabled) 12657 return false; 12658 FoundE = E; 12659 FoundD = E->getDecl()->getCanonicalDecl(); 12660 UniqueDeclName = It->second; 12661 IVLVal = D.IVLVal; 12662 FoundFn = D.Fn; 12663 break; 12664 } 12665 return FoundE == E; 12666 } 12667 bool VisitMemberExpr(const MemberExpr *E) { 12668 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 12669 return false; 12670 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12671 llvm::reverse(LPM)) { 12672 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 12673 if (It == D.DeclToUniqueName.end()) 12674 continue; 12675 if (D.Disabled) 12676 return false; 12677 FoundE = E; 12678 FoundD = E->getMemberDecl()->getCanonicalDecl(); 12679 UniqueDeclName = It->second; 12680 IVLVal = D.IVLVal; 12681 FoundFn = D.Fn; 12682 break; 12683 } 12684 return FoundE == E; 12685 } 12686 bool VisitStmt(const Stmt *S) { 12687 for (const Stmt *Child : S->children()) { 12688 if (!Child) 12689 continue; 12690 if (const auto *E = dyn_cast<Expr>(Child)) 12691 if (!E->isGLValue()) 12692 continue; 12693 if (Visit(Child)) 12694 return true; 12695 } 12696 return false; 12697 } 12698 explicit LastprivateConditionalRefChecker( 12699 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 12700 : LPM(LPM) {} 12701 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 12702 getFoundData() const { 12703 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 12704 } 12705 }; 12706 } // namespace 12707 12708 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 12709 LValue IVLVal, 12710 StringRef UniqueDeclName, 12711 LValue LVal, 12712 SourceLocation Loc) { 12713 // Last updated loop counter for the lastprivate conditional var. 12714 // int<xx> last_iv = 0; 12715 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 12716 llvm::Constant *LastIV = 12717 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 12718 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 12719 IVLVal.getAlignment().getAsAlign()); 12720 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 12721 12722 // Last value of the lastprivate conditional. 12723 // decltype(priv_a) last_a; 12724 llvm::GlobalVariable *Last = getOrCreateInternalVariable( 12725 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 12726 Last->setAlignment(LVal.getAlignment().getAsAlign()); 12727 LValue LastLVal = CGF.MakeAddrLValue( 12728 Address(Last, Last->getValueType(), LVal.getAlignment()), LVal.getType()); 12729 12730 // Global loop counter. Required to handle inner parallel-for regions. 12731 // iv 12732 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 12733 12734 // #pragma omp critical(a) 12735 // if (last_iv <= iv) { 12736 // last_iv = iv; 12737 // last_a = priv_a; 12738 // } 12739 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 12740 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 12741 Action.Enter(CGF); 12742 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 12743 // (last_iv <= iv) ? Check if the variable is updated and store new 12744 // value in global var. 12745 llvm::Value *CmpRes; 12746 if (IVLVal.getType()->isSignedIntegerType()) { 12747 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 12748 } else { 12749 assert(IVLVal.getType()->isUnsignedIntegerType() && 12750 "Loop iteration variable must be integer."); 12751 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 12752 } 12753 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 12754 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 12755 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 12756 // { 12757 CGF.EmitBlock(ThenBB); 12758 12759 // last_iv = iv; 12760 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 12761 12762 // last_a = priv_a; 12763 switch (CGF.getEvaluationKind(LVal.getType())) { 12764 case TEK_Scalar: { 12765 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 12766 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 12767 break; 12768 } 12769 case TEK_Complex: { 12770 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 12771 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 12772 break; 12773 } 12774 case TEK_Aggregate: 12775 llvm_unreachable( 12776 "Aggregates are not supported in lastprivate conditional."); 12777 } 12778 // } 12779 CGF.EmitBranch(ExitBB); 12780 // There is no need to emit line number for unconditional branch. 12781 (void)ApplyDebugLocation::CreateEmpty(CGF); 12782 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 12783 }; 12784 12785 if (CGM.getLangOpts().OpenMPSimd) { 12786 // Do not emit as a critical region as no parallel region could be emitted. 12787 RegionCodeGenTy ThenRCG(CodeGen); 12788 ThenRCG(CGF); 12789 } else { 12790 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 12791 } 12792 } 12793 12794 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 12795 const Expr *LHS) { 12796 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12797 return; 12798 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 12799 if (!Checker.Visit(LHS)) 12800 return; 12801 const Expr *FoundE; 12802 const Decl *FoundD; 12803 StringRef UniqueDeclName; 12804 LValue IVLVal; 12805 llvm::Function *FoundFn; 12806 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 12807 Checker.getFoundData(); 12808 if (FoundFn != CGF.CurFn) { 12809 // Special codegen for inner parallel regions. 12810 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 12811 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 12812 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 12813 "Lastprivate conditional is not found in outer region."); 12814 QualType StructTy = std::get<0>(It->getSecond()); 12815 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 12816 LValue PrivLVal = CGF.EmitLValue(FoundE); 12817 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12818 PrivLVal.getAddress(CGF), 12819 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy)), 12820 CGF.ConvertTypeForMem(StructTy)); 12821 LValue BaseLVal = 12822 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 12823 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 12824 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 12825 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 12826 FiredLVal, llvm::AtomicOrdering::Unordered, 12827 /*IsVolatile=*/true, /*isInit=*/false); 12828 return; 12829 } 12830 12831 // Private address of the lastprivate conditional in the current context. 12832 // priv_a 12833 LValue LVal = CGF.EmitLValue(FoundE); 12834 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 12835 FoundE->getExprLoc()); 12836 } 12837 12838 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 12839 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12840 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 12841 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12842 return; 12843 auto Range = llvm::reverse(LastprivateConditionalStack); 12844 auto It = llvm::find_if( 12845 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 12846 if (It == Range.end() || It->Fn != CGF.CurFn) 12847 return; 12848 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 12849 assert(LPCI != LastprivateConditionalToTypes.end() && 12850 "Lastprivates must be registered already."); 12851 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12852 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 12853 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 12854 for (const auto &Pair : It->DeclToUniqueName) { 12855 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 12856 if (!CS->capturesVariable(VD) || IgnoredDecls.contains(VD)) 12857 continue; 12858 auto I = LPCI->getSecond().find(Pair.first); 12859 assert(I != LPCI->getSecond().end() && 12860 "Lastprivate must be rehistered already."); 12861 // bool Cmp = priv_a.Fired != 0; 12862 LValue BaseLVal = std::get<3>(I->getSecond()); 12863 LValue FiredLVal = 12864 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 12865 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 12866 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 12867 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 12868 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 12869 // if (Cmp) { 12870 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 12871 CGF.EmitBlock(ThenBB); 12872 Address Addr = CGF.GetAddrOfLocalVar(VD); 12873 LValue LVal; 12874 if (VD->getType()->isReferenceType()) 12875 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 12876 AlignmentSource::Decl); 12877 else 12878 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 12879 AlignmentSource::Decl); 12880 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 12881 D.getBeginLoc()); 12882 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 12883 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 12884 // } 12885 } 12886 } 12887 12888 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 12889 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 12890 SourceLocation Loc) { 12891 if (CGF.getLangOpts().OpenMP < 50) 12892 return; 12893 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 12894 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 12895 "Unknown lastprivate conditional variable."); 12896 StringRef UniqueName = It->second; 12897 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 12898 // The variable was not updated in the region - exit. 12899 if (!GV) 12900 return; 12901 LValue LPLVal = CGF.MakeAddrLValue( 12902 Address(GV, GV->getValueType(), PrivLVal.getAlignment()), 12903 PrivLVal.getType().getNonReferenceType()); 12904 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 12905 CGF.EmitStoreOfScalar(Res, PrivLVal); 12906 } 12907 12908 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 12909 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12910 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12911 llvm_unreachable("Not supported in SIMD-only mode"); 12912 } 12913 12914 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 12915 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12916 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12917 llvm_unreachable("Not supported in SIMD-only mode"); 12918 } 12919 12920 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 12921 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12922 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 12923 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 12924 bool Tied, unsigned &NumberOfParts) { 12925 llvm_unreachable("Not supported in SIMD-only mode"); 12926 } 12927 12928 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 12929 SourceLocation Loc, 12930 llvm::Function *OutlinedFn, 12931 ArrayRef<llvm::Value *> CapturedVars, 12932 const Expr *IfCond, 12933 llvm::Value *NumThreads) { 12934 llvm_unreachable("Not supported in SIMD-only mode"); 12935 } 12936 12937 void CGOpenMPSIMDRuntime::emitCriticalRegion( 12938 CodeGenFunction &CGF, StringRef CriticalName, 12939 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 12940 const Expr *Hint) { 12941 llvm_unreachable("Not supported in SIMD-only mode"); 12942 } 12943 12944 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 12945 const RegionCodeGenTy &MasterOpGen, 12946 SourceLocation Loc) { 12947 llvm_unreachable("Not supported in SIMD-only mode"); 12948 } 12949 12950 void CGOpenMPSIMDRuntime::emitMaskedRegion(CodeGenFunction &CGF, 12951 const RegionCodeGenTy &MasterOpGen, 12952 SourceLocation Loc, 12953 const Expr *Filter) { 12954 llvm_unreachable("Not supported in SIMD-only mode"); 12955 } 12956 12957 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 12958 SourceLocation Loc) { 12959 llvm_unreachable("Not supported in SIMD-only mode"); 12960 } 12961 12962 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 12963 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 12964 SourceLocation Loc) { 12965 llvm_unreachable("Not supported in SIMD-only mode"); 12966 } 12967 12968 void CGOpenMPSIMDRuntime::emitSingleRegion( 12969 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 12970 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 12971 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 12972 ArrayRef<const Expr *> AssignmentOps) { 12973 llvm_unreachable("Not supported in SIMD-only mode"); 12974 } 12975 12976 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 12977 const RegionCodeGenTy &OrderedOpGen, 12978 SourceLocation Loc, 12979 bool IsThreads) { 12980 llvm_unreachable("Not supported in SIMD-only mode"); 12981 } 12982 12983 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 12984 SourceLocation Loc, 12985 OpenMPDirectiveKind Kind, 12986 bool EmitChecks, 12987 bool ForceSimpleCall) { 12988 llvm_unreachable("Not supported in SIMD-only mode"); 12989 } 12990 12991 void CGOpenMPSIMDRuntime::emitForDispatchInit( 12992 CodeGenFunction &CGF, SourceLocation Loc, 12993 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 12994 bool Ordered, const DispatchRTInput &DispatchValues) { 12995 llvm_unreachable("Not supported in SIMD-only mode"); 12996 } 12997 12998 void CGOpenMPSIMDRuntime::emitForStaticInit( 12999 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 13000 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 13001 llvm_unreachable("Not supported in SIMD-only mode"); 13002 } 13003 13004 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 13005 CodeGenFunction &CGF, SourceLocation Loc, 13006 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 13007 llvm_unreachable("Not supported in SIMD-only mode"); 13008 } 13009 13010 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 13011 SourceLocation Loc, 13012 unsigned IVSize, 13013 bool IVSigned) { 13014 llvm_unreachable("Not supported in SIMD-only mode"); 13015 } 13016 13017 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 13018 SourceLocation Loc, 13019 OpenMPDirectiveKind DKind) { 13020 llvm_unreachable("Not supported in SIMD-only mode"); 13021 } 13022 13023 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 13024 SourceLocation Loc, 13025 unsigned IVSize, bool IVSigned, 13026 Address IL, Address LB, 13027 Address UB, Address ST) { 13028 llvm_unreachable("Not supported in SIMD-only mode"); 13029 } 13030 13031 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 13032 llvm::Value *NumThreads, 13033 SourceLocation Loc) { 13034 llvm_unreachable("Not supported in SIMD-only mode"); 13035 } 13036 13037 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 13038 ProcBindKind ProcBind, 13039 SourceLocation Loc) { 13040 llvm_unreachable("Not supported in SIMD-only mode"); 13041 } 13042 13043 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 13044 const VarDecl *VD, 13045 Address VDAddr, 13046 SourceLocation Loc) { 13047 llvm_unreachable("Not supported in SIMD-only mode"); 13048 } 13049 13050 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 13051 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 13052 CodeGenFunction *CGF) { 13053 llvm_unreachable("Not supported in SIMD-only mode"); 13054 } 13055 13056 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 13057 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 13058 llvm_unreachable("Not supported in SIMD-only mode"); 13059 } 13060 13061 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 13062 ArrayRef<const Expr *> Vars, 13063 SourceLocation Loc, 13064 llvm::AtomicOrdering AO) { 13065 llvm_unreachable("Not supported in SIMD-only mode"); 13066 } 13067 13068 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 13069 const OMPExecutableDirective &D, 13070 llvm::Function *TaskFunction, 13071 QualType SharedsTy, Address Shareds, 13072 const Expr *IfCond, 13073 const OMPTaskDataTy &Data) { 13074 llvm_unreachable("Not supported in SIMD-only mode"); 13075 } 13076 13077 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 13078 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 13079 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 13080 const Expr *IfCond, const OMPTaskDataTy &Data) { 13081 llvm_unreachable("Not supported in SIMD-only mode"); 13082 } 13083 13084 void CGOpenMPSIMDRuntime::emitReduction( 13085 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 13086 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 13087 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 13088 assert(Options.SimpleReduction && "Only simple reduction is expected."); 13089 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 13090 ReductionOps, Options); 13091 } 13092 13093 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 13094 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 13095 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 13096 llvm_unreachable("Not supported in SIMD-only mode"); 13097 } 13098 13099 void CGOpenMPSIMDRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 13100 SourceLocation Loc, 13101 bool IsWorksharingReduction) { 13102 llvm_unreachable("Not supported in SIMD-only mode"); 13103 } 13104 13105 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 13106 SourceLocation Loc, 13107 ReductionCodeGen &RCG, 13108 unsigned N) { 13109 llvm_unreachable("Not supported in SIMD-only mode"); 13110 } 13111 13112 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 13113 SourceLocation Loc, 13114 llvm::Value *ReductionsPtr, 13115 LValue SharedLVal) { 13116 llvm_unreachable("Not supported in SIMD-only mode"); 13117 } 13118 13119 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 13120 SourceLocation Loc, 13121 const OMPTaskDataTy &Data) { 13122 llvm_unreachable("Not supported in SIMD-only mode"); 13123 } 13124 13125 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 13126 CodeGenFunction &CGF, SourceLocation Loc, 13127 OpenMPDirectiveKind CancelRegion) { 13128 llvm_unreachable("Not supported in SIMD-only mode"); 13129 } 13130 13131 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 13132 SourceLocation Loc, const Expr *IfCond, 13133 OpenMPDirectiveKind CancelRegion) { 13134 llvm_unreachable("Not supported in SIMD-only mode"); 13135 } 13136 13137 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 13138 const OMPExecutableDirective &D, StringRef ParentName, 13139 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 13140 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 13141 llvm_unreachable("Not supported in SIMD-only mode"); 13142 } 13143 13144 void CGOpenMPSIMDRuntime::emitTargetCall( 13145 CodeGenFunction &CGF, const OMPExecutableDirective &D, 13146 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 13147 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 13148 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 13149 const OMPLoopDirective &D)> 13150 SizeEmitter) { 13151 llvm_unreachable("Not supported in SIMD-only mode"); 13152 } 13153 13154 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 13155 llvm_unreachable("Not supported in SIMD-only mode"); 13156 } 13157 13158 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 13159 llvm_unreachable("Not supported in SIMD-only mode"); 13160 } 13161 13162 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 13163 return false; 13164 } 13165 13166 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 13167 const OMPExecutableDirective &D, 13168 SourceLocation Loc, 13169 llvm::Function *OutlinedFn, 13170 ArrayRef<llvm::Value *> CapturedVars) { 13171 llvm_unreachable("Not supported in SIMD-only mode"); 13172 } 13173 13174 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 13175 const Expr *NumTeams, 13176 const Expr *ThreadLimit, 13177 SourceLocation Loc) { 13178 llvm_unreachable("Not supported in SIMD-only mode"); 13179 } 13180 13181 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 13182 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 13183 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 13184 llvm_unreachable("Not supported in SIMD-only mode"); 13185 } 13186 13187 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 13188 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 13189 const Expr *Device) { 13190 llvm_unreachable("Not supported in SIMD-only mode"); 13191 } 13192 13193 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 13194 const OMPLoopDirective &D, 13195 ArrayRef<Expr *> NumIterations) { 13196 llvm_unreachable("Not supported in SIMD-only mode"); 13197 } 13198 13199 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 13200 const OMPDependClause *C) { 13201 llvm_unreachable("Not supported in SIMD-only mode"); 13202 } 13203 13204 const VarDecl * 13205 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 13206 const VarDecl *NativeParam) const { 13207 llvm_unreachable("Not supported in SIMD-only mode"); 13208 } 13209 13210 Address 13211 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 13212 const VarDecl *NativeParam, 13213 const VarDecl *TargetParam) const { 13214 llvm_unreachable("Not supported in SIMD-only mode"); 13215 } 13216